mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 09:14:20 +00:00
allow generating drop glue without the TyDesc
Reflection is now the only user of type descriptors. Uses of drop glue no longer cause a type descriptor to be generated.
This commit is contained in:
parent
940d1ae2f3
commit
eced501226
@ -214,8 +214,7 @@ impl Arena {
|
||||
#[inline]
|
||||
fn alloc_pod<'a, T>(&'a mut self, op: || -> T) -> &'a T {
|
||||
unsafe {
|
||||
let tydesc = get_tydesc::<T>();
|
||||
let ptr = self.alloc_pod_inner((*tydesc).size, (*tydesc).align);
|
||||
let ptr = self.alloc_pod_inner(mem::size_of::<T>(), mem::min_align_of::<T>());
|
||||
let ptr: *mut T = transmute(ptr);
|
||||
intrinsics::move_val_init(&mut (*ptr), op());
|
||||
return transmute(ptr);
|
||||
@ -272,7 +271,7 @@ impl Arena {
|
||||
unsafe {
|
||||
let tydesc = get_tydesc::<T>();
|
||||
let (ty_ptr, ptr) =
|
||||
self.alloc_nonpod_inner((*tydesc).size, (*tydesc).align);
|
||||
self.alloc_nonpod_inner(mem::size_of::<T>(), mem::min_align_of::<T>());
|
||||
let ty_ptr: *mut uint = transmute(ty_ptr);
|
||||
let ptr: *mut T = transmute(ptr);
|
||||
// Write in our tydesc along with a bit indicating that it
|
||||
|
@ -376,12 +376,8 @@ pub fn malloc_raw_dyn<'a>(
|
||||
let llty = type_of(ccx, box_ptr_ty);
|
||||
let llalign = C_uint(ccx, llalign_of_min(ccx, llty) as uint);
|
||||
|
||||
// Get the tydesc for the body:
|
||||
let static_ti = get_tydesc(ccx, t);
|
||||
glue::lazily_emit_tydesc_glue(ccx, abi::tydesc_field_drop_glue, static_ti);
|
||||
|
||||
// Allocate space:
|
||||
let drop_glue = static_ti.drop_glue.get().unwrap();
|
||||
let drop_glue = glue::get_drop_glue(ccx, t);
|
||||
let r = callee::trans_lang_call(
|
||||
bcx,
|
||||
langcall,
|
||||
|
@ -114,7 +114,6 @@ pub struct tydesc_info {
|
||||
size: ValueRef,
|
||||
align: ValueRef,
|
||||
name: ValueRef,
|
||||
drop_glue: Cell<Option<ValueRef>>,
|
||||
visit_glue: Cell<Option<ValueRef>>,
|
||||
}
|
||||
|
||||
|
@ -36,83 +36,84 @@ use syntax::ast;
|
||||
use syntax::parse::token::InternedString;
|
||||
|
||||
pub struct CrateContext {
|
||||
sess: session::Session,
|
||||
llmod: ModuleRef,
|
||||
llcx: ContextRef,
|
||||
metadata_llmod: ModuleRef,
|
||||
td: TargetData,
|
||||
tn: TypeNames,
|
||||
externs: RefCell<ExternMap>,
|
||||
intrinsics: HashMap<&'static str, ValueRef>,
|
||||
item_vals: RefCell<HashMap<ast::NodeId, ValueRef>>,
|
||||
exp_map2: resolve::ExportMap2,
|
||||
reachable: @RefCell<HashSet<ast::NodeId>>,
|
||||
item_symbols: RefCell<HashMap<ast::NodeId, ~str>>,
|
||||
link_meta: LinkMeta,
|
||||
tydescs: RefCell<HashMap<ty::t, @tydesc_info>>,
|
||||
// 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<HashMap<ast::DefId, Option<ast::NodeId>>>,
|
||||
// Backwards version of the `external` map (inlined items to where they
|
||||
// came from)
|
||||
external_srcs: RefCell<HashMap<ast::NodeId, ast::DefId>>,
|
||||
// A set of static items which cannot be inlined into other crates. This
|
||||
// will pevent in IIItem() structures from being encoded into the metadata
|
||||
// that is generated
|
||||
non_inlineable_statics: RefCell<HashSet<ast::NodeId>>,
|
||||
// Cache instances of monomorphized functions
|
||||
monomorphized: RefCell<HashMap<mono_id, ValueRef>>,
|
||||
monomorphizing: RefCell<HashMap<ast::DefId, uint>>,
|
||||
// Cache generated vtables
|
||||
vtables: RefCell<HashMap<(ty::t, mono_id), ValueRef>>,
|
||||
// Cache of constant strings,
|
||||
const_cstr_cache: RefCell<HashMap<InternedString, ValueRef>>,
|
||||
sess: session::Session,
|
||||
llmod: ModuleRef,
|
||||
llcx: ContextRef,
|
||||
metadata_llmod: ModuleRef,
|
||||
td: TargetData,
|
||||
tn: TypeNames,
|
||||
externs: RefCell<ExternMap>,
|
||||
intrinsics: HashMap<&'static str, ValueRef>,
|
||||
item_vals: RefCell<HashMap<ast::NodeId, ValueRef>>,
|
||||
exp_map2: resolve::ExportMap2,
|
||||
reachable: @RefCell<HashSet<ast::NodeId>>,
|
||||
item_symbols: RefCell<HashMap<ast::NodeId, ~str>>,
|
||||
link_meta: LinkMeta,
|
||||
drop_glues: RefCell<HashMap<ty::t, ValueRef>>,
|
||||
tydescs: RefCell<HashMap<ty::t, @tydesc_info>>,
|
||||
// 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<HashMap<ast::DefId, Option<ast::NodeId>>>,
|
||||
// Backwards version of the `external` map (inlined items to where they
|
||||
// came from)
|
||||
external_srcs: RefCell<HashMap<ast::NodeId, ast::DefId>>,
|
||||
// A set of static items which cannot be inlined into other crates. This
|
||||
// will pevent in IIItem() structures from being encoded into the metadata
|
||||
// that is generated
|
||||
non_inlineable_statics: RefCell<HashSet<ast::NodeId>>,
|
||||
// Cache instances of monomorphized functions
|
||||
monomorphized: RefCell<HashMap<mono_id, ValueRef>>,
|
||||
monomorphizing: RefCell<HashMap<ast::DefId, uint>>,
|
||||
// Cache generated vtables
|
||||
vtables: RefCell<HashMap<(ty::t, mono_id), ValueRef>>,
|
||||
// Cache of constant strings,
|
||||
const_cstr_cache: RefCell<HashMap<InternedString, ValueRef>>,
|
||||
|
||||
// Reverse-direction for const ptrs cast from globals.
|
||||
// Key is an int, cast from a ValueRef holding a *T,
|
||||
// Val is a ValueRef holding a *[T].
|
||||
//
|
||||
// Needed because LLVM loses pointer->pointee association
|
||||
// when we ptrcast, and we have to ptrcast during translation
|
||||
// of a [T] const because we form a slice, a [*T,int] pair, not
|
||||
// a pointer to an LLVM array type.
|
||||
const_globals: RefCell<HashMap<int, ValueRef>>,
|
||||
// Reverse-direction for const ptrs cast from globals.
|
||||
// Key is an int, cast from a ValueRef holding a *T,
|
||||
// Val is a ValueRef holding a *[T].
|
||||
//
|
||||
// Needed because LLVM loses pointer->pointee association
|
||||
// when we ptrcast, and we have to ptrcast during translation
|
||||
// of a [T] const because we form a slice, a [*T,int] pair, not
|
||||
// a pointer to an LLVM array type.
|
||||
const_globals: RefCell<HashMap<int, ValueRef>>,
|
||||
|
||||
// Cache of emitted const values
|
||||
const_values: RefCell<HashMap<ast::NodeId, ValueRef>>,
|
||||
// Cache of emitted const values
|
||||
const_values: RefCell<HashMap<ast::NodeId, ValueRef>>,
|
||||
|
||||
// Cache of external const values
|
||||
extern_const_values: RefCell<HashMap<ast::DefId, ValueRef>>,
|
||||
// Cache of external const values
|
||||
extern_const_values: RefCell<HashMap<ast::DefId, ValueRef>>,
|
||||
|
||||
impl_method_cache: RefCell<HashMap<(ast::DefId, ast::Name), ast::DefId>>,
|
||||
impl_method_cache: RefCell<HashMap<(ast::DefId, ast::Name), ast::DefId>>,
|
||||
|
||||
// Cache of closure wrappers for bare fn's.
|
||||
closure_bare_wrapper_cache: RefCell<HashMap<ValueRef, ValueRef>>,
|
||||
// Cache of closure wrappers for bare fn's.
|
||||
closure_bare_wrapper_cache: RefCell<HashMap<ValueRef, ValueRef>>,
|
||||
|
||||
module_data: RefCell<HashMap<~str, ValueRef>>,
|
||||
lltypes: RefCell<HashMap<ty::t, Type>>,
|
||||
llsizingtypes: RefCell<HashMap<ty::t, Type>>,
|
||||
adt_reprs: RefCell<HashMap<ty::t, @adt::Repr>>,
|
||||
symbol_hasher: RefCell<Sha256>,
|
||||
type_hashcodes: RefCell<HashMap<ty::t, ~str>>,
|
||||
all_llvm_symbols: RefCell<HashSet<~str>>,
|
||||
tcx: ty::ctxt,
|
||||
maps: astencode::Maps,
|
||||
stats: @Stats,
|
||||
tydesc_type: Type,
|
||||
int_type: Type,
|
||||
opaque_vec_type: Type,
|
||||
builder: BuilderRef_res,
|
||||
crate_map: ValueRef,
|
||||
crate_map_name: ~str,
|
||||
// Set when at least one function uses GC. Needed so that
|
||||
// decl_gc_metadata knows whether to link to the module metadata, which
|
||||
// is not emitted by LLVM's GC pass when no functions use GC.
|
||||
uses_gc: bool,
|
||||
dbg_cx: Option<debuginfo::CrateDebugContext>,
|
||||
do_not_commit_warning_issued: Cell<bool>,
|
||||
module_data: RefCell<HashMap<~str, ValueRef>>,
|
||||
lltypes: RefCell<HashMap<ty::t, Type>>,
|
||||
llsizingtypes: RefCell<HashMap<ty::t, Type>>,
|
||||
adt_reprs: RefCell<HashMap<ty::t, @adt::Repr>>,
|
||||
symbol_hasher: RefCell<Sha256>,
|
||||
type_hashcodes: RefCell<HashMap<ty::t, ~str>>,
|
||||
all_llvm_symbols: RefCell<HashSet<~str>>,
|
||||
tcx: ty::ctxt,
|
||||
maps: astencode::Maps,
|
||||
stats: @Stats,
|
||||
tydesc_type: Type,
|
||||
int_type: Type,
|
||||
opaque_vec_type: Type,
|
||||
builder: BuilderRef_res,
|
||||
crate_map: ValueRef,
|
||||
crate_map_name: ~str,
|
||||
// Set when at least one function uses GC. Needed so that
|
||||
// decl_gc_metadata knows whether to link to the module metadata, which
|
||||
// is not emitted by LLVM's GC pass when no functions use GC.
|
||||
uses_gc: bool,
|
||||
dbg_cx: Option<debuginfo::CrateDebugContext>,
|
||||
do_not_commit_warning_issued: Cell<bool>,
|
||||
}
|
||||
|
||||
impl CrateContext {
|
||||
@ -175,64 +176,65 @@ impl CrateContext {
|
||||
}
|
||||
|
||||
CrateContext {
|
||||
sess: sess,
|
||||
llmod: llmod,
|
||||
llcx: llcx,
|
||||
metadata_llmod: metadata_llmod,
|
||||
td: td,
|
||||
tn: tn,
|
||||
externs: RefCell::new(HashMap::new()),
|
||||
intrinsics: intrinsics,
|
||||
item_vals: RefCell::new(HashMap::new()),
|
||||
exp_map2: emap2,
|
||||
reachable: reachable,
|
||||
item_symbols: RefCell::new(HashMap::new()),
|
||||
link_meta: link_meta,
|
||||
tydescs: RefCell::new(HashMap::new()),
|
||||
finished_tydescs: Cell::new(false),
|
||||
external: RefCell::new(HashMap::new()),
|
||||
external_srcs: RefCell::new(HashMap::new()),
|
||||
non_inlineable_statics: RefCell::new(HashSet::new()),
|
||||
monomorphized: RefCell::new(HashMap::new()),
|
||||
monomorphizing: RefCell::new(HashMap::new()),
|
||||
vtables: RefCell::new(HashMap::new()),
|
||||
const_cstr_cache: RefCell::new(HashMap::new()),
|
||||
const_globals: RefCell::new(HashMap::new()),
|
||||
const_values: RefCell::new(HashMap::new()),
|
||||
extern_const_values: RefCell::new(HashMap::new()),
|
||||
impl_method_cache: RefCell::new(HashMap::new()),
|
||||
closure_bare_wrapper_cache: RefCell::new(HashMap::new()),
|
||||
module_data: RefCell::new(HashMap::new()),
|
||||
lltypes: RefCell::new(HashMap::new()),
|
||||
llsizingtypes: RefCell::new(HashMap::new()),
|
||||
adt_reprs: RefCell::new(HashMap::new()),
|
||||
symbol_hasher: RefCell::new(symbol_hasher),
|
||||
type_hashcodes: RefCell::new(HashMap::new()),
|
||||
all_llvm_symbols: RefCell::new(HashSet::new()),
|
||||
tcx: tcx,
|
||||
maps: maps,
|
||||
stats: @Stats {
|
||||
n_static_tydescs: Cell::new(0u),
|
||||
n_glues_created: Cell::new(0u),
|
||||
n_null_glues: Cell::new(0u),
|
||||
n_real_glues: Cell::new(0u),
|
||||
n_fns: Cell::new(0u),
|
||||
n_monos: Cell::new(0u),
|
||||
n_inlines: Cell::new(0u),
|
||||
n_closures: Cell::new(0u),
|
||||
n_llvm_insns: Cell::new(0u),
|
||||
llvm_insns: RefCell::new(HashMap::new()),
|
||||
fn_stats: RefCell::new(~[]),
|
||||
},
|
||||
tydesc_type: tydesc_type,
|
||||
int_type: int_type,
|
||||
opaque_vec_type: opaque_vec_type,
|
||||
builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)),
|
||||
crate_map: crate_map,
|
||||
crate_map_name: crate_map_name,
|
||||
uses_gc: false,
|
||||
dbg_cx: dbg_cx,
|
||||
do_not_commit_warning_issued: Cell::new(false),
|
||||
sess: sess,
|
||||
llmod: llmod,
|
||||
llcx: llcx,
|
||||
metadata_llmod: metadata_llmod,
|
||||
td: td,
|
||||
tn: tn,
|
||||
externs: RefCell::new(HashMap::new()),
|
||||
intrinsics: intrinsics,
|
||||
item_vals: RefCell::new(HashMap::new()),
|
||||
exp_map2: emap2,
|
||||
reachable: reachable,
|
||||
item_symbols: RefCell::new(HashMap::new()),
|
||||
link_meta: link_meta,
|
||||
drop_glues: RefCell::new(HashMap::new()),
|
||||
tydescs: RefCell::new(HashMap::new()),
|
||||
finished_tydescs: Cell::new(false),
|
||||
external: RefCell::new(HashMap::new()),
|
||||
external_srcs: RefCell::new(HashMap::new()),
|
||||
non_inlineable_statics: RefCell::new(HashSet::new()),
|
||||
monomorphized: RefCell::new(HashMap::new()),
|
||||
monomorphizing: RefCell::new(HashMap::new()),
|
||||
vtables: RefCell::new(HashMap::new()),
|
||||
const_cstr_cache: RefCell::new(HashMap::new()),
|
||||
const_globals: RefCell::new(HashMap::new()),
|
||||
const_values: RefCell::new(HashMap::new()),
|
||||
extern_const_values: RefCell::new(HashMap::new()),
|
||||
impl_method_cache: RefCell::new(HashMap::new()),
|
||||
closure_bare_wrapper_cache: RefCell::new(HashMap::new()),
|
||||
module_data: RefCell::new(HashMap::new()),
|
||||
lltypes: RefCell::new(HashMap::new()),
|
||||
llsizingtypes: RefCell::new(HashMap::new()),
|
||||
adt_reprs: RefCell::new(HashMap::new()),
|
||||
symbol_hasher: RefCell::new(symbol_hasher),
|
||||
type_hashcodes: RefCell::new(HashMap::new()),
|
||||
all_llvm_symbols: RefCell::new(HashSet::new()),
|
||||
tcx: tcx,
|
||||
maps: maps,
|
||||
stats: @Stats {
|
||||
n_static_tydescs: Cell::new(0u),
|
||||
n_glues_created: Cell::new(0u),
|
||||
n_null_glues: Cell::new(0u),
|
||||
n_real_glues: Cell::new(0u),
|
||||
n_fns: Cell::new(0u),
|
||||
n_monos: Cell::new(0u),
|
||||
n_inlines: Cell::new(0u),
|
||||
n_closures: Cell::new(0u),
|
||||
n_llvm_insns: Cell::new(0u),
|
||||
llvm_insns: RefCell::new(HashMap::new()),
|
||||
fn_stats: RefCell::new(~[]),
|
||||
},
|
||||
tydesc_type: tydesc_type,
|
||||
int_type: int_type,
|
||||
opaque_vec_type: opaque_vec_type,
|
||||
builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)),
|
||||
crate_map: crate_map,
|
||||
crate_map_name: crate_map_name,
|
||||
uses_gc: false,
|
||||
dbg_cx: dbg_cx,
|
||||
do_not_commit_warning_issued: Cell::new(false),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -73,14 +73,49 @@ pub fn take_ty<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn drop_ty<'a>(cx: &'a Block<'a>, v: ValueRef, t: ty::t)
|
||||
fn get_drop_glue_type(ccx: &CrateContext, t: ty::t) -> ty::t {
|
||||
let tcx = ccx.tcx;
|
||||
if !ty::type_needs_drop(tcx, t) {
|
||||
return ty::mk_i8();
|
||||
}
|
||||
match ty::get(t).sty {
|
||||
ty::ty_box(typ) if !ty::type_needs_drop(tcx, typ) =>
|
||||
ty::mk_box(tcx, ty::mk_i8()),
|
||||
|
||||
ty::ty_uniq(typ) if !ty::type_needs_drop(tcx, typ) => {
|
||||
let llty = sizing_type_of(ccx, typ);
|
||||
// Unique boxes do not allocate for zero-size types. The standard library may assume
|
||||
// that `free` is never called on the pointer returned for `~ZeroSizeType`.
|
||||
if llsize_of_alloc(ccx, llty) == 0 {
|
||||
ty::mk_i8()
|
||||
} else {
|
||||
ty::mk_uniq(tcx, ty::mk_i8())
|
||||
}
|
||||
}
|
||||
|
||||
ty::ty_vec(mt, ty::vstore_uniq) if !ty::type_needs_drop(tcx, mt.ty) =>
|
||||
ty::mk_uniq(tcx, ty::mk_i8()),
|
||||
|
||||
_ => t
|
||||
}
|
||||
}
|
||||
|
||||
pub fn drop_ty<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
|
||||
-> &'a Block<'a> {
|
||||
// NB: v is an *alias* of type t here, not a direct value.
|
||||
let _icx = push_ctxt("drop_ty");
|
||||
if ty::type_needs_drop(cx.tcx(), t) {
|
||||
return call_tydesc_glue(cx, v, t, abi::tydesc_field_drop_glue);
|
||||
let ccx = bcx.ccx();
|
||||
if ty::type_needs_drop(bcx.tcx(), t) {
|
||||
let glue = get_drop_glue(ccx, t);
|
||||
let glue_type = get_drop_glue_type(ccx, t);
|
||||
let ptr = if glue_type != t {
|
||||
PointerCast(bcx, v, type_of(ccx, glue_type).ptr_to())
|
||||
} else {
|
||||
v
|
||||
};
|
||||
Call(bcx, glue, [ptr], []);
|
||||
}
|
||||
return cx;
|
||||
bcx
|
||||
}
|
||||
|
||||
pub fn drop_ty_immediate<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
|
||||
@ -91,95 +126,49 @@ pub fn drop_ty_immediate<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
|
||||
drop_ty(bcx, vp, t)
|
||||
}
|
||||
|
||||
pub fn lazily_emit_all_tydesc_glue(ccx: @CrateContext,
|
||||
static_ti: @tydesc_info) {
|
||||
lazily_emit_tydesc_glue(ccx, abi::tydesc_field_drop_glue, static_ti);
|
||||
lazily_emit_tydesc_glue(ccx, abi::tydesc_field_visit_glue, static_ti);
|
||||
}
|
||||
|
||||
fn get_glue_type(ccx: &CrateContext, field: uint, t: ty::t) -> ty::t {
|
||||
let tcx = ccx.tcx;
|
||||
if field == abi::tydesc_field_drop_glue {
|
||||
if !ty::type_needs_drop(tcx, t) {
|
||||
return ty::mk_i8();
|
||||
}
|
||||
match ty::get(t).sty {
|
||||
ty::ty_box(typ) if !ty::type_needs_drop(tcx, typ) =>
|
||||
return ty::mk_box(tcx, ty::mk_i8()),
|
||||
|
||||
ty::ty_uniq(typ) if !ty::type_needs_drop(tcx, typ) => {
|
||||
let llty = sizing_type_of(ccx, typ);
|
||||
// Unique boxes do not allocate for zero-size types. The standard library may assume
|
||||
// that `free` is never called on the pointer returned for `~ZeroSizeType`.
|
||||
if llsize_of_alloc(ccx, llty) == 0 {
|
||||
return ty::mk_i8();
|
||||
} else {
|
||||
return ty::mk_uniq(tcx, ty::mk_i8());
|
||||
}
|
||||
}
|
||||
|
||||
ty::ty_vec(mt, ty::vstore_uniq) if !ty::type_needs_drop(tcx, mt.ty) =>
|
||||
return ty::mk_uniq(tcx, ty::mk_i8()),
|
||||
|
||||
_ => {}
|
||||
pub fn get_drop_glue(ccx: @CrateContext, t: ty::t) -> ValueRef {
|
||||
let t = get_drop_glue_type(ccx, t);
|
||||
{
|
||||
let drop_glues = ccx.drop_glues.borrow();
|
||||
match drop_glues.get().find(&t) {
|
||||
Some(&glue) => return glue,
|
||||
_ => { }
|
||||
}
|
||||
}
|
||||
|
||||
t
|
||||
let llfnty = Type::glue_fn(type_of(ccx, t).ptr_to());
|
||||
let glue = declare_generic_glue(ccx, t, llfnty, "drop");
|
||||
|
||||
{
|
||||
let mut drop_glues = ccx.drop_glues.borrow_mut();
|
||||
drop_glues.get().insert(t, glue);
|
||||
}
|
||||
|
||||
make_generic_glue(ccx, t, glue, make_drop_glue, "drop");
|
||||
|
||||
glue
|
||||
}
|
||||
|
||||
pub fn lazily_emit_tydesc_glue(ccx: @CrateContext, field: uint, ti: @tydesc_info) {
|
||||
let _icx = push_ctxt("lazily_emit_tydesc_glue");
|
||||
|
||||
let simpl = get_glue_type(ccx, field, ti.ty);
|
||||
if simpl != ti.ty {
|
||||
let _icx = push_ctxt("lazily_emit_simplified_tydesc_glue");
|
||||
let simpl_ti = get_tydesc(ccx, simpl);
|
||||
lazily_emit_tydesc_glue(ccx, field, simpl_ti);
|
||||
|
||||
if field == abi::tydesc_field_drop_glue {
|
||||
ti.drop_glue.set(simpl_ti.drop_glue.get());
|
||||
} else if field == abi::tydesc_field_visit_glue {
|
||||
ti.visit_glue.set(simpl_ti.visit_glue.get());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
pub fn lazily_emit_visit_glue(ccx: @CrateContext, ti: @tydesc_info) {
|
||||
let _icx = push_ctxt("lazily_emit_visit_glue");
|
||||
|
||||
let llfnty = Type::glue_fn(type_of(ccx, ti.ty).ptr_to());
|
||||
|
||||
if field == abi::tydesc_field_drop_glue {
|
||||
match ti.drop_glue.get() {
|
||||
Some(_) => (),
|
||||
None => {
|
||||
debug!("+++ lazily_emit_tydesc_glue DROP {}",
|
||||
ppaux::ty_to_str(ccx.tcx, ti.ty));
|
||||
let glue_fn = declare_generic_glue(ccx, ti.ty, llfnty, "drop");
|
||||
ti.drop_glue.set(Some(glue_fn));
|
||||
make_generic_glue(ccx, ti.ty, glue_fn, make_drop_glue, "drop");
|
||||
debug!("--- lazily_emit_tydesc_glue DROP {}",
|
||||
ppaux::ty_to_str(ccx.tcx, ti.ty));
|
||||
}
|
||||
}
|
||||
} else if field == abi::tydesc_field_visit_glue {
|
||||
match ti.visit_glue.get() {
|
||||
Some(_) => (),
|
||||
None => {
|
||||
debug!("+++ lazily_emit_tydesc_glue VISIT {}",
|
||||
ppaux::ty_to_str(ccx.tcx, ti.ty));
|
||||
match ti.visit_glue.get() {
|
||||
Some(_) => (),
|
||||
None => {
|
||||
debug!("+++ lazily_emit_tydesc_glue VISIT {}", ppaux::ty_to_str(ccx.tcx, ti.ty));
|
||||
let glue_fn = declare_generic_glue(ccx, ti.ty, llfnty, "visit");
|
||||
ti.visit_glue.set(Some(glue_fn));
|
||||
make_generic_glue(ccx, ti.ty, glue_fn, make_visit_glue, "visit");
|
||||
debug!("--- lazily_emit_tydesc_glue VISIT {}",
|
||||
ppaux::ty_to_str(ccx.tcx, ti.ty));
|
||||
}
|
||||
debug!("--- lazily_emit_tydesc_glue VISIT {}", ppaux::ty_to_str(ccx.tcx, ti.ty));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See [Note-arg-mode]
|
||||
pub fn call_tydesc_glue_full(bcx: &Block, v: ValueRef, tydesc: ValueRef,
|
||||
field: uint, static_ti: Option<@tydesc_info>) {
|
||||
pub fn call_visit_glue(bcx: &Block, v: ValueRef, tydesc: ValueRef,
|
||||
static_ti: Option<@tydesc_info>) {
|
||||
let _icx = push_ctxt("call_tydesc_glue_full");
|
||||
let ccx = bcx.ccx();
|
||||
// NB: Don't short-circuit even if this block is unreachable because
|
||||
@ -189,37 +178,23 @@ pub fn call_tydesc_glue_full(bcx: &Block, v: ValueRef, tydesc: ValueRef,
|
||||
let static_glue_fn = match static_ti {
|
||||
None => None,
|
||||
Some(sti) => {
|
||||
lazily_emit_tydesc_glue(ccx, field, sti);
|
||||
if field == abi::tydesc_field_drop_glue {
|
||||
sti.drop_glue.get()
|
||||
} else if field == abi::tydesc_field_visit_glue {
|
||||
sti.visit_glue.get()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
lazily_emit_visit_glue(ccx, sti);
|
||||
sti.visit_glue.get()
|
||||
}
|
||||
};
|
||||
|
||||
// When static type info is available, avoid casting parameter unless the
|
||||
// glue is using a simplified type, because the function already has the
|
||||
// right type. Otherwise cast to generic pointer.
|
||||
// When static type info is available, avoid casting to a generic pointer.
|
||||
let llrawptr = if static_glue_fn.is_none() {
|
||||
PointerCast(bcx, v, Type::i8p())
|
||||
} else {
|
||||
let ty = static_ti.unwrap().ty;
|
||||
let simpl = get_glue_type(ccx, field, ty);
|
||||
if simpl != ty {
|
||||
PointerCast(bcx, v, type_of(ccx, simpl).ptr_to())
|
||||
} else {
|
||||
v
|
||||
}
|
||||
v
|
||||
};
|
||||
|
||||
let llfn = {
|
||||
match static_glue_fn {
|
||||
None => {
|
||||
// Select out the glue function to call from the tydesc
|
||||
let llfnptr = GEPi(bcx, tydesc, [0u, field]);
|
||||
let llfnptr = GEPi(bcx, tydesc, [0u, abi::tydesc_field_visit_glue]);
|
||||
Load(bcx, llfnptr)
|
||||
}
|
||||
Some(sgf) => sgf
|
||||
@ -229,15 +204,6 @@ pub fn call_tydesc_glue_full(bcx: &Block, v: ValueRef, tydesc: ValueRef,
|
||||
Call(bcx, llfn, [llrawptr], []);
|
||||
}
|
||||
|
||||
// See [Note-arg-mode]
|
||||
fn call_tydesc_glue<'a>(cx: &'a Block<'a>, v: ValueRef, t: ty::t, field: uint)
|
||||
-> &'a Block<'a> {
|
||||
let _icx = push_ctxt("call_tydesc_glue");
|
||||
let ti = get_tydesc(cx.ccx(), t);
|
||||
call_tydesc_glue_full(cx, v, ti.tydesc, field, Some(ti));
|
||||
cx
|
||||
}
|
||||
|
||||
fn make_visit_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
|
||||
-> &'a Block<'a> {
|
||||
let _icx = push_ctxt("make_visit_glue");
|
||||
@ -462,7 +428,6 @@ pub fn declare_tydesc(ccx: &CrateContext, t: ty::t) -> @tydesc_info {
|
||||
size: llsize,
|
||||
align: llalign,
|
||||
name: ty_name,
|
||||
drop_glue: Cell::new(None),
|
||||
visit_glue: Cell::new(None),
|
||||
};
|
||||
debug!("--- declare_tydesc {}", ppaux::ty_to_str(ccx.tcx, t));
|
||||
@ -514,7 +479,7 @@ fn make_generic_glue(ccx: @CrateContext,
|
||||
llfn
|
||||
}
|
||||
|
||||
pub fn emit_tydescs(ccx: &CrateContext) {
|
||||
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);
|
||||
@ -527,21 +492,10 @@ pub fn emit_tydescs(ccx: &CrateContext) {
|
||||
// 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 =
|
||||
match ti.drop_glue.get() {
|
||||
None => {
|
||||
ccx.stats.n_null_glues.set(ccx.stats.n_null_glues.get() +
|
||||
1u);
|
||||
C_null(glue_fn_ty)
|
||||
}
|
||||
Some(v) => {
|
||||
unsafe {
|
||||
ccx.stats.n_real_glues.set(ccx.stats.n_real_glues.get() +
|
||||
1);
|
||||
llvm::LLVMConstPointerCast(v, glue_fn_ty.to_ref())
|
||||
}
|
||||
}
|
||||
};
|
||||
let drop_glue = unsafe {
|
||||
llvm::LLVMConstPointerCast(get_drop_glue(ccx, ti.ty), glue_fn_ty.to_ref())
|
||||
};
|
||||
ccx.stats.n_real_glues.set(ccx.stats.n_real_glues.get() + 1);
|
||||
let visit_glue =
|
||||
match ti.visit_glue.get() {
|
||||
None => {
|
||||
|
@ -11,7 +11,6 @@
|
||||
#[allow(non_uppercase_pattern_statics)];
|
||||
|
||||
use arena::TypedArena;
|
||||
use back::abi;
|
||||
use lib::llvm::{SequentiallyConsistent, Acquire, Release, Xchg};
|
||||
use lib::llvm::{ValueRef, Pointer, Array, Struct};
|
||||
use lib;
|
||||
@ -326,7 +325,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
|
||||
"get_tydesc" => {
|
||||
let tp_ty = substs.tys[0];
|
||||
let static_ti = get_tydesc(ccx, tp_ty);
|
||||
glue::lazily_emit_all_tydesc_glue(ccx, static_ti);
|
||||
glue::lazily_emit_visit_glue(ccx, static_ti);
|
||||
|
||||
// FIXME (#3730): ideally this shouldn't need a cast,
|
||||
// but there's a circularity between translating rust types to llvm
|
||||
@ -459,8 +458,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
|
||||
let td = get_param(decl, first_real_arg);
|
||||
let visitor = get_param(decl, first_real_arg + 1u);
|
||||
let td = PointerCast(bcx, td, ccx.tydesc_type.ptr_to());
|
||||
glue::call_tydesc_glue_full(bcx, visitor, td,
|
||||
abi::tydesc_field_visit_glue, None);
|
||||
glue::call_visit_glue(bcx, visitor, td, None);
|
||||
RetVoid(bcx);
|
||||
}
|
||||
"morestack_addr" => {
|
||||
|
@ -479,11 +479,9 @@ pub fn get_vtable(bcx: &Block,
|
||||
}
|
||||
});
|
||||
|
||||
// Generate a type descriptor for the vtable.
|
||||
let tydesc = get_tydesc(ccx, self_ty);
|
||||
glue::lazily_emit_tydesc_glue(ccx, abi::tydesc_field_drop_glue, tydesc);
|
||||
|
||||
let vtable = make_vtable(ccx, tydesc, methods);
|
||||
// Generate a destructor for the vtable.
|
||||
let drop_glue = glue::get_drop_glue(ccx, self_ty);
|
||||
let vtable = make_vtable(ccx, drop_glue, methods);
|
||||
|
||||
let mut vtables = ccx.vtables.borrow_mut();
|
||||
vtables.get().insert(hash_id, vtable);
|
||||
@ -492,13 +490,13 @@ pub fn get_vtable(bcx: &Block,
|
||||
|
||||
/// Helper function to declare and initialize the vtable.
|
||||
pub fn make_vtable(ccx: &CrateContext,
|
||||
tydesc: &tydesc_info,
|
||||
drop_glue: ValueRef,
|
||||
ptrs: &[ValueRef])
|
||||
-> ValueRef {
|
||||
unsafe {
|
||||
let _icx = push_ctxt("meth::make_vtable");
|
||||
|
||||
let mut components = ~[tydesc.drop_glue.get().unwrap()];
|
||||
let mut components = ~[drop_glue];
|
||||
for &ptr in ptrs.iter() {
|
||||
components.push(ptr)
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ impl<'a> Reflector<'a> {
|
||||
pub fn c_tydesc(&mut self, t: ty::t) -> ValueRef {
|
||||
let bcx = self.bcx;
|
||||
let static_ti = get_tydesc(bcx.ccx(), t);
|
||||
glue::lazily_emit_all_tydesc_glue(bcx.ccx(), static_ti);
|
||||
glue::lazily_emit_visit_glue(bcx.ccx(), static_ti);
|
||||
PointerCast(bcx, static_ti.tydesc, self.tydesc_ty.ptr_to())
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user