diff options
| author | Michael Woerister <michaelwoerister@posteo.net> | 2016-07-20 07:55:45 -0400 |
|---|---|---|
| committer | Michael Woerister <michaelwoerister@posteo.net> | 2016-07-20 10:26:25 -0400 |
| commit | ecc12953dbe401b3e8cb663ce6529706c50cbf8d (patch) | |
| tree | ae5fc233e0535676c6245c439862f16c21d8d63f /src | |
| parent | f7820888daeb961339643dd142ba032847181555 (diff) | |
| download | rust-ecc12953dbe401b3e8cb663ce6529706c50cbf8d.tar.gz rust-ecc12953dbe401b3e8cb663ce6529706c50cbf8d.zip | |
trans: Make base::internalize_symbols() respect explicit linkage directives.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_trans/base.rs | 72 |
1 files changed, 57 insertions, 15 deletions
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index f9e1a4f1608..ea8c248d023 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -89,13 +89,14 @@ use value::Value; use Disr; use util::common::indenter; use util::sha2::Sha256; -use util::nodemap::{NodeMap, NodeSet}; +use util::nodemap::{NodeMap, NodeSet, FnvHashSet}; use arena::TypedArena; use libc::c_uint; use std::ffi::{CStr, CString}; +use std::borrow::Cow; use std::cell::{Cell, RefCell}; -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use std::ptr; use std::rc::Rc; use std::str; @@ -2256,12 +2257,20 @@ fn write_metadata(cx: &SharedCrateContext, /// Find any symbols that are defined in one compilation unit, but not declared /// in any other compilation unit. Give these symbols internal linkage. -fn internalize_symbols(cx: &CrateContextList, reachable: &HashSet<&str>) { +fn internalize_symbols<'a, 'tcx>(ccxs: &CrateContextList<'a, 'tcx>, + symbol_map: &SymbolMap<'tcx>, + reachable: &FnvHashSet<&str>) { + let scx = ccxs.shared(); + let tcx = scx.tcx(); + + // 'unsafe' because we are holding on to CStr's from the LLVM module within + // this block. unsafe { - let mut declared = HashSet::new(); + let mut referenced_somewhere = FnvHashSet(); - // Collect all external declarations in all compilation units. - for ccx in cx.iter() { + // Collect all symbols that need to stay externally visible because they + // are referenced via a declaration in some other codegen unit. + for ccx in ccxs.iter() { for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) { let linkage = llvm::LLVMGetLinkage(val); // We only care about external declarations (not definitions) @@ -2270,16 +2279,43 @@ fn internalize_symbols(cx: &CrateContextList, reachable: &HashSet<&str>) { let is_decl = llvm::LLVMIsDeclaration(val) != 0; if is_decl || is_available_externally { - let name = CStr::from_ptr(llvm::LLVMGetValueName(val)); - declared.insert(name); + let symbol_name = CStr::from_ptr(llvm::LLVMGetValueName(val)); + referenced_somewhere.insert(symbol_name); } } } + // Also collect all symbols for which we cannot adjust linkage, because + // it is fixed by some directive in the source code (e.g. #[no_mangle]). + let linkage_fixed_explicitly: FnvHashSet<_> = scx + .translation_items() + .borrow() + .iter() + .cloned() + .filter(|trans_item|{ + let def_id = match *trans_item { + TransItem::DropGlue(..) => { + return false + }, + TransItem::Fn(ref instance) => { + instance.def + } + TransItem::Static(node_id) => { + tcx.map.local_def_id(node_id) + } + }; + + trans_item.explicit_linkage(tcx).is_some() || + attr::contains_extern_indicator(tcx.sess.diagnostic(), + &tcx.get_attrs(def_id)) + }) + .map(|trans_item| symbol_map.get_or_compute(scx, trans_item)) + .collect(); + // Examine each external definition. If the definition is not used in // any other compilation unit, and is not reachable from other crates, // then give it internal linkage. - for ccx in cx.iter() { + for ccx in ccxs.iter() { for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) { let linkage = llvm::LLVMGetLinkage(val); @@ -2293,16 +2329,17 @@ fn internalize_symbols(cx: &CrateContextList, reachable: &HashSet<&str>) { if is_definition && is_externally_visible { let name_cstr = CStr::from_ptr(llvm::LLVMGetValueName(val)); let name_str = name_cstr.to_str().unwrap(); + let name_cow = Cow::Borrowed(name_str); - let is_referenced_somewhere = declared.contains(&name_cstr); - let is_reachable = reachable.contains(name_str); + let is_referenced_somewhere = referenced_somewhere.contains(&name_cstr); + let is_reachable = reachable.contains(&name_str); + let has_fixed_linkage = linkage_fixed_explicitly.contains(&name_cow); - if !is_referenced_somewhere && !is_reachable { + if !is_referenced_somewhere && !is_reachable && !has_fixed_linkage { llvm::SetLinkage(val, llvm::InternalLinkage); llvm::SetDLLStorageClass(val, llvm::DefaultStorageClass); llvm::UnsetComdat(val); } - } } } @@ -2616,8 +2653,13 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, })); } - internalize_symbols(&crate_context_list, - &reachable_symbols.iter().map(|x| &x[..]).collect()); + time(shared_ccx.sess().time_passes(), "internalize symbols", || { + internalize_symbols(&crate_context_list, + &symbol_map, + &reachable_symbols.iter() + .map(|s| &s[..]) + .collect()) + }); if sess.target.target.options.is_like_msvc && sess.crate_types.borrow().iter().any(|ct| *ct == config::CrateTypeRlib) { |
