From d5ed655a0824b2d525e6fad4f3b23f77432ebf98 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 19 Feb 2018 12:41:10 +0100 Subject: [PATCH 1/6] Use DefId instead of NodeId while generating debuginfo for statics. --- src/librustc_trans/consts.rs | 2 +- src/librustc_trans/debuginfo/metadata.rs | 19 +++++++++---------- src/librustc_trans/debuginfo/mod.rs | 6 +++--- src/librustc_trans/debuginfo/namespace.rs | 11 ----------- src/librustc_trans/debuginfo/utils.rs | 4 +--- 5 files changed, 14 insertions(+), 28 deletions(-) diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index d5b33d837c5bd..82e59bf4f5d16 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -304,7 +304,7 @@ pub fn trans_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, } } - debuginfo::create_global_var_metadata(cx, id, g); + debuginfo::create_global_var_metadata(cx, def_id, g); if attr::contains_name(attrs, "thread_local") { llvm::set_thread_local_mode(g, cx.tls_model); diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 62ba91840d95e..2c430d03c968e 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -14,7 +14,7 @@ use self::EnumDiscriminantInfo::*; use super::utils::{debug_context, DIB, span_start, get_namespace_for_item, create_DIArray, is_node_local_to_unit}; -use super::namespace::mangled_name_of_item; +use super::namespace::mangled_name_of_instance; use super::type_names::compute_debuginfo_type_name; use super::{CrateDebugContext}; use abi; @@ -1634,19 +1634,18 @@ fn create_union_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, /// /// Adds the created metadata nodes directly to the crate's IR. pub fn create_global_var_metadata(cx: &CodegenCx, - node_id: ast::NodeId, + def_id: DefId, global: ValueRef) { if cx.dbg_cx.is_none() { return; } let tcx = cx.tcx; - let node_def_id = tcx.hir.local_def_id(node_id); - let no_mangle = attr::contains_name(&tcx.get_attrs(node_def_id), "no_mangle"); + let no_mangle = attr::contains_name(&tcx.get_attrs(def_id), "no_mangle"); // We may want to remove the namespace scope if we're in an extern block, see: // https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952 - let var_scope = get_namespace_for_item(cx, node_def_id); - let span = cx.tcx.def_span(node_def_id); + let var_scope = get_namespace_for_item(cx, def_id); + let span = cx.tcx.def_span(def_id); let (file_metadata, line_number) = if span != syntax_pos::DUMMY_SP { let loc = span_start(cx, span); @@ -1655,15 +1654,15 @@ pub fn create_global_var_metadata(cx: &CodegenCx, (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) }; - let is_local_to_unit = is_node_local_to_unit(cx, node_id); - let variable_type = Instance::mono(cx.tcx, node_def_id).ty(cx.tcx); + let is_local_to_unit = is_node_local_to_unit(cx, def_id); + let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx); let type_metadata = type_metadata(cx, variable_type, span); - let var_name = tcx.item_name(node_def_id).to_string(); + let var_name = tcx.item_name(def_id).to_string(); let var_name = CString::new(var_name).unwrap(); let linkage_name = if no_mangle { None } else { - let linkage_name = mangled_name_of_item(cx, node_id); + let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id)); Some(CString::new(linkage_name.to_string()).unwrap()) }; diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index 9071eb776d529..16279f31836a9 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -254,14 +254,14 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let linkage_name = mangled_name_of_instance(cx, instance); let scope_line = span_start(cx, span).line; - - let local_id = cx.tcx.hir.as_local_node_id(instance.def_id()); - let is_local_to_unit = local_id.map_or(false, |id| is_node_local_to_unit(cx, id)); + let is_local_to_unit = is_node_local_to_unit(cx, def_id); let function_name = CString::new(name).unwrap(); let linkage_name = CString::new(linkage_name.to_string()).unwrap(); let mut flags = DIFlags::FlagPrototyped; + + let local_id = cx.tcx.hir.as_local_node_id(def_id); match *cx.sess().entry_fn.borrow() { Some((id, _)) => { if local_id == Some(id) { diff --git a/src/librustc_trans/debuginfo/namespace.rs b/src/librustc_trans/debuginfo/namespace.rs index 46067a4330396..891bf649c388a 100644 --- a/src/librustc_trans/debuginfo/namespace.rs +++ b/src/librustc_trans/debuginfo/namespace.rs @@ -14,7 +14,6 @@ use super::metadata::{unknown_file_metadata, UNKNOWN_LINE_NUMBER}; use super::utils::{DIB, debug_context}; use monomorphize::Instance; use rustc::ty; -use syntax::ast; use llvm; use llvm::debuginfo::DIScope; @@ -33,16 +32,6 @@ pub fn mangled_name_of_instance<'a, 'tcx>( tcx.symbol_name(instance) } -pub fn mangled_name_of_item<'a, 'tcx>( - cx: &CodegenCx<'a, 'tcx>, - node_id: ast::NodeId, -) -> ty::SymbolName { - let tcx = cx.tcx; - let node_def_id = tcx.hir.local_def_id(node_id); - let instance = Instance::mono(tcx, node_def_id); - tcx.symbol_name(instance) -} - pub fn item_namespace(cx: &CodegenCx, def_id: DefId) -> DIScope { if let Some(&scope) = debug_context(cx).namespace_map.borrow().get(&def_id) { return scope; diff --git a/src/librustc_trans/debuginfo/utils.rs b/src/librustc_trans/debuginfo/utils.rs index c571b84b8e9ed..9559cd4d9ea2d 100644 --- a/src/librustc_trans/debuginfo/utils.rs +++ b/src/librustc_trans/debuginfo/utils.rs @@ -21,9 +21,8 @@ use llvm::debuginfo::{DIScope, DIBuilderRef, DIDescriptor, DIArray}; use common::{CodegenCx}; use syntax_pos::{self, Span}; -use syntax::ast; -pub fn is_node_local_to_unit(cx: &CodegenCx, node_id: ast::NodeId) -> bool +pub fn is_node_local_to_unit(cx: &CodegenCx, def_id: DefId) -> bool { // The is_local_to_unit flag indicates whether a function is local to the // current compilation unit (i.e. if it is *static* in the C-sense). The @@ -33,7 +32,6 @@ pub fn is_node_local_to_unit(cx: &CodegenCx, node_id: ast::NodeId) -> bool // visible). It might better to use the `exported_items` set from // `driver::CrateAnalysis` in the future, but (atm) this set is not // available in the translation pass. - let def_id = cx.tcx.hir.local_def_id(node_id); !cx.tcx.is_exported_symbol(def_id) } From 15ff0adcde77776e2947d147a756d4289aa42e59 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 19 Feb 2018 13:29:22 +0100 Subject: [PATCH 2/6] Use DefId instead of NodeId in MonoItem::Static. --- src/librustc/mir/mono.rs | 7 +++-- src/librustc_mir/monomorphize/collector.rs | 12 ++++---- src/librustc_mir/monomorphize/item.rs | 16 +++++------ src/librustc_mir/monomorphize/partitioning.rs | 16 +++++++++-- src/librustc_trans/consts.rs | 26 ++++++++--------- src/librustc_trans/trans_item.rs | 28 ++++++++++++++----- 6 files changed, 64 insertions(+), 41 deletions(-) diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs index 49e5c0dc21f9e..7f8f2e9b90603 100644 --- a/src/librustc/mir/mono.rs +++ b/src/librustc/mir/mono.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use hir::def_id::DefId; use syntax::ast::NodeId; use syntax::symbol::InternedString; use ty::{Instance, TyCtxt}; @@ -21,7 +22,7 @@ use std::hash::Hash; #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)] pub enum MonoItem<'tcx> { Fn(Instance<'tcx>), - Static(NodeId), + Static(DefId), GlobalAsm(NodeId), } @@ -50,7 +51,9 @@ impl<'tcx> HashStable> for MonoItem<'tcx> { MonoItem::Fn(ref instance) => { instance.hash_stable(hcx, hasher); } - MonoItem::Static(node_id) | + MonoItem::Static(def_id) => { + def_id.hash_stable(hcx, hasher); + } MonoItem::GlobalAsm(node_id) => { hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { node_id.hash_stable(hcx, hasher); diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index a80dfaef0dab1..eb4ba21489c3d 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -368,8 +368,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let recursion_depth_reset; match starting_point { - MonoItem::Static(node_id) => { - let def_id = tcx.hir.local_def_id(node_id); + MonoItem::Static(def_id) => { let instance = Instance::mono(tcx, def_id); // Sanity check whether this ended up being collected accidentally @@ -652,8 +651,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { let tcx = self.tcx; let instance = Instance::mono(tcx, static_.def_id); if should_monomorphize_locally(tcx, &instance) { - let node_id = tcx.hir.as_local_node_id(static_.def_id).unwrap(); - self.output.push(MonoItem::Static(node_id)); + self.output.push(MonoItem::Static(static_.def_id)); } self.super_static(static_, context, location); @@ -946,10 +944,10 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> { self.output.push(MonoItem::GlobalAsm(item.id)); } hir::ItemStatic(..) => { + let def_id = self.tcx.hir.local_def_id(item.id); debug!("RootCollector: ItemStatic({})", - def_id_to_string(self.tcx, - self.tcx.hir.local_def_id(item.id))); - self.output.push(MonoItem::Static(item.id)); + def_id_to_string(self.tcx, def_id)); + self.output.push(MonoItem::Static(def_id)); } hir::ItemConst(..) => { // const items only generate mono items if they are diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index a5078187a57e3..549919a2c8919 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -97,8 +97,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug { fn symbol_name(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::SymbolName { match *self.as_mono_item() { MonoItem::Fn(instance) => tcx.symbol_name(instance), - MonoItem::Static(node_id) => { - let def_id = tcx.hir.local_def_id(node_id); + MonoItem::Static(def_id) => { tcx.symbol_name(Instance::mono(tcx, def_id)) } MonoItem::GlobalAsm(node_id) => { @@ -159,7 +158,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug { fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option { let def_id = match *self.as_mono_item() { MonoItem::Fn(ref instance) => instance.def_id(), - MonoItem::Static(node_id) => tcx.hir.local_def_id(node_id), + MonoItem::Static(def_id) => def_id, MonoItem::GlobalAsm(..) => return None, }; @@ -209,7 +208,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug { debug!("is_instantiable({:?})", self); let (def_id, substs) = match *self.as_mono_item() { MonoItem::Fn(ref instance) => (instance.def_id(), instance.substs), - MonoItem::Static(node_id) => (tcx.hir.local_def_id(node_id), Substs::empty()), + MonoItem::Static(def_id) => (def_id, Substs::empty()), // global asm never has predicates MonoItem::GlobalAsm(..) => return true }; @@ -218,14 +217,11 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug { } fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String { - let hir_map = &tcx.hir; - return match *self.as_mono_item() { MonoItem::Fn(instance) => { to_string_internal(tcx, "fn ", instance) }, - MonoItem::Static(node_id) => { - let def_id = hir_map.local_def_id(node_id); + MonoItem::Static(def_id) => { let instance = Instance::new(def_id, tcx.intern_substs(&[])); to_string_internal(tcx, "static ", instance) }, @@ -251,7 +247,9 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug { MonoItem::Fn(Instance { def, .. }) => { tcx.hir.as_local_node_id(def.def_id()) } - MonoItem::Static(node_id) | + MonoItem::Static(def_id) => { + tcx.hir.as_local_node_id(def_id) + } MonoItem::GlobalAsm(node_id) => { Some(node_id) } diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index e9471cdb4f949..2b558e71483c6 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -180,7 +180,9 @@ pub trait CodegenUnitExt<'tcx> { } } } - MonoItem::Static(node_id) | + MonoItem::Static(def_id) => { + tcx.hir.as_local_node_id(def_id) + } MonoItem::GlobalAsm(node_id) => { Some(node_id) } @@ -382,7 +384,15 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; (Linkage::External, visibility) } - MonoItem::Static(node_id) | + MonoItem::Static(def_id) => { + let visibility = if tcx.is_exported_symbol(def_id) { + can_be_internalized = false; + default_visibility(def_id) + } else { + Visibility::Hidden + }; + (Linkage::External, visibility) + } MonoItem::GlobalAsm(node_id) => { let def_id = tcx.hir.local_def_id(node_id); let visibility = if tcx.is_exported_symbol(def_id) { @@ -643,7 +653,7 @@ fn characteristic_def_id_of_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Some(def_id) } - MonoItem::Static(node_id) | + MonoItem::Static(def_id) => Some(def_id), MonoItem::GlobalAsm(node_id) => Some(tcx.hir.local_def_id(node_id)), } } diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index 82e59bf4f5d16..f9f185dfa5161 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; use base; -use monomorphize::{MonoItem, MonoItemExt}; +use monomorphize::MonoItem; use common::{CodegenCx, val_ty}; use declare; use monomorphize::Instance; @@ -110,7 +110,17 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { return g; } + let defined_in_current_codegen_unit = cx.codegen_unit + .items() + .contains_key(&MonoItem::Static(def_id)); + assert!(!defined_in_current_codegen_unit, + "consts::get_static() should always hit the cache for \ + statics defined in the same CGU, but did not for `{:?}`", + def_id); + let ty = instance.ty(cx.tcx); + let sym = cx.tcx.symbol_name(instance); + let g = if let Some(id) = cx.tcx.hir.as_local_node_id(def_id) { let llty = cx.layout_of(ty).llvm_type(cx); @@ -118,13 +128,6 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { hir_map::NodeItem(&hir::Item { ref attrs, span, node: hir::ItemStatic(..), .. }) => { - let sym = MonoItem::Static(id).symbol_name(cx.tcx); - - let defined_in_current_codegen_unit = cx.codegen_unit - .items() - .contains_key(&MonoItem::Static(id)); - assert!(!defined_in_current_codegen_unit); - if declare::get_declared_value(cx, &sym[..]).is_some() { span_bug!(span, "trans: Conflicting symbol names for static?"); } @@ -143,7 +146,7 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { hir_map::NodeForeignItem(&hir::ForeignItem { ref attrs, span, node: hir::ForeignItemStatic(..), .. }) => { - let sym = cx.tcx.symbol_name(instance); + let g = if let Some(name) = attr::first_attr_value_str_by_name(&attrs, "linkage") { // If this is a static with a linkage specified, then we need to handle @@ -203,8 +206,6 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { g } else { - let sym = cx.tcx.symbol_name(instance); - // FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow? // FIXME(nagisa): investigate whether it can be changed into define_global let g = declare::declare_global(cx, &sym, cx.layout_of(ty).llvm_type(cx)); @@ -246,11 +247,10 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { pub fn trans_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, m: hir::Mutability, - id: ast::NodeId, + def_id: DefId, attrs: &[ast::Attribute]) -> Result> { unsafe { - let def_id = cx.tcx.hir.local_def_id(id); let g = get_static(cx, def_id); let v = ::mir::trans_static_initializer(cx, def_id)?; diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 5eb6679fe252c..2751e32925931 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -24,10 +24,10 @@ use llvm; use monomorphize::Instance; use type_of::LayoutLlvmExt; use rustc::hir; +use rustc::hir::def_id::DefId; use rustc::mir::mono::{Linkage, Visibility}; use rustc::ty::TypeFoldable; use rustc::ty::layout::LayoutOf; -use syntax::ast; use syntax::attr; use std::fmt; @@ -44,11 +44,18 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> { cx.codegen_unit.name()); match *self.as_mono_item() { - MonoItem::Static(node_id) => { + MonoItem::Static(def_id) => { let tcx = cx.tcx; + let node_id = match tcx.hir.as_local_node_id(def_id) { + Some(node_id) => node_id, + None => { + bug!("MonoItemExt::define() called for non-local \ + static `{:?}`.", def_id) + } + }; let item = tcx.hir.expect_item(node_id); if let hir::ItemStatic(_, m, _) = item.node { - match consts::trans_static(&cx, m, item.id, &item.attrs) { + match consts::trans_static(&cx, m, def_id, &item.attrs) { Ok(_) => { /* Cool, everything's alright. */ }, Err(err) => { err.report(tcx, item.span, "static"); @@ -91,8 +98,8 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> { debug!("symbol {}", &symbol_name); match *self.as_mono_item() { - MonoItem::Static(node_id) => { - predefine_static(cx, node_id, linkage, visibility, &symbol_name); + MonoItem::Static(def_id) => { + predefine_static(cx, def_id, linkage, visibility, &symbol_name); } MonoItem::Fn(instance) => { predefine_fn(cx, instance, linkage, visibility, &symbol_name); @@ -126,11 +133,18 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> { impl<'a, 'tcx> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {} fn predefine_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - node_id: ast::NodeId, + def_id: DefId, linkage: Linkage, visibility: Visibility, symbol_name: &str) { - let def_id = cx.tcx.hir.local_def_id(node_id); + let node_id = match cx.tcx.hir.as_local_node_id(def_id) { + Some(node_id) => node_id, + None => { + bug!("MonoItemExt::predefine() called for non-local static `{:?}`.", + def_id) + } + }; + let instance = Instance::mono(cx.tcx, def_id); let ty = instance.ty(cx.tcx); let llty = cx.layout_of(ty).llvm_type(cx); From 8ff633cc3b85933e76c84b43d2c19250c397e9cb Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 19 Feb 2018 16:46:40 +0100 Subject: [PATCH 3/6] Implement describe_def query for LOCAL_CRATE --- src/librustc/hir/map/mod.rs | 98 +++++++++++++++++++++++++++++++++++ src/librustc/hir/mod.rs | 6 +++ src/librustc_driver/driver.rs | 1 + 3 files changed, 105 insertions(+) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index b6b3e8955351c..3799bdada888e 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -22,6 +22,7 @@ use hir::def_id::{CRATE_DEF_INDEX, DefId, LocalDefId, DefIndexAddressSpace}; use syntax::abi::Abi; use syntax::ast::{self, Name, NodeId, CRATE_NODE_ID}; use syntax::codemap::Spanned; +use syntax::ext::base::MacroKind; use syntax_pos::Span; use hir::*; @@ -32,6 +33,7 @@ use util::nodemap::{DefIdMap, FxHashMap}; use arena::TypedArena; use std::cell::RefCell; use std::io; +use ty::TyCtxt; pub mod blocks; mod collector; @@ -39,6 +41,7 @@ mod def_collector; pub mod definitions; mod hir_id_validator; + pub const ITEM_LIKE_SPACE: DefIndexAddressSpace = DefIndexAddressSpace::Low; pub const REGULAR_SPACE: DefIndexAddressSpace = DefIndexAddressSpace::High; @@ -373,6 +376,92 @@ impl<'hir> Map<'hir> { self.definitions.as_local_node_id(def_id.to_def_id()).unwrap() } + pub fn describe_def(&self, node_id: NodeId) -> Option { + let node = if let Some(node) = self.find(node_id) { + node + } else { + return None + }; + + match node { + NodeItem(item) => { + let def_id = || { + self.local_def_id(item.id) + }; + + match item.node { + ItemStatic(_, m, _) => Some(Def::Static(def_id(), + m == MutMutable)), + ItemConst(..) => Some(Def::Const(def_id())), + ItemFn(..) => Some(Def::Fn(def_id())), + ItemMod(..) => Some(Def::Mod(def_id())), + ItemGlobalAsm(..) => Some(Def::GlobalAsm(def_id())), + ItemTy(..) => Some(Def::TyAlias(def_id())), + ItemEnum(..) => Some(Def::Enum(def_id())), + ItemStruct(..) => Some(Def::Struct(def_id())), + ItemUnion(..) => Some(Def::Union(def_id())), + ItemTrait(..) => Some(Def::Trait(def_id())), + ItemTraitAlias(..) => { + bug!("trait aliases are not yet implemented (see issue #41517)") + }, + ItemExternCrate(_) | + ItemUse(..) | + ItemForeignMod(..) | + ItemImpl(..) => None, + } + } + NodeForeignItem(item) => { + let def_id = self.local_def_id(item.id); + match item.node { + ForeignItemFn(..) => Some(Def::Fn(def_id)), + ForeignItemStatic(_, m) => Some(Def::Static(def_id, m)), + ForeignItemType => Some(Def::TyForeign(def_id)), + } + } + NodeTraitItem(item) => { + let def_id = self.local_def_id(item.id); + match item.node { + TraitItemKind::Const(..) => Some(Def::AssociatedConst(def_id)), + TraitItemKind::Method(..) => Some(Def::Method(def_id)), + TraitItemKind::Type(..) => Some(Def::AssociatedTy(def_id)), + } + } + NodeImplItem(item) => { + let def_id = self.local_def_id(item.id); + match item.node { + ImplItemKind::Const(..) => Some(Def::AssociatedConst(def_id)), + ImplItemKind::Method(..) => Some(Def::Method(def_id)), + ImplItemKind::Type(..) => Some(Def::AssociatedTy(def_id)), + } + } + NodeVariant(variant) => { + let def_id = self.local_def_id(variant.node.data.id()); + Some(Def::Variant(def_id)) + } + NodeField(_) | + NodeExpr(_) | + NodeStmt(_) | + NodeTy(_) | + NodeTraitRef(_) | + NodePat(_) | + NodeBinding(_) | + NodeStructCtor(_) | + NodeLifetime(_) | + NodeVisibility(_) | + NodeBlock(_) => None, + NodeLocal(local) => { + Some(Def::Local(local.id)) + } + NodeMacroDef(macro_def) => { + Some(Def::Macro(self.local_def_id(macro_def.id), + MacroKind::Bang)) + } + NodeTyParam(param) => { + Some(Def::TyParam(self.local_def_id(param.id))) + } + } + } + fn entry_count(&self) -> usize { self.map.len() } @@ -1275,3 +1364,12 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { } } } + +pub fn describe_def(tcx: TyCtxt, def_id: DefId) -> Option { + if let Some(node_id) = tcx.hir.as_local_node_id(def_id) { + tcx.hir.describe_def(node_id) + } else { + bug!("Calling local describe_def query provider for upstream DefId: {:?}", + def_id) + } +} diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index bc03f7ead8187..0fa1b95d8e777 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -43,6 +43,7 @@ use syntax::tokenstream::TokenStream; use syntax::util::ThinVec; use syntax::util::parser::ExprPrecedence; use ty::AdtKind; +use ty::maps::Providers; use rustc_data_structures::indexed_vec; @@ -2204,3 +2205,8 @@ pub type TraitMap = NodeMap>; // Map from the NodeId of a glob import to a list of items which are actually // imported. pub type GlobMap = NodeMap>; + + +pub fn provide(providers: &mut Providers) { + providers.describe_def = map::describe_def; +} diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index b8a1fe9910540..d283e13c95823 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -929,6 +929,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, } pub fn default_provide(providers: &mut ty::maps::Providers) { + hir::provide(providers); borrowck::provide(providers); mir::provide(providers); reachable::provide(providers); From 1be7f966e03f41eb299c184a3c0ad98018fb8fc4 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 19 Feb 2018 16:47:59 +0100 Subject: [PATCH 4/6] Rename is_translated_fn query to is_translated_item and make it support statics. --- src/librustc/dep_graph/dep_node.rs | 2 +- src/librustc/ty/maps/mod.rs | 2 +- src/librustc/ty/maps/plumbing.rs | 2 +- src/librustc_trans/base.rs | 5 +++-- src/librustc_trans/callee.rs | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 4034055d04155..aa678ba788a5b 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -625,7 +625,7 @@ define_dep_nodes!( <'tcx> [eval_always] CollectAndPartitionTranslationItems, [] ExportName(DefId), [] ContainsExternIndicator(DefId), - [] IsTranslatedFunction(DefId), + [] IsTranslatedItem(DefId), [] CodegenUnit(InternedString), [] CompileCodegenUnit(InternedString), [input] OutputFilenames, diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 21ffe6b895e72..be1d255afa191 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -349,7 +349,7 @@ define_maps! { <'tcx> [] fn export_name: ExportName(DefId) -> Option, [] fn contains_extern_indicator: ContainsExternIndicator(DefId) -> bool, [] fn symbol_export_level: GetSymbolExportLevel(DefId) -> SymbolExportLevel, - [] fn is_translated_function: IsTranslatedFunction(DefId) -> bool, + [] fn is_translated_item: IsTranslatedItem(DefId) -> bool, [] fn codegen_unit: CodegenUnit(InternedString) -> Arc>, [] fn compile_codegen_unit: CompileCodegenUnit(InternedString) -> Stats, [] fn output_filenames: output_filenames_node(CrateNum) diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index f02c7cbd0ea3e..146b3c859e933 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -929,7 +929,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::ContainsExternIndicator => { force!(contains_extern_indicator, def_id!()); } - DepKind::IsTranslatedFunction => { force!(is_translated_function, def_id!()); } + DepKind::IsTranslatedItem => { force!(is_translated_item, def_id!()); } DepKind::OutputFilenames => { force!(output_filenames, LOCAL_CRATE); } DepKind::TargetFeaturesWhitelist => { force!(target_features_whitelist, LOCAL_CRATE); } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 466a86e7ea558..c0785f5393716 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -1004,6 +1004,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>( let translation_items: DefIdSet = items.iter().filter_map(|trans_item| { match *trans_item { MonoItem::Fn(ref instance) => Some(instance.def_id()), + MonoItem::Static(def_id) => Some(def_id), _ => None, } }).collect(); @@ -1107,7 +1108,7 @@ impl CrateInfo { } } -fn is_translated_function(tcx: TyCtxt, id: DefId) -> bool { +fn is_translated_item(tcx: TyCtxt, id: DefId) -> bool { let (all_trans_items, _) = tcx.collect_and_partition_translation_items(LOCAL_CRATE); all_trans_items.contains(&id) @@ -1222,7 +1223,7 @@ pub fn provide(providers: &mut Providers) { providers.collect_and_partition_translation_items = collect_and_partition_translation_items; - providers.is_translated_function = is_translated_function; + providers.is_translated_item = is_translated_item; providers.codegen_unit = |tcx, name| { let (_, all) = tcx.collect_and_partition_translation_items(LOCAL_CRATE); diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index c3d5e08c73e7e..8c40aa6a2acba 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -149,7 +149,7 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage); - if cx.tcx.is_translated_function(instance_def_id) { + if cx.tcx.is_translated_item(instance_def_id) { if instance_def_id.is_local() { if !cx.tcx.is_exported_symbol(instance_def_id) { llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden); From 89b3ef3e8eae1a9cf119888341509e10fd7e1b9a Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 19 Feb 2018 16:49:20 +0100 Subject: [PATCH 5/6] Allow for instantiating statics from upstream crates. --- src/librustc_trans/consts.rs | 15 ++++++++---- src/librustc_trans/trans_item.rs | 40 +++++++++++++------------------- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index f9f185dfa5161..1608c4a87bf5c 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -226,8 +226,15 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { // statically in the final application, we always mark such symbols as 'dllimport'. // If final linkage happens to be static, we rely on compiler-emitted __imp_ stubs to // make things work. - unsafe { - llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport); + // + // However, in some scenarios we defer emission of statics to downstream + // crates, so there are cases where a static with an upstream DefId + // is actually present in the current crate. We can find out via the + // is_translated_item query. + if !cx.tcx.is_translated_item(def_id) { + unsafe { + llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport); + } } } g @@ -246,8 +253,8 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { } pub fn trans_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - m: hir::Mutability, def_id: DefId, + is_mutable: bool, attrs: &[ast::Attribute]) -> Result> { unsafe { @@ -298,7 +305,7 @@ pub fn trans_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, // As an optimization, all shared statics which do not have interior // mutability are placed into read-only memory. - if m != hir::MutMutable { + if !is_mutable { if cx.type_is_freeze(ty) { llvm::LLVMSetGlobalConstant(g, llvm::True); } diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 2751e32925931..91c1097fc7f8a 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -24,6 +24,7 @@ use llvm; use monomorphize::Instance; use type_of::LayoutLlvmExt; use rustc::hir; +use rustc::hir::def::Def; use rustc::hir::def_id::DefId; use rustc::mir::mono::{Linkage, Visibility}; use rustc::ty::TypeFoldable; @@ -46,24 +47,23 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> { match *self.as_mono_item() { MonoItem::Static(def_id) => { let tcx = cx.tcx; - let node_id = match tcx.hir.as_local_node_id(def_id) { - Some(node_id) => node_id, + let is_mutable = match tcx.describe_def(def_id) { + Some(Def::Static(_, is_mutable)) => is_mutable, + Some(other) => { + bug!("Expected Def::Static, found {:?}", other) + } None => { - bug!("MonoItemExt::define() called for non-local \ - static `{:?}`.", def_id) + bug!("Expected Def::Static for {:?}, found nothing", def_id) + } + }; + let attrs = tcx.get_attrs(def_id); + + match consts::trans_static(&cx, def_id, is_mutable, &attrs) { + Ok(_) => { /* Cool, everything's alright. */ }, + Err(err) => { + err.report(tcx, tcx.def_span(def_id), "static"); } }; - let item = tcx.hir.expect_item(node_id); - if let hir::ItemStatic(_, m, _) = item.node { - match consts::trans_static(&cx, m, def_id, &item.attrs) { - Ok(_) => { /* Cool, everything's alright. */ }, - Err(err) => { - err.report(tcx, item.span, "static"); - } - }; - } else { - span_bug!(item.span, "Mismatch between hir::Item type and TransItem type") - } } MonoItem::GlobalAsm(node_id) => { let item = cx.tcx.hir.expect_item(node_id); @@ -137,20 +137,12 @@ fn predefine_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, linkage: Linkage, visibility: Visibility, symbol_name: &str) { - let node_id = match cx.tcx.hir.as_local_node_id(def_id) { - Some(node_id) => node_id, - None => { - bug!("MonoItemExt::predefine() called for non-local static `{:?}`.", - def_id) - } - }; - let instance = Instance::mono(cx.tcx, def_id); let ty = instance.ty(cx.tcx); let llty = cx.layout_of(ty).llvm_type(cx); let g = declare::define_global(cx, symbol_name, llty).unwrap_or_else(|| { - cx.sess().span_fatal(cx.tcx.hir.span(node_id), + cx.sess().span_fatal(cx.tcx.def_span(def_id), &format!("symbol `{}` is already defined", symbol_name)) }); From 96147469c572ee82f79d9bc71f3fe83c1b315d5c Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 20 Feb 2018 16:46:16 +0100 Subject: [PATCH 6/6] experimental MIR-only RLIB support. --- src/bootstrap/bin/rustc.rs | 5 ++ src/librustc/dep_graph/dep_node.rs | 1 + src/librustc/session/config.rs | 2 + src/librustc/ty/maps/config.rs | 7 +++ src/librustc/ty/maps/mod.rs | 2 + src/librustc/ty/maps/plumbing.rs | 1 + src/librustc_metadata/cstore_impl.rs | 2 + src/librustc_metadata/encoder.rs | 18 +++++-- src/librustc_metadata/schema.rs | 1 + src/librustc_mir/monomorphize/collector.rs | 36 +++++++++++-- src/librustc_mir/monomorphize/mod.rs | 59 +++++++++++++--------- 11 files changed, 104 insertions(+), 30 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 55d104b182698..4cfe6c29fc571 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -253,6 +253,11 @@ fn main() { if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() { cmd.arg("-Z").arg("force-unstable-if-unmarked"); } + + // Don't use MIR only RLIBs for the compiler yet + if stage != "0" { + cmd.arg("-Zmir-only-rlibs=no"); + } } else { // Override linker if necessary. if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") { diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index aa678ba788a5b..37573af95e490 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -642,6 +642,7 @@ define_dep_nodes!( <'tcx> [] GetSymbolExportLevel(DefId), + [input] IsMirOnlyRlib(CrateNum), ); trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug { diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index cfbf233297cf8..8a3642f1cabea 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1322,6 +1322,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, epoch). Crates compiled with different epochs can be linked together."), run_dsymutil: Option = (None, parse_opt_bool, [TRACKED], "run `dsymutil` and delete intermediate object files"), + + mir_only_rlibs: Option = (Some(true), parse_opt_bool, [TRACKED], "go!"), } pub fn default_lib_output() -> CrateType { diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index eb07876b05f26..ca9295d0506b6 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -50,6 +50,13 @@ impl<'tcx, M: QueryConfig> QueryDescription<'tcx> for M { } } + +impl<'tcx> QueryDescription<'tcx> for queries::is_mir_only_rlib<'tcx> { + fn describe(_tcx: TyCtxt, cnum: CrateNum) -> String { + format!("computing whether `{}` is a MIR-only RLIB", cnum) + } +} + impl<'tcx> QueryDescription<'tcx> for queries::is_copy_raw<'tcx> { fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String { format!("computing whether `{}` is `Copy`", env.value) diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index be1d255afa191..49e54fd875000 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -374,6 +374,8 @@ define_maps! { <'tcx> // Get an estimate of the size of an InstanceDef based on its MIR for CGU partitioning. [] fn instance_def_size_estimate: instance_def_size_estimate_dep_node(ty::InstanceDef<'tcx>) -> usize, + + [] fn is_mir_only_rlib: IsMirOnlyRlib(CrateNum) -> bool, } ////////////////////////////////////////////////////////////////////// diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 146b3c859e933..5a59540782bd1 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -936,6 +936,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::TargetFeaturesEnabled => { force!(target_features_enabled, def_id!()); } DepKind::GetSymbolExportLevel => { force!(symbol_export_level, def_id!()); } + DepKind::IsMirOnlyRlib => { force!(is_mir_only_rlib, krate!()); } } true diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index d73e968a82760..09df595f445c9 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -237,6 +237,8 @@ provide! { <'tcx> tcx, def_id, other, cdata, has_copy_closures => { cdata.has_copy_closures(tcx.sess) } has_clone_closures => { cdata.has_clone_closures(tcx.sess) } + + is_mir_only_rlib => { cdata.root.is_mir_only_rlib } } pub fn provide<'tcx>(providers: &mut Providers<'tcx>) { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 78578ca179c82..6f6d9553009ef 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -415,6 +415,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let has_default_lib_allocator = attr::contains_name(tcx.hir.krate_attrs(), "default_lib_allocator"); let has_global_allocator = tcx.sess.has_global_allocator.get(); + + let is_mir_only_rlib = if tcx.sess.opts.debugging_opts.mir_only_rlibs != Some(false) { + let crate_types = tcx.sess.crate_types.borrow(); + crate_types.len() == 1 && crate_types[0] == config::CrateTypeRlib + } else { + false + }; + let root = self.lazy(&CrateRoot { name: tcx.crate_name(LOCAL_CRATE), triple: tcx.sess.opts.target_triple.clone(), @@ -423,6 +431,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { panic_strategy: tcx.sess.panic_strategy(), has_global_allocator: has_global_allocator, has_default_lib_allocator: has_default_lib_allocator, + is_mir_only_rlib, plugin_registrar_fn: tcx.sess .plugin_registrar_fn .get() @@ -833,7 +842,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let needs_inline = types > 0 || attr::requests_inline(&ast_item.attrs); let is_const_fn = sig.constness == hir::Constness::Const; let ast = if is_const_fn { Some(body) } else { None }; - let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; + let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir || + self.tcx.sess.opts.debugging_opts.mir_only_rlibs != Some(false); (ast, needs_inline || is_const_fn || always_encode_mir) } else { (None, false) @@ -1115,14 +1125,16 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { _ => None, }, mir: match item.node { - hir::ItemStatic(..) if self.tcx.sess.opts.debugging_opts.always_encode_mir => { + hir::ItemStatic(..) if self.tcx.sess.opts.debugging_opts.always_encode_mir || + self.tcx.sess.opts.debugging_opts.mir_only_rlibs != Some(false) => { self.encode_optimized_mir(def_id) } hir::ItemConst(..) => self.encode_optimized_mir(def_id), hir::ItemFn(_, _, constness, _, ref generics, _) => { let has_tps = generics.ty_params().next().is_some(); let needs_inline = has_tps || attr::requests_inline(&item.attrs); - let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; + let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir || + self.tcx.sess.opts.debugging_opts.mir_only_rlibs != Some(false); if needs_inline || constness == hir::Constness::Const || always_encode_mir { self.encode_optimized_mir(def_id) } else { diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index c542f65dcecf3..52333db6ffb95 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -191,6 +191,7 @@ pub struct CrateRoot { pub panic_strategy: PanicStrategy, pub has_global_allocator: bool, pub has_default_lib_allocator: bool, + pub is_mir_only_rlib: bool, pub plugin_registrar_fn: Option, pub macro_derive_registrar: Option, diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index eb4ba21489c3d..380a568a3791f 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -192,6 +192,7 @@ use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::map as hir_map; +use rustc::hir::def::Def; use rustc::hir::def_id::DefId; use rustc::middle::const_val::ConstVal; use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem}; @@ -301,6 +302,18 @@ pub fn collect_crate_mono_items<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mode: MonoItemCollectionMode) -> (FxHashSet>, InliningMap<'tcx>) { + let current_crate_is_mir_only_rlib = + if tcx.sess.opts.debugging_opts.mir_only_rlibs != Some(false) { + let crate_types = tcx.sess.crate_types.borrow(); + crate_types.len() == 1 && crate_types[0] == config::CrateTypeRlib + } else { + false + }; + + if current_crate_is_mir_only_rlib { + return (FxHashSet(), InliningMap::new()) + } + let roots = collect_roots(tcx, mode); debug!("Building mono item graph, beginning at roots"); @@ -342,6 +355,22 @@ fn collect_roots<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; tcx.hir.krate().visit_all_item_likes(&mut visitor); + + // Collect upstream roots + for &cnum in tcx.crates().iter() { + if tcx.is_mir_only_rlib(cnum) { + for &def_id in tcx.exported_symbol_ids(cnum).iter() { + match tcx.describe_def(def_id) { + Some(Def::Static(..)) => { + visitor.output.push(MonoItem::Static(def_id)); + } + _ => { + visitor.push_if_root(def_id); + } + } + } + } + } } // We can only translate items that are instantiable - items all of @@ -383,7 +412,8 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } MonoItem::Fn(instance) => { // Sanity check whether this ended up being collected accidentally - debug_assert!(should_monomorphize_locally(tcx, &instance)); + debug_assert!(should_monomorphize_locally(tcx, &instance), + "Instantiation Error: {:?}", instance); // Keep track of the monomorphization recursion depth recursion_depth_reset = Some(check_recursion_limit(tcx, @@ -736,8 +766,8 @@ fn should_monomorphize_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: } Some(_) => true, None => { - if tcx.is_exported_symbol(def_id) || - tcx.is_foreign_item(def_id) + if tcx.is_foreign_item(def_id) || + (!tcx.is_mir_only_rlib(def_id.krate) && tcx.is_exported_symbol(def_id)) { // We can link to the item in question, no instance needed // in this crate diff --git a/src/librustc_mir/monomorphize/mod.rs b/src/librustc_mir/monomorphize/mod.rs index 95ebb6c970a58..4accabc0d5302 100644 --- a/src/librustc_mir/monomorphize/mod.rs +++ b/src/librustc_mir/monomorphize/mod.rs @@ -42,30 +42,41 @@ pub fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tra let trans_item1 = pair[0].0; let trans_item2 = pair[1].0; - let span1 = trans_item1.local_span(tcx); - let span2 = trans_item2.local_span(tcx); - - // Deterministically select one of the spans for error reporting - let span = match (span1, span2) { - (Some(span1), Some(span2)) => { - Some(if span1.lo().0 > span2.lo().0 { - span1 - } else { - span2 - }) - } - (Some(span), None) | - (None, Some(span)) => Some(span), - _ => None - }; - - let error_message = format!("symbol `{}` is already defined", sym1); - - if let Some(span) = span { - tcx.sess.span_fatal(span, &error_message) - } else { - tcx.sess.fatal(&error_message) - } + bug!("encountered two distinct MonoItems with the same symbol name:\n\ + symbol name: {}\n\ + item 1: {:?}\n\ + item 2: {:?}", + sym1, + trans_item1, + trans_item2) + + // let span1 = trans_item1.local_span(tcx); + // let span2 = trans_item2.local_span(tcx); + + // // Deterministically select one of the spans for error reporting + // let span = match (span1, span2) { + // (Some(span1), Some(span2)) => { + // Some(if span1.lo().0 > span2.lo().0 { + // span1 + // } else { + // span2 + // }) + // } + // (Some(span), None) | + // (None, Some(span)) => Some(span), + // _ => None + // }; + + + // let error_message = format!("assert_symbols_are_distinct: symbol `{}` is already defined", sym1); + + // if let Some(span) = span { + // tcx.sess.span_fatal(span, &error_message) + // span_bug!(span, "{}", ) + + // } else { + // tcx.sess.fatal(&error_message) + // } } } }