]> git.lizzy.rs Git - rust.git/commitdiff
Make drop-glue translation collector-driven.
authorMichael Woerister <michaelwoerister@posteo.net>
Tue, 10 May 2016 03:56:49 +0000 (23:56 -0400)
committerMichael Woerister <michaelwoerister@posteo.net>
Fri, 8 Jul 2016 14:42:47 +0000 (10:42 -0400)
src/librustc_trans/abi.rs
src/librustc_trans/back/symbol_names.rs
src/librustc_trans/base.rs
src/librustc_trans/collector.rs
src/librustc_trans/context.rs
src/librustc_trans/declare.rs
src/librustc_trans/glue.rs
src/librustc_trans/partitioning.rs
src/librustc_trans/trans_item.rs

index df3d2d149b99ce072fbbf3ba13a1755fafa67455..6c2a09f8060c5a4b36fb87e1701d74bff6f62ed7 100644 (file)
@@ -229,6 +229,7 @@ pub fn store_fn_arg(&self, bcx: &BlockAndBuilder, idx: &mut usize, dst: ValueRef
 ///
 /// I will do my best to describe this structure, but these
 /// comments are reverse-engineered and may be inaccurate. -NDM
+#[derive(Clone)]
 pub struct FnType {
     /// The LLVM types of each argument.
     pub args: Vec<ArgType>,
index 170c8f75b5056c5ab9054bd7562623a197fabea4..ebb6e0baf20a00e8c837a18249c5e9853e706caf 100644 (file)
@@ -304,6 +304,19 @@ fn push(&mut self, text: &str) {
     }
 }
 
+pub fn exported_name_from_type_and_prefix<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
+                                                    t: ty::Ty<'tcx>,
+                                                    prefix: &str)
+                                                    -> String {
+    let empty_def_path = DefPath {
+        data: vec![],
+        krate: cstore::LOCAL_CRATE,
+    };
+    let hash = get_symbol_hash(scx, &empty_def_path, t, &[]);
+    let path = [token::intern_and_get_ident(prefix)];
+    mangle(path.iter().cloned(), Some(&hash[..]))
+}
+
 /// Only symbols that are invisible outside their compilation unit should use a
 /// name generated by this function.
 pub fn internal_name_from_type_and_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
index 3ee53a4d95ed460bd454bbab9f921d565fc9f81d..5dc319aa5f9bc1c9373bd2ec549937a3d79ff33a 100644 (file)
@@ -2182,52 +2182,6 @@ pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
     }
 }
 
-/// Set the appropriate linkage for an LLVM `ValueRef` (function or global).
-/// If the `llval` is the direct translation of a specific Rust item, `id`
-/// should be set to the `NodeId` of that item.  (This mapping should be
-/// 1-to-1, so monomorphizations and drop/visit glue should have `id` set to
-/// `None`.)
-pub fn update_linkage(ccx: &CrateContext,
-                      llval: ValueRef,
-                      id: Option<ast::NodeId>) {
-    if let Some(id) = id {
-        let item = ccx.tcx().map.get(id);
-        if let hir_map::NodeItem(i) = item {
-            if let Some(name) = attr::first_attr_value_str_by_name(&i.attrs, "linkage") {
-                if let Some(linkage) = llvm_linkage_by_name(&name) {
-                    llvm::SetLinkage(llval, linkage);
-                } else {
-                    ccx.sess().span_fatal(i.span, "invalid linkage specified");
-                }
-                return;
-            }
-        }
-    }
-
-    let (is_reachable, is_generic) = if let Some(id) = id {
-        (ccx.reachable().contains(&id), false)
-    } else {
-        (false, true)
-    };
-
-    // We need external linkage for items reachable from other translation units, this include
-    // other codegen units in case of parallel compilations.
-    if is_reachable || ccx.sess().opts.cg.codegen_units > 1 {
-        if is_generic {
-            // This only happens with multiple codegen units, in which case we need to use weak_odr
-            // linkage because other crates might expose the same symbol. We cannot use
-            // linkonce_odr here because the symbol might then get dropped before the other codegen
-            // units get to link it.
-            llvm::SetUniqueComdat(ccx.llmod(), llval);
-            llvm::SetLinkage(llval, llvm::WeakODRLinkage);
-        } else {
-            llvm::SetLinkage(llval, llvm::ExternalLinkage);
-        }
-    } else {
-        llvm::SetLinkage(llval, llvm::InternalLinkage);
-    }
-}
-
 pub fn set_link_section(ccx: &CrateContext,
                         llval: ValueRef,
                         attrs: &[ast::Attribute]) {
@@ -2673,24 +2627,8 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     // ... and now that we have everything pre-defined, fill out those definitions.
     for ccx in crate_context_list.iter() {
-        for (&trans_item, _) in &ccx.codegen_unit().items {
-            match trans_item {
-                TransItem::Static(node_id) => {
-                    let item = ccx.tcx().map.expect_item(node_id);
-                    if let hir::ItemStatic(_, m, ref expr) = item.node {
-                        match consts::trans_static(&ccx, m, expr, item.id, &item.attrs) {
-                            Ok(_) => { /* Cool, everything's alright. */ },
-                            Err(err) => ccx.tcx().sess.span_fatal(expr.span, &err.description()),
-                        };
-                    } else {
-                        span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
-                    }
-                }
-                TransItem::Fn(instance) => {
-                    trans_instance(&ccx, instance);
-                }
-                _ => { }
-            }
+        for (trans_item, _) in &ccx.codegen_unit().items {
+           trans_item.define(&ccx);
         }
     }
 
@@ -2927,7 +2865,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
         let mut item_keys: Vec<_> = items
             .iter()
             .map(|i| {
-                let mut output = i.to_string(scx);
+                let mut output = i.to_string(scx.tcx());
                 output.push_str(" @@");
                 let mut empty = Vec::new();
                 let mut cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
index 8cb9fd23e49204188a6b976097bc86475ef787e5..aff50e5e1f404c6aba4e0caf64d01c0104ae9acf 100644 (file)
@@ -325,7 +325,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>,
         // We've been here already, no need to search again.
         return;
     }
-    debug!("BEGIN collect_items_rec({})", starting_point.to_string(scx));
+    debug!("BEGIN collect_items_rec({})", starting_point.to_string(scx.tcx()));
 
     let mut neighbors = Vec::new();
     let recursion_depth_reset;
@@ -396,7 +396,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>,
         recursion_depths.insert(def_id, depth);
     }
 
-    debug!("END collect_items_rec({})", starting_point.to_string(scx));
+    debug!("END collect_items_rec({})", starting_point.to_string(scx.tcx()));
 }
 
 fn record_inlining_canditates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -637,7 +637,8 @@ fn visit_terminator_kind(&mut self,
                             let operand_ty = monomorphize::apply_param_substs(tcx,
                                                                               self.param_substs,
                                                                               &mt.ty);
-                            self.output.push(TransItem::DropGlue(DropGlueKind::Ty(operand_ty)));
+                            let ty = glue::get_drop_glue_type(tcx, operand_ty);
+                            self.output.push(TransItem::DropGlue(DropGlueKind::Ty(ty)));
                         } else {
                             bug!("Has the drop_in_place() intrinsic's signature changed?")
                         }
@@ -1271,7 +1272,7 @@ fn hash<T: Hash>(t: &T) -> u64 {
         let mut item_keys = FnvHashMap();
 
         for (item, item_state) in trans_items.iter() {
-            let k = item.to_string(scx);
+            let k = item.to_string(scx.tcx());
 
             if item_keys.contains_key(&k) {
                 let prev: (TransItem, TransItemState) = item_keys[&k];
@@ -1299,7 +1300,7 @@ fn hash<T: Hash>(t: &T) -> u64 {
     let mut generated = FnvHashSet();
 
     for (item, item_state) in trans_items.iter() {
-        let item_key = item.to_string(scx);
+        let item_key = item.to_string(scx.tcx());
 
         match *item_state {
             TransItemState::PredictedAndGenerated => {
index bfcb1ae33b3019f000314b4e25005f23f1a839aa..7f6e8fa035ab735e3dff6b8fd0f1c81b117dc9e2 100644 (file)
@@ -36,7 +36,7 @@
 use session::config::NoDebugInfo;
 use session::Session;
 use util::sha2::Sha256;
-use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap, FnvHashSet};
+use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap};
 
 use std::ffi::{CStr, CString};
 use std::cell::{Cell, RefCell};
@@ -46,6 +46,7 @@
 use std::str;
 use syntax::ast;
 use syntax::parse::token::InternedString;
+use abi::FnType;
 
 pub struct Stats {
     pub n_glues_created: Cell<usize>,
@@ -80,8 +81,6 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
     mir_map: &'a MirMap<'tcx>,
     mir_cache: RefCell<DefIdMap<Rc<mir::Mir<'tcx>>>>,
 
-    available_monomorphizations: RefCell<FnvHashSet<String>>,
-    available_drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, String>>,
     use_dll_storage_attrs: bool,
 
     translation_items: RefCell<FnvHashMap<TransItem<'tcx>, TransItemState>>,
@@ -99,7 +98,7 @@ pub struct LocalCrateContext<'tcx> {
     codegen_unit: CodegenUnit<'tcx>,
     needs_unwind_cleanup_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
     fn_pointer_shims: RefCell<FnvHashMap<Ty<'tcx>, ValueRef>>,
-    drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, ValueRef>>,
+    drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, (ValueRef, FnType)>>,
     /// 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
@@ -413,8 +412,6 @@ pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>,
             },
             check_overflow: check_overflow,
             check_drop_flag_for_sanity: check_drop_flag_for_sanity,
-            available_monomorphizations: RefCell::new(FnvHashSet()),
-            available_drop_glues: RefCell::new(FnvHashMap()),
             use_dll_storage_attrs: use_dll_storage_attrs,
             translation_items: RefCell::new(FnvHashMap()),
             trait_cache: RefCell::new(DepTrackingMap::new(tcx.dep_graph.clone())),
@@ -730,7 +727,8 @@ pub fn fn_pointer_shims(&self) -> &RefCell<FnvHashMap<Ty<'tcx>, ValueRef>> {
         &self.local().fn_pointer_shims
     }
 
-    pub fn drop_glues<'a>(&'a self) -> &'a RefCell<FnvHashMap<DropGlueKind<'tcx>, ValueRef>> {
+    pub fn drop_glues<'a>(&'a self)
+                          -> &'a RefCell<FnvHashMap<DropGlueKind<'tcx>, (ValueRef, FnType)>> {
         &self.local().drop_glues
     }
 
@@ -816,14 +814,6 @@ pub fn stats<'a>(&'a self) -> &'a Stats {
         &self.shared.stats
     }
 
-    pub fn available_monomorphizations<'a>(&'a self) -> &'a RefCell<FnvHashSet<String>> {
-        &self.shared.available_monomorphizations
-    }
-
-    pub fn available_drop_glues(&self) -> &RefCell<FnvHashMap<DropGlueKind<'tcx>, String>> {
-        &self.shared.available_drop_glues
-    }
-
     pub fn int_type(&self) -> Type {
         self.local().int_type
     }
index e6db695943bbee5b5ae940255b31ed3e108f2c5b..2746d3fb6b0b6788e76397504e968b60d460491f 100644 (file)
@@ -138,24 +138,34 @@ pub fn define_global(ccx: &CrateContext, name: &str, ty: Type) -> Option<ValueRe
     }
 }
 
-
 /// Declare a Rust function with an intention to define it.
 ///
 /// Use this function when you intend to define a function. This function will
 /// return panic if the name already has a definition associated with it. This
 /// can happen with #[no_mangle] or #[export_name], for example.
-pub fn define_internal_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                                    name: &str,
-                                    fn_type: ty::Ty<'tcx>) -> ValueRef {
+pub fn define_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                           name: &str,
+                           fn_type: ty::Ty<'tcx>) -> ValueRef {
     if get_defined_value(ccx, name).is_some() {
         ccx.sess().fatal(&format!("symbol `{}` already defined", name))
     } else {
-        let llfn = declare_fn(ccx, name, fn_type);
-        llvm::SetLinkage(llfn, llvm::InternalLinkage);
-        llfn
+        declare_fn(ccx, name, fn_type)
     }
 }
 
+/// Declare a Rust function with an intention to define it.
+///
+/// Use this function when you intend to define a function. This function will
+/// return panic if the name already has a definition associated with it. This
+/// can happen with #[no_mangle] or #[export_name], for example.
+pub fn define_internal_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                                    name: &str,
+                                    fn_type: ty::Ty<'tcx>) -> ValueRef {
+    let llfn = define_fn(ccx, name, fn_type);
+    llvm::SetLinkage(llfn, llvm::InternalLinkage);
+    llfn
+}
+
 
 /// Get declared value by name.
 pub fn get_declared_value(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
index e4519ff82a0eaef4bde4068d8b737c9dd15cbb40..30eb71a90064c45e122a9e6c0b3665e87bfdb6fd 100644 (file)
 
 use std;
 
-use attributes;
-use back::symbol_names;
 use llvm;
 use llvm::{ValueRef, get_param};
 use middle::lang_items::ExchangeFreeFnLangItem;
 use rustc::ty::subst::{Substs};
 use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
-use abi::{Abi, FnType};
 use adt;
 use adt::GetDtorType; // for tcx.dtor_type()
 use base::*;
@@ -33,7 +30,6 @@
 use collector;
 use common::*;
 use debuginfo::DebugLoc;
-use declare;
 use expr;
 use machine::*;
 use monomorphize;
@@ -236,48 +232,21 @@ pub fn map_ty<F>(&self, mut f: F) -> DropGlueKind<'tcx> where F: FnMut(Ty<'tcx>)
 
 fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                 g: DropGlueKind<'tcx>) -> ValueRef {
-    debug!("make drop glue for {:?}", g);
     let g = g.map_ty(|t| get_drop_glue_type(ccx.tcx(), t));
-    debug!("drop glue type {:?}", g);
     match ccx.drop_glues().borrow().get(&g) {
-        Some(&glue) => return glue,
-        _ => { }
+        Some(&(glue, _)) => glue,
+        None => { bug!("Could not find drop glue for {:?} -- {} -- {}",
+                       g,
+                       TransItem::DropGlue(g).to_raw_string(),
+                       ccx.codegen_unit().name) }
     }
-    let t = g.ty();
+}
 
+pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                                     g: DropGlueKind<'tcx>) {
     let tcx = ccx.tcx();
-    let sig = ty::FnSig {
-        inputs: vec![tcx.mk_mut_ptr(tcx.types.i8)],
-        output: ty::FnOutput::FnConverging(tcx.mk_nil()),
-        variadic: false,
-    };
-    // Create a FnType for fn(*mut i8) and substitute the real type in
-    // later - that prevents FnType from splitting fat pointers up.
-    let mut fn_ty = FnType::new(ccx, Abi::Rust, &sig, &[]);
-    fn_ty.args[0].original_ty = type_of(ccx, t).ptr_to();
-    let llfnty = fn_ty.llvm_type(ccx);
-
-    // To avoid infinite recursion, don't `make_drop_glue` until after we've
-    // added the entry to the `drop_glues` cache.
-    if let Some(old_sym) = ccx.available_drop_glues().borrow().get(&g) {
-        let llfn = declare::declare_cfn(ccx, &old_sym, llfnty);
-        ccx.drop_glues().borrow_mut().insert(g, llfn);
-        return llfn;
-    };
-
-    let suffix = match g {
-        DropGlueKind::Ty(_) => "drop",
-        DropGlueKind::TyContents(_) => "drop_contents",
-    };
-
-    let fn_nm = symbol_names::internal_name_from_type_and_suffix(ccx, t, suffix);
-    assert!(declare::get_defined_value(ccx, &fn_nm).is_none());
-    let llfn = declare::declare_cfn(ccx, &fn_nm, llfnty);
-    attributes::set_frame_pointer_elimination(ccx, llfn);
-    ccx.available_drop_glues().borrow_mut().insert(g, fn_nm);
-    ccx.drop_glues().borrow_mut().insert(g, llfn);
-
-    let _s = StatRecorder::new(ccx, format!("drop {:?}", t));
+    assert_eq!(g.ty(), get_drop_glue_type(tcx, g.ty()));
+    let (llfn, fn_ty) = ccx.drop_glues().borrow().get(&g).unwrap().clone();
 
     let (arena, fcx): (TypedArena<_>, FunctionContext);
     arena = TypedArena::new();
@@ -285,8 +254,6 @@ fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     let bcx = fcx.init(false, None);
 
-    update_linkage(ccx, llfn, None);
-
     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
@@ -298,10 +265,9 @@ fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     let bcx = make_drop_glue(bcx, get_param(llfn, 0), g);
     fcx.finish(bcx, DebugLoc::None);
-
-    llfn
 }
 
+
 fn trans_struct_drop_flag<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                                       t: Ty<'tcx>,
                                       struct_data: ValueRef)
index cd08fe68f0cc5b103fc1491f54fc082537f18842..a0360a8ed226ecbe26e840d327458f6f1e3c111b 100644 (file)
@@ -165,10 +165,14 @@ pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                                 trans_items,
                                                                 reachable);
 
+    debug_dump(tcx, "INITIAL PARTITONING:", initial_partitioning.codegen_units.iter());
+
     // If the partitioning should produce a fixed count of codegen units, merge
     // until that count is reached.
     if let PartitioningStrategy::FixedUnitCount(count) = strategy {
         merge_codegen_units(&mut initial_partitioning, count, &tcx.crate_name[..]);
+
+        debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter());
     }
 
     // In the next step, we use the inlining map to determine which addtional
@@ -177,6 +181,9 @@ pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // local functions the definition of which is marked with #[inline].
     let post_inlining = place_inlined_translation_items(initial_partitioning,
                                                         inlining_map);
+
+    debug_dump(tcx, "POST INLINING:", post_inlining.0.iter());
+
     post_inlining.0
 }
 
@@ -484,3 +491,23 @@ fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString
         NUMBERED_CODEGEN_UNIT_MARKER,
         index)[..])
 }
+
+fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                               label: &str,
+                               cgus: I)
+    where I: Iterator<Item=&'b CodegenUnit<'tcx>>,
+          'tcx: 'a + 'b
+{
+    if cfg!(debug_assertions) {
+        debug!("{}", label);
+        for cgu in cgus {
+            debug!("CodegenUnit {}:", cgu.name);
+
+            for (trans_item, linkage) in &cgu.items {
+                debug!(" - {} [{:?}]", trans_item.to_string(tcx), linkage);
+            }
+
+            debug!("");
+        }
+    }
+}
index ae6e095d1429131a7781a700c0393efb8ffd5f04..a07deda2b1e5e8c20c7fda052999499d425b6cc9 100644 (file)
@@ -16,7 +16,8 @@
 
 use attributes;
 use base;
-use context::{SharedCrateContext, CrateContext};
+use consts;
+use context::CrateContext;
 use declare;
 use glue::DropGlueKind;
 use llvm;
@@ -32,7 +33,9 @@
 use syntax::{attr,errors};
 use syntax::parse::token;
 use type_of;
-
+use glue;
+use abi::{Abi, FnType};
+use back::symbol_names;
 
 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
 pub enum TransItem<'tcx> {
@@ -64,9 +67,47 @@ fn hash<H: Hasher>(&self, s: &mut H) {
 
 impl<'a, 'tcx> TransItem<'tcx> {
 
+    pub fn define(&self, ccx: &CrateContext<'a, 'tcx>) {
+
+        debug!("BEGIN IMPLEMENTING '{} ({})' in cgu {}",
+                  self.to_string(ccx.tcx()),
+                  self.to_raw_string(),
+                  ccx.codegen_unit().name);
+
+        match *self {
+            TransItem::Static(node_id) => {
+                let item = ccx.tcx().map.expect_item(node_id);
+                if let hir::ItemStatic(_, m, ref expr) = item.node {
+                    match consts::trans_static(&ccx, m, expr, item.id, &item.attrs) {
+                        Ok(_) => { /* Cool, everything's alright. */ },
+                        Err(err) => ccx.tcx().sess.span_fatal(expr.span, &err.description()),
+                    };
+                } else {
+                    span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
+                }
+            }
+            TransItem::Fn(instance) => {
+                base::trans_instance(&ccx, instance);
+            }
+            TransItem::DropGlue(dg) => {
+                glue::implement_drop_glue(&ccx, dg);
+            }
+        }
+
+        debug!("END IMPLEMENTING '{} ({})' in cgu {}",
+               self.to_string(ccx.tcx()),
+               self.to_raw_string(),
+               ccx.codegen_unit().name);
+    }
+
     pub fn predefine(&self,
                      ccx: &CrateContext<'a, 'tcx>,
                      linkage: llvm::Linkage) {
+        debug!("BEGIN PREDEFINING '{} ({})' in cgu {}",
+               self.to_string(ccx.tcx()),
+               self.to_raw_string(),
+               ccx.codegen_unit().name);
+
         match *self {
             TransItem::Static(node_id) => {
                 TransItem::predefine_static(ccx, node_id, linkage);
@@ -74,10 +115,15 @@ pub fn predefine(&self,
             TransItem::Fn(instance) => {
                 TransItem::predefine_fn(ccx, instance, linkage);
             }
-            _ => {
-                // Not yet implemented
+            TransItem::DropGlue(dg) => {
+                TransItem::predefine_drop_glue(ccx, dg, linkage);
             }
         }
+
+        debug!("END PREDEFINING '{} ({})' in cgu {}",
+               self.to_string(ccx.tcx()),
+               self.to_raw_string(),
+               ccx.codegen_unit().name);
     }
 
     fn predefine_static(ccx: &CrateContext<'a, 'tcx>,
@@ -93,7 +139,7 @@ fn predefine_static(ccx: &CrateContext<'a, 'tcx>,
             }) => {
                 let instance = Instance::mono(ccx.shared(), def_id);
                 let sym = instance.symbol_name(ccx.shared());
-                debug!("making {}", sym);
+                debug!("symbol {}", sym);
 
                 let g = declare::define_global(ccx, &sym, llty).unwrap_or_else(|| {
                     ccx.sess().span_fatal(span,
@@ -110,8 +156,6 @@ fn predefine_static(ccx: &CrateContext<'a, 'tcx>,
     fn predefine_fn(ccx: &CrateContext<'a, 'tcx>,
                     instance: Instance<'tcx>,
                     linkage: llvm::Linkage) {
-        let unit = ccx.codegen_unit();
-        debug!("predefine_fn[cg={}](instance={:?})", &unit.name[..], instance);
         assert!(!instance.substs.types.needs_infer() &&
                 !instance.substs.types.has_param_types());
 
@@ -143,10 +187,11 @@ fn predefine_fn(ccx: &CrateContext<'a, 'tcx>,
                 ref attrs, node: hir::ImplItemKind::Method(..), ..
             }) => {
                 let symbol = instance.symbol_name(ccx.shared());
-                let lldecl = declare::declare_fn(ccx, &symbol, mono_ty);
+                debug!("symbol {}", symbol);
 
-                attributes::from_fn_attrs(ccx, attrs, lldecl);
+                let lldecl = declare::declare_fn(ccx, &symbol, mono_ty);
                 llvm::SetLinkage(lldecl, linkage);
+                attributes::from_fn_attrs(ccx, attrs, lldecl);
                 base::set_link_section(ccx, lldecl, attrs);
 
                 ccx.instances().borrow_mut().insert(instance, lldecl);
@@ -156,6 +201,39 @@ fn predefine_fn(ccx: &CrateContext<'a, 'tcx>,
 
     }
 
+    fn predefine_drop_glue(ccx: &CrateContext<'a, 'tcx>,
+                           dg: glue::DropGlueKind<'tcx>,
+                           linkage: llvm::Linkage) {
+        let tcx = ccx.tcx();
+        assert_eq!(dg.ty(), glue::get_drop_glue_type(tcx, dg.ty()));
+        let t = dg.ty();
+
+        let sig = ty::FnSig {
+            inputs: vec![tcx.mk_mut_ptr(tcx.types.i8)],
+            output: ty::FnOutput::FnConverging(tcx.mk_nil()),
+            variadic: false,
+        };
+
+        // Create a FnType for fn(*mut i8) and substitute the real type in
+        // later - that prevents FnType from splitting fat pointers up.
+        let mut fn_ty = FnType::new(ccx, Abi::Rust, &sig, &[]);
+        fn_ty.args[0].original_ty = type_of::type_of(ccx, t).ptr_to();
+        let llfnty = fn_ty.llvm_type(ccx);
+
+        let prefix = match dg {
+            DropGlueKind::Ty(_) => "drop",
+            DropGlueKind::TyContents(_) => "drop_contents",
+        };
+
+        let symbol =
+            symbol_names::exported_name_from_type_and_prefix(ccx.shared(), t, prefix);
+        debug!(" symbol: {}", symbol);
+        assert!(declare::get_defined_value(ccx, &symbol).is_none());
+        let llfn = declare::declare_cfn(ccx, &symbol, llfnty);
+        attributes::set_frame_pointer_elimination(ccx, llfn);
+        llvm::SetLinkage(llfn, linkage);
+        ccx.drop_glues().borrow_mut().insert(dg, (llfn, fn_ty));
+    }
 
     pub fn requests_inline(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
         match *self {
@@ -216,8 +294,7 @@ pub fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<llvm::Link
         }
     }
 
-    pub fn to_string(&self, scx: &SharedCrateContext<'a, 'tcx>) -> String {
-        let tcx = scx.tcx();
+    pub fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
         let hir_map = &tcx.map;
 
         return match *self {
@@ -235,7 +312,8 @@ pub fn to_string(&self, scx: &SharedCrateContext<'a, 'tcx>) -> String {
             },
             TransItem::Static(node_id) => {
                 let def_id = hir_map.local_def_id(node_id);
-                let instance = Instance::mono(scx, def_id);
+                let instance = Instance::new(def_id,
+                                             tcx.mk_substs(subst::Substs::empty()));
                 to_string_internal(tcx, "static ", instance)
             },
         };
@@ -254,7 +332,11 @@ fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     pub fn to_raw_string(&self) -> String {
         match *self {
             TransItem::DropGlue(dg) => {
-                format!("DropGlue({})", dg.ty() as *const _ as usize)
+                let prefix = match dg {
+                    DropGlueKind::Ty(_) => "Ty",
+                    DropGlueKind::TyContents(_) => "TyContents",
+                };
+                format!("DropGlue({}: {})", prefix, dg.ty() as *const _ as usize)
             }
             TransItem::Fn(instance) => {
                 format!("Fn({:?}, {})",