]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/middle/trans/glue.rs
auto merge of #15999 : Kimundi/rust/fix_folder, r=nikomatsakis
[rust.git] / src / librustc / middle / trans / glue.rs
index 4d9f004e3dcd111ea895016269df715a4b5f83ce..40288a33930e5ebdb96131d92b2d24a9490bd1fd 100644 (file)
@@ -15,8 +15,8 @@
 
 use back::abi;
 use back::link::*;
-use lib::llvm::{llvm, ValueRef, True};
-use lib;
+use llvm::{ValueRef, True, get_param};
+use llvm;
 use middle::lang_items::{FreeFnLangItem, ExchangeFreeFnLangItem};
 use middle::subst;
 use middle::trans::adt;
@@ -129,7 +129,7 @@ pub fn drop_ty<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
         } else {
             v
         };
-        Call(bcx, glue, [ptr], []);
+        Call(bcx, glue, [ptr], None);
     }
     bcx
 }
@@ -178,35 +178,14 @@ pub fn lazily_emit_visit_glue(ccx: &CrateContext, ti: &tydesc_info) -> ValueRef
 }
 
 // See [Note-arg-mode]
-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
-    // GC-based cleanup needs to the see that the roots are live.
-    if bcx.unreachable.get() && !ccx.sess().no_landing_pads() { return; }
-
-    let static_glue_fn = static_ti.map(|sti| lazily_emit_visit_glue(ccx, sti));
+pub fn call_visit_glue(bcx: &Block, v: ValueRef, tydesc: ValueRef) {
+    let _icx = push_ctxt("call_visit_glue");
 
-    // 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(ccx))
-    } else {
-        v
-    };
+    // Select the glue function to call from the tydesc
+    let llfn = Load(bcx, GEPi(bcx, tydesc, [0u, abi::tydesc_field_visit_glue]));
+    let llrawptr = PointerCast(bcx, v, Type::i8p(bcx.ccx()));
 
-    let llfn = {
-        match static_glue_fn {
-            None => {
-                // Select out the glue function to call from the tydesc
-                let llfnptr = GEPi(bcx, tydesc, [0u, abi::tydesc_field_visit_glue]);
-                Load(bcx, llfnptr)
-            }
-            Some(sgf) => sgf
-        }
-    };
-
-    Call(bcx, llfn, [llrawptr], []);
+    Call(bcx, llfn, [llrawptr], None);
 }
 
 fn make_visit_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
@@ -225,7 +204,7 @@ fn make_visit_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
     bcx
 }
 
-fn trans_struct_drop_flag<'a>(bcx: &'a Block<'a>,
+fn trans_struct_drop_flag<'a>(mut bcx: &'a Block<'a>,
                               t: ty::t,
                               v0: ValueRef,
                               dtor_did: ast::DefId,
@@ -233,8 +212,8 @@ fn trans_struct_drop_flag<'a>(bcx: &'a Block<'a>,
                               substs: &subst::Substs)
                               -> &'a Block<'a> {
     let repr = adt::represent_type(bcx.ccx(), t);
-    let drop_flag = adt::trans_drop_flag_ptr(bcx, &*repr, v0);
-    with_cond(bcx, load_ty(bcx, drop_flag, ty::mk_bool()), |cx| {
+    let drop_flag = unpack_datum!(bcx, adt::trans_drop_flag_ptr(bcx, &*repr, v0));
+    with_cond(bcx, load_ty(bcx, drop_flag.val, ty::mk_bool()), |cx| {
         trans_struct_drop(cx, t, v0, dtor_did, class_did, substs)
     })
 }
@@ -258,33 +237,33 @@ fn trans_struct_drop<'a>(bcx: &'a Block<'a>,
         ty.element_type().func_params()
     };
 
-    // Class dtors have no explicit args, so the params should
-    // just consist of the environment (self)
-    assert_eq!(params.len(), 1);
-
-    // Be sure to put all of the fields into a scope so we can use an invoke
-    // instruction to call the user destructor but still call the field
-    // destructors if the user destructor fails.
-    let field_scope = bcx.fcx.push_custom_cleanup_scope();
-
-    let self_arg = PointerCast(bcx, v0, *params.get(0));
-    let args = vec!(self_arg);
-
-    // Add all the fields as a value which needs to be cleaned at the end of
-    // this scope.
-    let field_tys = ty::struct_fields(bcx.tcx(), class_did, substs);
-    for (i, fld) in field_tys.iter().enumerate() {
-        let llfld_a = adt::trans_field_ptr(bcx, &*repr, v0, 0, i);
-        bcx.fcx.schedule_drop_mem(cleanup::CustomScope(field_scope),
-                                  llfld_a,
-                                  fld.mt.ty);
-    }
+    adt::fold_variants(bcx, &*repr, v0, |variant_cx, st, value| {
+        // Be sure to put all of the fields into a scope so we can use an invoke
+        // instruction to call the user destructor but still call the field
+        // destructors if the user destructor fails.
+        let field_scope = variant_cx.fcx.push_custom_cleanup_scope();
+
+        // Class dtors have no explicit args, so the params should
+        // just consist of the environment (self).
+        assert_eq!(params.len(), 1);
+        let self_arg = PointerCast(variant_cx, value, *params.get(0));
+        let args = vec!(self_arg);
+
+        // Add all the fields as a value which needs to be cleaned at the end of
+        // this scope.
+        for (i, ty) in st.fields.iter().enumerate() {
+            let llfld_a = adt::struct_field_ptr(variant_cx, &*st, value, i, false);
+            variant_cx.fcx.schedule_drop_mem(cleanup::CustomScope(field_scope),
+                                             llfld_a, *ty);
+        }
 
-    let dtor_ty = ty::mk_ctor_fn(bcx.tcx(), ast::DUMMY_NODE_ID,
-                                 [get_drop_glue_type(bcx.ccx(), t)], ty::mk_nil());
-    let (_, bcx) = invoke(bcx, dtor_addr, args, dtor_ty, None);
+        let dtor_ty = ty::mk_ctor_fn(variant_cx.tcx(), ast::DUMMY_NODE_ID,
+                                     [get_drop_glue_type(bcx.ccx(), t)], ty::mk_nil());
+        let (_, variant_cx) = invoke(variant_cx, dtor_addr, args, dtor_ty, None);
 
-    bcx.fcx.pop_and_trans_custom_cleanup_scope(bcx, field_scope)
+        variant_cx.fcx.pop_and_trans_custom_cleanup_scope(variant_cx, field_scope);
+        variant_cx
+    })
 }
 
 fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<'a> {
@@ -324,7 +303,7 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<'
                         Call(bcx,
                              dtor,
                              [PointerCast(bcx, lluniquevalue, Type::i8p(bcx.ccx()))],
-                             []);
+                             None);
                         bcx
                     })
                 }
@@ -338,7 +317,7 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<'
                 }
             }
         }
-        ty::ty_struct(did, ref substs) => {
+        ty::ty_struct(did, ref substs) | ty::ty_enum(did, ref substs) => {
             let tcx = bcx.tcx();
             match ty::ty_dtor(tcx, did) {
                 ty::TraitDtor(dtor, true) => {
@@ -353,6 +332,7 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<'
                 }
             }
         }
+        ty::ty_unboxed_closure(..) => iter_structural_ty(bcx, v0, t, drop_ty),
         ty::ty_closure(ref f) if f.store == ty::UniqTraitStore => {
             let box_cell_v = GEPi(bcx, v0, [0u, abi::fn_field_box]);
             let env = Load(bcx, box_cell_v);
@@ -362,7 +342,7 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<'
                 let dtor_ptr = GEPi(bcx, env, [0u, abi::box_field_tydesc]);
                 let dtor = Load(bcx, dtor_ptr);
                 let cdata = GEPi(bcx, env, [0u, abi::box_field_body]);
-                Call(bcx, dtor, [PointerCast(bcx, cdata, Type::i8p(bcx.ccx()))], []);
+                Call(bcx, dtor, [PointerCast(bcx, cdata, Type::i8p(bcx.ccx()))], None);
 
                 // Free the environment itself
                 // FIXME: #13994: pass align and size here
@@ -488,11 +468,11 @@ fn make_generic_glue(ccx: &CrateContext,
     let arena = TypedArena::new();
     let empty_param_substs = param_substs::empty();
     let fcx = new_fn_ctxt(ccx, llfn, -1, false, ty::mk_nil(),
-                          &empty_param_substs, None, &arena);
+                          &empty_param_substs, None, &arena, TranslateItems);
 
     let bcx = init_function(&fcx, false, ty::mk_nil());
 
-    lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
+    llvm::SetLinkage(llfn, llvm::InternalLinkage);
     ccx.stats.n_glues_created.set(ccx.stats.n_glues_created.get() + 1u);
     // All glue functions take values passed *by alias*; this is a
     // requirement since in many contexts glue is invoked indirectly and
@@ -502,7 +482,7 @@ fn make_generic_glue(ccx: &CrateContext,
     // 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 = unsafe { llvm::LLVMGetParam(llfn, fcx.arg_pos(0) as c_uint) };
+    let llrawptr0 = get_param(llfn, fcx.arg_pos(0) as c_uint);
     let bcx = helper(bcx, llrawptr0, t);
     finish_fn(&fcx, bcx, ty::mk_nil());
 
@@ -550,7 +530,7 @@ pub fn emit_tydescs(ccx: &CrateContext) {
             let gvar = ti.tydesc;
             llvm::LLVMSetInitializer(gvar, tydesc);
             llvm::LLVMSetGlobalConstant(gvar, True);
-            lib::llvm::SetLinkage(gvar, lib::llvm::InternalLinkage);
+            llvm::SetLinkage(gvar, llvm::InternalLinkage);
         }
     };
 }