From 368e586a3d01797b8092b99279aac660c64187b3 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Tue, 27 Feb 2018 22:08:46 -0500 Subject: [PATCH] Add linkage to TransFnAttrs Part of #47320 --- src/librustc/hir/mod.rs | 3 ++ src/librustc/ich/impls_hir.rs | 2 ++ src/librustc/mir/mono.rs | 2 +- src/librustc_mir/monomorphize/item.rs | 46 ++------------------------- src/librustc_trans/base.rs | 1 - src/librustc_trans/consts.rs | 10 +----- src/librustc_typeck/collect.rs | 38 ++++++++++++++++++++++ 7 files changed, 48 insertions(+), 54 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index b484c62188d39..f4638c23c5f4b 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -30,6 +30,7 @@ pub use self::Visibility::{Public, Inherited}; use hir::def::Def; use hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX}; use util::nodemap::{NodeMap, FxHashSet}; +use mir::mono::Linkage; use syntax_pos::{Span, DUMMY_SP}; use syntax::codemap::{self, Spanned}; @@ -2218,6 +2219,7 @@ pub struct TransFnAttrs { pub inline: InlineAttr, pub export_name: Option, pub target_features: Vec, + pub linkage: Option, } bitflags! { @@ -2240,6 +2242,7 @@ impl TransFnAttrs { inline: InlineAttr::None, export_name: None, target_features: vec![], + linkage: None, } } diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 69487d3899e7f..faad3f3563164 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -1149,12 +1149,14 @@ impl<'hir> HashStable> for hir::TransFnAttrs inline, export_name, ref target_features, + linkage, } = *self; flags.hash_stable(hcx, hasher); inline.hash_stable(hcx, hasher); export_name.hash_stable(hcx, hasher); target_features.hash_stable(hcx, hasher); + linkage.hash_stable(hcx, hasher); } } diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs index 7f8f2e9b90603..d8eac2b415989 100644 --- a/src/librustc/mir/mono.rs +++ b/src/librustc/mir/mono.rs @@ -73,7 +73,7 @@ pub struct CodegenUnit<'tcx> { size_estimate: Option, } -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub enum Linkage { External, AvailableExternally, diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index 6f6f5e13c635c..38b8ffc6b9c80 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -21,7 +21,7 @@ use rustc::session::config::OptLevel; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::Substs; use syntax::ast; -use syntax::attr::{self, InlineAttr}; +use syntax::attr::InlineAttr; use std::fmt::{self, Write}; use std::iter; use rustc::mir::mono::Linkage; @@ -29,33 +29,6 @@ use syntax_pos::symbol::Symbol; use syntax::codemap::Span; pub use rustc::mir::mono::MonoItem; -pub fn linkage_by_name(name: &str) -> Option { - use rustc::mir::mono::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 - // the user knows what s/he's doing. Who knows, unanticipated use cases - // may pop up in the future. - // - // 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(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, - } -} - /// Describes how a translation item will be instantiated in object files. #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)] pub enum InstantiationMode { @@ -164,21 +137,8 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug { MonoItem::GlobalAsm(..) => return None, }; - let attributes = tcx.get_attrs(def_id); - if let Some(name) = attr::first_attr_value_str_by_name(&attributes, "linkage") { - if let Some(linkage) = linkage_by_name(&name.as_str()) { - Some(linkage) - } else { - let span = tcx.hir.span_if_local(def_id); - if let Some(span) = span { - tcx.sess.span_fatal(span, "invalid linkage specified") - } else { - tcx.sess.fatal(&format!("invalid linkage specified: {}", name)) - } - } - } else { - None - } + let trans_fn_attrs = tcx.trans_fn_attrs(def_id); + trans_fn_attrs.linkage } /// Returns whether this instance is instantiable - whether it has no unsatisfied diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index beb7a091bdcfe..3708f6f6ec4fc 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -90,7 +90,6 @@ use syntax::ast; use mir::operand::OperandValue; pub use rustc_trans_utils::check_for_rustc_errors_attr; -pub use rustc_mir::monomorphize::item::linkage_by_name; pub struct StatRecorder<'a, 'tcx: 'a> { cx: &'a CodegenCx<'a, 'tcx>, diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index fd9cb8c5a6bed..0ce3f729305b4 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -146,20 +146,12 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { hir_map::NodeForeignItem(&hir::ForeignItem { ref attrs, span, node: hir::ForeignItemStatic(..), .. }) => { - - let g = if let Some(name) = - attr::first_attr_value_str_by_name(&attrs, "linkage") { + let g = if let Some(linkage) = cx.tcx.trans_fn_attrs(def_id).linkage { // If this is a static with a linkage specified, then we need to handle // it a little specially. The typesystem prevents things like &T and // 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::linkage_by_name(&name.as_str()) { - Some(linkage) => linkage, - None => { - cx.sess().span_fatal(span, "invalid linkage specified"); - } - }; let llty2 = match ty.sty { ty::TyRawPtr(ref mt) => cx.layout_of(mt.ty).llvm_type(cx), _ => { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index c16d2c593aafc..1a7d8bb56780e 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -30,6 +30,7 @@ use constrained_type_params as ctp; use middle::lang_items::SizedTraitLangItem; use middle::const_val::ConstVal; use middle::resolve_lifetime as rl; +use rustc::mir::mono::Linkage; use rustc::traits::Reveal; use rustc::ty::subst::Substs; use rustc::ty::{ToPredicate, ReprOptions}; @@ -1782,6 +1783,39 @@ fn from_target_feature( } } +fn linkage_by_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, name: &str) -> Linkage { + use rustc::mir::mono::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 + // the user knows what s/he's doing. Who knows, unanticipated use cases + // may pop up in the future. + // + // 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" => Appending, + "available_externally" => AvailableExternally, + "common" => Common, + "extern_weak" => ExternalWeak, + "external" => External, + "internal" => Internal, + "linkonce" => LinkOnceAny, + "linkonce_odr" => LinkOnceODR, + "private" => Private, + "weak" => WeakAny, + "weak_odr" => WeakODR, + _ => { + let span = tcx.hir.span_if_local(def_id); + if let Some(span) = span { + tcx.sess.span_fatal(span, "invalid linkage specified") + } else { + tcx.sess.fatal(&format!("invalid linkage specified: {}", name)) + } + } + } +} fn trans_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> TransFnAttrs { let attrs = tcx.get_attrs(id); @@ -1868,6 +1902,10 @@ fn trans_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> TransFnAt tcx.sess.span_err(attr.span, msg); } from_target_feature(tcx, attr, &whitelist, &mut trans_fn_attrs.target_features); + } else if attr.check_name("linkage") { + if let Some(val) = attr.value_str() { + trans_fn_attrs.linkage = Some(linkage_by_name(tcx, id, &val.as_str())); + } } }