mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
rustc: Calculate ExportedSymbols
in a query
This commit moves the definition of the `ExportedSymbols` structure to the `rustc` crate and then creates a query that'll be used to construct the `ExportedSymbols` set. This in turn uses the reachablity query exposed in the previous commit.
This commit is contained in:
parent
baca9a6240
commit
dba3ddd8d4
@ -535,7 +535,7 @@ define_dep_nodes!( <'tcx>
|
||||
[] GetPanicStrategy(CrateNum),
|
||||
[] IsNoBuiltins(CrateNum),
|
||||
[] ImplDefaultness(DefId),
|
||||
[] ExportedSymbols(CrateNum),
|
||||
[] ExportedSymbolIds(CrateNum),
|
||||
[] NativeLibraries(CrateNum),
|
||||
[] PluginRegistrarFn(CrateNum),
|
||||
[] DeriveRegistrarFn(CrateNum),
|
||||
@ -575,6 +575,7 @@ define_dep_nodes!( <'tcx>
|
||||
[] MaybeUnusedExternCrates,
|
||||
[] StabilityIndex,
|
||||
[] AllCrateNums,
|
||||
[] ExportedSymbols,
|
||||
);
|
||||
|
||||
trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
|
||||
|
@ -92,6 +92,7 @@ pub mod middle {
|
||||
pub mod dependency_format;
|
||||
pub mod effect;
|
||||
pub mod entry;
|
||||
pub mod exported_symbols;
|
||||
pub mod free_region;
|
||||
pub mod intrinsicck;
|
||||
pub mod lang_items;
|
||||
|
77
src/librustc/middle/exported_symbols.rs
Normal file
77
src/librustc/middle/exported_symbols.rs
Normal file
@ -0,0 +1,77 @@
|
||||
// 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 util::nodemap::{FxHashMap, NodeSet};
|
||||
use hir::def_id::{DefId, CrateNum};
|
||||
|
||||
/// The SymbolExportLevel of a symbols specifies from which kinds of crates
|
||||
/// the symbol will be exported. `C` symbols will be exported from any
|
||||
/// kind of crate, including cdylibs which export very few things.
|
||||
/// `Rust` will only be exported if the crate produced is a Rust
|
||||
/// dylib.
|
||||
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
|
||||
pub enum SymbolExportLevel {
|
||||
C,
|
||||
Rust,
|
||||
}
|
||||
|
||||
/// The set of symbols exported from each crate in the crate graph.
|
||||
#[derive(Debug)]
|
||||
pub struct ExportedSymbols {
|
||||
pub export_threshold: SymbolExportLevel,
|
||||
exports: FxHashMap<CrateNum, Vec<(String, DefId, SymbolExportLevel)>>,
|
||||
local_exports: NodeSet,
|
||||
}
|
||||
|
||||
impl ExportedSymbols {
|
||||
pub fn new(export_threshold: SymbolExportLevel,
|
||||
exports: FxHashMap<CrateNum, Vec<(String, DefId, SymbolExportLevel)>>,
|
||||
local_exports: NodeSet) -> ExportedSymbols {
|
||||
ExportedSymbols {
|
||||
export_threshold,
|
||||
exports,
|
||||
local_exports,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn local_exports(&self) -> &NodeSet {
|
||||
&self.local_exports
|
||||
}
|
||||
|
||||
pub fn exported_symbols(&self, cnum: CrateNum)
|
||||
-> &[(String, DefId, SymbolExportLevel)]
|
||||
{
|
||||
match self.exports.get(&cnum) {
|
||||
Some(exports) => exports,
|
||||
None => &[]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn for_each_exported_symbol<F>(&self, cnum: CrateNum, mut f: F)
|
||||
where F: FnMut(&str, DefId, SymbolExportLevel)
|
||||
{
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_below_threshold(level: SymbolExportLevel,
|
||||
threshold: SymbolExportLevel)
|
||||
-> bool {
|
||||
if threshold == SymbolExportLevel::Rust {
|
||||
// We export everything from Rust dylibs
|
||||
true
|
||||
} else {
|
||||
level == SymbolExportLevel::C
|
||||
}
|
||||
}
|
@ -27,6 +27,7 @@ use middle::cstore::EncodedMetadata;
|
||||
use middle::free_region::FreeRegionMap;
|
||||
use middle::lang_items;
|
||||
use middle::resolve_lifetime::{self, ObjectLifetimeDefault};
|
||||
use middle::exported_symbols::ExportedSymbols;
|
||||
use middle::stability;
|
||||
use mir::Mir;
|
||||
use mir::transform::Passes;
|
||||
@ -64,6 +65,7 @@ use std::mem;
|
||||
use std::ops::Deref;
|
||||
use std::iter;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use syntax::abi;
|
||||
use syntax::ast::{self, Name, NodeId};
|
||||
use syntax::attr;
|
||||
@ -1218,6 +1220,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn crate_data_as_rc_any(self, cnum: CrateNum) -> Rc<Any> {
|
||||
self.cstore.crate_data_as_rc_any(cnum)
|
||||
}
|
||||
|
||||
pub fn exported_symbols(self) -> Arc<ExportedSymbols> {
|
||||
self.exported_symbol_set(LOCAL_CRATE)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||
|
@ -23,6 +23,7 @@ use middle::region;
|
||||
use middle::resolve_lifetime::{Region, ObjectLifetimeDefault};
|
||||
use middle::stability::{self, DeprecationEntry};
|
||||
use middle::lang_items::{LanguageItems, LangItem};
|
||||
use middle::exported_symbols::ExportedSymbols;
|
||||
use mir;
|
||||
use mir::transform::{MirSuite, MirPassIndex};
|
||||
use session::CompileResult;
|
||||
@ -48,6 +49,7 @@ use std::mem;
|
||||
use std::collections::BTreeMap;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use syntax::attr;
|
||||
use syntax::ast;
|
||||
@ -595,7 +597,7 @@ impl<'tcx> QueryDescription for queries::is_sanitizer_runtime<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::exported_symbols<'tcx> {
|
||||
impl<'tcx> QueryDescription for queries::exported_symbol_ids<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("looking up the exported symbols of a crate")
|
||||
}
|
||||
@ -745,6 +747,12 @@ impl<'tcx> QueryDescription for queries::all_crate_nums<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::exported_symbol_set<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("exported symbol set")
|
||||
}
|
||||
}
|
||||
|
||||
// If enabled, send a message to the profile-queries thread
|
||||
macro_rules! profq_msg {
|
||||
($tcx:expr, $msg:expr) => {
|
||||
@ -1322,7 +1330,7 @@ define_maps! { <'tcx>
|
||||
[] fn lint_levels: lint_levels_node(CrateNum) -> Rc<lint::LintLevelMap>,
|
||||
|
||||
[] fn impl_defaultness: ImplDefaultness(DefId) -> hir::Defaultness,
|
||||
[] fn exported_symbols: ExportedSymbols(CrateNum) -> Rc<Vec<DefId>>,
|
||||
[] fn exported_symbol_ids: ExportedSymbolIds(CrateNum) -> Rc<Vec<DefId>>,
|
||||
[] fn native_libraries: NativeLibraries(CrateNum) -> Rc<Vec<NativeLibrary>>,
|
||||
[] fn plugin_registrar_fn: PluginRegistrarFn(CrateNum) -> Option<DefId>,
|
||||
[] fn derive_registrar_fn: DeriveRegistrarFn(CrateNum) -> Option<DefId>,
|
||||
@ -1371,6 +1379,9 @@ define_maps! { <'tcx>
|
||||
|
||||
[] fn stability_index: stability_index_node(CrateNum) -> Rc<stability::Index<'tcx>>,
|
||||
[] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Rc<Vec<CrateNum>>,
|
||||
|
||||
[] fn exported_symbol_set: exported_symbol_set_node(CrateNum)
|
||||
-> Arc<ExportedSymbols>,
|
||||
}
|
||||
|
||||
fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> {
|
||||
@ -1484,3 +1495,7 @@ fn stability_index_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
|
||||
fn all_crate_nums_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
|
||||
DepConstructor::AllCrateNums
|
||||
}
|
||||
|
||||
fn exported_symbol_set_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
|
||||
DepConstructor::ExportedSymbols
|
||||
}
|
||||
|
@ -956,7 +956,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
||||
mir::provide(&mut local_providers);
|
||||
reachable::provide(&mut local_providers);
|
||||
rustc_privacy::provide(&mut local_providers);
|
||||
trans::provide(&mut local_providers);
|
||||
trans::provide_local(&mut local_providers);
|
||||
typeck::provide(&mut local_providers);
|
||||
ty::provide(&mut local_providers);
|
||||
traits::provide(&mut local_providers);
|
||||
@ -968,7 +968,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
||||
|
||||
let mut extern_providers = ty::maps::Providers::default();
|
||||
cstore::provide(&mut extern_providers);
|
||||
trans::provide(&mut extern_providers);
|
||||
trans::provide_extern(&mut extern_providers);
|
||||
ty::provide_extern(&mut extern_providers);
|
||||
traits::provide_extern(&mut extern_providers);
|
||||
// FIXME(eddyb) get rid of this once we replace const_eval with miri.
|
||||
|
@ -175,7 +175,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
|
||||
extern_crate => { Rc::new(cdata.extern_crate.get()) }
|
||||
is_no_builtins => { cdata.is_no_builtins() }
|
||||
impl_defaultness => { cdata.get_impl_defaultness(def_id.index) }
|
||||
exported_symbols => { Rc::new(cdata.get_exported_symbols()) }
|
||||
exported_symbol_ids => { Rc::new(cdata.get_exported_symbols()) }
|
||||
native_libraries => { Rc::new(cdata.get_native_libraries()) }
|
||||
plugin_registrar_fn => {
|
||||
cdata.root.plugin_registrar_fn.map(|index| {
|
||||
|
@ -19,8 +19,8 @@ use context::SharedCrateContext;
|
||||
|
||||
use back::archive;
|
||||
use back::command::Command;
|
||||
use back::symbol_export::ExportedSymbols;
|
||||
use rustc::middle::dependency_format::Linkage;
|
||||
use rustc::middle::exported_symbols::ExportedSymbols;
|
||||
use rustc::hir::def_id::{LOCAL_CRATE, CrateNum};
|
||||
use rustc_back::LinkerFlavor;
|
||||
use rustc::session::Session;
|
||||
|
@ -16,6 +16,7 @@ use errors::{FatalError, Handler};
|
||||
use llvm;
|
||||
use llvm::archive_ro::ArchiveRO;
|
||||
use llvm::{ModuleRef, TargetMachineRef, True, False};
|
||||
use rustc::middle::exported_symbols;
|
||||
use rustc::util::common::time;
|
||||
use rustc::util::common::path2cstr;
|
||||
use rustc::hir::def_id::LOCAL_CRATE;
|
||||
@ -68,7 +69,7 @@ pub fn run(cgcx: &CodegenContext,
|
||||
symbol_export::crates_export_threshold(&cgcx.crate_types);
|
||||
|
||||
let symbol_filter = &|&(ref name, _, level): &(String, _, _)| {
|
||||
if symbol_export::is_below_threshold(level, export_threshold) {
|
||||
if exported_symbols::is_below_threshold(level, export_threshold) {
|
||||
let mut bytes = Vec::with_capacity(name.len() + 1);
|
||||
bytes.extend(name.bytes());
|
||||
Some(CString::new(bytes).unwrap())
|
||||
|
@ -8,199 +8,143 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use base;
|
||||
use monomorphize::Instance;
|
||||
use rustc::util::nodemap::{FxHashMap, NodeSet};
|
||||
use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE, INVALID_CRATE, CRATE_DEF_INDEX};
|
||||
use rustc::hir::def_id::{DefId, LOCAL_CRATE, INVALID_CRATE, CRATE_DEF_INDEX};
|
||||
use rustc::session::config;
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc_allocator::ALLOCATOR_METHODS;
|
||||
use rustc::middle::exported_symbols::{ExportedSymbols, SymbolExportLevel};
|
||||
use rustc::middle::exported_symbols::is_below_threshold;
|
||||
use syntax::attr;
|
||||
|
||||
/// The SymbolExportLevel of a symbols specifies from which kinds of crates
|
||||
/// the symbol will be exported. `C` symbols will be exported from any
|
||||
/// kind of crate, including cdylibs which export very few things.
|
||||
/// `Rust` will only be exported if the crate produced is a Rust
|
||||
/// dylib.
|
||||
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
|
||||
pub enum SymbolExportLevel {
|
||||
C,
|
||||
Rust,
|
||||
}
|
||||
pub fn compute<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ExportedSymbols {
|
||||
let export_threshold = crates_export_threshold(&tcx.sess.crate_types.borrow());
|
||||
let local_exported_symbols = base::find_exported_symbols(tcx);
|
||||
|
||||
/// The set of symbols exported from each crate in the crate graph.
|
||||
#[derive(Debug)]
|
||||
pub struct ExportedSymbols {
|
||||
pub export_threshold: SymbolExportLevel,
|
||||
exports: FxHashMap<CrateNum, Vec<(String, DefId, SymbolExportLevel)>>,
|
||||
local_exports: NodeSet,
|
||||
}
|
||||
let mut local_crate: Vec<_> = local_exported_symbols
|
||||
.iter()
|
||||
.map(|&node_id| {
|
||||
tcx.hir.local_def_id(node_id)
|
||||
})
|
||||
.map(|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), def_id, export_level)
|
||||
})
|
||||
.collect();
|
||||
|
||||
impl ExportedSymbols {
|
||||
pub fn empty() -> ExportedSymbols {
|
||||
ExportedSymbols {
|
||||
export_threshold: SymbolExportLevel::C,
|
||||
exports: FxHashMap(),
|
||||
local_exports: NodeSet(),
|
||||
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 tcx.sess.allocator_kind.get().is_some() {
|
||||
for method in ALLOCATOR_METHODS {
|
||||
local_crate.push((format!("__rust_{}", method.name),
|
||||
INVALID_DEF_ID,
|
||||
SymbolExportLevel::Rust));
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
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 = 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);
|
||||
}
|
||||
|
||||
let mut local_crate: Vec<_> = local_exported_symbols
|
||||
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 tcx.crates().iter() {
|
||||
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 tcx.plugin_registrar_fn(cnum).is_some() ||
|
||||
tcx.derive_registrar_fn(cnum).is_some() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check to see if this crate is a "special runtime crate". These
|
||||
// crates, implementation details of the standard library, typically
|
||||
// have a bunch of `pub extern` and `#[no_mangle]` functions as the
|
||||
// ABI between them. We don't want their symbols to have a `C`
|
||||
// export level, however, as they're just implementation details.
|
||||
// Down below we'll hardwire all of the symbols to the `Rust` export
|
||||
// level instead.
|
||||
let special_runtime_crate =
|
||||
tcx.is_panic_runtime(cnum) || tcx.is_compiler_builtins(cnum);
|
||||
|
||||
let crate_exports = tcx
|
||||
.exported_symbol_ids(cnum)
|
||||
.iter()
|
||||
.map(|&node_id| {
|
||||
tcx.hir.local_def_id(node_id)
|
||||
})
|
||||
.map(|def_id| {
|
||||
.map(|&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);
|
||||
let export_level = if special_runtime_crate {
|
||||
// We can probably do better here by just ensuring that
|
||||
// it has hidden visibility rather than public
|
||||
// visibility, as this is primarily here to ensure it's
|
||||
// not stripped during LTO.
|
||||
//
|
||||
// In general though we won't link right if these
|
||||
// symbols are stripped, and LTO currently strips them.
|
||||
if &*name == "rust_eh_personality" ||
|
||||
&*name == "rust_eh_register_frames" ||
|
||||
&*name == "rust_eh_unregister_frames" {
|
||||
SymbolExportLevel::C
|
||||
} else {
|
||||
SymbolExportLevel::Rust
|
||||
}
|
||||
} else {
|
||||
export_level(tcx, def_id)
|
||||
};
|
||||
debug!("EXPORTED SYMBOL (re-export): {} ({:?})", name, export_level);
|
||||
(str::to_owned(&name), def_id, export_level)
|
||||
})
|
||||
.collect();
|
||||
|
||||
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 tcx.sess.allocator_kind.get().is_some() {
|
||||
for method in ALLOCATOR_METHODS {
|
||||
local_crate.push((format!("__rust_{}", method.name),
|
||||
INVALID_DEF_ID,
|
||||
SymbolExportLevel::Rust));
|
||||
}
|
||||
}
|
||||
|
||||
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 = 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 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 tcx.crates().iter() {
|
||||
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 tcx.plugin_registrar_fn(cnum).is_some() ||
|
||||
tcx.derive_registrar_fn(cnum).is_some() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check to see if this crate is a "special runtime crate". These
|
||||
// crates, implementation details of the standard library, typically
|
||||
// have a bunch of `pub extern` and `#[no_mangle]` functions as the
|
||||
// ABI between them. We don't want their symbols to have a `C`
|
||||
// export level, however, as they're just implementation details.
|
||||
// Down below we'll hardwire all of the symbols to the `Rust` export
|
||||
// level instead.
|
||||
let special_runtime_crate =
|
||||
tcx.is_panic_runtime(cnum) || tcx.is_compiler_builtins(cnum);
|
||||
|
||||
let crate_exports = tcx
|
||||
.exported_symbols(cnum)
|
||||
.iter()
|
||||
.map(|&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
|
||||
// visibility, as this is primarily here to ensure it's
|
||||
// not stripped during LTO.
|
||||
//
|
||||
// In general though we won't link right if these
|
||||
// symbols are stripped, and LTO currently strips them.
|
||||
if &*name == "rust_eh_personality" ||
|
||||
&*name == "rust_eh_register_frames" ||
|
||||
&*name == "rust_eh_unregister_frames" {
|
||||
SymbolExportLevel::C
|
||||
} else {
|
||||
SymbolExportLevel::Rust
|
||||
}
|
||||
} else {
|
||||
export_level(tcx, def_id)
|
||||
};
|
||||
debug!("EXPORTED SYMBOL (re-export): {} ({:?})", name, export_level);
|
||||
(str::to_owned(&name), def_id, export_level)
|
||||
})
|
||||
.collect();
|
||||
|
||||
exports.insert(cnum, crate_exports);
|
||||
}
|
||||
|
||||
return ExportedSymbols {
|
||||
export_threshold,
|
||||
exports,
|
||||
local_exports,
|
||||
};
|
||||
|
||||
fn export_level(tcx: TyCtxt,
|
||||
sym_def_id: DefId)
|
||||
-> SymbolExportLevel {
|
||||
let attrs = tcx.get_attrs(sym_def_id);
|
||||
if attr::contains_extern_indicator(tcx.sess.diagnostic(), &attrs) {
|
||||
SymbolExportLevel::C
|
||||
} else {
|
||||
SymbolExportLevel::Rust
|
||||
}
|
||||
}
|
||||
exports.insert(cnum, crate_exports);
|
||||
}
|
||||
|
||||
pub fn local_exports(&self) -> &NodeSet {
|
||||
&self.local_exports
|
||||
}
|
||||
return ExportedSymbols::new(export_threshold, exports, local_exports);
|
||||
|
||||
pub fn exported_symbols(&self,
|
||||
cnum: CrateNum)
|
||||
-> &[(String, DefId, SymbolExportLevel)] {
|
||||
match self.exports.get(&cnum) {
|
||||
Some(exports) => exports,
|
||||
None => &[]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn for_each_exported_symbol<F>(&self,
|
||||
cnum: CrateNum,
|
||||
mut f: F)
|
||||
where F: FnMut(&str, DefId, SymbolExportLevel)
|
||||
{
|
||||
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)
|
||||
}
|
||||
fn export_level(tcx: TyCtxt,
|
||||
sym_def_id: DefId)
|
||||
-> SymbolExportLevel {
|
||||
let attrs = tcx.get_attrs(sym_def_id);
|
||||
if attr::contains_extern_indicator(tcx.sess.diagnostic(), &attrs) {
|
||||
SymbolExportLevel::C
|
||||
} else {
|
||||
SymbolExportLevel::Rust
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -233,14 +177,3 @@ pub fn crates_export_threshold(crate_types: &[config::CrateType])
|
||||
SymbolExportLevel::C
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_below_threshold(level: SymbolExportLevel,
|
||||
threshold: SymbolExportLevel)
|
||||
-> bool {
|
||||
if threshold == SymbolExportLevel::Rust {
|
||||
// We export everything from Rust dylibs
|
||||
true
|
||||
} else {
|
||||
level == SymbolExportLevel::C
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
use back::lto;
|
||||
use back::link::{self, get_linker, remove};
|
||||
use back::linker::LinkerInfo;
|
||||
use back::symbol_export::ExportedSymbols;
|
||||
use rustc::middle::exported_symbols::ExportedSymbols;
|
||||
use rustc_incremental::{save_trans_partition, in_incr_comp_dir};
|
||||
use rustc::dep_graph::DepGraph;
|
||||
use rustc::middle::cstore::{LinkMeta, EncodedMetadata};
|
||||
|
@ -31,7 +31,7 @@ use super::ModuleKind;
|
||||
use assert_module_sources;
|
||||
use back::link;
|
||||
use back::linker::LinkerInfo;
|
||||
use back::symbol_export::{self, ExportedSymbols};
|
||||
use back::symbol_export;
|
||||
use back::write::{self, OngoingCrateTranslation};
|
||||
use llvm::{ContextRef, Linkage, ModuleRef, ValueRef, Vector, get_param};
|
||||
use llvm;
|
||||
@ -42,6 +42,7 @@ use rustc::middle::cstore::{EncodedMetadata, EncodedMetadataHashes};
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::dep_graph::AssertDepGraphSafe;
|
||||
use rustc::middle::cstore::{self, LinkMeta, LinkagePreference};
|
||||
use rustc::middle::exported_symbols::{ExportedSymbols, SymbolExportLevel};
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::util::common::{time, print_time_passes_entry};
|
||||
use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType};
|
||||
@ -973,7 +974,11 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
// Skip crate items and just output metadata in -Z no-trans mode.
|
||||
if tcx.sess.opts.debugging_opts.no_trans ||
|
||||
!tcx.sess.opts.output_types.should_trans() {
|
||||
let empty_exported_symbols = ExportedSymbols::empty();
|
||||
let empty_exported_symbols = ExportedSymbols::new(
|
||||
SymbolExportLevel::C,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
);
|
||||
let linker_info = LinkerInfo::new(&shared_ccx, &empty_exported_symbols);
|
||||
let ongoing_translation = write::start_async_translation(
|
||||
tcx.sess,
|
||||
@ -1001,13 +1006,12 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
return ongoing_translation;
|
||||
}
|
||||
|
||||
let exported_symbols = Arc::new(ExportedSymbols::compute(tcx,
|
||||
&exported_symbol_node_ids));
|
||||
let exported_symbols = tcx.exported_symbols();
|
||||
|
||||
// Run the translation item collector and partition the collected items into
|
||||
// codegen units.
|
||||
let (translation_items, codegen_units) =
|
||||
collect_and_partition_translation_items(&shared_ccx, &exported_symbols);
|
||||
collect_and_partition_translation_items(shared_ccx.tcx(), &exported_symbols);
|
||||
|
||||
assert!(codegen_units.len() <= 1 || !tcx.sess.lto());
|
||||
|
||||
@ -1394,13 +1398,13 @@ fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trans_i
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
fn collect_and_partition_translation_items<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
exported_symbols: &ExportedSymbols)
|
||||
-> (FxHashSet<TransItem<'tcx>>,
|
||||
Vec<CodegenUnit<'tcx>>) {
|
||||
let time_passes = scx.sess().time_passes();
|
||||
let time_passes = tcx.sess.time_passes();
|
||||
|
||||
let collection_mode = match scx.sess().opts.debugging_opts.print_trans_items {
|
||||
let collection_mode = match tcx.sess.opts.debugging_opts.print_trans_items {
|
||||
Some(ref s) => {
|
||||
let mode_string = s.to_lowercase();
|
||||
let mode_string = mode_string.trim();
|
||||
@ -1411,7 +1415,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
|
||||
let message = format!("Unknown codegen-item collection mode '{}'. \
|
||||
Falling back to 'lazy' mode.",
|
||||
mode_string);
|
||||
scx.sess().warn(&message);
|
||||
tcx.sess.warn(&message);
|
||||
}
|
||||
|
||||
TransItemCollectionMode::Lazy
|
||||
@ -1422,33 +1426,33 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
|
||||
|
||||
let (items, inlining_map) =
|
||||
time(time_passes, "translation item collection", || {
|
||||
collector::collect_crate_translation_items(scx.tcx(),
|
||||
collector::collect_crate_translation_items(tcx,
|
||||
exported_symbols,
|
||||
collection_mode)
|
||||
});
|
||||
|
||||
assert_symbols_are_distinct(scx.tcx(), items.iter());
|
||||
assert_symbols_are_distinct(tcx, items.iter());
|
||||
|
||||
let strategy = if scx.sess().opts.debugging_opts.incremental.is_some() {
|
||||
let strategy = if tcx.sess.opts.debugging_opts.incremental.is_some() {
|
||||
PartitioningStrategy::PerModule
|
||||
} else {
|
||||
PartitioningStrategy::FixedUnitCount(scx.sess().opts.cg.codegen_units)
|
||||
PartitioningStrategy::FixedUnitCount(tcx.sess.opts.cg.codegen_units)
|
||||
};
|
||||
|
||||
let codegen_units = time(time_passes, "codegen unit partitioning", || {
|
||||
partitioning::partition(scx.tcx(),
|
||||
partitioning::partition(tcx,
|
||||
items.iter().cloned(),
|
||||
strategy,
|
||||
&inlining_map,
|
||||
exported_symbols)
|
||||
});
|
||||
|
||||
assert!(scx.tcx().sess.opts.cg.codegen_units == codegen_units.len() ||
|
||||
scx.tcx().sess.opts.debugging_opts.incremental.is_some());
|
||||
assert!(tcx.sess.opts.cg.codegen_units == codegen_units.len() ||
|
||||
tcx.sess.opts.debugging_opts.incremental.is_some());
|
||||
|
||||
let translation_items: FxHashSet<TransItem<'tcx>> = items.iter().cloned().collect();
|
||||
|
||||
if scx.sess().opts.debugging_opts.print_trans_items.is_some() {
|
||||
if tcx.sess.opts.debugging_opts.print_trans_items.is_some() {
|
||||
let mut item_to_cgus = FxHashMap();
|
||||
|
||||
for cgu in &codegen_units {
|
||||
@ -1462,7 +1466,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.tcx());
|
||||
let mut output = i.to_string(tcx);
|
||||
output.push_str(" @@");
|
||||
let mut empty = Vec::new();
|
||||
let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
|
||||
|
@ -194,6 +194,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc::middle::exported_symbols::ExportedSymbols;
|
||||
use rustc::middle::lang_items::{ExchangeMallocFnLangItem};
|
||||
use rustc::traits;
|
||||
use rustc::ty::subst::Substs;
|
||||
@ -209,7 +210,6 @@ use rustc::util::nodemap::{FxHashSet, FxHashMap, DefIdMap};
|
||||
use trans_item::{TransItem, DefPathBasedNames, InstantiationMode};
|
||||
|
||||
use rustc_data_structures::bitvec::BitVector;
|
||||
use back::symbol_export::ExportedSymbols;
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
|
||||
pub enum TransItemCollectionMode {
|
||||
|
@ -14,10 +14,10 @@ use llvm::{ContextRef, ModuleRef, ValueRef};
|
||||
use rustc::dep_graph::{DepGraph, DepGraphSafe};
|
||||
use rustc::hir;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::middle::exported_symbols::ExportedSymbols;
|
||||
use rustc::traits;
|
||||
use debuginfo;
|
||||
use callee;
|
||||
use back::symbol_export::ExportedSymbols;
|
||||
use base;
|
||||
use declare;
|
||||
use monomorphize::Instance;
|
||||
|
@ -64,16 +64,17 @@ extern crate serialize;
|
||||
extern crate gcc; // Used to locate MSVC, not gcc :)
|
||||
|
||||
pub use base::trans_crate;
|
||||
pub use back::symbol_names::provide;
|
||||
|
||||
pub use metadata::LlvmMetadataLoader;
|
||||
pub use llvm_util::{init, target_features, print_version, print_passes, print, enable_llvm_debug};
|
||||
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc::hir::def_id::CrateNum;
|
||||
use rustc::util::nodemap::{FxHashSet, FxHashMap};
|
||||
use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
|
||||
use rustc::middle::cstore::{NativeLibrary, CrateSource, LibSource};
|
||||
use rustc::ty::maps::Providers;
|
||||
use rustc::util::nodemap::{FxHashSet, FxHashMap};
|
||||
|
||||
pub mod back {
|
||||
mod archive;
|
||||
@ -247,3 +248,15 @@ pub struct CrateInfo {
|
||||
}
|
||||
|
||||
__build_diagnostic_array! { librustc_trans, DIAGNOSTICS }
|
||||
|
||||
pub fn provide_local(providers: &mut Providers) {
|
||||
back::symbol_names::provide(providers);
|
||||
providers.exported_symbol_set = |tcx, cnum| {
|
||||
assert_eq!(cnum, LOCAL_CRATE);
|
||||
Arc::new(back::symbol_export::compute(tcx))
|
||||
};
|
||||
}
|
||||
|
||||
pub fn provide_extern(providers: &mut Providers) {
|
||||
back::symbol_names::provide(providers);
|
||||
}
|
||||
|
@ -102,7 +102,6 @@
|
||||
//! source-level module, functions from the same module will be available for
|
||||
//! inlining, even when they are not marked #[inline].
|
||||
|
||||
use back::symbol_export::ExportedSymbols;
|
||||
use collector::InliningMap;
|
||||
use common;
|
||||
use context::SharedCrateContext;
|
||||
@ -110,6 +109,7 @@ use llvm;
|
||||
use rustc::dep_graph::{DepNode, WorkProductId};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::map::DefPathData;
|
||||
use rustc::middle::exported_symbols::ExportedSymbols;
|
||||
use rustc::session::config::NUMBERED_CODEGEN_UNIT_MARKER;
|
||||
use rustc::ty::{self, TyCtxt, InstanceDef};
|
||||
use rustc::ty::item_path::characteristic_def_id_of_type;
|
||||
|
Loading…
Reference in New Issue
Block a user