diff --git a/src/librustc/back/abi.rs b/src/librustc/back/abi.rs index 8f639a5e499f1..83a17bd3231a2 100644 --- a/src/librustc/back/abi.rs +++ b/src/librustc/back/abi.rs @@ -42,11 +42,10 @@ pub static general_code_alignment: uint = 16u; pub static tydesc_field_size: uint = 0u; pub static tydesc_field_align: uint = 1u; -pub static tydesc_field_take_glue: uint = 2u; -pub static tydesc_field_drop_glue: uint = 3u; -pub static tydesc_field_visit_glue: uint = 4u; -pub static tydesc_field_name_offset: uint = 5u; -pub static n_tydesc_fields: uint = 6u; +pub static tydesc_field_drop_glue: uint = 2u; +pub static tydesc_field_visit_glue: uint = 3u; +pub static tydesc_field_name_offset: uint = 4u; +pub static n_tydesc_fields: uint = 5u; // The two halves of a closure: code and environment. pub static fn_field_code: uint = 0u; diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index c71469f0c3db0..1dea31939f57f 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -777,9 +777,6 @@ pub fn iter_structural_ty<'r, let variant_cx = fcx.new_temp_block(~"enum-iter-variant-" + variant.disr_val.to_str()); - let variant_cx = - iter_variant(variant_cx, repr, av, *variant, - substs.tps, |x,y,z| f(x,y,z)); match adt::trans_case(cx, repr, variant.disr_val) { _match::single_result(r) => { AddCase(llswitch, r.val, variant_cx.llbb) @@ -787,6 +784,9 @@ pub fn iter_structural_ty<'r, _ => ccx.sess.unimpl("value from adt::trans_case \ in iter_structural_ty") } + let variant_cx = + iter_variant(variant_cx, repr, av, *variant, + substs.tps, |x,y,z| f(x,y,z)); Br(variant_cx, next_cx.llbb); } cx = next_cx; @@ -1458,16 +1458,16 @@ pub fn build_return_block(fcx: &FunctionContext, ret_cx: &Block) { // trans_closure: Builds an LLVM function out of a source function. // If the function closes over its environment a closure will be // returned. -pub fn trans_closure(ccx: @CrateContext, - path: ast_map::Path, - decl: &ast::FnDecl, - body: &ast::Block, - llfndecl: ValueRef, - param_substs: Option<@param_substs>, - id: ast::NodeId, - _attributes: &[ast::Attribute], - output_type: ty::t, - maybe_load_env: |&FunctionContext|) { +pub fn trans_closure<'a>(ccx: @CrateContext, + path: ast_map::Path, + decl: &ast::FnDecl, + body: &ast::Block, + llfndecl: ValueRef, + param_substs: Option<@param_substs>, + id: ast::NodeId, + _attributes: &[ast::Attribute], + output_type: ty::t, + maybe_load_env: |&'a Block<'a>| -> &'a Block<'a>) { ccx.stats.n_closures.set(ccx.stats.n_closures.get() + 1); let _icx = push_ctxt("trans_closure"); @@ -1500,7 +1500,7 @@ pub fn trans_closure(ccx: @CrateContext, bcx = copy_args_to_allocas(&fcx, arg_scope, bcx, decl.inputs, arg_datums); - maybe_load_env(&fcx); + bcx = maybe_load_env(bcx); // Up until here, IR instructions for this function have explicitly not been annotated with // source code location, so we don't step into call setup code. From here on, source location @@ -1558,16 +1558,8 @@ pub fn trans_fn(ccx: @CrateContext, debug!("trans_fn(param_substs={})", param_substs.repr(ccx.tcx)); let _icx = push_ctxt("trans_fn"); let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx, id)); - trans_closure(ccx, - path.clone(), - decl, - body, - llfndecl, - param_substs, - id, - attrs, - output_type, - |_fcx| { }); + trans_closure(ccx, path.clone(), decl, body, llfndecl, + param_substs, id, attrs, output_type, |bcx| bcx); } pub fn trans_enum_variant(ccx: @CrateContext, diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 4d171bc86b1b0..5a8039f9c4d65 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -282,23 +282,22 @@ fn build_closure<'a>(bcx0: &'a Block<'a>, // Given an enclosing block context, a new function context, a closure type, // and a list of upvars, generate code to load and populate the environment // with the upvars and type descriptors. -fn load_environment(fcx: &FunctionContext, cdata_ty: ty::t, - cap_vars: &[moves::CaptureVar], sigil: ast::Sigil) { +fn load_environment<'a>(bcx: &'a Block<'a>, cdata_ty: ty::t, + cap_vars: &[moves::CaptureVar], + sigil: ast::Sigil) -> &'a Block<'a> { let _icx = push_ctxt("closure::load_environment"); // Don't bother to create the block if there's nothing to load if cap_vars.len() == 0 { - return; + return bcx; } - let bcx = fcx.entry_bcx.get().unwrap(); - // Load a pointer to the closure data, skipping over the box header: - let llcdata = at_box_body(bcx, cdata_ty, fcx.llenv.unwrap()); + let llcdata = at_box_body(bcx, cdata_ty, bcx.fcx.llenv.unwrap()); // Store the pointer to closure data in an alloca for debug info because that's what the // llvm.dbg.declare intrinsic expects - let env_pointer_alloca = if fcx.ccx.sess.opts.extra_debuginfo { + let env_pointer_alloca = if bcx.ccx().sess.opts.extra_debuginfo { let alloc = alloc_ty(bcx, ty::mk_mut_ptr(bcx.tcx(), cdata_ty), "__debuginfo_env_ptr"); Store(bcx, llcdata, alloc); Some(alloc) @@ -317,7 +316,7 @@ fn load_environment(fcx: &FunctionContext, cdata_ty: ty::t, let def_id = ast_util::def_id_of_def(cap_var.def); { - let mut llupvars = fcx.llupvars.borrow_mut(); + let mut llupvars = bcx.fcx.llupvars.borrow_mut(); llupvars.get().insert(def_id.node, upvarptr); } @@ -334,6 +333,8 @@ fn load_environment(fcx: &FunctionContext, cdata_ty: ty::t, i += 1u; } + + bcx } fn fill_fn_pair(bcx: &Block, pair: ValueRef, llfn: ValueRef, llenvptr: ValueRef) { @@ -405,7 +406,7 @@ pub fn trans_expr_fn<'a>( trans_closure(ccx, sub_path, decl, body, llfn, bcx.fcx.param_substs, user_id, [], ty::ty_fn_ret(fty), - |fcx| load_environment(fcx, cdata_ty, cap_vars, sigil)); + |bcx| load_environment(bcx, cdata_ty, cap_vars, sigil)); fill_fn_pair(bcx, dest_addr, llfn, llbox); bcx diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 45f5d84eb8ae4..38badc20c19ac 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -114,7 +114,6 @@ pub struct tydesc_info { size: ValueRef, align: ValueRef, name: ValueRef, - take_glue: Cell>, drop_glue: Cell>, visit_glue: Cell>, } diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs index 467501449b8d5..4888c2ce4d5dc 100644 --- a/src/librustc/middle/trans/datum.rs +++ b/src/librustc/middle/trans/datum.rs @@ -491,7 +491,7 @@ impl Datum { } ByValue => { let v = load(bcx, l.val, l.ty); - l.kind.post_store(bcx, l.val, l.ty); + bcx = l.kind.post_store(bcx, l.val, l.ty); DatumBlock(bcx, Datum(v, l.ty, Rvalue(ByValue))) } } diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 5004bcca91e3c..ea5e6e8d38604 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -58,14 +58,24 @@ pub fn trans_exchange_free<'a>(cx: &'a Block<'a>, v: ValueRef) Some(expr::Ignore)).bcx } -pub fn take_ty<'a>(cx: &'a Block<'a>, v: ValueRef, t: ty::t) +pub fn take_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("take_ty"); - if ty::type_needs_drop(cx.tcx(), t) { - return call_tydesc_glue(cx, v, t, abi::tydesc_field_take_glue); + match ty::get(t).sty { + ty::ty_box(_) | + ty::ty_vec(_, ty::vstore_box) | ty::ty_str(ty::vstore_box) => { + incr_refcnt_of_boxed(bcx, v) + } + ty::ty_trait(_, _, ty::BoxTraitStore, _, _) => { + incr_refcnt_of_boxed(bcx, GEPi(bcx, v, [0u, abi::trt_field_box])) + } + _ if ty::type_is_structural(t) + && ty::type_needs_drop(bcx.tcx(), t) => { + iter_structural_ty(bcx, v, t, take_ty) + } + _ => bcx } - return cx; } pub fn drop_ty<'a>(cx: &'a Block<'a>, v: ValueRef, t: ty::t) @@ -88,30 +98,15 @@ pub fn drop_ty_immediate<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t) pub fn lazily_emit_all_tydesc_glue(ccx: @CrateContext, static_ti: @tydesc_info) { - lazily_emit_tydesc_glue(ccx, abi::tydesc_field_take_glue, static_ti); 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 simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t { - if (field == abi::tydesc_field_take_glue || field == abi::tydesc_field_drop_glue) - && !ty::type_needs_drop(tcx, t) { - return ty::mk_nil(); - } - - if field == abi::tydesc_field_take_glue { - match ty::get(t).sty { - ty::ty_str(ty::vstore_uniq) | ty::ty_vec(_, ty::vstore_uniq) | - ty::ty_unboxed_vec(..) | ty::ty_uniq(..) => return ty::mk_nil(), - _ => {} - } - } - - if field == abi::tydesc_field_take_glue && ty::type_is_boxed(t) { - return ty::mk_box(tcx, ty::mk_nil()); - } - if field == abi::tydesc_field_drop_glue { + if !ty::type_needs_drop(tcx, t) { + return ty::mk_nil(); + } match ty::get(t).sty { ty::ty_box(typ) if !ty::type_needs_drop(tcx, typ) => @@ -145,9 +140,7 @@ fn lazily_emit_tydesc_glue(ccx: @CrateContext, field: uint, ti: @tydesc_info) { let simpl_ti = get_tydesc(ccx, simpl); lazily_emit_tydesc_glue(ccx, field, simpl_ti); - if field == abi::tydesc_field_take_glue { - ti.take_glue.set(simpl_ti.take_glue.get()); - } else if field == abi::tydesc_field_drop_glue { + 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()); @@ -158,20 +151,7 @@ fn lazily_emit_tydesc_glue(ccx: @CrateContext, field: uint, ti: @tydesc_info) { let llfnty = Type::glue_fn(type_of(ccx, ti.ty).ptr_to()); - if field == abi::tydesc_field_take_glue { - match ti.take_glue.get() { - Some(_) => (), - None => { - debug!("+++ lazily_emit_tydesc_glue TAKE {}", - ppaux::ty_to_str(ccx.tcx, ti.ty)); - let glue_fn = declare_generic_glue(ccx, ti.ty, llfnty, "take"); - ti.take_glue.set(Some(glue_fn)); - make_generic_glue(ccx, ti.ty, glue_fn, make_take_glue, "take"); - debug!("--- lazily_emit_tydesc_glue TAKE {}", - ppaux::ty_to_str(ccx.tcx, ti.ty)); - } - } - } else if field == abi::tydesc_field_drop_glue { + if field == abi::tydesc_field_drop_glue { match ti.drop_glue.get() { Some(_) => (), None => { @@ -213,9 +193,7 @@ pub fn call_tydesc_glue_full(bcx: &Block, v: ValueRef, tydesc: ValueRef, None => None, Some(sti) => { lazily_emit_tydesc_glue(ccx, field, sti); - if field == abi::tydesc_field_take_glue { - sti.take_glue.get() - } else if field == abi::tydesc_field_drop_glue { + if field == abi::tydesc_field_drop_glue { sti.drop_glue.get() } else if field == abi::tydesc_field_visit_glue { sti.visit_glue.get() @@ -472,53 +450,16 @@ fn decr_refcnt_maybe_free<'a>(bcx: &'a Block<'a>, box_ptr_ptr: ValueRef, next_bcx } -fn make_take_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t) -> &'a Block<'a> { - let _icx = push_ctxt("make_take_glue"); - // NB: v is a *pointer* to type t here, not a direct value. - match ty::get(t).sty { - ty::ty_box(_) | - ty::ty_vec(_, ty::vstore_box) | ty::ty_str(ty::vstore_box) => { - incr_refcnt_of_boxed(bcx, Load(bcx, v)); bcx - } - ty::ty_vec(_, ty::vstore_slice(_)) - | ty::ty_str(ty::vstore_slice(_)) => { - bcx - } - ty::ty_closure(_) => bcx, - ty::ty_trait(_, _, ty::BoxTraitStore, _, _) => { - let llbox = Load(bcx, GEPi(bcx, v, [0u, abi::trt_field_box])); - incr_refcnt_of_boxed(bcx, llbox); - bcx - } - ty::ty_trait(_, _, ty::UniqTraitStore, _, _) => { - let lluniquevalue = GEPi(bcx, v, [0, abi::trt_field_box]); - let llvtable = Load(bcx, GEPi(bcx, v, [0, abi::trt_field_vtable])); - - // Cast the vtable to a pointer to a pointer to a tydesc. - let llvtable = PointerCast(bcx, llvtable, - bcx.ccx().tydesc_type.ptr_to().ptr_to()); - let lltydesc = Load(bcx, llvtable); - call_tydesc_glue_full(bcx, - lluniquevalue, - lltydesc, - abi::tydesc_field_take_glue, - None); - bcx - } - _ if ty::type_is_structural(t) => { - iter_structural_ty(bcx, v, t, take_ty) - } - _ => bcx - } -} - -fn incr_refcnt_of_boxed(cx: &Block, box_ptr: ValueRef) { +fn incr_refcnt_of_boxed<'a>(bcx: &'a Block<'a>, + box_ptr_ptr: ValueRef) -> &'a Block<'a> { let _icx = push_ctxt("incr_refcnt_of_boxed"); - let ccx = cx.ccx(); - let rc_ptr = GEPi(cx, box_ptr, [0u, abi::box_field_refcnt]); - let rc = Load(cx, rc_ptr); - let rc = Add(cx, rc, C_int(ccx, 1)); - Store(cx, rc, rc_ptr); + let ccx = bcx.ccx(); + let box_ptr = Load(bcx, box_ptr_ptr); + let rc_ptr = GEPi(bcx, box_ptr, [0u, abi::box_field_refcnt]); + let rc = Load(bcx, rc_ptr); + let rc = Add(bcx, rc, C_int(ccx, 1)); + Store(bcx, rc, rc_ptr); + bcx } @@ -554,7 +495,6 @@ pub fn declare_tydesc(ccx: &CrateContext, t: ty::t) -> @tydesc_info { size: llsize, align: llalign, name: ty_name, - take_glue: Cell::new(None), drop_glue: Cell::new(None), visit_glue: Cell::new(None), }; @@ -616,21 +556,6 @@ 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 take_glue = - match ti.take_glue.get() { - None => { - ccx.stats.n_null_glues.set(ccx.stats.n_null_glues.get() + - 1); - 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 = match ti.drop_glue.get() { None => { @@ -665,7 +590,6 @@ pub fn emit_tydescs(ccx: &CrateContext) { let tydesc = C_named_struct(ccx.tydesc_type, [ti.size, // size ti.align, // align - take_glue, // take_glue drop_glue, // drop_glue visit_glue, // visit_glue ti.name]); // name diff --git a/src/librustc/middle/trans/type_.rs b/src/librustc/middle/trans/type_.rs index bbaf94afabe8c..e685849cbd85a 100644 --- a/src/librustc/middle/trans/type_.rs +++ b/src/librustc/middle/trans/type_.rs @@ -211,7 +211,6 @@ impl Type { let elems = [int_ty, // size int_ty, // align - glue_fn_ty, // take glue_fn_ty, // drop glue_fn_ty, // visit Type::struct_([Type::i8p(), Type::int(arch)], false)]; // name diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs index 1988993707fce..067826f04dc83 100644 --- a/src/libstd/unstable/intrinsics.rs +++ b/src/libstd/unstable/intrinsics.rs @@ -57,6 +57,8 @@ pub struct TyDesc { align: uint, // Called on a copy of a value of type `T` *after* memcpy + // NOTE remove after next snapshot + #[cfg(stage0)] take_glue: GlueFn, // Called when a value of type `T` is no longer needed