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,
|
||||
[] AllCrateNums,
|
||||
[] ExportedSymbols,
|
||||
[] CollectAndPartitionTranslationItems,
|
||||
);
|
||||
|
||||
trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
|
||||
|
|
|
@ -104,6 +104,7 @@ pub mod middle {
|
|||
pub mod recursion_limit;
|
||||
pub mod resolve_lifetime;
|
||||
pub mod stability;
|
||||
pub mod trans;
|
||||
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::lang_items::{LanguageItems, LangItem};
|
||||
use middle::exported_symbols::ExportedSymbols;
|
||||
use middle::trans::{TransItem, CodegenUnit};
|
||||
use mir;
|
||||
use mir::transform::{MirSuite, MirPassIndex};
|
||||
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
|
||||
macro_rules! profq_msg {
|
||||
($tcx:expr, $msg:expr) => {
|
||||
|
@ -1382,6 +1389,9 @@ define_maps! { <'tcx>
|
|||
|
||||
[] fn exported_symbol_set: exported_symbol_set_node(CrateNum)
|
||||
-> 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> {
|
||||
|
@ -1499,3 +1509,7 @@ fn all_crate_nums_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
|
|||
fn exported_symbol_set_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
|
||||
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 {
|
||||
pub fn new(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
exports: &ExportedSymbols) -> LinkerInfo {
|
||||
pub fn new(scx: &SharedCrateContext<'a, 'tcx>) -> LinkerInfo {
|
||||
let exports = scx.tcx().exported_symbols();
|
||||
LinkerInfo {
|
||||
exports: scx.sess().crate_types.borrow().iter().map(|&c| {
|
||||
(c, exported_symbols(scx, exports, c))
|
||||
(c, exported_symbols(scx, &exports, c))
|
||||
}).collect(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,16 +33,18 @@ use back::link;
|
|||
use back::linker::LinkerInfo;
|
||||
use back::symbol_export;
|
||||
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 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::trans::{Linkage, Visibility};
|
||||
use rustc::middle::cstore::{EncodedMetadata, EncodedMetadataHashes};
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::maps::Providers;
|
||||
use rustc::dep_graph::AssertDepGraphSafe;
|
||||
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::util::common::{time, print_time_passes_entry};
|
||||
use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType};
|
||||
|
@ -68,10 +70,10 @@ use machine;
|
|||
use meth;
|
||||
use mir;
|
||||
use monomorphize::{self, Instance};
|
||||
use partitioning::{self, PartitioningStrategy, CodegenUnit};
|
||||
use partitioning::{self, PartitioningStrategy, CodegenUnit, CodegenUnitExt};
|
||||
use symbol_names_test;
|
||||
use time_graph;
|
||||
use trans_item::{TransItem, DefPathBasedNames};
|
||||
use trans_item::{TransItem, TransItemExt, DefPathBasedNames};
|
||||
use type_::Type;
|
||||
use type_of;
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
// applicable to variable declarations and may not really make sense for
|
||||
// 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
|
||||
// and don't have to be, LLVM treats them as no-ops.
|
||||
match name {
|
||||
"appending" => Some(llvm::Linkage::AppendingLinkage),
|
||||
"available_externally" => Some(llvm::Linkage::AvailableExternallyLinkage),
|
||||
"common" => Some(llvm::Linkage::CommonLinkage),
|
||||
"extern_weak" => Some(llvm::Linkage::ExternalWeakLinkage),
|
||||
"external" => Some(llvm::Linkage::ExternalLinkage),
|
||||
"internal" => Some(llvm::Linkage::InternalLinkage),
|
||||
"linkonce" => Some(llvm::Linkage::LinkOnceAnyLinkage),
|
||||
"linkonce_odr" => Some(llvm::Linkage::LinkOnceODRLinkage),
|
||||
"private" => Some(llvm::Linkage::PrivateLinkage),
|
||||
"weak" => Some(llvm::Linkage::WeakAnyLinkage),
|
||||
"weak_odr" => Some(llvm::Linkage::WeakODRLinkage),
|
||||
"appending" => Some(Appending),
|
||||
"available_externally" => Some(AvailableExternally),
|
||||
"common" => Some(Common),
|
||||
"extern_weak" => Some(ExternalWeak),
|
||||
"external" => Some(External),
|
||||
"internal" => Some(Internal),
|
||||
"linkonce" => Some(LinkOnceAny),
|
||||
"linkonce_odr" => Some(LinkOnceODR),
|
||||
"private" => Some(Private),
|
||||
"weak" => Some(WeakAny),
|
||||
"weak_odr" => Some(WeakODR),
|
||||
_ => 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.
|
||||
if tcx.sess.opts.debugging_opts.no_trans ||
|
||||
!tcx.sess.opts.output_types.should_trans() {
|
||||
let empty_exported_symbols = ExportedSymbols::new(
|
||||
SymbolExportLevel::C,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
);
|
||||
let linker_info = LinkerInfo::new(&shared_ccx, &empty_exported_symbols);
|
||||
let linker_info = LinkerInfo::new(&shared_ccx);
|
||||
let ongoing_translation = write::start_async_translation(
|
||||
tcx.sess,
|
||||
output_filenames,
|
||||
|
@ -987,7 +986,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
tcx.crate_name(LOCAL_CRATE),
|
||||
link_meta,
|
||||
metadata,
|
||||
Arc::new(empty_exported_symbols),
|
||||
shared_ccx.tcx().exported_symbols(),
|
||||
no_builtins,
|
||||
None,
|
||||
linker_info,
|
||||
|
@ -1006,16 +1005,14 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
return ongoing_translation;
|
||||
}
|
||||
|
||||
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.tcx(), &exported_symbols);
|
||||
shared_ccx.tcx().collect_and_partition_translation_items(LOCAL_CRATE);
|
||||
|
||||
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,
|
||||
"windows_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),
|
||||
link_meta,
|
||||
metadata,
|
||||
exported_symbols.clone(),
|
||||
tcx.exported_symbols(),
|
||||
no_builtins,
|
||||
windows_subsystem,
|
||||
linker_info,
|
||||
|
@ -1090,8 +1087,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
metadata_module,
|
||||
codegen_unit_count == 0);
|
||||
|
||||
let translation_items = Arc::new(translation_items);
|
||||
|
||||
let mut all_stats = Stats::default();
|
||||
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((cgu,
|
||||
translation_items.clone(),
|
||||
exported_symbols.clone())),
|
||||
tcx.exported_symbols())),
|
||||
module_translation);
|
||||
all_stats.extend(stats);
|
||||
|
||||
|
@ -1165,7 +1160,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
|
||||
fn module_translation<'a, 'tcx>(
|
||||
scx: AssertDepGraphSafe<&SharedCrateContext<'a, 'tcx>>,
|
||||
args: AssertDepGraphSafe<(CodegenUnit<'tcx>,
|
||||
args: AssertDepGraphSafe<(Arc<CodegenUnit<'tcx>>,
|
||||
Arc<FxHashSet<TransItem<'tcx>>>,
|
||||
Arc<ExportedSymbols>)>)
|
||||
-> (Stats, ModuleTranslation)
|
||||
|
@ -1174,7 +1169,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
let AssertDepGraphSafe(scx) = scx;
|
||||
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 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>,
|
||||
exported_symbols: &ExportedSymbols)
|
||||
-> (FxHashSet<TransItem<'tcx>>,
|
||||
Vec<CodegenUnit<'tcx>>) {
|
||||
fn collect_and_partition_translation_items<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
cnum: CrateNum,
|
||||
) -> (Arc<FxHashSet<TransItem<'tcx>>>, Vec<Arc<CodegenUnit<'tcx>>>)
|
||||
{
|
||||
assert_eq!(cnum, LOCAL_CRATE);
|
||||
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 {
|
||||
Some(ref s) => {
|
||||
|
@ -1427,7 +1425,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>
|
|||
let (items, inlining_map) =
|
||||
time(time_passes, "translation item collection", || {
|
||||
collector::collect_crate_translation_items(tcx,
|
||||
exported_symbols,
|
||||
&exported_symbols,
|
||||
collection_mode)
|
||||
});
|
||||
|
||||
|
@ -1444,7 +1442,10 @@ fn collect_and_partition_translation_items<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>
|
|||
items.iter().cloned(),
|
||||
strategy,
|
||||
&inlining_map,
|
||||
exported_symbols)
|
||||
&exported_symbols)
|
||||
.into_iter()
|
||||
.map(Arc::new)
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
let linkage_abbrev = match linkage {
|
||||
llvm::Linkage::ExternalLinkage => "External",
|
||||
llvm::Linkage::AvailableExternallyLinkage => "Available",
|
||||
llvm::Linkage::LinkOnceAnyLinkage => "OnceAny",
|
||||
llvm::Linkage::LinkOnceODRLinkage => "OnceODR",
|
||||
llvm::Linkage::WeakAnyLinkage => "WeakAny",
|
||||
llvm::Linkage::WeakODRLinkage => "WeakODR",
|
||||
llvm::Linkage::AppendingLinkage => "Appending",
|
||||
llvm::Linkage::InternalLinkage => "Internal",
|
||||
llvm::Linkage::PrivateLinkage => "Private",
|
||||
llvm::Linkage::ExternalWeakLinkage => "ExternalWeak",
|
||||
llvm::Linkage::CommonLinkage => "Common",
|
||||
Linkage::External => "External",
|
||||
Linkage::AvailableExternally => "Available",
|
||||
Linkage::LinkOnceAny => "OnceAny",
|
||||
Linkage::LinkOnceODR => "OnceODR",
|
||||
Linkage::WeakAny => "WeakAny",
|
||||
Linkage::WeakODR => "WeakODR",
|
||||
Linkage::Appending => "Appending",
|
||||
Linkage::Internal => "Internal",
|
||||
Linkage::Private => "Private",
|
||||
Linkage::ExternalWeak => "ExternalWeak",
|
||||
Linkage::Common => "Common",
|
||||
};
|
||||
|
||||
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 {
|
||||
|
@ -1550,3 +1551,32 @@ impl CrateInfo {
|
|||
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 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;
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ use rustc::hir::map as hir_map;
|
|||
use rustc::middle::const_val::ConstEvalErr;
|
||||
use {debuginfo, machine};
|
||||
use base;
|
||||
use trans_item::TransItem;
|
||||
use trans_item::{TransItem, TransItemExt};
|
||||
use common::{self, CrateContext, val_ty};
|
||||
use declare;
|
||||
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
|
||||
// static and call it a day. Some linkages (like weak) will make it such
|
||||
// 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,
|
||||
None => {
|
||||
ccx.sess().span_fatal(span, "invalid linkage specified");
|
||||
|
@ -165,7 +165,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
|
|||
unsafe {
|
||||
// Declare a symbol `foo` with the desired linkage.
|
||||
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
|
||||
// is initialized with the address of `foo`. If `foo` is
|
||||
|
|
|
@ -93,7 +93,7 @@ pub struct LocalCrateContext<'a, 'tcx: 'a> {
|
|||
llmod: ModuleRef,
|
||||
llcx: ContextRef,
|
||||
stats: Stats,
|
||||
codegen_unit: CodegenUnit<'tcx>,
|
||||
codegen_unit: Arc<CodegenUnit<'tcx>>,
|
||||
|
||||
/// The translation items of the whole crate.
|
||||
crate_trans_items: Arc<FxHashSet<TransItem<'tcx>>>,
|
||||
|
@ -330,7 +330,7 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
|
|||
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
|
||||
}
|
||||
|
||||
|
@ -353,7 +353,7 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
|
|||
|
||||
impl<'a, 'tcx> LocalCrateContext<'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>>>,
|
||||
exported_symbols: Arc<ExportedSymbols>,)
|
||||
-> LocalCrateContext<'a, 'tcx> {
|
||||
|
@ -465,7 +465,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
|
|||
self.local_ccx
|
||||
}
|
||||
|
||||
pub fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
|
||||
pub fn tcx(&self) -> TyCtxt<'b, 'tcx, 'tcx> {
|
||||
self.shared.tcx
|
||||
}
|
||||
|
||||
|
|
|
@ -251,6 +251,7 @@ __build_diagnostic_array! { librustc_trans, DIAGNOSTICS }
|
|||
|
||||
pub fn provide_local(providers: &mut Providers) {
|
||||
back::symbol_names::provide(providers);
|
||||
base::provide(providers);
|
||||
providers.exported_symbol_set = |tcx, cnum| {
|
||||
assert_eq!(cnum, LOCAL_CRATE);
|
||||
Arc::new(back::symbol_export::compute(tcx))
|
||||
|
|
|
@ -105,11 +105,11 @@
|
|||
use collector::InliningMap;
|
||||
use common;
|
||||
use context::SharedCrateContext;
|
||||
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::middle::trans::{Linkage, Visibility};
|
||||
use rustc::session::config::NUMBERED_CODEGEN_UNIT_MARKER;
|
||||
use rustc::ty::{self, TyCtxt, InstanceDef};
|
||||
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 syntax::ast::NodeId;
|
||||
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 {
|
||||
/// Generate one codegen unit per source-level module.
|
||||
|
@ -129,53 +131,34 @@ pub enum PartitioningStrategy {
|
|||
FixedUnitCount(usize)
|
||||
}
|
||||
|
||||
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,
|
||||
pub trait CodegenUnitExt<'tcx> {
|
||||
fn as_codegen_unit(&self) -> &CodegenUnit<'tcx>;
|
||||
|
||||
items: FxHashMap<TransItem<'tcx>, (llvm::Linkage, llvm::Visibility)>,
|
||||
}
|
||||
|
||||
impl<'tcx> CodegenUnit<'tcx> {
|
||||
pub fn new(name: InternedString,
|
||||
items: FxHashMap<TransItem<'tcx>, (llvm::Linkage, llvm::Visibility)>)
|
||||
-> Self {
|
||||
CodegenUnit {
|
||||
name,
|
||||
items,
|
||||
}
|
||||
fn contains_item(&self, item: &TransItem<'tcx>) -> bool {
|
||||
self.items().contains_key(item)
|
||||
}
|
||||
|
||||
pub fn empty(name: InternedString) -> Self {
|
||||
Self::new(name, FxHashMap())
|
||||
fn name<'a>(&'a self) -> &'a InternedString
|
||||
where 'tcx: 'a,
|
||||
{
|
||||
&self.as_codegen_unit().name()
|
||||
}
|
||||
|
||||
pub fn contains_item(&self, item: &TransItem<'tcx>) -> bool {
|
||||
self.items.contains_key(item)
|
||||
fn items(&self) -> &FxHashMap<TransItem<'tcx>, (Linkage, Visibility)> {
|
||||
&self.as_codegen_unit().items()
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn items(&self) -> &FxHashMap<TransItem<'tcx>, (llvm::Linkage, llvm::Visibility)> {
|
||||
&self.items
|
||||
}
|
||||
|
||||
pub fn work_product_id(&self) -> WorkProductId {
|
||||
fn work_product_id(&self) -> WorkProductId {
|
||||
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()
|
||||
}
|
||||
|
||||
pub fn compute_symbol_name_hash<'a>(&self,
|
||||
scx: &SharedCrateContext<'a, 'tcx>)
|
||||
-> u64 {
|
||||
fn compute_symbol_name_hash<'a>(&self,
|
||||
scx: &SharedCrateContext<'a, 'tcx>)
|
||||
-> u64 {
|
||||
let mut state = IchHasher::new();
|
||||
let all_items = self.items_in_deterministic_order(scx.tcx());
|
||||
for (item, (linkage, visibility)) in all_items {
|
||||
|
@ -188,10 +171,10 @@ impl<'tcx> CodegenUnit<'tcx> {
|
|||
state.finish().to_smaller_hash()
|
||||
}
|
||||
|
||||
pub fn items_in_deterministic_order<'a>(&self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
||||
-> Vec<(TransItem<'tcx>,
|
||||
(llvm::Linkage, llvm::Visibility))> {
|
||||
fn items_in_deterministic_order<'a>(&self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
||||
-> Vec<(TransItem<'tcx>,
|
||||
(Linkage, Visibility))> {
|
||||
// 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
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||
|
@ -209,7 +192,7 @@ impl<'tcx> CodegenUnit<'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()
|
||||
.map(|il| (il, item_sort_key(tcx, il.0))).collect();
|
||||
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.
|
||||
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;
|
||||
|
||||
result.sort_by(|cgu1, cgu2| {
|
||||
(&cgu1.name[..]).cmp(&cgu2.name[..])
|
||||
cgu1.name().cmp(cgu2.name())
|
||||
});
|
||||
|
||||
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 = || {
|
||||
CodegenUnit::empty(codegen_unit_name.clone())
|
||||
CodegenUnit::new(codegen_unit_name.clone())
|
||||
};
|
||||
|
||||
let codegen_unit = codegen_units.entry(codegen_unit_name.clone())
|
||||
.or_insert_with(make_codegen_unit);
|
||||
|
||||
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 => {
|
||||
match trans_item {
|
||||
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) => {
|
||||
if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
|
||||
if exported_symbols.contains(&node_id) {
|
||||
llvm::Visibility::Default
|
||||
Visibility::Default
|
||||
} else {
|
||||
internalization_candidates.insert(trans_item);
|
||||
llvm::Visibility::Hidden
|
||||
Visibility::Hidden
|
||||
}
|
||||
} else {
|
||||
internalization_candidates.insert(trans_item);
|
||||
llvm::Visibility::Hidden
|
||||
Visibility::Hidden
|
||||
}
|
||||
}
|
||||
InstanceDef::FnPtrShim(..) |
|
||||
|
@ -365,23 +353,23 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
trans_item)
|
||||
}
|
||||
};
|
||||
(llvm::ExternalLinkage, visibility)
|
||||
(Linkage::External, visibility)
|
||||
}
|
||||
TransItem::Static(node_id) |
|
||||
TransItem::GlobalAsm(node_id) => {
|
||||
let visibility = if exported_symbols.contains(&node_id) {
|
||||
llvm::Visibility::Default
|
||||
Visibility::Default
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -391,7 +379,7 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
if codegen_units.is_empty() {
|
||||
let codegen_unit_name = Symbol::intern(FALLBACK_CODEGEN_UNIT).as_str();
|
||||
codegen_units.insert(codegen_unit_name.clone(),
|
||||
CodegenUnit::empty(codegen_unit_name.clone()));
|
||||
CodegenUnit::new(codegen_unit_name.clone()));
|
||||
}
|
||||
|
||||
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.
|
||||
while codegen_units.len() > target_cgu_count {
|
||||
// Sort small cgus to the back
|
||||
codegen_units.sort_by_key(|cgu| -(cgu.items.len() as i64));
|
||||
let smallest = codegen_units.pop().unwrap();
|
||||
codegen_units.sort_by_key(|cgu| -(cgu.items().len() as i64));
|
||||
let mut smallest = codegen_units.pop().unwrap();
|
||||
let second_smallest = codegen_units.last_mut().unwrap();
|
||||
|
||||
for (k, v) in smallest.items.into_iter() {
|
||||
second_smallest.items.insert(k, v);
|
||||
for (k, v) in smallest.items_mut().drain() {
|
||||
second_smallest.items_mut().insert(k, v);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -432,8 +420,8 @@ fn merge_codegen_units<'tcx>(initial_partitioning: &mut PreInliningPartitioning<
|
|||
// we reach the target count
|
||||
while codegen_units.len() < target_cgu_count {
|
||||
let index = codegen_units.len();
|
||||
codegen_units.push(
|
||||
CodegenUnit::empty(numbered_codegen_unit_name(crate_name, index)));
|
||||
let name = 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 {
|
||||
// Collect all items that need to be available in this codegen unit
|
||||
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);
|
||||
}
|
||||
|
||||
let mut new_codegen_unit = CodegenUnit {
|
||||
name: old_codegen_unit.name,
|
||||
items: FxHashMap(),
|
||||
};
|
||||
let mut new_codegen_unit = CodegenUnit::new(old_codegen_unit.name().clone());
|
||||
|
||||
// Add all translation items that are not already there
|
||||
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
|
||||
new_codegen_unit.items.insert(trans_item, *linkage);
|
||||
new_codegen_unit.items_mut().insert(trans_item, *linkage);
|
||||
} else {
|
||||
if roots.contains(&trans_item) {
|
||||
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
|
||||
new_codegen_unit.items.insert(trans_item,
|
||||
(llvm::InternalLinkage, llvm::Visibility::Default));
|
||||
new_codegen_unit.items_mut().insert(
|
||||
trans_item,
|
||||
(Linkage::Internal, Visibility::Default),
|
||||
);
|
||||
}
|
||||
|
||||
if !single_codegen_unit {
|
||||
|
@ -487,7 +474,7 @@ fn place_inlined_translation_items<'tcx>(initial_partitioning: PreInliningPartit
|
|||
let placement = e.into_mut();
|
||||
debug_assert!(match *placement {
|
||||
TransItemPlacement::SingleCgu { ref cgu_name } => {
|
||||
*cgu_name != new_codegen_unit.name
|
||||
*cgu_name != *new_codegen_unit.name()
|
||||
}
|
||||
TransItemPlacement::MultipleCgus => true,
|
||||
});
|
||||
|
@ -495,7 +482,7 @@ fn place_inlined_translation_items<'tcx>(initial_partitioning: PreInliningPartit
|
|||
}
|
||||
Entry::Vacant(e) => {
|
||||
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.
|
||||
for cgu in &mut partitioning.codegen_units {
|
||||
for candidate in &partitioning.internalization_candidates {
|
||||
cgu.items.insert(*candidate, (llvm::InternalLinkage,
|
||||
llvm::Visibility::Default));
|
||||
cgu.items_mut().insert(*candidate,
|
||||
(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.
|
||||
for cgu in &mut partitioning.codegen_units {
|
||||
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) {
|
||||
// This item is no candidate for internalizing, so skip it.
|
||||
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,
|
||||
// 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) {
|
||||
debug!("{}", label);
|
||||
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_hash_start = symbol_name.rfind('h');
|
||||
let symbol_hash = symbol_hash_start.map(|i| &symbol_name[i ..])
|
||||
|
|
|
@ -25,23 +25,19 @@ use llvm;
|
|||
use monomorphize::Instance;
|
||||
use rustc::hir;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::middle::trans::{Linkage, Visibility};
|
||||
use rustc::traits;
|
||||
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc::ty::subst::{Subst, Substs};
|
||||
use syntax::ast::{self, NodeId};
|
||||
use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax_pos::Span;
|
||||
use syntax_pos::symbol::Symbol;
|
||||
use type_of;
|
||||
use std::fmt::Write;
|
||||
use std::fmt::{self, Write};
|
||||
use std::iter;
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
|
||||
pub enum TransItem<'tcx> {
|
||||
Fn(Instance<'tcx>),
|
||||
Static(NodeId),
|
||||
GlobalAsm(NodeId),
|
||||
}
|
||||
pub use rustc::middle::trans::TransItem;
|
||||
|
||||
/// Describes how a translation item will be instantiated in object files.
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
|
||||
|
@ -55,15 +51,16 @@ pub enum InstantiationMode {
|
|||
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 {}",
|
||||
self.to_string(ccx.tcx()),
|
||||
self.to_raw_string(),
|
||||
ccx.codegen_unit().name());
|
||||
self.to_string(ccx.tcx()),
|
||||
self.to_raw_string(),
|
||||
ccx.codegen_unit().name());
|
||||
|
||||
match *self {
|
||||
match *self.as_trans_item() {
|
||||
TransItem::Static(node_id) => {
|
||||
let tcx = ccx.tcx();
|
||||
let item = tcx.hir.expect_item(node_id);
|
||||
|
@ -97,10 +94,10 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
|||
ccx.codegen_unit().name());
|
||||
}
|
||||
|
||||
pub fn predefine(&self,
|
||||
ccx: &CrateContext<'a, 'tcx>,
|
||||
linkage: llvm::Linkage,
|
||||
visibility: llvm::Visibility) {
|
||||
fn predefine(&self,
|
||||
ccx: &CrateContext<'a, 'tcx>,
|
||||
linkage: Linkage,
|
||||
visibility: Visibility) {
|
||||
debug!("BEGIN PREDEFINING '{} ({})' in cgu {}",
|
||||
self.to_string(ccx.tcx()),
|
||||
self.to_raw_string(),
|
||||
|
@ -110,12 +107,12 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
|||
|
||||
debug!("symbol {}", &symbol_name);
|
||||
|
||||
match *self {
|
||||
match *self.as_trans_item() {
|
||||
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::predefine_fn(ccx, instance, linkage, visibility, &symbol_name);
|
||||
predefine_fn(ccx, instance, linkage, visibility, &symbol_name);
|
||||
}
|
||||
TransItem::GlobalAsm(..) => {}
|
||||
}
|
||||
|
@ -126,75 +123,8 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
|||
ccx.codegen_unit().name());
|
||||
}
|
||||
|
||||
fn predefine_static(ccx: &CrateContext<'a, 'tcx>,
|
||||
node_id: ast::NodeId,
|
||||
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 {
|
||||
fn symbol_name(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::SymbolName {
|
||||
match *self.as_trans_item() {
|
||||
TransItem::Fn(instance) => tcx.symbol_name(instance),
|
||||
TransItem::Static(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> {
|
||||
match *self {
|
||||
fn local_span(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Span> {
|
||||
match *self.as_trans_item() {
|
||||
TransItem::Fn(Instance { def, .. }) => {
|
||||
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))
|
||||
}
|
||||
|
||||
pub fn instantiation_mode(&self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
||||
-> InstantiationMode {
|
||||
match *self {
|
||||
fn instantiation_mode(&self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
||||
-> InstantiationMode {
|
||||
match *self.as_trans_item() {
|
||||
TransItem::Fn(ref instance) => {
|
||||
if self.explicit_linkage(tcx).is_none() &&
|
||||
common::requests_inline(tcx, instance)
|
||||
|
@ -239,8 +169,8 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_generic_fn(&self) -> bool {
|
||||
match *self {
|
||||
fn is_generic_fn(&self) -> bool {
|
||||
match *self.as_trans_item() {
|
||||
TransItem::Fn(ref instance) => {
|
||||
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> {
|
||||
let def_id = match *self {
|
||||
fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Linkage> {
|
||||
let def_id = match *self.as_trans_item() {
|
||||
TransItem::Fn(ref instance) => instance.def_id(),
|
||||
TransItem::Static(node_id) => tcx.hir.local_def_id(node_id),
|
||||
TransItem::GlobalAsm(..) => return None,
|
||||
|
@ -258,7 +188,7 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
|||
|
||||
let attributes = tcx.get_attrs(def_id);
|
||||
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)
|
||||
} else {
|
||||
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
|
||||
/// be used, we can just not emit it and have a placeholder (a null pointer,
|
||||
/// 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);
|
||||
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::Static(node_id) => (tcx.hir.local_def_id(node_id), Substs::empty()),
|
||||
// global asm never has predicates
|
||||
|
@ -311,10 +241,10 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
|||
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;
|
||||
|
||||
return match *self {
|
||||
return match *self.as_trans_item() {
|
||||
TransItem::Fn(instance) => {
|
||||
to_string_internal(tcx, "fn ", instance)
|
||||
},
|
||||
|
@ -340,8 +270,8 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn to_raw_string(&self) -> String {
|
||||
match *self {
|
||||
fn to_raw_string(&self) -> String {
|
||||
match *self.as_trans_item() {
|
||||
TransItem::Fn(instance) => {
|
||||
format!("Fn({:?}, {})",
|
||||
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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue