]> git.lizzy.rs Git - rust.git/commitdiff
Build SymbolMap for symbol name conflict checking and caching.
authorMichael Woerister <michaelwoerister@posteo.net>
Thu, 26 May 2016 12:59:58 +0000 (08:59 -0400)
committerMichael Woerister <michaelwoerister@posteo.net>
Fri, 8 Jul 2016 14:42:47 +0000 (10:42 -0400)
src/librustc_trans/base.rs
src/librustc_trans/callee.rs
src/librustc_trans/consts.rs
src/librustc_trans/context.rs
src/librustc_trans/lib.rs
src/librustc_trans/monomorphize.rs
src/librustc_trans/symbol_map.rs [new file with mode: 0644]
src/librustc_trans/trans_item.rs

index 5dc319aa5f9bc1c9373bd2ec549937a3d79ff33a..3fc7fe5128877cca4eca0934be2ca208d004fb25 100644 (file)
@@ -80,6 +80,7 @@
 use mir;
 use monomorphize::{self, Instance};
 use partitioning::{self, PartitioningStrategy, CodegenUnit};
+use symbol_map::SymbolMap;
 use symbol_names_test;
 use trans_item::TransItem;
 use tvec;
@@ -97,6 +98,7 @@
 use std::ffi::{CStr, CString};
 use std::cell::{Cell, RefCell};
 use std::collections::{HashMap, HashSet};
+use std::rc::Rc;
 use std::str;
 use std::{i8, i16, i32, i64};
 use syntax_pos::{Span, DUMMY_SP};
@@ -2588,14 +2590,18 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     };
     let no_builtins = attr::contains_name(&krate.attrs, "no_builtins");
 
-    let codegen_units = collect_and_partition_translation_items(&shared_ccx);
+    let (codegen_units, symbol_map) =
+        collect_and_partition_translation_items(&shared_ccx);
     let codegen_unit_count = codegen_units.len();
 
     assert!(tcx.sess.opts.cg.codegen_units == codegen_unit_count ||
             tcx.sess.opts.debugging_opts.incremental.is_some());
 
-    let crate_context_list = CrateContextList::new(&shared_ccx, codegen_units);
+    let symbol_map = Rc::new(symbol_map);
 
+    let crate_context_list = CrateContextList::new(&shared_ccx,
+                                                   codegen_units,
+                                                   symbol_map.clone());
     let modules = crate_context_list.iter()
         .map(|ccx| ModuleTranslation {
             name: String::from(&ccx.codegen_unit().name[..]),
@@ -2693,8 +2699,9 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let sess = shared_ccx.sess();
     let mut reachable_symbols = shared_ccx.reachable().iter().map(|&id| {
         let def_id = shared_ccx.tcx().map.local_def_id(id);
-        Instance::mono(&shared_ccx, def_id).symbol_name(&shared_ccx)
+        symbol_for_def_id(def_id, &shared_ccx, &symbol_map)
     }).collect::<Vec<_>>();
+
     if sess.entry_fn.borrow().is_some() {
         reachable_symbols.push("main".to_string());
     }
@@ -2716,7 +2723,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         reachable_symbols.extend(syms.into_iter().filter(|did| {
             sess.cstore.is_extern_item(shared_ccx.tcx(), *did)
         }).map(|did| {
-            Instance::mono(&shared_ccx, did).symbol_name(&shared_ccx)
+            symbol_for_def_id(did, &shared_ccx, &symbol_map)
         }));
     }
 
@@ -2810,7 +2817,7 @@ fn visit_item(&mut self, i: &hir::Item) {
 }
 
 fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>)
-                                                     -> Vec<CodegenUnit<'tcx>> {
+                                                     -> (Vec<CodegenUnit<'tcx>>, SymbolMap<'tcx>) {
     let time_passes = scx.sess().time_passes();
 
     let collection_mode = match scx.sess().opts.debugging_opts.print_trans_items {
@@ -2833,10 +2840,13 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
         None => TransItemCollectionMode::Lazy
     };
 
-    let (items, inlining_map) = time(time_passes, "translation item collection", || {
-        collector::collect_crate_translation_items(&scx, collection_mode)
+    let (items, inlining_map) =
+        time(time_passes, "translation item collection", || {
+            collector::collect_crate_translation_items(&scx, collection_mode)
     });
 
+    let symbol_map = SymbolMap::build(scx, items.iter().cloned());
+
     let strategy = if scx.sess().opts.debugging_opts.incremental.is_some() {
         PartitioningStrategy::PerModule
     } else {
@@ -2910,5 +2920,24 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
         }
     }
 
-    codegen_units
+    (codegen_units, symbol_map)
+}
+
+fn symbol_for_def_id<'a, 'tcx>(def_id: DefId,
+                               scx: &SharedCrateContext<'a, 'tcx>,
+                               symbol_map: &SymbolMap<'tcx>)
+                               -> String {
+    // Just try to look things up in the symbol map. If nothing's there, we
+    // recompute.
+    if let Some(node_id) = scx.tcx().map.as_local_node_id(def_id) {
+        if let Some(sym) = symbol_map.get(TransItem::Static(node_id)) {
+            return sym.to_owned();
+        }
+    }
+
+    let instance = Instance::mono(scx, def_id);
+
+    symbol_map.get(TransItem::Fn(instance))
+              .map(str::to_owned)
+              .unwrap_or_else(|| instance.symbol_name(scx))
 }
index 9ea65532b35b61c8c3a1cd35deda4ca89861ad34..b7cf43a437169a937a64670778145475c1c295f5 100644 (file)
@@ -46,6 +46,7 @@
 use machine::llalign_of_min;
 use meth;
 use monomorphize::{self, Instance};
+use trans_item::TransItem;
 use type_::Type;
 use type_of;
 use value::Value;
@@ -536,11 +537,18 @@ fn is_named_tuple_constructor(tcx: TyCtxt, def_id: DefId) -> bool {
     // reference. It also occurs when testing libcore and in some
     // other weird situations. Annoying.
 
-    let sym = instance.symbol_name(ccx.shared());
+    // Let's see if we can get the symbol name from the symbol_map, so we don't
+    // have to recompute it.
+    let mut sym_data = String::new();
+    let sym = ccx.symbol_map().get(TransItem::Fn(instance)).unwrap_or_else(|| {
+        sym_data = instance.symbol_name(ccx.shared());
+        &sym_data[..]
+    });
+
     let llptrty = type_of::type_of(ccx, fn_ptr_ty);
-    let llfn = if let Some(llfn) = declare::get_declared_value(ccx, &sym) {
+    let llfn = if let Some(llfn) = declare::get_declared_value(ccx, sym) {
         if let Some(span) = local_item {
-            if declare::get_defined_value(ccx, &sym).is_some() {
+            if declare::get_defined_value(ccx, sym).is_some() {
                 ccx.sess().span_fatal(span,
                     &format!("symbol `{}` is already defined", sym));
             }
@@ -558,7 +566,7 @@ fn is_named_tuple_constructor(tcx: TyCtxt, def_id: DefId) -> bool {
             llfn
         }
     } else {
-        let llfn = declare::declare_fn(ccx, &sym, ty);
+        let llfn = declare::declare_fn(ccx, sym, ty);
         assert_eq!(common::val_ty(llfn), llptrty);
         debug!("get_fn: not casting pointer!");
 
index 1a38baeff37841ba3559d05acc7bd49489323313..3f18c61fbd26caada391283588bcc08ebfb6ae20 100644 (file)
@@ -1013,14 +1013,16 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId)
         return Datum::new(g, ty, Lvalue::new("static"));
     }
 
-    let sym = instance.symbol_name(ccx.shared());
-
     let g = if let Some(id) = ccx.tcx().map.as_local_node_id(def_id) {
+
         let llty = type_of::type_of(ccx, ty);
         let (g, attrs) = match ccx.tcx().map.get(id) {
             hir_map::NodeItem(&hir::Item {
                 ref attrs, span, node: hir::ItemStatic(..), ..
             }) => {
+                let sym = ccx.symbol_map()
+                             .get(TransItem::Static(id))
+                             .expect("Local statics should always be in the SymbolMap");
                 // Make sure that this is never executed for something inlined.
                 assert!(!ccx.external_srcs().borrow().contains_key(&id));
 
@@ -1028,16 +1030,16 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId)
                                                          .items
                                                          .contains_key(&TransItem::Static(id));
                 if defined_in_current_codegen_unit {
-                    if declare::get_declared_value(ccx, &sym).is_none() {
+                    if declare::get_declared_value(ccx, sym).is_none() {
                         span_bug!(span, "trans: Static not properly pre-defined?");
                     }
                 } else {
-                    if declare::get_declared_value(ccx, &sym).is_some() {
+                    if declare::get_declared_value(ccx, sym).is_some() {
                         span_bug!(span, "trans: Conflicting symbol names for static?");
                     }
                 }
 
-                let g = declare::define_global(ccx, &sym, llty).unwrap();
+                let g = declare::define_global(ccx, sym, llty).unwrap();
 
                 (g, attrs)
             }
@@ -1045,6 +1047,7 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId)
             hir_map::NodeForeignItem(&hir::ForeignItem {
                 ref attrs, span, node: hir::ForeignItemStatic(..), ..
             }) => {
+                let sym = instance.symbol_name(ccx.shared());
                 let g = if let Some(name) =
                         attr::first_attr_value_str_by_name(&attrs, "linkage") {
                     // If this is a static with a linkage specified, then we need to handle
@@ -1079,7 +1082,7 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId)
                         real_name.push_str(&sym);
                         let g2 = declare::define_global(ccx, &real_name, llty).unwrap_or_else(||{
                             ccx.sess().span_fatal(span,
-                                &format!("symbol `{}` is already defined", sym))
+                                &format!("symbol `{}` is already defined", &sym))
                         });
                         llvm::SetLinkage(g2, llvm::InternalLinkage);
                         llvm::LLVMSetInitializer(g2, g1);
@@ -1104,6 +1107,8 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId)
 
         g
     } else {
+        let sym = instance.symbol_name(ccx.shared());
+
         // FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow?
         // FIXME(nagisa): investigate whether it can be changed into define_global
         let g = declare::declare_global(ccx, &sym, type_of::type_of(ccx, ty));
index 7f6e8fa035ab735e3dff6b8fd0f1c81b117dc9e2..64e0351610f24441a12c7aa45b9899ad6c0ca49f 100644 (file)
@@ -35,6 +35,7 @@
 use rustc::ty::{self, Ty, TyCtxt};
 use session::config::NoDebugInfo;
 use session::Session;
+use symbol_map::SymbolMap;
 use util::sha2::Sha256;
 use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap};
 
@@ -171,6 +172,8 @@ pub struct LocalCrateContext<'tcx> {
 
     /// Depth of the current type-of computation - used to bail out
     type_of_depth: Cell<usize>,
+
+    symbol_map: Rc<SymbolMap<'tcx>>,
 }
 
 // Implement DepTrackingMapConfig for `trait_cache`
@@ -197,12 +200,13 @@ pub struct CrateContextList<'a, 'tcx: 'a> {
 impl<'a, 'tcx: 'a> CrateContextList<'a, 'tcx> {
 
     pub fn new(shared_ccx: &'a SharedCrateContext<'a, 'tcx>,
-               codegen_units: Vec<CodegenUnit<'tcx>>)
+               codegen_units: Vec<CodegenUnit<'tcx>>,
+               symbol_map: Rc<SymbolMap<'tcx>>)
                -> CrateContextList<'a, 'tcx> {
         CrateContextList {
             shared: shared_ccx,
             local_ccxs: codegen_units.into_iter().map(|codegen_unit| {
-                LocalCrateContext::new(shared_ccx, codegen_unit)
+                LocalCrateContext::new(shared_ccx, codegen_unit, symbol_map.clone())
             }).collect()
         }
     }
@@ -512,7 +516,8 @@ pub fn metadata_symbol_name(&self) -> String {
 
 impl<'tcx> LocalCrateContext<'tcx> {
     fn new<'a>(shared: &SharedCrateContext<'a, 'tcx>,
-               codegen_unit: CodegenUnit<'tcx>)
+               codegen_unit: CodegenUnit<'tcx>,
+               symbol_map: Rc<SymbolMap<'tcx>>)
            -> LocalCrateContext<'tcx> {
         unsafe {
             // Append ".rs" to LLVM module identifier.
@@ -571,6 +576,7 @@ fn new<'a>(shared: &SharedCrateContext<'a, 'tcx>,
                 intrinsics: RefCell::new(FnvHashMap()),
                 n_llvm_insns: Cell::new(0),
                 type_of_depth: Cell::new(0),
+                symbol_map: symbol_map,
             };
 
             let (int_type, opaque_vec_type, str_slice_ty, mut local_ccx) = {
@@ -890,6 +896,10 @@ pub fn get_mir(&self, def_id: DefId) -> Option<CachedMir<'b, 'tcx>> {
         self.shared.get_mir(def_id)
     }
 
+    pub fn symbol_map(&self) -> &SymbolMap<'tcx> {
+        &*self.local().symbol_map
+    }
+
     pub fn translation_items(&self) -> &RefCell<FnvHashMap<TransItem<'tcx>, TransItemState>> {
         &self.shared.translation_items
     }
index c465edc7311af7e23976d4770cc46ca9dd9055ed..fa0a1fdc37523dbff9f012d6a0bb33f82baf93a1 100644 (file)
@@ -122,6 +122,7 @@ pub mod back {
 mod mir;
 mod monomorphize;
 mod partitioning;
+mod symbol_map;
 mod symbol_names_test;
 mod trans_item;
 mod tvec;
index 832acfe14bedc7ac163734df070a440af9d6b14f..8a2cc53432d86e1f55621e62987df52bde35cef3 100644 (file)
@@ -84,19 +84,24 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         monomorphizing.insert(fn_id, depth + 1);
     }
 
-    let symbol = instance.symbol_name(ccx.shared());
+    // Let's see if we can get the symbol name from the symbol_map, so we don't
+    // have to recompute it.
+    let mut sym_data = String::new();
+    let symbol = ccx.symbol_map().get(TransItem::Fn(instance)).unwrap_or_else(|| {
+        sym_data = instance.symbol_name(ccx.shared());
+        &sym_data[..]
+    });
 
     debug!("monomorphize_fn mangled to {}", symbol);
-    assert!(declare::get_defined_value(ccx, &symbol).is_none());
+    assert!(declare::get_defined_value(ccx, symbol).is_none());
 
     // FIXME(nagisa): perhaps needs a more fine grained selection?
-    let lldecl = declare::define_internal_fn(ccx, &symbol, mono_ty);
+    let lldecl = declare::define_internal_fn(ccx, symbol, mono_ty);
     // FIXME(eddyb) Doubt all extern fn should allow unwinding.
     attributes::unwind(lldecl, true);
 
     ccx.instances().borrow_mut().insert(instance, lldecl);
 
-
     // we can only monomorphize things in this crate (or inlined into it)
     let fn_node_id = ccx.tcx().map.as_local_node_id(fn_id).unwrap();
     let map_node = errors::expect(
diff --git a/src/librustc_trans/symbol_map.rs b/src/librustc_trans/symbol_map.rs
new file mode 100644 (file)
index 0000000..4f82b54
--- /dev/null
@@ -0,0 +1,115 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use context::SharedCrateContext;
+use monomorphize::Instance;
+use rustc::ty::TyCtxt;
+use syntax::codemap::Span;
+use trans_item::TransItem;
+use util::nodemap::FnvHashMap;
+
+
+// In the SymbolMap we collect the symbol names of all translation items of
+// the current crate.
+
+pub struct SymbolMap<'tcx> {
+    index: FnvHashMap<TransItem<'tcx>, (usize, usize)>,
+    arena: String,
+}
+
+impl<'tcx> SymbolMap<'tcx> {
+
+    pub fn build<'a, I>(scx: &SharedCrateContext<'a, 'tcx>,
+                        trans_items: I)
+                        -> SymbolMap<'tcx>
+        where I: Iterator<Item=TransItem<'tcx>>
+    {
+        // Check for duplicate symbol names
+        let mut symbols: Vec<_> = trans_items.map(|trans_item| {
+            (trans_item, trans_item.compute_symbol_name(scx))
+        }).collect();
+
+        (&mut symbols[..]).sort_by(|&(_, ref sym1), &(_, ref sym2)|{
+            sym1.cmp(sym2)
+        });
+
+        for pair in (&symbols[..]).windows(2) {
+            let sym1 = &pair[0].1;
+            let sym2 = &pair[1].1;
+
+            if *sym1 == *sym2 {
+                let trans_item1 = pair[0].0;
+                let trans_item2 = pair[1].0;
+
+                let span1 = get_span(scx.tcx(), trans_item1);
+                let span2 = get_span(scx.tcx(), trans_item2);
+
+                // Deterministically select one of the spans for error reporting
+                let span = match (span1, span2) {
+                    (Some(span1), Some(span2)) => {
+                        Some(if span1.lo.0 > span2.lo.0 {
+                            span1
+                        } else {
+                            span2
+                        })
+                    }
+                    (Some(span), None) |
+                    (None, Some(span)) => Some(span),
+                    _ => None
+                };
+
+                let error_message = format!("symbol `{}` is already defined", sym1);
+
+                if let Some(span) = span {
+                    scx.sess().span_fatal(span, &error_message)
+                } else {
+                    scx.sess().fatal(&error_message)
+                }
+            }
+        }
+
+        let mut symbol_map = SymbolMap {
+            index: FnvHashMap(),
+            arena: String::with_capacity(1024),
+        };
+
+        for (trans_item, symbol) in symbols {
+            let start_index = symbol_map.arena.len();
+            symbol_map.arena.push_str(&symbol[..]);
+            let end_index = symbol_map.arena.len();
+            let prev_entry = symbol_map.index.insert(trans_item,
+                                                     (start_index, end_index));
+            if prev_entry.is_some() {
+                bug!("TransItem encountered twice?")
+            }
+        }
+
+        fn get_span<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                              trans_item: TransItem<'tcx>) -> Option<Span> {
+            match trans_item {
+                TransItem::Fn(Instance { def, .. }) => {
+                    tcx.map.as_local_node_id(def)
+                }
+                TransItem::Static(node_id) => Some(node_id),
+                TransItem::DropGlue(_) => None,
+            }.map(|node_id| {
+                tcx.map.span(node_id)
+            })
+        }
+
+        symbol_map
+    }
+
+    pub fn get(&self, trans_item: TransItem<'tcx>) -> Option<&str> {
+        self.index.get(&trans_item).map(|&(start_index, end_index)| {
+            &self.arena[start_index .. end_index]
+        })
+    }
+}
index a07deda2b1e5e8c20c7fda052999499d425b6cc9..4fa0ba03005abb80fa7ccc81c5e2f8eee5673464 100644 (file)
@@ -17,7 +17,7 @@
 use attributes;
 use base;
 use consts;
-use context::CrateContext;
+use context::{CrateContext, SharedCrateContext};
 use declare;
 use glue::DropGlueKind;
 use llvm;
@@ -64,7 +64,6 @@ fn hash<H: Hasher>(&self, s: &mut H) {
     }
 }
 
-
 impl<'a, 'tcx> TransItem<'tcx> {
 
     pub fn define(&self, ccx: &CrateContext<'a, 'tcx>) {
@@ -108,15 +107,20 @@ pub fn predefine(&self,
                self.to_raw_string(),
                ccx.codegen_unit().name);
 
+        let symbol_name = ccx.symbol_map()
+                             .get(*self)
+                             .expect("Name not present in SymbolMap?");
+        debug!("symbol {}", symbol_name);
+
         match *self {
             TransItem::Static(node_id) => {
-                TransItem::predefine_static(ccx, node_id, linkage);
+                TransItem::predefine_static(ccx, node_id, linkage, symbol_name);
             }
             TransItem::Fn(instance) => {
-                TransItem::predefine_fn(ccx, instance, linkage);
+                TransItem::predefine_fn(ccx, instance, linkage, symbol_name);
             }
             TransItem::DropGlue(dg) => {
-                TransItem::predefine_drop_glue(ccx, dg, linkage);
+                TransItem::predefine_drop_glue(ccx, dg, linkage, symbol_name);
             }
         }
 
@@ -128,7 +132,8 @@ pub fn predefine(&self,
 
     fn predefine_static(ccx: &CrateContext<'a, 'tcx>,
                         node_id: ast::NodeId,
-                        linkage: llvm::Linkage) {
+                        linkage: llvm::Linkage,
+                        symbol_name: &str) {
         let def_id = ccx.tcx().map.local_def_id(node_id);
         let ty = ccx.tcx().lookup_item_type(def_id).ty;
         let llty = type_of::type_of(ccx, ty);
@@ -137,13 +142,9 @@ fn predefine_static(ccx: &CrateContext<'a, 'tcx>,
             hir::map::NodeItem(&hir::Item {
                 span, node: hir::ItemStatic(..), ..
             }) => {
-                let instance = Instance::mono(ccx.shared(), def_id);
-                let sym = instance.symbol_name(ccx.shared());
-                debug!("symbol {}", sym);
-
-                let g = declare::define_global(ccx, &sym, llty).unwrap_or_else(|| {
+                let g = declare::define_global(ccx, symbol_name, llty).unwrap_or_else(|| {
                     ccx.sess().span_fatal(span,
-                        &format!("symbol `{}` is already defined", sym))
+                        &format!("symbol `{}` is already defined", symbol_name))
                 });
 
                 llvm::SetLinkage(g, linkage);
@@ -155,7 +156,8 @@ fn predefine_static(ccx: &CrateContext<'a, 'tcx>,
 
     fn predefine_fn(ccx: &CrateContext<'a, 'tcx>,
                     instance: Instance<'tcx>,
-                    linkage: llvm::Linkage) {
+                    linkage: llvm::Linkage,
+                    symbol_name: &str) {
         assert!(!instance.substs.types.needs_infer() &&
                 !instance.substs.types.has_param_types());
 
@@ -186,10 +188,7 @@ fn predefine_fn(ccx: &CrateContext<'a, 'tcx>,
             hir_map::NodeImplItem(&hir::ImplItem {
                 ref attrs, node: hir::ImplItemKind::Method(..), ..
             }) => {
-                let symbol = instance.symbol_name(ccx.shared());
-                debug!("symbol {}", symbol);
-
-                let lldecl = declare::declare_fn(ccx, &symbol, mono_ty);
+                let lldecl = declare::declare_fn(ccx, symbol_name, mono_ty);
                 llvm::SetLinkage(lldecl, linkage);
                 attributes::from_fn_attrs(ccx, attrs, lldecl);
                 base::set_link_section(ccx, lldecl, attrs);
@@ -203,7 +202,8 @@ fn predefine_fn(ccx: &CrateContext<'a, 'tcx>,
 
     fn predefine_drop_glue(ccx: &CrateContext<'a, 'tcx>,
                            dg: glue::DropGlueKind<'tcx>,
-                           linkage: llvm::Linkage) {
+                           linkage: llvm::Linkage,
+                           symbol_name: &str) {
         let tcx = ccx.tcx();
         assert_eq!(dg.ty(), glue::get_drop_glue_type(tcx, dg.ty()));
         let t = dg.ty();
@@ -220,21 +220,31 @@ fn predefine_drop_glue(ccx: &CrateContext<'a, 'tcx>,
         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);
+        assert!(declare::get_defined_value(ccx, symbol_name).is_none());
+        let llfn = declare::declare_cfn(ccx, symbol_name, llfnty);
+       llvm::SetLinkage(llfn, linkage);
         attributes::set_frame_pointer_elimination(ccx, llfn);
-        llvm::SetLinkage(llfn, linkage);
         ccx.drop_glues().borrow_mut().insert(dg, (llfn, fn_ty));
     }
 
+    pub fn compute_symbol_name(&self,
+                               scx: &SharedCrateContext<'a, 'tcx>) -> String {
+        match *self {
+            TransItem::Fn(instance) => instance.symbol_name(scx),
+            TransItem::Static(node_id) => {
+                let def_id = scx.tcx().map.local_def_id(node_id);
+                Instance::mono(scx, def_id).symbol_name(scx)
+            }
+            TransItem::DropGlue(dg) => {
+                let prefix = match dg {
+                    DropGlueKind::Ty(_) => "drop",
+                    DropGlueKind::TyContents(_) => "drop_contents",
+                };
+                symbol_names::exported_name_from_type_and_prefix(scx, dg.ty(), prefix)
+            }
+        }
+    }
+
     pub fn requests_inline(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
         match *self {
             TransItem::Fn(ref instance) => {