Skip to content

Commit af87681

Browse files
authored
Auto merge of #34917 - michaelwoerister:fix-internalize-symbols, r=eddyb
Fix wrong condition in base::internalize_symbols(). Fix a typo that snuck into #34899 (and completely broke `internalize_symbols()`).
2 parents d15e265 + ecc1295 commit af87681

File tree

2 files changed

+78
-16
lines changed

2 files changed

+78
-16
lines changed

src/librustc_trans/base.rs

+58-16
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,14 @@ use value::Value;
8989
use Disr;
9090
use util::common::indenter;
9191
use util::sha2::Sha256;
92-
use util::nodemap::{NodeMap, NodeSet};
92+
use util::nodemap::{NodeMap, NodeSet, FnvHashSet};
9393

9494
use arena::TypedArena;
9595
use libc::c_uint;
9696
use std::ffi::{CStr, CString};
97+
use std::borrow::Cow;
9798
use std::cell::{Cell, RefCell};
98-
use std::collections::{HashMap, HashSet};
99+
use std::collections::HashMap;
99100
use std::ptr;
100101
use std::rc::Rc;
101102
use std::str;
@@ -2256,12 +2257,20 @@ fn write_metadata(cx: &SharedCrateContext,
22562257

22572258
/// Find any symbols that are defined in one compilation unit, but not declared
22582259
/// in any other compilation unit. Give these symbols internal linkage.
2259-
fn internalize_symbols(cx: &CrateContextList, reachable: &HashSet<&str>) {
2260+
fn internalize_symbols<'a, 'tcx>(ccxs: &CrateContextList<'a, 'tcx>,
2261+
symbol_map: &SymbolMap<'tcx>,
2262+
reachable: &FnvHashSet<&str>) {
2263+
let scx = ccxs.shared();
2264+
let tcx = scx.tcx();
2265+
2266+
// 'unsafe' because we are holding on to CStr's from the LLVM module within
2267+
// this block.
22602268
unsafe {
2261-
let mut declared = HashSet::new();
2269+
let mut referenced_somewhere = FnvHashSet();
22622270

2263-
// Collect all external declarations in all compilation units.
2264-
for ccx in cx.iter() {
2271+
// Collect all symbols that need to stay externally visible because they
2272+
// are referenced via a declaration in some other codegen unit.
2273+
for ccx in ccxs.iter() {
22652274
for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) {
22662275
let linkage = llvm::LLVMGetLinkage(val);
22672276
// We only care about external declarations (not definitions)
@@ -2270,39 +2279,67 @@ fn internalize_symbols(cx: &CrateContextList, reachable: &HashSet<&str>) {
22702279
let is_decl = llvm::LLVMIsDeclaration(val) != 0;
22712280

22722281
if is_decl || is_available_externally {
2273-
let name = CStr::from_ptr(llvm::LLVMGetValueName(val));
2274-
declared.insert(name);
2282+
let symbol_name = CStr::from_ptr(llvm::LLVMGetValueName(val));
2283+
referenced_somewhere.insert(symbol_name);
22752284
}
22762285
}
22772286
}
22782287

2288+
// Also collect all symbols for which we cannot adjust linkage, because
2289+
// it is fixed by some directive in the source code (e.g. #[no_mangle]).
2290+
let linkage_fixed_explicitly: FnvHashSet<_> = scx
2291+
.translation_items()
2292+
.borrow()
2293+
.iter()
2294+
.cloned()
2295+
.filter(|trans_item|{
2296+
let def_id = match *trans_item {
2297+
TransItem::DropGlue(..) => {
2298+
return false
2299+
},
2300+
TransItem::Fn(ref instance) => {
2301+
instance.def
2302+
}
2303+
TransItem::Static(node_id) => {
2304+
tcx.map.local_def_id(node_id)
2305+
}
2306+
};
2307+
2308+
trans_item.explicit_linkage(tcx).is_some() ||
2309+
attr::contains_extern_indicator(tcx.sess.diagnostic(),
2310+
&tcx.get_attrs(def_id))
2311+
})
2312+
.map(|trans_item| symbol_map.get_or_compute(scx, trans_item))
2313+
.collect();
2314+
22792315
// Examine each external definition. If the definition is not used in
22802316
// any other compilation unit, and is not reachable from other crates,
22812317
// then give it internal linkage.
2282-
for ccx in cx.iter() {
2318+
for ccx in ccxs.iter() {
22832319
for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) {
22842320
let linkage = llvm::LLVMGetLinkage(val);
22852321

22862322
let is_externally_visible = (linkage == llvm::ExternalLinkage as c_uint) ||
22872323
(linkage == llvm::LinkOnceODRLinkage as c_uint) ||
22882324
(linkage == llvm::WeakODRLinkage as c_uint);
2289-
let is_definition = llvm::LLVMIsDeclaration(val) != 0;
2325+
let is_definition = llvm::LLVMIsDeclaration(val) == 0;
22902326

22912327
// If this is a definition (as opposed to just a declaration)
22922328
// and externally visible, check if we can internalize it
22932329
if is_definition && is_externally_visible {
22942330
let name_cstr = CStr::from_ptr(llvm::LLVMGetValueName(val));
22952331
let name_str = name_cstr.to_str().unwrap();
2332+
let name_cow = Cow::Borrowed(name_str);
22962333

2297-
let is_referenced_somewhere = declared.contains(&name_cstr);
2298-
let is_reachable = reachable.contains(name_str);
2334+
let is_referenced_somewhere = referenced_somewhere.contains(&name_cstr);
2335+
let is_reachable = reachable.contains(&name_str);
2336+
let has_fixed_linkage = linkage_fixed_explicitly.contains(&name_cow);
22992337

2300-
if !is_referenced_somewhere && !is_reachable {
2338+
if !is_referenced_somewhere && !is_reachable && !has_fixed_linkage {
23012339
llvm::SetLinkage(val, llvm::InternalLinkage);
23022340
llvm::SetDLLStorageClass(val, llvm::DefaultStorageClass);
23032341
llvm::UnsetComdat(val);
23042342
}
2305-
23062343
}
23072344
}
23082345
}
@@ -2616,8 +2653,13 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
26162653
}));
26172654
}
26182655

2619-
internalize_symbols(&crate_context_list,
2620-
&reachable_symbols.iter().map(|x| &x[..]).collect());
2656+
time(shared_ccx.sess().time_passes(), "internalize symbols", || {
2657+
internalize_symbols(&crate_context_list,
2658+
&symbol_map,
2659+
&reachable_symbols.iter()
2660+
.map(|s| &s[..])
2661+
.collect())
2662+
});
26212663

26222664
if sess.target.target.options.is_like_msvc &&
26232665
sess.crate_types.borrow().iter().any(|ct| *ct == config::CrateTypeRlib) {
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: -C no-prepopulate-passes
12+
13+
pub fn main() {
14+
15+
// We want to make sure that closures get 'internal' linkage instead of
16+
// 'weak_odr' when they are not shared between codegen units
17+
// CHECK: define internal {{.*}}_ZN20internalize_closures4main{{.*}}$u7b$$u7b$closure$u7d$$u7d$
18+
let c = |x:i32| { x + 1 };
19+
let _ = c(1);
20+
}

0 commit comments

Comments
 (0)