rustc: Make trans collect/partition a query
This commit moves the `collect_and_partition_translation_items` function into a query on `TyCtxt` instead of a free function in trans, allowing us to track dependencies and such of the function.
This commit is contained in:
parent
dba3ddd8d4
commit
132bde7cf1
12 changed files with 352 additions and 248 deletions
|
@ -576,6 +576,7 @@ define_dep_nodes!( <'tcx>
|
||||||
[] StabilityIndex,
|
[] StabilityIndex,
|
||||||
[] AllCrateNums,
|
[] AllCrateNums,
|
||||||
[] ExportedSymbols,
|
[] ExportedSymbols,
|
||||||
|
[] CollectAndPartitionTranslationItems,
|
||||||
);
|
);
|
||||||
|
|
||||||
trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
|
trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
|
||||||
|
|
|
@ -104,6 +104,7 @@ pub mod middle {
|
||||||
pub mod recursion_limit;
|
pub mod recursion_limit;
|
||||||
pub mod resolve_lifetime;
|
pub mod resolve_lifetime;
|
||||||
pub mod stability;
|
pub mod stability;
|
||||||
|
pub mod trans;
|
||||||
pub mod weak_lang_items;
|
pub mod weak_lang_items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
69
src/librustc/middle/trans.rs
Normal file
69
src/librustc/middle/trans.rs
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
use syntax::ast::NodeId;
|
||||||
|
use syntax::symbol::InternedString;
|
||||||
|
use ty::Instance;
|
||||||
|
use util::nodemap::FxHashMap;
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
|
||||||
|
pub enum TransItem<'tcx> {
|
||||||
|
Fn(Instance<'tcx>),
|
||||||
|
Static(NodeId),
|
||||||
|
GlobalAsm(NodeId),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CodegenUnit<'tcx> {
|
||||||
|
/// A name for this CGU. Incremental compilation requires that
|
||||||
|
/// name be unique amongst **all** crates. Therefore, it should
|
||||||
|
/// contain something unique to this crate (e.g., a module path)
|
||||||
|
/// as well as the crate name and disambiguator.
|
||||||
|
name: InternedString,
|
||||||
|
items: FxHashMap<TransItem<'tcx>, (Linkage, Visibility)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
|
pub enum Linkage {
|
||||||
|
External,
|
||||||
|
AvailableExternally,
|
||||||
|
LinkOnceAny,
|
||||||
|
LinkOnceODR,
|
||||||
|
WeakAny,
|
||||||
|
WeakODR,
|
||||||
|
Appending,
|
||||||
|
Internal,
|
||||||
|
Private,
|
||||||
|
ExternalWeak,
|
||||||
|
Common,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
|
pub enum Visibility {
|
||||||
|
Default,
|
||||||
|
Hidden,
|
||||||
|
Protected,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> CodegenUnit<'tcx> {
|
||||||
|
pub fn new(name: InternedString) -> CodegenUnit<'tcx> {
|
||||||
|
CodegenUnit {
|
||||||
|
name: name,
|
||||||
|
items: FxHashMap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &InternedString {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_name(&mut self, name: InternedString) {
|
||||||
|
self.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn items(&self) -> &FxHashMap<TransItem<'tcx>, (Linkage, Visibility)> {
|
||||||
|
&self.items
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn items_mut(&mut self)
|
||||||
|
-> &mut FxHashMap<TransItem<'tcx>, (Linkage, Visibility)>
|
||||||
|
{
|
||||||
|
&mut self.items
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,6 +24,7 @@ use middle::resolve_lifetime::{Region, ObjectLifetimeDefault};
|
||||||
use middle::stability::{self, DeprecationEntry};
|
use middle::stability::{self, DeprecationEntry};
|
||||||
use middle::lang_items::{LanguageItems, LangItem};
|
use middle::lang_items::{LanguageItems, LangItem};
|
||||||
use middle::exported_symbols::ExportedSymbols;
|
use middle::exported_symbols::ExportedSymbols;
|
||||||
|
use middle::trans::{TransItem, CodegenUnit};
|
||||||
use mir;
|
use mir;
|
||||||
use mir::transform::{MirSuite, MirPassIndex};
|
use mir::transform::{MirSuite, MirPassIndex};
|
||||||
use session::CompileResult;
|
use session::CompileResult;
|
||||||
|
@ -753,6 +754,12 @@ impl<'tcx> QueryDescription for queries::exported_symbol_set<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> QueryDescription for queries::collect_and_partition_translation_items<'tcx> {
|
||||||
|
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||||
|
format!("collect_and_partition_translation_items")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If enabled, send a message to the profile-queries thread
|
// If enabled, send a message to the profile-queries thread
|
||||||
macro_rules! profq_msg {
|
macro_rules! profq_msg {
|
||||||
($tcx:expr, $msg:expr) => {
|
($tcx:expr, $msg:expr) => {
|
||||||
|
@ -1382,6 +1389,9 @@ define_maps! { <'tcx>
|
||||||
|
|
||||||
[] fn exported_symbol_set: exported_symbol_set_node(CrateNum)
|
[] fn exported_symbol_set: exported_symbol_set_node(CrateNum)
|
||||||
-> Arc<ExportedSymbols>,
|
-> Arc<ExportedSymbols>,
|
||||||
|
[] fn collect_and_partition_translation_items:
|
||||||
|
collect_and_partition_translation_items_node(CrateNum)
|
||||||
|
-> (Arc<FxHashSet<TransItem<'tcx>>>, Vec<Arc<CodegenUnit<'tcx>>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> {
|
fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> {
|
||||||
|
@ -1499,3 +1509,7 @@ fn all_crate_nums_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
|
||||||
fn exported_symbol_set_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
|
fn exported_symbol_set_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
|
||||||
DepConstructor::ExportedSymbols
|
DepConstructor::ExportedSymbols
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn collect_and_partition_translation_items_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
|
||||||
|
DepConstructor::CollectAndPartitionTranslationItems
|
||||||
|
}
|
||||||
|
|
|
@ -34,11 +34,11 @@ pub struct LinkerInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> LinkerInfo {
|
impl<'a, 'tcx> LinkerInfo {
|
||||||
pub fn new(scx: &SharedCrateContext<'a, 'tcx>,
|
pub fn new(scx: &SharedCrateContext<'a, 'tcx>) -> LinkerInfo {
|
||||||
exports: &ExportedSymbols) -> LinkerInfo {
|
let exports = scx.tcx().exported_symbols();
|
||||||
LinkerInfo {
|
LinkerInfo {
|
||||||
exports: scx.sess().crate_types.borrow().iter().map(|&c| {
|
exports: scx.sess().crate_types.borrow().iter().map(|&c| {
|
||||||
(c, exported_symbols(scx, exports, c))
|
(c, exported_symbols(scx, &exports, c))
|
||||||
}).collect(),
|
}).collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,16 +33,18 @@ use back::link;
|
||||||
use back::linker::LinkerInfo;
|
use back::linker::LinkerInfo;
|
||||||
use back::symbol_export;
|
use back::symbol_export;
|
||||||
use back::write::{self, OngoingCrateTranslation};
|
use back::write::{self, OngoingCrateTranslation};
|
||||||
use llvm::{ContextRef, Linkage, ModuleRef, ValueRef, Vector, get_param};
|
use llvm::{ContextRef, ModuleRef, ValueRef, Vector, get_param};
|
||||||
use llvm;
|
use llvm;
|
||||||
use metadata;
|
use metadata;
|
||||||
use rustc::hir::def_id::LOCAL_CRATE;
|
use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
|
||||||
use rustc::middle::lang_items::StartFnLangItem;
|
use rustc::middle::lang_items::StartFnLangItem;
|
||||||
|
use rustc::middle::trans::{Linkage, Visibility};
|
||||||
use rustc::middle::cstore::{EncodedMetadata, EncodedMetadataHashes};
|
use rustc::middle::cstore::{EncodedMetadata, EncodedMetadataHashes};
|
||||||
use rustc::ty::{self, Ty, TyCtxt};
|
use rustc::ty::{self, Ty, TyCtxt};
|
||||||
|
use rustc::ty::maps::Providers;
|
||||||
use rustc::dep_graph::AssertDepGraphSafe;
|
use rustc::dep_graph::AssertDepGraphSafe;
|
||||||
use rustc::middle::cstore::{self, LinkMeta, LinkagePreference};
|
use rustc::middle::cstore::{self, LinkMeta, LinkagePreference};
|
||||||
use rustc::middle::exported_symbols::{ExportedSymbols, SymbolExportLevel};
|
use rustc::middle::exported_symbols::ExportedSymbols;
|
||||||
use rustc::hir::map as hir_map;
|
use rustc::hir::map as hir_map;
|
||||||
use rustc::util::common::{time, print_time_passes_entry};
|
use rustc::util::common::{time, print_time_passes_entry};
|
||||||
use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType};
|
use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType};
|
||||||
|
@ -68,10 +70,10 @@ use machine;
|
||||||
use meth;
|
use meth;
|
||||||
use mir;
|
use mir;
|
||||||
use monomorphize::{self, Instance};
|
use monomorphize::{self, Instance};
|
||||||
use partitioning::{self, PartitioningStrategy, CodegenUnit};
|
use partitioning::{self, PartitioningStrategy, CodegenUnit, CodegenUnitExt};
|
||||||
use symbol_names_test;
|
use symbol_names_test;
|
||||||
use time_graph;
|
use time_graph;
|
||||||
use trans_item::{TransItem, DefPathBasedNames};
|
use trans_item::{TransItem, TransItemExt, DefPathBasedNames};
|
||||||
use type_::Type;
|
use type_::Type;
|
||||||
use type_of;
|
use type_of;
|
||||||
use value::Value;
|
use value::Value;
|
||||||
|
@ -615,7 +617,9 @@ pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance
|
||||||
mir::trans_mir(ccx, lldecl, &mir, instance, sig);
|
mir::trans_mir(ccx, lldecl, &mir, instance, sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
|
pub fn linkage_by_name(name: &str) -> Option<Linkage> {
|
||||||
|
use rustc::middle::trans::Linkage::*;
|
||||||
|
|
||||||
// Use the names from src/llvm/docs/LangRef.rst here. Most types are only
|
// Use the names from src/llvm/docs/LangRef.rst here. Most types are only
|
||||||
// applicable to variable declarations and may not really make sense for
|
// applicable to variable declarations and may not really make sense for
|
||||||
// Rust code in the first place but whitelist them anyway and trust that
|
// Rust code in the first place but whitelist them anyway and trust that
|
||||||
|
@ -625,17 +629,17 @@ pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
|
||||||
// ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
|
// ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
|
||||||
// and don't have to be, LLVM treats them as no-ops.
|
// and don't have to be, LLVM treats them as no-ops.
|
||||||
match name {
|
match name {
|
||||||
"appending" => Some(llvm::Linkage::AppendingLinkage),
|
"appending" => Some(Appending),
|
||||||
"available_externally" => Some(llvm::Linkage::AvailableExternallyLinkage),
|
"available_externally" => Some(AvailableExternally),
|
||||||
"common" => Some(llvm::Linkage::CommonLinkage),
|
"common" => Some(Common),
|
||||||
"extern_weak" => Some(llvm::Linkage::ExternalWeakLinkage),
|
"extern_weak" => Some(ExternalWeak),
|
||||||
"external" => Some(llvm::Linkage::ExternalLinkage),
|
"external" => Some(External),
|
||||||
"internal" => Some(llvm::Linkage::InternalLinkage),
|
"internal" => Some(Internal),
|
||||||
"linkonce" => Some(llvm::Linkage::LinkOnceAnyLinkage),
|
"linkonce" => Some(LinkOnceAny),
|
||||||
"linkonce_odr" => Some(llvm::Linkage::LinkOnceODRLinkage),
|
"linkonce_odr" => Some(LinkOnceODR),
|
||||||
"private" => Some(llvm::Linkage::PrivateLinkage),
|
"private" => Some(Private),
|
||||||
"weak" => Some(llvm::Linkage::WeakAnyLinkage),
|
"weak" => Some(WeakAny),
|
||||||
"weak_odr" => Some(llvm::Linkage::WeakODRLinkage),
|
"weak_odr" => Some(WeakODR),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -974,12 +978,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
// Skip crate items and just output metadata in -Z no-trans mode.
|
// Skip crate items and just output metadata in -Z no-trans mode.
|
||||||
if tcx.sess.opts.debugging_opts.no_trans ||
|
if tcx.sess.opts.debugging_opts.no_trans ||
|
||||||
!tcx.sess.opts.output_types.should_trans() {
|
!tcx.sess.opts.output_types.should_trans() {
|
||||||
let empty_exported_symbols = ExportedSymbols::new(
|
let linker_info = LinkerInfo::new(&shared_ccx);
|
||||||
SymbolExportLevel::C,
|
|
||||||
Default::default(),
|
|
||||||
Default::default(),
|
|
||||||
);
|
|
||||||
let linker_info = LinkerInfo::new(&shared_ccx, &empty_exported_symbols);
|
|
||||||
let ongoing_translation = write::start_async_translation(
|
let ongoing_translation = write::start_async_translation(
|
||||||
tcx.sess,
|
tcx.sess,
|
||||||
output_filenames,
|
output_filenames,
|
||||||
|
@ -987,7 +986,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
tcx.crate_name(LOCAL_CRATE),
|
tcx.crate_name(LOCAL_CRATE),
|
||||||
link_meta,
|
link_meta,
|
||||||
metadata,
|
metadata,
|
||||||
Arc::new(empty_exported_symbols),
|
shared_ccx.tcx().exported_symbols(),
|
||||||
no_builtins,
|
no_builtins,
|
||||||
None,
|
None,
|
||||||
linker_info,
|
linker_info,
|
||||||
|
@ -1006,16 +1005,14 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
return ongoing_translation;
|
return ongoing_translation;
|
||||||
}
|
}
|
||||||
|
|
||||||
let exported_symbols = tcx.exported_symbols();
|
|
||||||
|
|
||||||
// Run the translation item collector and partition the collected items into
|
// Run the translation item collector and partition the collected items into
|
||||||
// codegen units.
|
// codegen units.
|
||||||
let (translation_items, codegen_units) =
|
let (translation_items, codegen_units) =
|
||||||
collect_and_partition_translation_items(shared_ccx.tcx(), &exported_symbols);
|
shared_ccx.tcx().collect_and_partition_translation_items(LOCAL_CRATE);
|
||||||
|
|
||||||
assert!(codegen_units.len() <= 1 || !tcx.sess.lto());
|
assert!(codegen_units.len() <= 1 || !tcx.sess.lto());
|
||||||
|
|
||||||
let linker_info = LinkerInfo::new(&shared_ccx, &exported_symbols);
|
let linker_info = LinkerInfo::new(&shared_ccx);
|
||||||
let subsystem = attr::first_attr_value_str_by_name(&krate.attrs,
|
let subsystem = attr::first_attr_value_str_by_name(&krate.attrs,
|
||||||
"windows_subsystem");
|
"windows_subsystem");
|
||||||
let windows_subsystem = subsystem.map(|subsystem| {
|
let windows_subsystem = subsystem.map(|subsystem| {
|
||||||
|
@ -1039,7 +1036,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
tcx.crate_name(LOCAL_CRATE),
|
tcx.crate_name(LOCAL_CRATE),
|
||||||
link_meta,
|
link_meta,
|
||||||
metadata,
|
metadata,
|
||||||
exported_symbols.clone(),
|
tcx.exported_symbols(),
|
||||||
no_builtins,
|
no_builtins,
|
||||||
windows_subsystem,
|
windows_subsystem,
|
||||||
linker_info,
|
linker_info,
|
||||||
|
@ -1090,8 +1087,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
metadata_module,
|
metadata_module,
|
||||||
codegen_unit_count == 0);
|
codegen_unit_count == 0);
|
||||||
|
|
||||||
let translation_items = Arc::new(translation_items);
|
|
||||||
|
|
||||||
let mut all_stats = Stats::default();
|
let mut all_stats = Stats::default();
|
||||||
let mut module_dispositions = tcx.sess.opts.incremental.as_ref().map(|_| Vec::new());
|
let mut module_dispositions = tcx.sess.opts.incremental.as_ref().map(|_| Vec::new());
|
||||||
|
|
||||||
|
@ -1124,7 +1119,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
AssertDepGraphSafe(&shared_ccx),
|
AssertDepGraphSafe(&shared_ccx),
|
||||||
AssertDepGraphSafe((cgu,
|
AssertDepGraphSafe((cgu,
|
||||||
translation_items.clone(),
|
translation_items.clone(),
|
||||||
exported_symbols.clone())),
|
tcx.exported_symbols())),
|
||||||
module_translation);
|
module_translation);
|
||||||
all_stats.extend(stats);
|
all_stats.extend(stats);
|
||||||
|
|
||||||
|
@ -1165,7 +1160,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
|
||||||
fn module_translation<'a, 'tcx>(
|
fn module_translation<'a, 'tcx>(
|
||||||
scx: AssertDepGraphSafe<&SharedCrateContext<'a, 'tcx>>,
|
scx: AssertDepGraphSafe<&SharedCrateContext<'a, 'tcx>>,
|
||||||
args: AssertDepGraphSafe<(CodegenUnit<'tcx>,
|
args: AssertDepGraphSafe<(Arc<CodegenUnit<'tcx>>,
|
||||||
Arc<FxHashSet<TransItem<'tcx>>>,
|
Arc<FxHashSet<TransItem<'tcx>>>,
|
||||||
Arc<ExportedSymbols>)>)
|
Arc<ExportedSymbols>)>)
|
||||||
-> (Stats, ModuleTranslation)
|
-> (Stats, ModuleTranslation)
|
||||||
|
@ -1174,7 +1169,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
let AssertDepGraphSafe(scx) = scx;
|
let AssertDepGraphSafe(scx) = scx;
|
||||||
let AssertDepGraphSafe((cgu, crate_trans_items, exported_symbols)) = args;
|
let AssertDepGraphSafe((cgu, crate_trans_items, exported_symbols)) = args;
|
||||||
|
|
||||||
let cgu_name = String::from(cgu.name());
|
let cgu_name = cgu.name().to_string();
|
||||||
let cgu_id = cgu.work_product_id();
|
let cgu_id = cgu.work_product_id();
|
||||||
let symbol_name_hash = cgu.compute_symbol_name_hash(scx);
|
let symbol_name_hash = cgu.compute_symbol_name_hash(scx);
|
||||||
|
|
||||||
|
@ -1398,11 +1393,14 @@ fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trans_i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_and_partition_translation_items<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
fn collect_and_partition_translation_items<'a, 'tcx>(
|
||||||
exported_symbols: &ExportedSymbols)
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
-> (FxHashSet<TransItem<'tcx>>,
|
cnum: CrateNum,
|
||||||
Vec<CodegenUnit<'tcx>>) {
|
) -> (Arc<FxHashSet<TransItem<'tcx>>>, Vec<Arc<CodegenUnit<'tcx>>>)
|
||||||
|
{
|
||||||
|
assert_eq!(cnum, LOCAL_CRATE);
|
||||||
let time_passes = tcx.sess.time_passes();
|
let time_passes = tcx.sess.time_passes();
|
||||||
|
let exported_symbols = tcx.exported_symbols();
|
||||||
|
|
||||||
let collection_mode = match tcx.sess.opts.debugging_opts.print_trans_items {
|
let collection_mode = match tcx.sess.opts.debugging_opts.print_trans_items {
|
||||||
Some(ref s) => {
|
Some(ref s) => {
|
||||||
|
@ -1427,7 +1425,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>
|
||||||
let (items, inlining_map) =
|
let (items, inlining_map) =
|
||||||
time(time_passes, "translation item collection", || {
|
time(time_passes, "translation item collection", || {
|
||||||
collector::collect_crate_translation_items(tcx,
|
collector::collect_crate_translation_items(tcx,
|
||||||
exported_symbols,
|
&exported_symbols,
|
||||||
collection_mode)
|
collection_mode)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1444,7 +1442,10 @@ fn collect_and_partition_translation_items<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>
|
||||||
items.iter().cloned(),
|
items.iter().cloned(),
|
||||||
strategy,
|
strategy,
|
||||||
&inlining_map,
|
&inlining_map,
|
||||||
exported_symbols)
|
&exported_symbols)
|
||||||
|
.into_iter()
|
||||||
|
.map(Arc::new)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
});
|
});
|
||||||
|
|
||||||
assert!(tcx.sess.opts.cg.codegen_units == codegen_units.len() ||
|
assert!(tcx.sess.opts.cg.codegen_units == codegen_units.len() ||
|
||||||
|
@ -1477,17 +1478,17 @@ fn collect_and_partition_translation_items<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>
|
||||||
output.push_str(&cgu_name);
|
output.push_str(&cgu_name);
|
||||||
|
|
||||||
let linkage_abbrev = match linkage {
|
let linkage_abbrev = match linkage {
|
||||||
llvm::Linkage::ExternalLinkage => "External",
|
Linkage::External => "External",
|
||||||
llvm::Linkage::AvailableExternallyLinkage => "Available",
|
Linkage::AvailableExternally => "Available",
|
||||||
llvm::Linkage::LinkOnceAnyLinkage => "OnceAny",
|
Linkage::LinkOnceAny => "OnceAny",
|
||||||
llvm::Linkage::LinkOnceODRLinkage => "OnceODR",
|
Linkage::LinkOnceODR => "OnceODR",
|
||||||
llvm::Linkage::WeakAnyLinkage => "WeakAny",
|
Linkage::WeakAny => "WeakAny",
|
||||||
llvm::Linkage::WeakODRLinkage => "WeakODR",
|
Linkage::WeakODR => "WeakODR",
|
||||||
llvm::Linkage::AppendingLinkage => "Appending",
|
Linkage::Appending => "Appending",
|
||||||
llvm::Linkage::InternalLinkage => "Internal",
|
Linkage::Internal => "Internal",
|
||||||
llvm::Linkage::PrivateLinkage => "Private",
|
Linkage::Private => "Private",
|
||||||
llvm::Linkage::ExternalWeakLinkage => "ExternalWeak",
|
Linkage::ExternalWeak => "ExternalWeak",
|
||||||
llvm::Linkage::CommonLinkage => "Common",
|
Linkage::Common => "Common",
|
||||||
};
|
};
|
||||||
|
|
||||||
output.push_str("[");
|
output.push_str("[");
|
||||||
|
@ -1505,7 +1506,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(translation_items, codegen_units)
|
(Arc::new(translation_items), codegen_units)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CrateInfo {
|
impl CrateInfo {
|
||||||
|
@ -1550,3 +1551,32 @@ impl CrateInfo {
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn provide(providers: &mut Providers) {
|
||||||
|
providers.collect_and_partition_translation_items =
|
||||||
|
collect_and_partition_translation_items;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn linkage_to_llvm(linkage: Linkage) -> llvm::Linkage {
|
||||||
|
match linkage {
|
||||||
|
Linkage::External => llvm::Linkage::ExternalLinkage,
|
||||||
|
Linkage::AvailableExternally => llvm::Linkage::AvailableExternallyLinkage,
|
||||||
|
Linkage::LinkOnceAny => llvm::Linkage::LinkOnceAnyLinkage,
|
||||||
|
Linkage::LinkOnceODR => llvm::Linkage::LinkOnceODRLinkage,
|
||||||
|
Linkage::WeakAny => llvm::Linkage::WeakAnyLinkage,
|
||||||
|
Linkage::WeakODR => llvm::Linkage::WeakODRLinkage,
|
||||||
|
Linkage::Appending => llvm::Linkage::AppendingLinkage,
|
||||||
|
Linkage::Internal => llvm::Linkage::InternalLinkage,
|
||||||
|
Linkage::Private => llvm::Linkage::PrivateLinkage,
|
||||||
|
Linkage::ExternalWeak => llvm::Linkage::ExternalWeakLinkage,
|
||||||
|
Linkage::Common => llvm::Linkage::CommonLinkage,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility {
|
||||||
|
match linkage {
|
||||||
|
Visibility::Default => llvm::Visibility::Default,
|
||||||
|
Visibility::Hidden => llvm::Visibility::Hidden,
|
||||||
|
Visibility::Protected => llvm::Visibility::Protected,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -207,7 +207,7 @@ use common::{def_ty, instance_ty, type_is_sized};
|
||||||
use monomorphize::{self, Instance};
|
use monomorphize::{self, Instance};
|
||||||
use rustc::util::nodemap::{FxHashSet, FxHashMap, DefIdMap};
|
use rustc::util::nodemap::{FxHashSet, FxHashMap, DefIdMap};
|
||||||
|
|
||||||
use trans_item::{TransItem, DefPathBasedNames, InstantiationMode};
|
use trans_item::{TransItem, TransItemExt, DefPathBasedNames, InstantiationMode};
|
||||||
|
|
||||||
use rustc_data_structures::bitvec::BitVector;
|
use rustc_data_structures::bitvec::BitVector;
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ use rustc::hir::map as hir_map;
|
||||||
use rustc::middle::const_val::ConstEvalErr;
|
use rustc::middle::const_val::ConstEvalErr;
|
||||||
use {debuginfo, machine};
|
use {debuginfo, machine};
|
||||||
use base;
|
use base;
|
||||||
use trans_item::TransItem;
|
use trans_item::{TransItem, TransItemExt};
|
||||||
use common::{self, CrateContext, val_ty};
|
use common::{self, CrateContext, val_ty};
|
||||||
use declare;
|
use declare;
|
||||||
use monomorphize::Instance;
|
use monomorphize::Instance;
|
||||||
|
@ -150,7 +150,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
|
||||||
// extern "C" fn() from being non-null, so we can't just declare a
|
// extern "C" fn() from being non-null, so we can't just declare a
|
||||||
// static and call it a day. Some linkages (like weak) will make it such
|
// static and call it a day. Some linkages (like weak) will make it such
|
||||||
// that the static actually has a null value.
|
// that the static actually has a null value.
|
||||||
let linkage = match base::llvm_linkage_by_name(&name.as_str()) {
|
let linkage = match base::linkage_by_name(&name.as_str()) {
|
||||||
Some(linkage) => linkage,
|
Some(linkage) => linkage,
|
||||||
None => {
|
None => {
|
||||||
ccx.sess().span_fatal(span, "invalid linkage specified");
|
ccx.sess().span_fatal(span, "invalid linkage specified");
|
||||||
|
@ -165,7 +165,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
// Declare a symbol `foo` with the desired linkage.
|
// Declare a symbol `foo` with the desired linkage.
|
||||||
let g1 = declare::declare_global(ccx, &sym, llty2);
|
let g1 = declare::declare_global(ccx, &sym, llty2);
|
||||||
llvm::LLVMRustSetLinkage(g1, linkage);
|
llvm::LLVMRustSetLinkage(g1, base::linkage_to_llvm(linkage));
|
||||||
|
|
||||||
// Declare an internal global `extern_with_linkage_foo` which
|
// Declare an internal global `extern_with_linkage_foo` which
|
||||||
// is initialized with the address of `foo`. If `foo` is
|
// is initialized with the address of `foo`. If `foo` is
|
||||||
|
|
|
@ -93,7 +93,7 @@ pub struct LocalCrateContext<'a, 'tcx: 'a> {
|
||||||
llmod: ModuleRef,
|
llmod: ModuleRef,
|
||||||
llcx: ContextRef,
|
llcx: ContextRef,
|
||||||
stats: Stats,
|
stats: Stats,
|
||||||
codegen_unit: CodegenUnit<'tcx>,
|
codegen_unit: Arc<CodegenUnit<'tcx>>,
|
||||||
|
|
||||||
/// The translation items of the whole crate.
|
/// The translation items of the whole crate.
|
||||||
crate_trans_items: Arc<FxHashSet<TransItem<'tcx>>>,
|
crate_trans_items: Arc<FxHashSet<TransItem<'tcx>>>,
|
||||||
|
@ -330,7 +330,7 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
|
||||||
common::type_is_freeze(self.tcx, ty)
|
common::type_is_freeze(self.tcx, ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
|
pub fn tcx(&self) -> TyCtxt<'b, 'tcx, 'tcx> {
|
||||||
self.tcx
|
self.tcx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,7 +353,7 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
|
||||||
|
|
||||||
impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> {
|
impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> {
|
||||||
pub fn new(shared: &SharedCrateContext<'a, 'tcx>,
|
pub fn new(shared: &SharedCrateContext<'a, 'tcx>,
|
||||||
codegen_unit: CodegenUnit<'tcx>,
|
codegen_unit: Arc<CodegenUnit<'tcx>>,
|
||||||
crate_trans_items: Arc<FxHashSet<TransItem<'tcx>>>,
|
crate_trans_items: Arc<FxHashSet<TransItem<'tcx>>>,
|
||||||
exported_symbols: Arc<ExportedSymbols>,)
|
exported_symbols: Arc<ExportedSymbols>,)
|
||||||
-> LocalCrateContext<'a, 'tcx> {
|
-> LocalCrateContext<'a, 'tcx> {
|
||||||
|
@ -465,7 +465,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
|
||||||
self.local_ccx
|
self.local_ccx
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
|
pub fn tcx(&self) -> TyCtxt<'b, 'tcx, 'tcx> {
|
||||||
self.shared.tcx
|
self.shared.tcx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -251,6 +251,7 @@ __build_diagnostic_array! { librustc_trans, DIAGNOSTICS }
|
||||||
|
|
||||||
pub fn provide_local(providers: &mut Providers) {
|
pub fn provide_local(providers: &mut Providers) {
|
||||||
back::symbol_names::provide(providers);
|
back::symbol_names::provide(providers);
|
||||||
|
base::provide(providers);
|
||||||
providers.exported_symbol_set = |tcx, cnum| {
|
providers.exported_symbol_set = |tcx, cnum| {
|
||||||
assert_eq!(cnum, LOCAL_CRATE);
|
assert_eq!(cnum, LOCAL_CRATE);
|
||||||
Arc::new(back::symbol_export::compute(tcx))
|
Arc::new(back::symbol_export::compute(tcx))
|
||||||
|
|
|
@ -105,11 +105,11 @@
|
||||||
use collector::InliningMap;
|
use collector::InliningMap;
|
||||||
use common;
|
use common;
|
||||||
use context::SharedCrateContext;
|
use context::SharedCrateContext;
|
||||||
use llvm;
|
|
||||||
use rustc::dep_graph::{DepNode, WorkProductId};
|
use rustc::dep_graph::{DepNode, WorkProductId};
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::hir::map::DefPathData;
|
use rustc::hir::map::DefPathData;
|
||||||
use rustc::middle::exported_symbols::ExportedSymbols;
|
use rustc::middle::exported_symbols::ExportedSymbols;
|
||||||
|
use rustc::middle::trans::{Linkage, Visibility};
|
||||||
use rustc::session::config::NUMBERED_CODEGEN_UNIT_MARKER;
|
use rustc::session::config::NUMBERED_CODEGEN_UNIT_MARKER;
|
||||||
use rustc::ty::{self, TyCtxt, InstanceDef};
|
use rustc::ty::{self, TyCtxt, InstanceDef};
|
||||||
use rustc::ty::item_path::characteristic_def_id_of_type;
|
use rustc::ty::item_path::characteristic_def_id_of_type;
|
||||||
|
@ -119,7 +119,9 @@ use std::collections::hash_map::Entry;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use syntax::ast::NodeId;
|
use syntax::ast::NodeId;
|
||||||
use syntax::symbol::{Symbol, InternedString};
|
use syntax::symbol::{Symbol, InternedString};
|
||||||
use trans_item::{TransItem, InstantiationMode};
|
use trans_item::{TransItem, TransItemExt, InstantiationMode};
|
||||||
|
|
||||||
|
pub use rustc::middle::trans::CodegenUnit;
|
||||||
|
|
||||||
pub enum PartitioningStrategy {
|
pub enum PartitioningStrategy {
|
||||||
/// Generate one codegen unit per source-level module.
|
/// Generate one codegen unit per source-level module.
|
||||||
|
@ -129,53 +131,34 @@ pub enum PartitioningStrategy {
|
||||||
FixedUnitCount(usize)
|
FixedUnitCount(usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CodegenUnit<'tcx> {
|
pub trait CodegenUnitExt<'tcx> {
|
||||||
/// A name for this CGU. Incremental compilation requires that
|
fn as_codegen_unit(&self) -> &CodegenUnit<'tcx>;
|
||||||
/// name be unique amongst **all** crates. Therefore, it should
|
|
||||||
/// contain something unique to this crate (e.g., a module path)
|
|
||||||
/// as well as the crate name and disambiguator.
|
|
||||||
name: InternedString,
|
|
||||||
|
|
||||||
items: FxHashMap<TransItem<'tcx>, (llvm::Linkage, llvm::Visibility)>,
|
fn contains_item(&self, item: &TransItem<'tcx>) -> bool {
|
||||||
}
|
self.items().contains_key(item)
|
||||||
|
|
||||||
impl<'tcx> CodegenUnit<'tcx> {
|
|
||||||
pub fn new(name: InternedString,
|
|
||||||
items: FxHashMap<TransItem<'tcx>, (llvm::Linkage, llvm::Visibility)>)
|
|
||||||
-> Self {
|
|
||||||
CodegenUnit {
|
|
||||||
name,
|
|
||||||
items,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn empty(name: InternedString) -> Self {
|
fn name<'a>(&'a self) -> &'a InternedString
|
||||||
Self::new(name, FxHashMap())
|
where 'tcx: 'a,
|
||||||
|
{
|
||||||
|
&self.as_codegen_unit().name()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains_item(&self, item: &TransItem<'tcx>) -> bool {
|
fn items(&self) -> &FxHashMap<TransItem<'tcx>, (Linkage, Visibility)> {
|
||||||
self.items.contains_key(item)
|
&self.as_codegen_unit().items()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
fn work_product_id(&self) -> WorkProductId {
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn items(&self) -> &FxHashMap<TransItem<'tcx>, (llvm::Linkage, llvm::Visibility)> {
|
|
||||||
&self.items
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn work_product_id(&self) -> WorkProductId {
|
|
||||||
WorkProductId::from_cgu_name(self.name())
|
WorkProductId::from_cgu_name(self.name())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn work_product_dep_node(&self) -> DepNode {
|
fn work_product_dep_node(&self) -> DepNode {
|
||||||
self.work_product_id().to_dep_node()
|
self.work_product_id().to_dep_node()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compute_symbol_name_hash<'a>(&self,
|
fn compute_symbol_name_hash<'a>(&self,
|
||||||
scx: &SharedCrateContext<'a, 'tcx>)
|
scx: &SharedCrateContext<'a, 'tcx>)
|
||||||
-> u64 {
|
-> u64 {
|
||||||
let mut state = IchHasher::new();
|
let mut state = IchHasher::new();
|
||||||
let all_items = self.items_in_deterministic_order(scx.tcx());
|
let all_items = self.items_in_deterministic_order(scx.tcx());
|
||||||
for (item, (linkage, visibility)) in all_items {
|
for (item, (linkage, visibility)) in all_items {
|
||||||
|
@ -188,10 +171,10 @@ impl<'tcx> CodegenUnit<'tcx> {
|
||||||
state.finish().to_smaller_hash()
|
state.finish().to_smaller_hash()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn items_in_deterministic_order<'a>(&self,
|
fn items_in_deterministic_order<'a>(&self,
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
||||||
-> Vec<(TransItem<'tcx>,
|
-> Vec<(TransItem<'tcx>,
|
||||||
(llvm::Linkage, llvm::Visibility))> {
|
(Linkage, Visibility))> {
|
||||||
// The codegen tests rely on items being process in the same order as
|
// The codegen tests rely on items being process in the same order as
|
||||||
// they appear in the file, so for local items, we sort by node_id first
|
// they appear in the file, so for local items, we sort by node_id first
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
@ -209,7 +192,7 @@ impl<'tcx> CodegenUnit<'tcx> {
|
||||||
}, item.symbol_name(tcx))
|
}, item.symbol_name(tcx))
|
||||||
}
|
}
|
||||||
|
|
||||||
let items: Vec<_> = self.items.iter().map(|(&i, &l)| (i, l)).collect();
|
let items: Vec<_> = self.items().iter().map(|(&i, &l)| (i, l)).collect();
|
||||||
let mut items : Vec<_> = items.iter()
|
let mut items : Vec<_> = items.iter()
|
||||||
.map(|il| (il, item_sort_key(tcx, il.0))).collect();
|
.map(|il| (il, item_sort_key(tcx, il.0))).collect();
|
||||||
items.sort_by(|&(_, ref key1), &(_, ref key2)| key1.cmp(key2));
|
items.sort_by(|&(_, ref key1), &(_, ref key2)| key1.cmp(key2));
|
||||||
|
@ -217,6 +200,11 @@ impl<'tcx> CodegenUnit<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> CodegenUnitExt<'tcx> for CodegenUnit<'tcx> {
|
||||||
|
fn as_codegen_unit(&self) -> &CodegenUnit<'tcx> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Anything we can't find a proper codegen unit for goes into this.
|
// Anything we can't find a proper codegen unit for goes into this.
|
||||||
const FALLBACK_CODEGEN_UNIT: &'static str = "__rustc_fallback_codegen_unit";
|
const FALLBACK_CODEGEN_UNIT: &'static str = "__rustc_fallback_codegen_unit";
|
||||||
|
@ -267,7 +255,7 @@ pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
} = post_inlining;
|
} = post_inlining;
|
||||||
|
|
||||||
result.sort_by(|cgu1, cgu2| {
|
result.sort_by(|cgu1, cgu2| {
|
||||||
(&cgu1.name[..]).cmp(&cgu2.name[..])
|
cgu1.name().cmp(cgu2.name())
|
||||||
});
|
});
|
||||||
|
|
||||||
if tcx.sess.opts.enable_dep_node_debug_strs() {
|
if tcx.sess.opts.enable_dep_node_debug_strs() {
|
||||||
|
@ -329,14 +317,14 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
};
|
};
|
||||||
|
|
||||||
let make_codegen_unit = || {
|
let make_codegen_unit = || {
|
||||||
CodegenUnit::empty(codegen_unit_name.clone())
|
CodegenUnit::new(codegen_unit_name.clone())
|
||||||
};
|
};
|
||||||
|
|
||||||
let codegen_unit = codegen_units.entry(codegen_unit_name.clone())
|
let codegen_unit = codegen_units.entry(codegen_unit_name.clone())
|
||||||
.or_insert_with(make_codegen_unit);
|
.or_insert_with(make_codegen_unit);
|
||||||
|
|
||||||
let (linkage, visibility) = match trans_item.explicit_linkage(tcx) {
|
let (linkage, visibility) = match trans_item.explicit_linkage(tcx) {
|
||||||
Some(explicit_linkage) => (explicit_linkage, llvm::Visibility::Default),
|
Some(explicit_linkage) => (explicit_linkage, Visibility::Default),
|
||||||
None => {
|
None => {
|
||||||
match trans_item {
|
match trans_item {
|
||||||
TransItem::Fn(ref instance) => {
|
TransItem::Fn(ref instance) => {
|
||||||
|
@ -344,14 +332,14 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
InstanceDef::Item(def_id) => {
|
InstanceDef::Item(def_id) => {
|
||||||
if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
|
if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
|
||||||
if exported_symbols.contains(&node_id) {
|
if exported_symbols.contains(&node_id) {
|
||||||
llvm::Visibility::Default
|
Visibility::Default
|
||||||
} else {
|
} else {
|
||||||
internalization_candidates.insert(trans_item);
|
internalization_candidates.insert(trans_item);
|
||||||
llvm::Visibility::Hidden
|
Visibility::Hidden
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
internalization_candidates.insert(trans_item);
|
internalization_candidates.insert(trans_item);
|
||||||
llvm::Visibility::Hidden
|
Visibility::Hidden
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstanceDef::FnPtrShim(..) |
|
InstanceDef::FnPtrShim(..) |
|
||||||
|
@ -365,23 +353,23 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
trans_item)
|
trans_item)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
(llvm::ExternalLinkage, visibility)
|
(Linkage::External, visibility)
|
||||||
}
|
}
|
||||||
TransItem::Static(node_id) |
|
TransItem::Static(node_id) |
|
||||||
TransItem::GlobalAsm(node_id) => {
|
TransItem::GlobalAsm(node_id) => {
|
||||||
let visibility = if exported_symbols.contains(&node_id) {
|
let visibility = if exported_symbols.contains(&node_id) {
|
||||||
llvm::Visibility::Default
|
Visibility::Default
|
||||||
} else {
|
} else {
|
||||||
internalization_candidates.insert(trans_item);
|
internalization_candidates.insert(trans_item);
|
||||||
llvm::Visibility::Hidden
|
Visibility::Hidden
|
||||||
};
|
};
|
||||||
(llvm::ExternalLinkage, visibility)
|
(Linkage::External, visibility)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
codegen_unit.items.insert(trans_item, (linkage, visibility));
|
codegen_unit.items_mut().insert(trans_item, (linkage, visibility));
|
||||||
roots.insert(trans_item);
|
roots.insert(trans_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -391,7 +379,7 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
if codegen_units.is_empty() {
|
if codegen_units.is_empty() {
|
||||||
let codegen_unit_name = Symbol::intern(FALLBACK_CODEGEN_UNIT).as_str();
|
let codegen_unit_name = Symbol::intern(FALLBACK_CODEGEN_UNIT).as_str();
|
||||||
codegen_units.insert(codegen_unit_name.clone(),
|
codegen_units.insert(codegen_unit_name.clone(),
|
||||||
CodegenUnit::empty(codegen_unit_name.clone()));
|
CodegenUnit::new(codegen_unit_name.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
PreInliningPartitioning {
|
PreInliningPartitioning {
|
||||||
|
@ -414,17 +402,17 @@ fn merge_codegen_units<'tcx>(initial_partitioning: &mut PreInliningPartitioning<
|
||||||
// translation items in a given unit. This could be improved on.
|
// translation items in a given unit. This could be improved on.
|
||||||
while codegen_units.len() > target_cgu_count {
|
while codegen_units.len() > target_cgu_count {
|
||||||
// Sort small cgus to the back
|
// Sort small cgus to the back
|
||||||
codegen_units.sort_by_key(|cgu| -(cgu.items.len() as i64));
|
codegen_units.sort_by_key(|cgu| -(cgu.items().len() as i64));
|
||||||
let smallest = codegen_units.pop().unwrap();
|
let mut smallest = codegen_units.pop().unwrap();
|
||||||
let second_smallest = codegen_units.last_mut().unwrap();
|
let second_smallest = codegen_units.last_mut().unwrap();
|
||||||
|
|
||||||
for (k, v) in smallest.items.into_iter() {
|
for (k, v) in smallest.items_mut().drain() {
|
||||||
second_smallest.items.insert(k, v);
|
second_smallest.items_mut().insert(k, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (index, cgu) in codegen_units.iter_mut().enumerate() {
|
for (index, cgu) in codegen_units.iter_mut().enumerate() {
|
||||||
cgu.name = numbered_codegen_unit_name(crate_name, index);
|
cgu.set_name(numbered_codegen_unit_name(crate_name, index));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the initial partitioning contained less than target_cgu_count to begin
|
// If the initial partitioning contained less than target_cgu_count to begin
|
||||||
|
@ -432,8 +420,8 @@ fn merge_codegen_units<'tcx>(initial_partitioning: &mut PreInliningPartitioning<
|
||||||
// we reach the target count
|
// we reach the target count
|
||||||
while codegen_units.len() < target_cgu_count {
|
while codegen_units.len() < target_cgu_count {
|
||||||
let index = codegen_units.len();
|
let index = codegen_units.len();
|
||||||
codegen_units.push(
|
let name = numbered_codegen_unit_name(crate_name, index);
|
||||||
CodegenUnit::empty(numbered_codegen_unit_name(crate_name, index)));
|
codegen_units.push(CodegenUnit::new(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,20 +442,17 @@ fn place_inlined_translation_items<'tcx>(initial_partitioning: PreInliningPartit
|
||||||
for old_codegen_unit in initial_cgus {
|
for old_codegen_unit in initial_cgus {
|
||||||
// Collect all items that need to be available in this codegen unit
|
// Collect all items that need to be available in this codegen unit
|
||||||
let mut reachable = FxHashSet();
|
let mut reachable = FxHashSet();
|
||||||
for root in old_codegen_unit.items.keys() {
|
for root in old_codegen_unit.items().keys() {
|
||||||
follow_inlining(*root, inlining_map, &mut reachable);
|
follow_inlining(*root, inlining_map, &mut reachable);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut new_codegen_unit = CodegenUnit {
|
let mut new_codegen_unit = CodegenUnit::new(old_codegen_unit.name().clone());
|
||||||
name: old_codegen_unit.name,
|
|
||||||
items: FxHashMap(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add all translation items that are not already there
|
// Add all translation items that are not already there
|
||||||
for trans_item in reachable {
|
for trans_item in reachable {
|
||||||
if let Some(linkage) = old_codegen_unit.items.get(&trans_item) {
|
if let Some(linkage) = old_codegen_unit.items().get(&trans_item) {
|
||||||
// This is a root, just copy it over
|
// This is a root, just copy it over
|
||||||
new_codegen_unit.items.insert(trans_item, *linkage);
|
new_codegen_unit.items_mut().insert(trans_item, *linkage);
|
||||||
} else {
|
} else {
|
||||||
if roots.contains(&trans_item) {
|
if roots.contains(&trans_item) {
|
||||||
bug!("GloballyShared trans-item inlined into other CGU: \
|
bug!("GloballyShared trans-item inlined into other CGU: \
|
||||||
|
@ -475,8 +460,10 @@ fn place_inlined_translation_items<'tcx>(initial_partitioning: PreInliningPartit
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a cgu-private copy
|
// This is a cgu-private copy
|
||||||
new_codegen_unit.items.insert(trans_item,
|
new_codegen_unit.items_mut().insert(
|
||||||
(llvm::InternalLinkage, llvm::Visibility::Default));
|
trans_item,
|
||||||
|
(Linkage::Internal, Visibility::Default),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !single_codegen_unit {
|
if !single_codegen_unit {
|
||||||
|
@ -487,7 +474,7 @@ fn place_inlined_translation_items<'tcx>(initial_partitioning: PreInliningPartit
|
||||||
let placement = e.into_mut();
|
let placement = e.into_mut();
|
||||||
debug_assert!(match *placement {
|
debug_assert!(match *placement {
|
||||||
TransItemPlacement::SingleCgu { ref cgu_name } => {
|
TransItemPlacement::SingleCgu { ref cgu_name } => {
|
||||||
*cgu_name != new_codegen_unit.name
|
*cgu_name != *new_codegen_unit.name()
|
||||||
}
|
}
|
||||||
TransItemPlacement::MultipleCgus => true,
|
TransItemPlacement::MultipleCgus => true,
|
||||||
});
|
});
|
||||||
|
@ -495,7 +482,7 @@ fn place_inlined_translation_items<'tcx>(initial_partitioning: PreInliningPartit
|
||||||
}
|
}
|
||||||
Entry::Vacant(e) => {
|
Entry::Vacant(e) => {
|
||||||
e.insert(TransItemPlacement::SingleCgu {
|
e.insert(TransItemPlacement::SingleCgu {
|
||||||
cgu_name: new_codegen_unit.name.clone()
|
cgu_name: new_codegen_unit.name().clone()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -533,8 +520,8 @@ fn internalize_symbols<'a, 'tcx>(_tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
// could be accessed from.
|
// could be accessed from.
|
||||||
for cgu in &mut partitioning.codegen_units {
|
for cgu in &mut partitioning.codegen_units {
|
||||||
for candidate in &partitioning.internalization_candidates {
|
for candidate in &partitioning.internalization_candidates {
|
||||||
cgu.items.insert(*candidate, (llvm::InternalLinkage,
|
cgu.items_mut().insert(*candidate,
|
||||||
llvm::Visibility::Default));
|
(Linkage::Internal, Visibility::Default));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,10 +545,10 @@ fn internalize_symbols<'a, 'tcx>(_tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
// accessed from outside its defining codegen unit.
|
// accessed from outside its defining codegen unit.
|
||||||
for cgu in &mut partitioning.codegen_units {
|
for cgu in &mut partitioning.codegen_units {
|
||||||
let home_cgu = TransItemPlacement::SingleCgu {
|
let home_cgu = TransItemPlacement::SingleCgu {
|
||||||
cgu_name: cgu.name.clone()
|
cgu_name: cgu.name().clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
for (accessee, linkage_and_visibility) in &mut cgu.items {
|
for (accessee, linkage_and_visibility) in cgu.items_mut() {
|
||||||
if !partitioning.internalization_candidates.contains(accessee) {
|
if !partitioning.internalization_candidates.contains(accessee) {
|
||||||
// This item is no candidate for internalizing, so skip it.
|
// This item is no candidate for internalizing, so skip it.
|
||||||
continue
|
continue
|
||||||
|
@ -584,7 +571,7 @@ fn internalize_symbols<'a, 'tcx>(_tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
|
||||||
// If we got here, we did not find any accesses from other CGUs,
|
// If we got here, we did not find any accesses from other CGUs,
|
||||||
// so it's fine to make this translation item internal.
|
// so it's fine to make this translation item internal.
|
||||||
*linkage_and_visibility = (llvm::InternalLinkage, llvm::Visibility::Default);
|
*linkage_and_visibility = (Linkage::Internal, Visibility::Default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -675,9 +662,9 @@ fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
debug!("{}", label);
|
debug!("{}", label);
|
||||||
for cgu in cgus {
|
for cgu in cgus {
|
||||||
debug!("CodegenUnit {}:", cgu.name);
|
debug!("CodegenUnit {}:", cgu.name());
|
||||||
|
|
||||||
for (trans_item, linkage) in &cgu.items {
|
for (trans_item, linkage) in cgu.items() {
|
||||||
let symbol_name = trans_item.symbol_name(tcx);
|
let symbol_name = trans_item.symbol_name(tcx);
|
||||||
let symbol_hash_start = symbol_name.rfind('h');
|
let symbol_hash_start = symbol_name.rfind('h');
|
||||||
let symbol_hash = symbol_hash_start.map(|i| &symbol_name[i ..])
|
let symbol_hash = symbol_hash_start.map(|i| &symbol_name[i ..])
|
||||||
|
|
|
@ -25,23 +25,19 @@ use llvm;
|
||||||
use monomorphize::Instance;
|
use monomorphize::Instance;
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
|
use rustc::middle::trans::{Linkage, Visibility};
|
||||||
use rustc::traits;
|
use rustc::traits;
|
||||||
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
|
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||||
use rustc::ty::subst::{Subst, Substs};
|
use rustc::ty::subst::{Subst, Substs};
|
||||||
use syntax::ast::{self, NodeId};
|
use syntax::ast;
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
use syntax_pos::symbol::Symbol;
|
use syntax_pos::symbol::Symbol;
|
||||||
use type_of;
|
use type_of;
|
||||||
use std::fmt::Write;
|
use std::fmt::{self, Write};
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
|
pub use rustc::middle::trans::TransItem;
|
||||||
pub enum TransItem<'tcx> {
|
|
||||||
Fn(Instance<'tcx>),
|
|
||||||
Static(NodeId),
|
|
||||||
GlobalAsm(NodeId),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Describes how a translation item will be instantiated in object files.
|
/// Describes how a translation item will be instantiated in object files.
|
||||||
#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
|
#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
|
||||||
|
@ -55,15 +51,16 @@ pub enum InstantiationMode {
|
||||||
LocalCopy,
|
LocalCopy,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> TransItem<'tcx> {
|
pub trait TransItemExt<'a, 'tcx>: fmt::Debug {
|
||||||
|
fn as_trans_item(&self) -> &TransItem<'tcx>;
|
||||||
|
|
||||||
pub fn define(&self, ccx: &CrateContext<'a, 'tcx>) {
|
fn define(&self, ccx: &CrateContext<'a, 'tcx>) {
|
||||||
debug!("BEGIN IMPLEMENTING '{} ({})' in cgu {}",
|
debug!("BEGIN IMPLEMENTING '{} ({})' in cgu {}",
|
||||||
self.to_string(ccx.tcx()),
|
self.to_string(ccx.tcx()),
|
||||||
self.to_raw_string(),
|
self.to_raw_string(),
|
||||||
ccx.codegen_unit().name());
|
ccx.codegen_unit().name());
|
||||||
|
|
||||||
match *self {
|
match *self.as_trans_item() {
|
||||||
TransItem::Static(node_id) => {
|
TransItem::Static(node_id) => {
|
||||||
let tcx = ccx.tcx();
|
let tcx = ccx.tcx();
|
||||||
let item = tcx.hir.expect_item(node_id);
|
let item = tcx.hir.expect_item(node_id);
|
||||||
|
@ -97,10 +94,10 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
ccx.codegen_unit().name());
|
ccx.codegen_unit().name());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn predefine(&self,
|
fn predefine(&self,
|
||||||
ccx: &CrateContext<'a, 'tcx>,
|
ccx: &CrateContext<'a, 'tcx>,
|
||||||
linkage: llvm::Linkage,
|
linkage: Linkage,
|
||||||
visibility: llvm::Visibility) {
|
visibility: Visibility) {
|
||||||
debug!("BEGIN PREDEFINING '{} ({})' in cgu {}",
|
debug!("BEGIN PREDEFINING '{} ({})' in cgu {}",
|
||||||
self.to_string(ccx.tcx()),
|
self.to_string(ccx.tcx()),
|
||||||
self.to_raw_string(),
|
self.to_raw_string(),
|
||||||
|
@ -110,12 +107,12 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
|
|
||||||
debug!("symbol {}", &symbol_name);
|
debug!("symbol {}", &symbol_name);
|
||||||
|
|
||||||
match *self {
|
match *self.as_trans_item() {
|
||||||
TransItem::Static(node_id) => {
|
TransItem::Static(node_id) => {
|
||||||
TransItem::predefine_static(ccx, node_id, linkage, visibility, &symbol_name);
|
predefine_static(ccx, node_id, linkage, visibility, &symbol_name);
|
||||||
}
|
}
|
||||||
TransItem::Fn(instance) => {
|
TransItem::Fn(instance) => {
|
||||||
TransItem::predefine_fn(ccx, instance, linkage, visibility, &symbol_name);
|
predefine_fn(ccx, instance, linkage, visibility, &symbol_name);
|
||||||
}
|
}
|
||||||
TransItem::GlobalAsm(..) => {}
|
TransItem::GlobalAsm(..) => {}
|
||||||
}
|
}
|
||||||
|
@ -126,75 +123,8 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
ccx.codegen_unit().name());
|
ccx.codegen_unit().name());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn predefine_static(ccx: &CrateContext<'a, 'tcx>,
|
fn symbol_name(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::SymbolName {
|
||||||
node_id: ast::NodeId,
|
match *self.as_trans_item() {
|
||||||
linkage: llvm::Linkage,
|
|
||||||
visibility: llvm::Visibility,
|
|
||||||
symbol_name: &str) {
|
|
||||||
let def_id = ccx.tcx().hir.local_def_id(node_id);
|
|
||||||
let instance = Instance::mono(ccx.tcx(), def_id);
|
|
||||||
let ty = common::instance_ty(ccx.tcx(), &instance);
|
|
||||||
let llty = type_of::type_of(ccx, ty);
|
|
||||||
|
|
||||||
let g = declare::define_global(ccx, symbol_name, llty).unwrap_or_else(|| {
|
|
||||||
ccx.sess().span_fatal(ccx.tcx().hir.span(node_id),
|
|
||||||
&format!("symbol `{}` is already defined", symbol_name))
|
|
||||||
});
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
llvm::LLVMRustSetLinkage(g, linkage);
|
|
||||||
llvm::LLVMRustSetVisibility(g, visibility);
|
|
||||||
}
|
|
||||||
|
|
||||||
ccx.instances().borrow_mut().insert(instance, g);
|
|
||||||
ccx.statics().borrow_mut().insert(g, def_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn predefine_fn(ccx: &CrateContext<'a, 'tcx>,
|
|
||||||
instance: Instance<'tcx>,
|
|
||||||
linkage: llvm::Linkage,
|
|
||||||
visibility: llvm::Visibility,
|
|
||||||
symbol_name: &str) {
|
|
||||||
assert!(!instance.substs.needs_infer() &&
|
|
||||||
!instance.substs.has_param_types());
|
|
||||||
|
|
||||||
let mono_ty = common::instance_ty(ccx.tcx(), &instance);
|
|
||||||
let attrs = instance.def.attrs(ccx.tcx());
|
|
||||||
let lldecl = declare::declare_fn(ccx, symbol_name, mono_ty);
|
|
||||||
unsafe { llvm::LLVMRustSetLinkage(lldecl, linkage) };
|
|
||||||
base::set_link_section(ccx, lldecl, &attrs);
|
|
||||||
if linkage == llvm::Linkage::LinkOnceODRLinkage ||
|
|
||||||
linkage == llvm::Linkage::WeakODRLinkage {
|
|
||||||
llvm::SetUniqueComdat(ccx.llmod(), lldecl);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're compiling the compiler-builtins crate, e.g. the equivalent of
|
|
||||||
// compiler-rt, then we want to implicitly compile everything with hidden
|
|
||||||
// visibility as we're going to link this object all over the place but
|
|
||||||
// don't want the symbols to get exported.
|
|
||||||
if linkage != llvm::Linkage::InternalLinkage &&
|
|
||||||
linkage != llvm::Linkage::PrivateLinkage &&
|
|
||||||
attr::contains_name(ccx.tcx().hir.krate_attrs(), "compiler_builtins") {
|
|
||||||
unsafe {
|
|
||||||
llvm::LLVMRustSetVisibility(lldecl, llvm::Visibility::Hidden);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
llvm::LLVMRustSetVisibility(lldecl, visibility);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug!("predefine_fn: mono_ty = {:?} instance = {:?}", mono_ty, instance);
|
|
||||||
if common::is_inline_instance(ccx.tcx(), &instance) {
|
|
||||||
attributes::inline(lldecl, attributes::InlineAttr::Hint);
|
|
||||||
}
|
|
||||||
attributes::from_fn_attrs(ccx, &attrs, lldecl);
|
|
||||||
|
|
||||||
ccx.instances().borrow_mut().insert(instance, lldecl);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn symbol_name(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::SymbolName {
|
|
||||||
match *self {
|
|
||||||
TransItem::Fn(instance) => tcx.symbol_name(instance),
|
TransItem::Fn(instance) => tcx.symbol_name(instance),
|
||||||
TransItem::Static(node_id) => {
|
TransItem::Static(node_id) => {
|
||||||
let def_id = tcx.hir.local_def_id(node_id);
|
let def_id = tcx.hir.local_def_id(node_id);
|
||||||
|
@ -209,8 +139,8 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn local_span(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Span> {
|
fn local_span(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Span> {
|
||||||
match *self {
|
match *self.as_trans_item() {
|
||||||
TransItem::Fn(Instance { def, .. }) => {
|
TransItem::Fn(Instance { def, .. }) => {
|
||||||
tcx.hir.as_local_node_id(def.def_id())
|
tcx.hir.as_local_node_id(def.def_id())
|
||||||
}
|
}
|
||||||
|
@ -221,10 +151,10 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
}.map(|node_id| tcx.hir.span(node_id))
|
}.map(|node_id| tcx.hir.span(node_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn instantiation_mode(&self,
|
fn instantiation_mode(&self,
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
||||||
-> InstantiationMode {
|
-> InstantiationMode {
|
||||||
match *self {
|
match *self.as_trans_item() {
|
||||||
TransItem::Fn(ref instance) => {
|
TransItem::Fn(ref instance) => {
|
||||||
if self.explicit_linkage(tcx).is_none() &&
|
if self.explicit_linkage(tcx).is_none() &&
|
||||||
common::requests_inline(tcx, instance)
|
common::requests_inline(tcx, instance)
|
||||||
|
@ -239,8 +169,8 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_generic_fn(&self) -> bool {
|
fn is_generic_fn(&self) -> bool {
|
||||||
match *self {
|
match *self.as_trans_item() {
|
||||||
TransItem::Fn(ref instance) => {
|
TransItem::Fn(ref instance) => {
|
||||||
instance.substs.types().next().is_some()
|
instance.substs.types().next().is_some()
|
||||||
}
|
}
|
||||||
|
@ -249,8 +179,8 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<llvm::Linkage> {
|
fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Linkage> {
|
||||||
let def_id = match *self {
|
let def_id = match *self.as_trans_item() {
|
||||||
TransItem::Fn(ref instance) => instance.def_id(),
|
TransItem::Fn(ref instance) => instance.def_id(),
|
||||||
TransItem::Static(node_id) => tcx.hir.local_def_id(node_id),
|
TransItem::Static(node_id) => tcx.hir.local_def_id(node_id),
|
||||||
TransItem::GlobalAsm(..) => return None,
|
TransItem::GlobalAsm(..) => return None,
|
||||||
|
@ -258,7 +188,7 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
|
|
||||||
let attributes = tcx.get_attrs(def_id);
|
let attributes = tcx.get_attrs(def_id);
|
||||||
if let Some(name) = attr::first_attr_value_str_by_name(&attributes, "linkage") {
|
if let Some(name) = attr::first_attr_value_str_by_name(&attributes, "linkage") {
|
||||||
if let Some(linkage) = base::llvm_linkage_by_name(&name.as_str()) {
|
if let Some(linkage) = base::linkage_by_name(&name.as_str()) {
|
||||||
Some(linkage)
|
Some(linkage)
|
||||||
} else {
|
} else {
|
||||||
let span = tcx.hir.span_if_local(def_id);
|
let span = tcx.hir.span_if_local(def_id);
|
||||||
|
@ -298,9 +228,9 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
/// Similarly, if a vtable method has such a signature, and therefore can't
|
/// Similarly, if a vtable method has such a signature, and therefore can't
|
||||||
/// be used, we can just not emit it and have a placeholder (a null pointer,
|
/// be used, we can just not emit it and have a placeholder (a null pointer,
|
||||||
/// which will never be accessed) in its place.
|
/// which will never be accessed) in its place.
|
||||||
pub fn is_instantiable(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
|
fn is_instantiable(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
|
||||||
debug!("is_instantiable({:?})", self);
|
debug!("is_instantiable({:?})", self);
|
||||||
let (def_id, substs) = match *self {
|
let (def_id, substs) = match *self.as_trans_item() {
|
||||||
TransItem::Fn(ref instance) => (instance.def_id(), instance.substs),
|
TransItem::Fn(ref instance) => (instance.def_id(), instance.substs),
|
||||||
TransItem::Static(node_id) => (tcx.hir.local_def_id(node_id), Substs::empty()),
|
TransItem::Static(node_id) => (tcx.hir.local_def_id(node_id), Substs::empty()),
|
||||||
// global asm never has predicates
|
// global asm never has predicates
|
||||||
|
@ -311,10 +241,10 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
traits::normalize_and_test_predicates(tcx, predicates)
|
traits::normalize_and_test_predicates(tcx, predicates)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
|
fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
|
||||||
let hir_map = &tcx.hir;
|
let hir_map = &tcx.hir;
|
||||||
|
|
||||||
return match *self {
|
return match *self.as_trans_item() {
|
||||||
TransItem::Fn(instance) => {
|
TransItem::Fn(instance) => {
|
||||||
to_string_internal(tcx, "fn ", instance)
|
to_string_internal(tcx, "fn ", instance)
|
||||||
},
|
},
|
||||||
|
@ -340,8 +270,8 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_raw_string(&self) -> String {
|
fn to_raw_string(&self) -> String {
|
||||||
match *self {
|
match *self.as_trans_item() {
|
||||||
TransItem::Fn(instance) => {
|
TransItem::Fn(instance) => {
|
||||||
format!("Fn({:?}, {})",
|
format!("Fn({:?}, {})",
|
||||||
instance.def,
|
instance.def,
|
||||||
|
@ -357,6 +287,77 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> TransItemExt<'a, 'tcx> for TransItem<'tcx> {
|
||||||
|
fn as_trans_item(&self) -> &TransItem<'tcx> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn predefine_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||||
|
node_id: ast::NodeId,
|
||||||
|
linkage: Linkage,
|
||||||
|
visibility: Visibility,
|
||||||
|
symbol_name: &str) {
|
||||||
|
let def_id = ccx.tcx().hir.local_def_id(node_id);
|
||||||
|
let instance = Instance::mono(ccx.tcx(), def_id);
|
||||||
|
let ty = common::instance_ty(ccx.tcx(), &instance);
|
||||||
|
let llty = type_of::type_of(ccx, ty);
|
||||||
|
|
||||||
|
let g = declare::define_global(ccx, symbol_name, llty).unwrap_or_else(|| {
|
||||||
|
ccx.sess().span_fatal(ccx.tcx().hir.span(node_id),
|
||||||
|
&format!("symbol `{}` is already defined", symbol_name))
|
||||||
|
});
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
llvm::LLVMRustSetLinkage(g, base::linkage_to_llvm(linkage));
|
||||||
|
llvm::LLVMRustSetVisibility(g, base::visibility_to_llvm(visibility));
|
||||||
|
}
|
||||||
|
|
||||||
|
ccx.instances().borrow_mut().insert(instance, g);
|
||||||
|
ccx.statics().borrow_mut().insert(g, def_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn predefine_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||||
|
instance: Instance<'tcx>,
|
||||||
|
linkage: Linkage,
|
||||||
|
visibility: Visibility,
|
||||||
|
symbol_name: &str) {
|
||||||
|
assert!(!instance.substs.needs_infer() &&
|
||||||
|
!instance.substs.has_param_types());
|
||||||
|
|
||||||
|
let mono_ty = common::instance_ty(ccx.tcx(), &instance);
|
||||||
|
let attrs = instance.def.attrs(ccx.tcx());
|
||||||
|
let lldecl = declare::declare_fn(ccx, symbol_name, mono_ty);
|
||||||
|
unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) };
|
||||||
|
base::set_link_section(ccx, lldecl, &attrs);
|
||||||
|
if linkage == Linkage::LinkOnceODR ||
|
||||||
|
linkage == Linkage::WeakODR {
|
||||||
|
llvm::SetUniqueComdat(ccx.llmod(), lldecl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're compiling the compiler-builtins crate, e.g. the equivalent of
|
||||||
|
// compiler-rt, then we want to implicitly compile everything with hidden
|
||||||
|
// visibility as we're going to link this object all over the place but
|
||||||
|
// don't want the symbols to get exported.
|
||||||
|
if linkage != Linkage::Internal && linkage != Linkage::Private &&
|
||||||
|
attr::contains_name(ccx.tcx().hir.krate_attrs(), "compiler_builtins") {
|
||||||
|
unsafe {
|
||||||
|
llvm::LLVMRustSetVisibility(lldecl, llvm::Visibility::Hidden);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unsafe {
|
||||||
|
llvm::LLVMRustSetVisibility(lldecl, base::visibility_to_llvm(visibility));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!("predefine_fn: mono_ty = {:?} instance = {:?}", mono_ty, instance);
|
||||||
|
if common::is_inline_instance(ccx.tcx(), &instance) {
|
||||||
|
attributes::inline(lldecl, attributes::InlineAttr::Hint);
|
||||||
|
}
|
||||||
|
attributes::from_fn_attrs(ccx, &attrs, lldecl);
|
||||||
|
|
||||||
|
ccx.instances().borrow_mut().insert(instance, lldecl);
|
||||||
|
}
|
||||||
|
|
||||||
//=-----------------------------------------------------------------------------
|
//=-----------------------------------------------------------------------------
|
||||||
// TransItem String Keys
|
// TransItem String Keys
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue