提交 132bde7c 编写于 作者: A Alex Crichton

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.
上级 dba3ddd8
......@@ -576,6 +576,7 @@ pub fn to_dep_node(self, tcx: TyCtxt, kind: DepKind) -> DepNode {
[] 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;
}
......
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::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 @@ fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
}
}
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 @@ fn default() -> Self {
[] 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::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 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 @@ fn module_translation<'a, '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 @@ pub fn new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> 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 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::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 @@ pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
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 @@ pub fn output_filenames(&self) -> &OutputFilenames {
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 @@ fn local(&self) -> &'b LocalCrateContext<'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 @@ pub struct CrateInfo {
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::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,
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,
}
}
pub trait CodegenUnitExt<'tcx> {
fn as_codegen_unit(&self) -> &CodegenUnit<'tcx>;
pub fn empty(name: InternedString) -> Self {
Self::new(name, FxHashMap())
fn contains_item(&self, item: &TransItem<'tcx>) -> bool {
self.items().contains_key(item)
}
pub fn contains_item(&self, item: &TransItem<'tcx>) -> bool {
self.items.contains_key(item)
fn name<'a>(&'a self) -> &'a InternedString
where 'tcx: 'a,
{
&self.as_codegen_unit().name()
}
pub fn name(&self) -> &str {
&self.name
fn items(&self) -> &FxHashMap<TransItem<'tcx>, (Linkage, Visibility)> {
&self.as_codegen_unit().items()
}
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 @@ pub fn compute_symbol_name_hash<'a>(&self,
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 @@ fn item_sort_key<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, '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 @@ fn item_sort_key<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, '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 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 @@ pub fn define(&self, ccx: &CrateContext<'a, '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 @@ pub fn predefine(&self,
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 @@ pub fn predefine(&self,
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 @@ pub fn symbol_name(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::SymbolName {
}
}
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 @@ pub fn local_span(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Span> {
}.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 @@ pub fn instantiation_mode(&self,
}
}
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 @@ pub fn is_generic_fn(&self) -> bool {
}
}
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 @@ pub fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<llvm::Link
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 @@ pub fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<llvm::Link
/// 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 @@ pub fn is_instantiable(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
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 @@ fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, '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 @@ pub fn to_raw_string(&self) -> String {
}
}
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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册