From 132bde7cf1ee102b6eb370561bf9af9cfbfb4224 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 12 Sep 2017 11:04:46 -0700 Subject: [PATCH] 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. --- src/librustc/dep_graph/dep_node.rs | 1 + src/librustc/lib.rs | 1 + src/librustc/middle/trans.rs | 69 +++++++++ src/librustc/ty/maps.rs | 14 ++ src/librustc_trans/back/linker.rs | 6 +- src/librustc_trans/base.rs | 134 +++++++++++------- src/librustc_trans/collector.rs | 2 +- src/librustc_trans/consts.rs | 6 +- src/librustc_trans/context.rs | 8 +- src/librustc_trans/lib.rs | 1 + src/librustc_trans/partitioning.rs | 143 +++++++++---------- src/librustc_trans/trans_item.rs | 215 +++++++++++++++-------------- 12 files changed, 352 insertions(+), 248 deletions(-) create mode 100644 src/librustc/middle/trans.rs diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 757a256164e..afd31306817 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -576,6 +576,7 @@ define_dep_nodes!( <'tcx> [] StabilityIndex, [] AllCrateNums, [] ExportedSymbols, + [] CollectAndPartitionTranslationItems, ); trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug { diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 59edc9fb083..f7b1d2d92f7 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -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; } diff --git a/src/librustc/middle/trans.rs b/src/librustc/middle/trans.rs new file mode 100644 index 00000000000..e871a38c4ef --- /dev/null +++ b/src/librustc/middle/trans.rs @@ -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, (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, (Linkage, Visibility)> { + &self.items + } + + pub fn items_mut(&mut self) + -> &mut FxHashMap, (Linkage, Visibility)> + { + &mut self.items + } +} diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 2d3dc6cd65b..c6fff0071bf 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -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, + [] fn collect_and_partition_translation_items: + collect_and_partition_translation_items_node(CrateNum) + -> (Arc>>, Vec>>), } 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 +} diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index ec436bcb241..1eb3e86a15b 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -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(), } } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 5f8e95b6ca9..7d0e7c21074 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -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 { +pub fn linkage_by_name(name: &str) -> Option { + 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 { // 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>, Arc>>, Arc)>) -> (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>, - Vec>) { +fn collect_and_partition_translation_items<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + cnum: CrateNum, +) -> (Arc>>, Vec>>) +{ + 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::>() }); 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, + } +} diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index ff550d10c6d..a45bcb51ab5 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -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; diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index a566cddde56..4f78e77fc69 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -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 diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 94695b4e046..7a2db29705d 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -93,7 +93,7 @@ pub struct LocalCrateContext<'a, 'tcx: 'a> { llmod: ModuleRef, llcx: ContextRef, stats: Stats, - codegen_unit: CodegenUnit<'tcx>, + codegen_unit: Arc>, /// The translation items of the whole crate. crate_trans_items: Arc>>, @@ -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>, crate_trans_items: Arc>>, exported_symbols: Arc,) -> 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 } diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 8c8bd6a5e50..701c7be8ad6 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -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)) diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index d47739b906c..d4aecb9e56c 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -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, (llvm::Linkage, llvm::Visibility)>, -} - -impl<'tcx> CodegenUnit<'tcx> { - pub fn new(name: InternedString, - items: FxHashMap, (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, (Linkage, Visibility)> { + &self.as_codegen_unit().items() } - pub fn name(&self) -> &str { - &self.name - } - - pub fn items(&self) -> &FxHashMap, (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 ..]) diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 5a51f690c45..526b61303e1 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -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 { - match *self { + fn local_span(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option { + 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 { - let def_id = match *self { + fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option { + 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