Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

trans: Internalize symbols without relying on LLVM #43183

Merged
8 changes: 3 additions & 5 deletions src/librustc_trans/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use std::process::Command;
use context::SharedCrateContext;

use back::archive;
use back::symbol_export::{self, ExportedSymbols};
use back::symbol_export::ExportedSymbols;
use rustc::middle::dependency_format::Linkage;
use rustc::hir::def_id::{LOCAL_CRATE, CrateNum};
use rustc_back::LinkerFlavor;
Expand Down Expand Up @@ -687,10 +687,8 @@ fn exported_symbols(scx: &SharedCrateContext,
exported_symbols: &ExportedSymbols,
crate_type: CrateType)
-> Vec<String> {
let export_threshold = symbol_export::crate_export_threshold(crate_type);

let mut symbols = Vec::new();
exported_symbols.for_each_exported_symbol(LOCAL_CRATE, export_threshold, |name, _| {
exported_symbols.for_each_exported_symbol(LOCAL_CRATE, |name, _, _| {
symbols.push(name.to_owned());
});

Expand All @@ -702,7 +700,7 @@ fn exported_symbols(scx: &SharedCrateContext,
// For each dependency that we are linking to statically ...
if *dep_format == Linkage::Static {
// ... we add its symbol list to our export list.
exported_symbols.for_each_exported_symbol(cnum, export_threshold, |name, _| {
exported_symbols.for_each_exported_symbol(cnum, |name, _, _| {
symbols.push(name.to_owned());
})
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/back/lto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ pub fn run(cgcx: &CodegenContext,
let export_threshold =
symbol_export::crates_export_threshold(&cgcx.crate_types);

let symbol_filter = &|&(ref name, level): &(String, _)| {
let symbol_filter = &|&(ref name, _, level): &(String, _, _)| {
if symbol_export::is_below_threshold(level, export_threshold) {
let mut bytes = Vec::with_capacity(name.len() + 1);
bytes.extend(name.bytes());
Expand Down
112 changes: 72 additions & 40 deletions src/librustc_trans/back/symbol_export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use context::SharedCrateContext;
use monomorphize::Instance;
use rustc::util::nodemap::FxHashMap;
use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
use rustc::util::nodemap::{FxHashMap, NodeSet};
use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE, INVALID_CRATE, CRATE_DEF_INDEX};
use rustc::session::config;
use rustc::ty::TyCtxt;
use syntax::attr;
Expand All @@ -28,59 +27,87 @@ pub enum SymbolExportLevel {
}

/// The set of symbols exported from each crate in the crate graph.
#[derive(Debug)]
pub struct ExportedSymbols {
exports: FxHashMap<CrateNum, Vec<(String, SymbolExportLevel)>>,
pub export_threshold: SymbolExportLevel,
exports: FxHashMap<CrateNum, Vec<(String, DefId, SymbolExportLevel)>>,
local_exports: NodeSet,
}

impl ExportedSymbols {
pub fn empty() -> ExportedSymbols {
ExportedSymbols {
export_threshold: SymbolExportLevel::C,
exports: FxHashMap(),
local_exports: NodeSet(),
}
}

pub fn compute<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>) -> ExportedSymbols {
let mut local_crate: Vec<_> = scx
.exported_symbols()
pub fn compute<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
local_exported_symbols: &NodeSet)
-> ExportedSymbols {
let export_threshold = crates_export_threshold(&tcx.sess.crate_types.borrow());

let mut local_crate: Vec<_> = local_exported_symbols
.iter()
.map(|&node_id| {
scx.tcx().hir.local_def_id(node_id)
tcx.hir.local_def_id(node_id)
})
.map(|def_id| {
let name = scx.tcx().symbol_name(Instance::mono(scx.tcx(), def_id));
let export_level = export_level(scx, def_id);
let name = tcx.symbol_name(Instance::mono(tcx, def_id));
let export_level = export_level(tcx, def_id);
debug!("EXPORTED SYMBOL (local): {} ({:?})", name, export_level);
(str::to_owned(&name), export_level)
(str::to_owned(&name), def_id, export_level)
})
.collect();

if scx.sess().entry_fn.borrow().is_some() {
local_crate.push(("main".to_string(), SymbolExportLevel::C));
let mut local_exports = local_crate
.iter()
.filter_map(|&(_, def_id, level)| {
if is_below_threshold(level, export_threshold) {
tcx.hir.as_local_node_id(def_id)
} else {
None
}
})
.collect::<NodeSet>();

const INVALID_DEF_ID: DefId = DefId {
krate: INVALID_CRATE,
index: CRATE_DEF_INDEX,
};

if let Some(_) = *tcx.sess.entry_fn.borrow() {
local_crate.push(("main".to_string(),
INVALID_DEF_ID,
SymbolExportLevel::C));
}

if let Some(id) = scx.sess().derive_registrar_fn.get() {
let def_id = scx.tcx().hir.local_def_id(id);
if let Some(id) = tcx.sess.derive_registrar_fn.get() {
let def_id = tcx.hir.local_def_id(id);
let idx = def_id.index;
let disambiguator = scx.sess().local_crate_disambiguator();
let registrar = scx.sess().generate_derive_registrar_symbol(disambiguator, idx);
local_crate.push((registrar, SymbolExportLevel::C));
let disambiguator = tcx.sess.local_crate_disambiguator();
let registrar = tcx.sess.generate_derive_registrar_symbol(disambiguator, idx);
local_crate.push((registrar, def_id, SymbolExportLevel::C));
local_exports.insert(id);
}

if scx.sess().crate_types.borrow().contains(&config::CrateTypeDylib) {
local_crate.push((metadata_symbol_name(scx.tcx()),
if tcx.sess.crate_types.borrow().contains(&config::CrateTypeDylib) {
local_crate.push((metadata_symbol_name(tcx),
INVALID_DEF_ID,
SymbolExportLevel::Rust));
}

let mut exports = FxHashMap();
exports.insert(LOCAL_CRATE, local_crate);

for cnum in scx.sess().cstore.crates() {
for cnum in tcx.sess.cstore.crates() {
debug_assert!(cnum != LOCAL_CRATE);

// If this crate is a plugin and/or a custom derive crate, then
// we're not even going to link those in so we skip those crates.
if scx.sess().cstore.plugin_registrar_fn(cnum).is_some() ||
scx.sess().cstore.derive_registrar_fn(cnum).is_some() {
if tcx.sess.cstore.plugin_registrar_fn(cnum).is_some() ||
tcx.sess.cstore.derive_registrar_fn(cnum).is_some() {
continue;
}

Expand All @@ -92,16 +119,16 @@ impl ExportedSymbols {
// Down below we'll hardwire all of the symbols to the `Rust` export
// level instead.
let special_runtime_crate =
scx.tcx().is_panic_runtime(cnum.as_def_id()) ||
scx.sess().cstore.is_compiler_builtins(cnum);
tcx.is_panic_runtime(cnum.as_def_id()) ||
tcx.sess.cstore.is_compiler_builtins(cnum);

let crate_exports = scx
.sess()
let crate_exports = tcx
.sess
.cstore
.exported_symbols(cnum)
.iter()
.map(|&def_id| {
let name = scx.tcx().symbol_name(Instance::mono(scx.tcx(), def_id));
let name = tcx.symbol_name(Instance::mono(tcx, def_id));
let export_level = if special_runtime_crate {
// We can probably do better here by just ensuring that
// it has hidden visibility rather than public
Expand All @@ -118,35 +145,41 @@ impl ExportedSymbols {
SymbolExportLevel::Rust
}
} else {
export_level(scx, def_id)
export_level(tcx, def_id)
};
debug!("EXPORTED SYMBOL (re-export): {} ({:?})", name, export_level);
(str::to_owned(&name), export_level)
(str::to_owned(&name), def_id, export_level)
})
.collect();

exports.insert(cnum, crate_exports);
}

return ExportedSymbols {
exports: exports
export_threshold,
exports,
local_exports,
};

fn export_level(scx: &SharedCrateContext,
fn export_level(tcx: TyCtxt,
sym_def_id: DefId)
-> SymbolExportLevel {
let attrs = scx.tcx().get_attrs(sym_def_id);
if attr::contains_extern_indicator(scx.sess().diagnostic(), &attrs) {
let attrs = tcx.get_attrs(sym_def_id);
if attr::contains_extern_indicator(tcx.sess.diagnostic(), &attrs) {
SymbolExportLevel::C
} else {
SymbolExportLevel::Rust
}
}
}

pub fn local_exports(&self) -> &NodeSet {
&self.local_exports
}

pub fn exported_symbols(&self,
cnum: CrateNum)
-> &[(String, SymbolExportLevel)] {
-> &[(String, DefId, SymbolExportLevel)] {
match self.exports.get(&cnum) {
Some(exports) => exports,
None => &[]
Expand All @@ -155,13 +188,12 @@ impl ExportedSymbols {

pub fn for_each_exported_symbol<F>(&self,
cnum: CrateNum,
export_threshold: SymbolExportLevel,
mut f: F)
where F: FnMut(&str, SymbolExportLevel)
where F: FnMut(&str, DefId, SymbolExportLevel)
{
for &(ref name, export_level) in self.exported_symbols(cnum) {
if is_below_threshold(export_level, export_threshold) {
f(&name, export_level)
for &(ref name, def_id, export_level) in self.exported_symbols(cnum) {
if is_below_threshold(export_level, self.export_threshold) {
f(&name, def_id, export_level)
}
}
}
Expand Down
Loading