Skip to content

Commit

Permalink
Add linkage to TransFnAttrs
Browse files Browse the repository at this point in the history
Part of #47320
  • Loading branch information
wesleywiser committed Mar 7, 2018
1 parent 07890c5 commit 368e586
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 54 deletions.
3 changes: 3 additions & 0 deletions src/librustc/hir/mod.rs
Expand Up @@ -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};
Expand Down Expand Up @@ -2218,6 +2219,7 @@ pub struct TransFnAttrs {
pub inline: InlineAttr,
pub export_name: Option<Symbol>,
pub target_features: Vec<Symbol>,
pub linkage: Option<Linkage>,
}

bitflags! {
Expand All @@ -2240,6 +2242,7 @@ impl TransFnAttrs {
inline: InlineAttr::None,
export_name: None,
target_features: vec![],
linkage: None,
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/librustc/ich/impls_hir.rs
Expand Up @@ -1149,12 +1149,14 @@ impl<'hir> HashStable<StableHashingContext<'hir>> 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);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/mir/mono.rs
Expand Up @@ -73,7 +73,7 @@ pub struct CodegenUnit<'tcx> {
size_estimate: Option<usize>,
}

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
pub enum Linkage {
External,
AvailableExternally,
Expand Down
46 changes: 3 additions & 43 deletions src/librustc_mir/monomorphize/item.rs
Expand Up @@ -21,41 +21,14 @@ 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;
use syntax_pos::symbol::Symbol;
use syntax::codemap::Span;
pub use rustc::mir::mono::MonoItem;

pub fn linkage_by_name(name: &str) -> Option<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" => 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 {
Expand Down Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion src/librustc_trans/base.rs
Expand Up @@ -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>,
Expand Down
10 changes: 1 addition & 9 deletions src/librustc_trans/consts.rs
Expand Up @@ -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),
_ => {
Expand Down
38 changes: 38 additions & 0 deletions src/librustc_typeck/collect.rs
Expand Up @@ -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};
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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()));
}
}
}

Expand Down

0 comments on commit 368e586

Please sign in to comment.