Replace TyDesc and its uses with trait vtables and a type_name intrinsic.
This commit is contained in:
@@ -42,8 +42,9 @@ extern crate alloc;
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::cmp;
|
||||
use std::intrinsics::{TyDesc, get_tydesc};
|
||||
use std::intrinsics;
|
||||
#[cfg(stage0)] // SNAP 270a677
|
||||
use std::intrinsics::{get_tydesc, TyDesc};
|
||||
use std::marker;
|
||||
use std::mem;
|
||||
#[cfg(stage0)]
|
||||
@@ -186,6 +187,27 @@ fn un_bitpack_tydesc_ptr(p: usize) -> (*const TyDesc, bool) {
|
||||
((p & !1) as *const TyDesc, p & 1 == 1)
|
||||
}
|
||||
|
||||
// HACK(eddyb) TyDesc replacement using a trait object vtable.
|
||||
// This could be replaced in the future with a custom DST layout,
|
||||
// or `&'static (drop_glue, size, align)` created by a `const fn`.
|
||||
#[cfg(not(stage0))] // SNAP 270a677
|
||||
struct TyDesc {
|
||||
drop_glue: fn(*const i8),
|
||||
size: usize,
|
||||
align: usize
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))] // SNAP 270a677
|
||||
unsafe fn get_tydesc<T>() -> *const TyDesc {
|
||||
use std::raw::TraitObject;
|
||||
|
||||
let ptr = &*(1 as *const T);
|
||||
|
||||
// Can use any trait that is implemented for all types.
|
||||
let obj = mem::transmute::<&marker::MarkerTrait, TraitObject>(ptr);
|
||||
obj.vtable as *const TyDesc
|
||||
}
|
||||
|
||||
impl<'longer_than_self> Arena<'longer_than_self> {
|
||||
fn chunk_size(&self) -> usize {
|
||||
self.copy_head.borrow().capacity()
|
||||
|
||||
@@ -44,10 +44,12 @@
|
||||
|
||||
use marker::Sized;
|
||||
|
||||
#[cfg(stage0)] // SNAP 270a677
|
||||
pub type GlueFn = extern "Rust" fn(*const i8);
|
||||
|
||||
#[lang="ty_desc"]
|
||||
#[derive(Copy)]
|
||||
#[cfg(stage0)] // SNAP 270a677
|
||||
pub struct TyDesc {
|
||||
// sizeof(T)
|
||||
pub size: usize,
|
||||
@@ -197,8 +199,13 @@ extern "rust-intrinsic" {
|
||||
pub fn pref_align_of<T>() -> usize;
|
||||
|
||||
/// Get a static pointer to a type descriptor.
|
||||
#[cfg(stage0)] // SNAP 270a677
|
||||
pub fn get_tydesc<T: ?Sized>() -> *const TyDesc;
|
||||
|
||||
/// Gets a static string slice containing the name of a type.
|
||||
#[cfg(not(stage0))] // SNAP 270a677
|
||||
pub fn type_name<T: ?Sized>() -> &'static str;
|
||||
|
||||
/// Gets an identifier which is globally unique to the specified type. This
|
||||
/// function will return the same value for a type regardless of whichever
|
||||
/// crate it is invoked in.
|
||||
|
||||
@@ -316,9 +316,6 @@ lets_do_this! {
|
||||
|
||||
StartFnLangItem, "start", start_fn;
|
||||
|
||||
TyDescStructLangItem, "ty_desc", ty_desc;
|
||||
OpaqueStructLangItem, "opaque", opaque;
|
||||
|
||||
EhPersonalityLangItem, "eh_personality", eh_personality;
|
||||
|
||||
ExchangeHeapLangItem, "exchange_heap", exchange_heap;
|
||||
|
||||
@@ -47,8 +47,7 @@ use middle::check_const;
|
||||
use middle::const_eval;
|
||||
use middle::def::{self, DefMap, ExportMap};
|
||||
use middle::dependency_format;
|
||||
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem};
|
||||
use middle::lang_items::{FnOnceTraitLangItem, TyDescStructLangItem};
|
||||
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
|
||||
use middle::mem_categorization as mc;
|
||||
use middle::region;
|
||||
use middle::resolve_lifetime;
|
||||
@@ -723,7 +722,6 @@ pub struct ctxt<'tcx> {
|
||||
pub object_cast_map: ObjectCastMap<'tcx>,
|
||||
|
||||
pub map: ast_map::Map<'tcx>,
|
||||
pub intrinsic_defs: RefCell<DefIdMap<Ty<'tcx>>>,
|
||||
pub freevars: RefCell<FreevarMap>,
|
||||
pub tcache: RefCell<DefIdMap<TypeScheme<'tcx>>>,
|
||||
pub rcache: RefCell<FnvHashMap<creader_cache_key, Ty<'tcx>>>,
|
||||
@@ -2575,7 +2573,6 @@ pub fn mk_ctxt<'tcx>(s: Session,
|
||||
super_predicates: RefCell::new(DefIdMap()),
|
||||
object_cast_map: RefCell::new(NodeMap()),
|
||||
map: map,
|
||||
intrinsic_defs: RefCell::new(DefIdMap()),
|
||||
freevars: freevars,
|
||||
tcache: RefCell::new(DefIdMap()),
|
||||
rcache: RefCell::new(FnvHashMap()),
|
||||
@@ -5951,13 +5948,6 @@ pub fn required_region_bounds<'tcx>(tcx: &ctxt<'tcx>,
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn get_tydesc_ty<'tcx>(tcx: &ctxt<'tcx>) -> Result<Ty<'tcx>, String> {
|
||||
tcx.lang_items.require(TyDescStructLangItem).map(|tydesc_lang_item| {
|
||||
tcx.intrinsic_defs.borrow().get(&tydesc_lang_item).cloned()
|
||||
.expect("Failed to resolve TyDesc")
|
||||
})
|
||||
}
|
||||
|
||||
pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc<ItemVariances> {
|
||||
lookup_locally_or_in_crate_store(
|
||||
"item_variance_map", item_id, &mut *tcx.item_variance_map.borrow_mut(),
|
||||
|
||||
@@ -57,8 +57,7 @@ use trans::common::{C_null, C_struct_in_context, C_u64, C_u8, C_undef};
|
||||
use trans::common::{CrateContext, ExternMap, FunctionContext};
|
||||
use trans::common::{Result, NodeIdAndSpan};
|
||||
use trans::common::{node_id_type, return_type_is_void};
|
||||
use trans::common::{tydesc_info, type_is_immediate};
|
||||
use trans::common::{type_is_zero_size, val_ty};
|
||||
use trans::common::{type_is_immediate, type_is_zero_size, val_ty};
|
||||
use trans::common;
|
||||
use trans::consts;
|
||||
use trans::context::SharedCrateContext;
|
||||
@@ -90,7 +89,6 @@ use std::ffi::{CStr, CString};
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::HashSet;
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use std::str;
|
||||
use std::{i8, i16, i32, i64};
|
||||
use syntax::abi::{Rust, RustCall, RustIntrinsic, Abi};
|
||||
@@ -392,22 +390,6 @@ pub fn malloc_raw_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
Result::new(r.bcx, PointerCast(r.bcx, r.val, llty_ptr))
|
||||
}
|
||||
|
||||
// Type descriptor and type glue stuff
|
||||
|
||||
pub fn get_tydesc<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
t: Ty<'tcx>) -> Rc<tydesc_info<'tcx>> {
|
||||
match ccx.tydescs().borrow().get(&t) {
|
||||
Some(inf) => return inf.clone(),
|
||||
_ => { }
|
||||
}
|
||||
|
||||
ccx.stats().n_static_tydescs.set(ccx.stats().n_static_tydescs.get() + 1);
|
||||
let inf = Rc::new(glue::declare_tydesc(ccx, t));
|
||||
|
||||
ccx.tydescs().borrow_mut().insert(t, inf.clone());
|
||||
inf
|
||||
}
|
||||
|
||||
#[allow(dead_code)] // useful
|
||||
pub fn set_optimize_for_size(f: ValueRef) {
|
||||
llvm::SetFunctionAttribute(f, llvm::OptimizeForSizeAttribute)
|
||||
@@ -3137,7 +3119,6 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>)
|
||||
}
|
||||
|
||||
for ccx in shared_ccx.iter() {
|
||||
glue::emit_tydescs(&ccx);
|
||||
if ccx.sess().opts.debuginfo != NoDebugInfo {
|
||||
debuginfo::finalize(&ccx);
|
||||
}
|
||||
@@ -3149,7 +3130,6 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>)
|
||||
if shared_ccx.sess().trans_stats() {
|
||||
let stats = shared_ccx.stats();
|
||||
println!("--- trans stats ---");
|
||||
println!("n_static_tydescs: {}", stats.n_static_tydescs.get());
|
||||
println!("n_glues_created: {}", stats.n_glues_created.get());
|
||||
println!("n_null_glues: {}", stats.n_null_glues.get());
|
||||
println!("n_real_glues: {}", stats.n_real_glues.get());
|
||||
|
||||
@@ -316,15 +316,6 @@ pub fn gensym_name(name: &str) -> PathElem {
|
||||
PathName(token::gensym(&format!("{}:{}", name, num)))
|
||||
}
|
||||
|
||||
#[derive(Copy)]
|
||||
pub struct tydesc_info<'tcx> {
|
||||
pub ty: Ty<'tcx>,
|
||||
pub tydesc: ValueRef,
|
||||
pub size: ValueRef,
|
||||
pub align: ValueRef,
|
||||
pub name: ValueRef,
|
||||
}
|
||||
|
||||
/*
|
||||
* A note on nomenclature of linking: "extern", "foreign", and "upcall".
|
||||
*
|
||||
|
||||
@@ -18,7 +18,7 @@ use middle::traits;
|
||||
use trans::adt;
|
||||
use trans::base;
|
||||
use trans::builder::Builder;
|
||||
use trans::common::{ExternMap,tydesc_info,BuilderRef_res};
|
||||
use trans::common::{ExternMap,BuilderRef_res};
|
||||
use trans::debuginfo;
|
||||
use trans::monomorphize::MonoId;
|
||||
use trans::type_::{Type, TypeNames};
|
||||
@@ -38,7 +38,6 @@ use syntax::ast;
|
||||
use syntax::parse::token::InternedString;
|
||||
|
||||
pub struct Stats {
|
||||
pub n_static_tydescs: Cell<uint>,
|
||||
pub n_glues_created: Cell<uint>,
|
||||
pub n_null_glues: Cell<uint>,
|
||||
pub n_real_glues: Cell<uint>,
|
||||
@@ -89,10 +88,6 @@ pub struct LocalCrateContext<'tcx> {
|
||||
needs_unwind_cleanup_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
|
||||
fn_pointer_shims: RefCell<FnvHashMap<Ty<'tcx>, ValueRef>>,
|
||||
drop_glues: RefCell<FnvHashMap<Ty<'tcx>, ValueRef>>,
|
||||
tydescs: RefCell<FnvHashMap<Ty<'tcx>, Rc<tydesc_info<'tcx>>>>,
|
||||
/// Set when running emit_tydescs to enforce that no more tydescs are
|
||||
/// created.
|
||||
finished_tydescs: Cell<bool>,
|
||||
/// Track mapping of external ids to local items imported for inlining
|
||||
external: RefCell<DefIdMap<Option<ast::NodeId>>>,
|
||||
/// Backwards version of the `external` map (inlined items to where they
|
||||
@@ -264,7 +259,6 @@ impl<'tcx> SharedCrateContext<'tcx> {
|
||||
symbol_hasher: RefCell::new(symbol_hasher),
|
||||
tcx: tcx,
|
||||
stats: Stats {
|
||||
n_static_tydescs: Cell::new(0),
|
||||
n_glues_created: Cell::new(0),
|
||||
n_null_glues: Cell::new(0),
|
||||
n_real_glues: Cell::new(0),
|
||||
@@ -399,8 +393,6 @@ impl<'tcx> LocalCrateContext<'tcx> {
|
||||
needs_unwind_cleanup_cache: RefCell::new(FnvHashMap()),
|
||||
fn_pointer_shims: RefCell::new(FnvHashMap()),
|
||||
drop_glues: RefCell::new(FnvHashMap()),
|
||||
tydescs: RefCell::new(FnvHashMap()),
|
||||
finished_tydescs: Cell::new(false),
|
||||
external: RefCell::new(DefIdMap()),
|
||||
external_srcs: RefCell::new(NodeMap()),
|
||||
monomorphized: RefCell::new(FnvHashMap()),
|
||||
@@ -442,8 +434,6 @@ impl<'tcx> LocalCrateContext<'tcx> {
|
||||
str_slice_ty.set_struct_body(&[Type::i8p(&ccx), ccx.int_type()], false);
|
||||
ccx.tn().associate_type("str_slice", &str_slice_ty);
|
||||
|
||||
ccx.tn().associate_type("tydesc", &Type::tydesc(&ccx, str_slice_ty));
|
||||
|
||||
if ccx.sess().count_llvm_insns() {
|
||||
base::init_insn_ctxt()
|
||||
}
|
||||
@@ -519,10 +509,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
|
||||
self.local.builder.b
|
||||
}
|
||||
|
||||
pub fn tydesc_type(&self) -> Type {
|
||||
self.local.tn.find_type("tydesc").unwrap()
|
||||
}
|
||||
|
||||
pub fn get_intrinsic(&self, key: & &'static str) -> ValueRef {
|
||||
if let Some(v) = self.intrinsics().borrow().get(key).cloned() {
|
||||
return v;
|
||||
@@ -590,14 +576,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
|
||||
&self.local.drop_glues
|
||||
}
|
||||
|
||||
pub fn tydescs<'a>(&'a self) -> &'a RefCell<FnvHashMap<Ty<'tcx>, Rc<tydesc_info<'tcx>>>> {
|
||||
&self.local.tydescs
|
||||
}
|
||||
|
||||
pub fn finished_tydescs<'a>(&'a self) -> &'a Cell<bool> {
|
||||
&self.local.finished_tydescs
|
||||
}
|
||||
|
||||
pub fn external<'a>(&'a self) -> &'a RefCell<DefIdMap<Option<ast::NodeId>>> {
|
||||
&self.local.external
|
||||
}
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
|
||||
//!
|
||||
//
|
||||
// Code relating to taking, dropping, etc as well as type descriptors.
|
||||
// Code relating to drop glue.
|
||||
|
||||
|
||||
use back::abi;
|
||||
use back::link::*;
|
||||
use llvm::{ValueRef, True, get_param};
|
||||
use llvm::{ValueRef, get_param};
|
||||
use llvm;
|
||||
use middle::lang_items::ExchangeFreeFnLangItem;
|
||||
use middle::subst;
|
||||
@@ -26,23 +26,20 @@ use trans::build::*;
|
||||
use trans::callee;
|
||||
use trans::cleanup;
|
||||
use trans::cleanup::CleanupMethods;
|
||||
use trans::consts;
|
||||
use trans::common::*;
|
||||
use trans::datum;
|
||||
use trans::debuginfo::DebugLoc;
|
||||
use trans::expr;
|
||||
use trans::machine::*;
|
||||
use trans::type_::Type;
|
||||
use trans::type_of::{self, type_of, sizing_type_of, align_of};
|
||||
use trans::type_of::{type_of, sizing_type_of, align_of};
|
||||
use middle::ty::{self, Ty};
|
||||
use util::ppaux::{ty_to_short_str, Repr};
|
||||
use util::ppaux;
|
||||
|
||||
use arena::TypedArena;
|
||||
use libc::c_uint;
|
||||
use std::ffi::CString;
|
||||
use syntax::ast;
|
||||
use syntax::parse::token;
|
||||
|
||||
pub fn trans_exchange_free_dyn<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
|
||||
v: ValueRef,
|
||||
@@ -177,31 +174,46 @@ pub fn get_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Val
|
||||
|
||||
let llfnty = Type::glue_fn(ccx, llty);
|
||||
|
||||
let (glue, new_sym) = match ccx.available_drop_glues().borrow().get(&t) {
|
||||
Some(old_sym) => {
|
||||
let glue = decl_cdecl_fn(ccx, &old_sym[..], llfnty, ty::mk_nil(ccx.tcx()));
|
||||
(glue, None)
|
||||
},
|
||||
None => {
|
||||
let (sym, glue) = declare_generic_glue(ccx, t, llfnty, "drop");
|
||||
(glue, Some(sym))
|
||||
},
|
||||
};
|
||||
|
||||
ccx.drop_glues().borrow_mut().insert(t, glue);
|
||||
|
||||
// To avoid infinite recursion, don't `make_drop_glue` until after we've
|
||||
// added the entry to the `drop_glues` cache.
|
||||
match new_sym {
|
||||
Some(sym) => {
|
||||
ccx.available_drop_glues().borrow_mut().insert(t, sym);
|
||||
// We're creating a new drop glue, so also generate a body.
|
||||
make_generic_glue(ccx, t, glue, make_drop_glue, "drop");
|
||||
},
|
||||
None => {},
|
||||
}
|
||||
if let Some(old_sym) = ccx.available_drop_glues().borrow().get(&t) {
|
||||
let llfn = decl_cdecl_fn(ccx, &old_sym, llfnty, ty::mk_nil(ccx.tcx()));
|
||||
ccx.drop_glues().borrow_mut().insert(t, llfn);
|
||||
return llfn;
|
||||
};
|
||||
|
||||
glue
|
||||
let fn_nm = mangle_internal_name_by_type_and_seq(ccx, t, "drop");
|
||||
let llfn = decl_cdecl_fn(ccx, &fn_nm, llfnty, ty::mk_nil(ccx.tcx()));
|
||||
note_unique_llvm_symbol(ccx, fn_nm.clone());
|
||||
ccx.available_drop_glues().borrow_mut().insert(t, fn_nm);
|
||||
|
||||
let _s = StatRecorder::new(ccx, format!("drop {}", ty_to_short_str(ccx.tcx(), t)));
|
||||
|
||||
let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
|
||||
let (arena, fcx): (TypedArena<_>, FunctionContext);
|
||||
arena = TypedArena::new();
|
||||
fcx = new_fn_ctxt(ccx, llfn, ast::DUMMY_NODE_ID, false,
|
||||
ty::FnConverging(ty::mk_nil(ccx.tcx())),
|
||||
empty_substs, None, &arena);
|
||||
|
||||
let bcx = init_function(&fcx, false, ty::FnConverging(ty::mk_nil(ccx.tcx())));
|
||||
|
||||
update_linkage(ccx, llfn, None, OriginalTranslation);
|
||||
|
||||
ccx.stats().n_glues_created.set(ccx.stats().n_glues_created.get() + 1);
|
||||
// All glue functions take values passed *by alias*; this is a
|
||||
// requirement since in many contexts glue is invoked indirectly and
|
||||
// the caller has no idea if it's dealing with something that can be
|
||||
// passed by value.
|
||||
//
|
||||
// llfn is expected be declared to take a parameter of the appropriate
|
||||
// type, so we don't need to explicitly cast the function parameter.
|
||||
|
||||
let llrawptr0 = get_param(llfn, fcx.arg_pos(0) as c_uint);
|
||||
let bcx = make_drop_glue(bcx, llrawptr0, t);
|
||||
finish_fn(&fcx, bcx, ty::FnConverging(ty::mk_nil(ccx.tcx())), DebugLoc::None);
|
||||
|
||||
llfn
|
||||
}
|
||||
|
||||
fn trans_struct_drop_flag<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
||||
@@ -467,124 +479,3 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generates the declaration for (but doesn't emit) a type descriptor.
|
||||
pub fn declare_tydesc<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
|
||||
-> tydesc_info<'tcx> {
|
||||
// If emit_tydescs already ran, then we shouldn't be creating any new
|
||||
// tydescs.
|
||||
assert!(!ccx.finished_tydescs().get());
|
||||
|
||||
// This really shouldn't be like this, size/align will be wrong for
|
||||
// unsized types (i.e. [T] will have the size/align of T).
|
||||
// But we need it until we split this out into a "type name" intrinsic.
|
||||
let llty = type_of::in_memory_type_of(ccx, t);
|
||||
|
||||
if ccx.sess().count_type_sizes() {
|
||||
println!("{}\t{}", llsize_of_real(ccx, llty),
|
||||
ppaux::ty_to_string(ccx.tcx(), t));
|
||||
}
|
||||
|
||||
let llsize = llsize_of(ccx, llty);
|
||||
let llalign = llalign_of(ccx, llty);
|
||||
let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc");
|
||||
debug!("+++ declare_tydesc {} {}", ppaux::ty_to_string(ccx.tcx(), t), name);
|
||||
let buf = CString::new(name.clone()).unwrap();
|
||||
let gvar = unsafe {
|
||||
llvm::LLVMAddGlobal(ccx.llmod(), ccx.tydesc_type().to_ref(),
|
||||
buf.as_ptr())
|
||||
};
|
||||
note_unique_llvm_symbol(ccx, name);
|
||||
|
||||
let ty_name = token::intern_and_get_ident(
|
||||
&ppaux::ty_to_string(ccx.tcx(), t));
|
||||
let ty_name = C_str_slice(ccx, ty_name);
|
||||
|
||||
debug!("--- declare_tydesc {}", ppaux::ty_to_string(ccx.tcx(), t));
|
||||
tydesc_info {
|
||||
ty: t,
|
||||
tydesc: gvar,
|
||||
size: llsize,
|
||||
align: llalign,
|
||||
name: ty_name,
|
||||
}
|
||||
}
|
||||
|
||||
fn declare_generic_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>,
|
||||
llfnty: Type, name: &str) -> (String, ValueRef) {
|
||||
let _icx = push_ctxt("declare_generic_glue");
|
||||
let fn_nm = mangle_internal_name_by_type_and_seq(
|
||||
ccx,
|
||||
t,
|
||||
&format!("glue_{}", name));
|
||||
let llfn = decl_cdecl_fn(ccx, &fn_nm[..], llfnty, ty::mk_nil(ccx.tcx()));
|
||||
note_unique_llvm_symbol(ccx, fn_nm.clone());
|
||||
return (fn_nm, llfn);
|
||||
}
|
||||
|
||||
fn make_generic_glue<'a, 'tcx, F>(ccx: &CrateContext<'a, 'tcx>,
|
||||
t: Ty<'tcx>,
|
||||
llfn: ValueRef,
|
||||
helper: F,
|
||||
name: &str)
|
||||
-> ValueRef where
|
||||
F: for<'blk> FnOnce(Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>,
|
||||
{
|
||||
let _icx = push_ctxt("make_generic_glue");
|
||||
let glue_name = format!("glue {} {}", name, ty_to_short_str(ccx.tcx(), t));
|
||||
let _s = StatRecorder::new(ccx, glue_name);
|
||||
|
||||
let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
|
||||
let (arena, fcx): (TypedArena<_>, FunctionContext);
|
||||
arena = TypedArena::new();
|
||||
fcx = new_fn_ctxt(ccx, llfn, ast::DUMMY_NODE_ID, false,
|
||||
ty::FnConverging(ty::mk_nil(ccx.tcx())),
|
||||
empty_substs, None, &arena);
|
||||
|
||||
let bcx = init_function(&fcx, false, ty::FnConverging(ty::mk_nil(ccx.tcx())));
|
||||
|
||||
update_linkage(ccx, llfn, None, OriginalTranslation);
|
||||
|
||||
ccx.stats().n_glues_created.set(ccx.stats().n_glues_created.get() + 1);
|
||||
// All glue functions take values passed *by alias*; this is a
|
||||
// requirement since in many contexts glue is invoked indirectly and
|
||||
// the caller has no idea if it's dealing with something that can be
|
||||
// passed by value.
|
||||
//
|
||||
// llfn is expected be declared to take a parameter of the appropriate
|
||||
// type, so we don't need to explicitly cast the function parameter.
|
||||
|
||||
let llrawptr0 = get_param(llfn, fcx.arg_pos(0) as c_uint);
|
||||
let bcx = helper(bcx, llrawptr0, t);
|
||||
finish_fn(&fcx, bcx, ty::FnConverging(ty::mk_nil(ccx.tcx())), DebugLoc::None);
|
||||
|
||||
llfn
|
||||
}
|
||||
|
||||
pub fn emit_tydescs(ccx: &CrateContext) {
|
||||
let _icx = push_ctxt("emit_tydescs");
|
||||
// As of this point, allow no more tydescs to be created.
|
||||
ccx.finished_tydescs().set(true);
|
||||
let glue_fn_ty = Type::generic_glue_fn(ccx).ptr_to();
|
||||
for (_, ti) in &*ccx.tydescs().borrow() {
|
||||
// Each of the glue functions needs to be cast to a generic type
|
||||
// before being put into the tydesc because we only have a singleton
|
||||
// tydesc type. Then we'll recast each function to its real type when
|
||||
// calling it.
|
||||
let drop_glue = consts::ptrcast(get_drop_glue(ccx, ti.ty), glue_fn_ty);
|
||||
ccx.stats().n_real_glues.set(ccx.stats().n_real_glues.get() + 1);
|
||||
|
||||
let tydesc = C_named_struct(ccx.tydesc_type(),
|
||||
&[ti.size, // size
|
||||
ti.align, // align
|
||||
drop_glue, // drop_glue
|
||||
ti.name]); // name
|
||||
|
||||
unsafe {
|
||||
let gvar = ti.tydesc;
|
||||
llvm::LLVMSetInitializer(gvar, tydesc);
|
||||
llvm::LLVMSetGlobalConstant(gvar, True);
|
||||
llvm::SetLinkage(gvar, llvm::InternalLinkage);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -347,15 +347,10 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
||||
bcx = src.store_to(bcx, llargs[0]);
|
||||
C_nil(ccx)
|
||||
}
|
||||
(_, "get_tydesc") => {
|
||||
(_, "type_name") => {
|
||||
let tp_ty = *substs.types.get(FnSpace, 0);
|
||||
let static_ti = get_tydesc(ccx, tp_ty);
|
||||
|
||||
// FIXME (#3730): ideally this shouldn't need a cast,
|
||||
// but there's a circularity between translating rust types to llvm
|
||||
// types and having a tydesc type available. So I can't directly access
|
||||
// the llvm type of intrinsic::TyDesc struct.
|
||||
PointerCast(bcx, static_ti.tydesc, llret_ty)
|
||||
let ty_name = token::intern_and_get_ident(&ty_to_string(ccx.tcx(), tp_ty));
|
||||
C_str_slice(ccx, ty_name)
|
||||
}
|
||||
(_, "type_id") => {
|
||||
let hash = ty::hash_crate_independent(
|
||||
|
||||
@@ -12,9 +12,7 @@
|
||||
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
use llvm;
|
||||
use llvm::{ValueRef};
|
||||
use llvm::False;
|
||||
use llvm::{self, ValueRef};
|
||||
use trans::common::*;
|
||||
|
||||
use trans::type_::Type;
|
||||
@@ -101,16 +99,6 @@ pub fn llalign_of_min(cx: &CrateContext, ty: Type) -> llalign {
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the "default" alignment of t, which is calculated by casting
|
||||
// null to a record containing a single-bit followed by a t value, then
|
||||
// doing gep(0,1) to get at the trailing (and presumably padded) t cell.
|
||||
pub fn llalign_of(cx: &CrateContext, ty: Type) -> ValueRef {
|
||||
unsafe {
|
||||
return llvm::LLVMConstIntCast(
|
||||
llvm::LLVMAlignOf(ty.to_ref()), cx.int_type().to_ref(), False);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn llelement_offset(cx: &CrateContext, struct_ty: Type, element: uint) -> u64 {
|
||||
unsafe {
|
||||
return llvm::LLVMOffsetOfElement(cx.td().lltd, struct_ty.to_ref(),
|
||||
|
||||
@@ -175,41 +175,10 @@ impl Type {
|
||||
Type::array(&Type::i8p(ccx).ptr_to(), 1)
|
||||
}
|
||||
|
||||
pub fn generic_glue_fn(cx: &CrateContext) -> Type {
|
||||
match cx.tn().find_type("glue_fn") {
|
||||
Some(ty) => return ty,
|
||||
None => ()
|
||||
}
|
||||
|
||||
let ty = Type::glue_fn(cx, Type::i8p(cx));
|
||||
cx.tn().associate_type("glue_fn", &ty);
|
||||
|
||||
ty
|
||||
}
|
||||
|
||||
pub fn glue_fn(ccx: &CrateContext, t: Type) -> Type {
|
||||
Type::func(&[t], &Type::void(ccx))
|
||||
}
|
||||
|
||||
pub fn tydesc(ccx: &CrateContext, str_slice_ty: Type) -> Type {
|
||||
let mut tydesc = Type::named_struct(ccx, "tydesc");
|
||||
let glue_fn_ty = Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to();
|
||||
|
||||
let int_ty = Type::int(ccx);
|
||||
|
||||
// Must mirror:
|
||||
//
|
||||
// std::unstable::intrinsics::TyDesc
|
||||
|
||||
let elems = [int_ty, // size
|
||||
int_ty, // align
|
||||
glue_fn_ty, // drop
|
||||
str_slice_ty]; // name
|
||||
tydesc.set_struct_body(&elems, false);
|
||||
|
||||
tydesc
|
||||
}
|
||||
|
||||
pub fn array(ty: &Type, len: u64) -> Type {
|
||||
ty!(llvm::LLVMRustArrayType(ty.to_ref(), len))
|
||||
}
|
||||
|
||||
@@ -5347,17 +5347,8 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
|
||||
"needs_drop" => (1, Vec::new(), ccx.tcx.types.bool),
|
||||
"owns_managed" => (1, Vec::new(), ccx.tcx.types.bool),
|
||||
|
||||
"get_tydesc" => {
|
||||
let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
|
||||
Ok(t) => t,
|
||||
Err(s) => { span_fatal!(tcx.sess, it.span, E0240, "{}", &s[..]); }
|
||||
};
|
||||
let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
|
||||
ty: tydesc_ty,
|
||||
mutbl: ast::MutImmutable
|
||||
});
|
||||
(1, Vec::new(), td_ptr)
|
||||
}
|
||||
"type_name" => (1, Vec::new(), ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic),
|
||||
ast::MutImmutable)),
|
||||
"type_id" => (1, Vec::new(), ccx.tcx.types.u64),
|
||||
"offset" => {
|
||||
(1,
|
||||
|
||||
@@ -102,15 +102,6 @@ use syntax::visit;
|
||||
pub fn collect_item_types(tcx: &ty::ctxt) {
|
||||
let ccx = &CrateCtxt { tcx: tcx, stack: RefCell::new(Vec::new()) };
|
||||
|
||||
match ccx.tcx.lang_items.ty_desc() {
|
||||
Some(id) => { collect_intrinsic_type(ccx, id); }
|
||||
None => {}
|
||||
}
|
||||
match ccx.tcx.lang_items.opaque() {
|
||||
Some(id) => { collect_intrinsic_type(ccx, id); }
|
||||
None => {}
|
||||
}
|
||||
|
||||
let mut visitor = CollectTraitDefVisitor{ ccx: ccx };
|
||||
visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
|
||||
|
||||
@@ -152,15 +143,6 @@ enum AstConvRequest {
|
||||
GetTypeParameterBounds(ast::NodeId),
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Zeroth phase: collect types of intrinsics
|
||||
|
||||
fn collect_intrinsic_type(ccx: &CrateCtxt,
|
||||
lang_item: ast::DefId) {
|
||||
let ty::TypeScheme { ty, .. } = type_scheme_of_def_id(ccx, lang_item);
|
||||
ccx.tcx.intrinsic_defs.borrow_mut().insert(lang_item, ty);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// First phase: just collect *trait definitions* -- basically, the set
|
||||
// of type parameters and supertraits. This is information we need to
|
||||
|
||||
@@ -13,17 +13,17 @@ struct NT(str);
|
||||
struct DST { a: u32, b: str }
|
||||
|
||||
fn main() {
|
||||
// get_tydesc should support unsized types
|
||||
// type_name should support unsized types
|
||||
assert_eq!(unsafe {(
|
||||
// Slice
|
||||
(*std::intrinsics::get_tydesc::<[u8]>()).name,
|
||||
std::intrinsics::type_name::<[u8]>(),
|
||||
// str
|
||||
(*std::intrinsics::get_tydesc::<str>()).name,
|
||||
std::intrinsics::type_name::<str>(),
|
||||
// Trait
|
||||
(*std::intrinsics::get_tydesc::<Copy>()).name,
|
||||
std::intrinsics::type_name::<Copy>(),
|
||||
// Newtype
|
||||
(*std::intrinsics::get_tydesc::<NT>()).name,
|
||||
std::intrinsics::type_name::<NT>(),
|
||||
// DST
|
||||
(*std::intrinsics::get_tydesc::<DST>()).name
|
||||
std::intrinsics::type_name::<DST>()
|
||||
)}, ("[u8]", "str", "core::marker::Copy", "NT", "DST"));
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
use std::intrinsics::get_tydesc;
|
||||
use std::intrinsics::type_name;
|
||||
|
||||
struct Foo<T> {
|
||||
x: T
|
||||
@@ -17,7 +17,7 @@ struct Foo<T> {
|
||||
|
||||
pub fn main() {
|
||||
unsafe {
|
||||
assert_eq!((*get_tydesc::<int>()).name, "isize");
|
||||
assert_eq!((*get_tydesc::<Foo<uint>>()).name, "Foo<usize>");
|
||||
assert_eq!(type_name::<int>(), "isize");
|
||||
assert_eq!(type_name::<Foo<uint>>(), "Foo<usize>");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user