From d5ed655a0824b2d525e6fad4f3b23f77432ebf98 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 19 Feb 2018 12:41:10 +0100 Subject: [PATCH 1/5] 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/5] 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/5] 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/5] 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/5] 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)) });