trans: move exported_symbol to Instance::symbol_name.

This commit is contained in:
Eduard Burtescu 2016-05-12 19:52:38 +03:00
parent a6a5e4884a
commit c9a10bd26b
12 changed files with 155 additions and 135 deletions

View File

@ -205,6 +205,7 @@ pub trait CrateStore<'tcx> {
fn is_impl(&self, did: DefId) -> bool;
fn is_default_impl(&self, impl_did: DefId) -> bool;
fn is_extern_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId) -> bool;
fn is_foreign_item(&self, did: DefId) -> bool;
fn is_static_method(&self, did: DefId) -> bool;
fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool;
fn is_typedef(&self, did: DefId) -> bool;
@ -399,6 +400,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
fn is_default_impl(&self, impl_did: DefId) -> bool { bug!("is_default_impl") }
fn is_extern_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId) -> bool
{ bug!("is_extern_item") }
fn is_foreign_item(&self, did: DefId) -> bool { bug!("is_foreign_item") }
fn is_static_method(&self, did: DefId) -> bool { bug!("is_static_method") }
fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool { false }
fn is_typedef(&self, did: DefId) -> bool { bug!("is_typedef") }

View File

@ -284,6 +284,11 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
decoder::is_extern_item(&cdata, did.index, tcx)
}
fn is_foreign_item(&self, did: DefId) -> bool {
let cdata = self.get_crate_data(did.krate);
decoder::is_foreign_item(&cdata, did.index)
}
fn is_static_method(&self, def: DefId) -> bool
{
self.dep_graph.read(DepNode::MetaData(def));

View File

@ -1634,6 +1634,16 @@ pub fn is_extern_item<'a, 'tcx>(cdata: Cmd,
}
}
pub fn is_foreign_item(cdata: Cmd, id: DefIndex) -> bool {
let item_doc = cdata.lookup_item(id);
let parent_item_id = match item_parent_item(cdata, item_doc) {
None => return false,
Some(item_id) => item_id,
};
let parent_item_doc = cdata.lookup_item(parent_item_id.index);
item_family(parent_item_doc) == ForeignMod
}
pub fn is_impl(cdata: Cmd, id: DefIndex) -> bool {
let item_doc = cdata.lookup_item(id);
match item_family(item_doc) {

View File

@ -1354,6 +1354,8 @@ fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
let _task = index.record(def_id, rbml_w);
rbml_w.start_tag(tag_items_data_item);
encode_def_id_and_key(ecx, rbml_w, def_id);
let parent_id = ecx.tcx.map.get_parent(nitem.id);
encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id));
encode_visibility(rbml_w, &nitem.vis);
match nitem.node {
hir::ForeignItemFn(ref fndecl, _) => {

View File

@ -103,6 +103,7 @@ use util::sha2::{Digest, Sha256};
use rustc::middle::{cstore, weak_lang_items};
use rustc::hir::def_id::DefId;
use rustc::hir::map as hir_map;
use rustc::ty::{self, TyCtxt, TypeFoldable};
use rustc::ty::item_path::{self, ItemPathBuffer, RootMode};
use rustc::hir::map::definitions::{DefPath, DefPathData};
@ -192,89 +193,100 @@ fn get_symbol_hash<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
}
}
pub fn exported_name<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
instance: Instance<'tcx>)
-> String {
let Instance { def: def_id, ref substs } = instance;
impl<'a, 'tcx> Instance<'tcx> {
pub fn symbol_name(self, scx: &SharedCrateContext<'a, 'tcx>) -> String {
let Instance { def: def_id, ref substs } = self;
debug!("exported_name(def_id={:?}, substs={:?})",
def_id, substs);
debug!("symbol_name(def_id={:?}, substs={:?})",
def_id, substs);
let node_id = scx.tcx().map.as_local_node_id(instance.def);
let node_id = scx.tcx().map.as_local_node_id(def_id);
if let Some(id) = node_id {
if scx.sess().plugin_registrar_fn.get() == Some(id) {
let svh = &scx.link_meta().crate_hash;
let idx = instance.def.index;
return scx.sess().generate_plugin_registrar_symbol(svh, idx);
}
}
// FIXME(eddyb) Precompute a custom symbol name based on attributes.
let attrs;
let attrs = if let Some(id) = node_id {
scx.tcx().map.attrs(id)
} else {
attrs = scx.sess().cstore.item_attrs(def_id);
&attrs[..]
};
if let Some(name) = attr::find_export_name_attr(scx.sess().diagnostic(), attrs) {
// Use provided name
return name.to_string();
}
if attr::contains_name(attrs, "no_mangle") {
// Don't mangle
return scx.tcx().item_name(instance.def).as_str().to_string()
}
if let Some(name) = weak_lang_items::link_name(attrs) {
return name.to_string();
}
let def_path = scx.tcx().def_path(def_id);
// We want to compute the "type" of this item. Unfortunately, some
// kinds of items (e.g., closures) don't have an entry in the
// item-type array. So walk back up the find the closest parent
// that DOES have an entry.
let mut ty_def_id = def_id;
let instance_ty;
loop {
let key = scx.tcx().def_key(ty_def_id);
match key.disambiguated_data.data {
DefPathData::TypeNs(_) |
DefPathData::ValueNs(_) => {
instance_ty = scx.tcx().lookup_item_type(ty_def_id);
break;
}
_ => {
// if we're making a symbol for something, there ought
// to be a value or type-def or something in there
// *somewhere*
ty_def_id.index = key.parent.unwrap_or_else(|| {
bug!("finding type for {:?}, encountered def-id {:?} with no \
parent", def_id, ty_def_id);
});
if let Some(id) = node_id {
if scx.sess().plugin_registrar_fn.get() == Some(id) {
let svh = &scx.link_meta().crate_hash;
let idx = def_id.index;
return scx.sess().generate_plugin_registrar_symbol(svh, idx);
}
}
// FIXME(eddyb) Precompute a custom symbol name based on attributes.
let attrs = scx.tcx().get_attrs(def_id);
let is_foreign = if let Some(id) = node_id {
match scx.tcx().map.get(id) {
hir_map::NodeForeignItem(_) => true,
_ => false
}
} else {
scx.sess().cstore.is_foreign_item(def_id)
};
if let Some(name) = weak_lang_items::link_name(&attrs) {
return name.to_string();
}
if is_foreign {
if let Some(name) = attr::first_attr_value_str_by_name(&attrs, "link_name") {
return name.to_string();
}
// Don't mangle foreign items.
return scx.tcx().item_name(def_id).as_str().to_string();
}
if let Some(name) = attr::find_export_name_attr(scx.sess().diagnostic(), &attrs) {
// Use provided name
return name.to_string();
}
if attr::contains_name(&attrs, "no_mangle") {
// Don't mangle
return scx.tcx().item_name(def_id).as_str().to_string();
}
let def_path = scx.tcx().def_path(def_id);
// We want to compute the "type" of this item. Unfortunately, some
// kinds of items (e.g., closures) don't have an entry in the
// item-type array. So walk back up the find the closest parent
// that DOES have an entry.
let mut ty_def_id = def_id;
let instance_ty;
loop {
let key = scx.tcx().def_key(ty_def_id);
match key.disambiguated_data.data {
DefPathData::TypeNs(_) |
DefPathData::ValueNs(_) => {
instance_ty = scx.tcx().lookup_item_type(ty_def_id);
break;
}
_ => {
// if we're making a symbol for something, there ought
// to be a value or type-def or something in there
// *somewhere*
ty_def_id.index = key.parent.unwrap_or_else(|| {
bug!("finding type for {:?}, encountered def-id {:?} with no \
parent", def_id, ty_def_id);
});
}
}
}
// Erase regions because they may not be deterministic when hashed
// and should not matter anyhow.
let instance_ty = scx.tcx().erase_regions(&instance_ty.ty);
let hash = get_symbol_hash(scx, &def_path, instance_ty, substs.types.as_slice());
let mut buffer = SymbolPathBuffer {
names: Vec::with_capacity(def_path.data.len())
};
item_path::with_forced_absolute_paths(|| {
scx.tcx().push_item_path(&mut buffer, def_id);
});
mangle(buffer.names.into_iter(), Some(&hash[..]))
}
// Erase regions because they may not be deterministic when hashed
// and should not matter anyhow.
let instance_ty = scx.tcx().erase_regions(&instance_ty.ty);
let hash = get_symbol_hash(scx, &def_path, instance_ty, substs.types.as_slice());
let mut buffer = SymbolPathBuffer {
names: Vec::with_capacity(def_path.data.len())
};
item_path::with_forced_absolute_paths(|| {
scx.tcx().push_item_path(&mut buffer, def_id);
});
mangle(buffer.names.into_iter(), Some(&hash[..]))
}
struct SymbolPathBuffer {

View File

@ -30,7 +30,7 @@ pub use self::ValueOrigin::*;
use super::CrateTranslation;
use super::ModuleTranslation;
use back::{link, symbol_names};
use back::link;
use lint;
use llvm::{BasicBlockRef, Linkage, ValueRef, Vector, get_param};
use llvm;
@ -2635,10 +2635,7 @@ fn iter_functions(llmod: llvm::ModuleRef) -> ValueIter {
/// This list is later used by linkers to determine the set of symbols needed to
/// be exposed from a dynamic library and it's also encoded into the metadata.
pub fn filter_reachable_ids(scx: &SharedCrateContext) -> NodeSet {
scx.reachable().iter().map(|x| *x).filter(|id| {
// First, only worry about nodes which have a symbol name
scx.item_symbols().borrow().contains_key(id)
}).filter(|&id| {
scx.reachable().iter().map(|x| *x).filter(|&id| {
// Next, we want to ignore some FFI functions that are not exposed from
// this crate. Reachable FFI functions can be lumped into two
// categories:
@ -2656,7 +2653,18 @@ pub fn filter_reachable_ids(scx: &SharedCrateContext) -> NodeSet {
hir_map::NodeForeignItem(..) => {
scx.sess().cstore.is_statically_included_foreign_item(id)
}
_ => true,
// Only consider nodes that actually have exported symbols.
hir_map::NodeItem(&hir::Item {
node: hir::ItemStatic(..), .. }) |
hir_map::NodeItem(&hir::Item {
node: hir::ItemFn(..), .. }) |
hir_map::NodeTraitItem(&hir::TraitItem {
node: hir::MethodTraitItem(_, Some(_)), .. }) |
hir_map::NodeImplItem(&hir::ImplItem {
node: hir::ImplItemKind::Method(..), .. }) => true,
_ => false
}
}).collect()
}
@ -2775,8 +2783,9 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
.collect();
let sess = shared_ccx.sess();
let mut reachable_symbols = reachable_symbol_ids.iter().map(|id| {
shared_ccx.item_symbols().borrow()[id].to_string()
let mut reachable_symbols = reachable_symbol_ids.iter().map(|&id| {
let def_id = shared_ccx.tcx().map.local_def_id(id);
Instance::mono(&shared_ccx, def_id).symbol_name(&shared_ccx)
}).collect::<Vec<_>>();
if sess.entry_fn.borrow().is_some() {
reachable_symbols.push("main".to_string());
@ -2799,8 +2808,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
reachable_symbols.extend(syms.into_iter().filter(|did| {
sess.cstore.is_extern_item(shared_ccx.tcx(), *did)
}).map(|did| {
let instance = Instance::mono(shared_ccx.tcx(), did);
symbol_names::exported_name(&shared_ccx, instance)
Instance::mono(&shared_ccx, did).symbol_name(&shared_ccx)
}));
}

View File

@ -499,44 +499,20 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
return immediate_rvalue(llfn, fn_ptr_ty);
}
let attrs;
let local_id = ccx.tcx().map.as_local_node_id(def_id);
let maybe_node = local_id.and_then(|id| tcx.map.find(id));
let (sym, attrs, local_item) = match maybe_node {
let local_item = match local_id.and_then(|id| tcx.map.find(id)) {
Some(hir_map::NodeItem(&hir::Item {
ref attrs, id, span, node: hir::ItemFn(..), ..
span, node: hir::ItemFn(..), ..
})) |
Some(hir_map::NodeTraitItem(&hir::TraitItem {
ref attrs, id, span, node: hir::MethodTraitItem(_, Some(_)), ..
span, node: hir::MethodTraitItem(_, Some(_)), ..
})) |
Some(hir_map::NodeImplItem(&hir::ImplItem {
ref attrs, id, span, node: hir::ImplItemKind::Method(..), ..
span, node: hir::ImplItemKind::Method(..), ..
})) => {
let sym = symbol_names::exported_name(ccx.shared(), instance);
if declare::get_defined_value(ccx, &sym).is_some() {
ccx.sess().span_fatal(span,
&format!("symbol `{}` is already defined", sym));
}
(sym, &attrs[..], Some(id))
}
Some(hir_map::NodeForeignItem(&hir::ForeignItem {
ref attrs, name, node: hir::ForeignItemFn(..), ..
})) => {
(imported_name(name, attrs).to_string(), &attrs[..], None)
}
None => {
attrs = ccx.sess().cstore.item_attrs(def_id);
let sym = symbol_names::exported_name(ccx.shared(), instance);
(sym, &attrs[..], None)
}
ref variant => {
bug!("get_fn: unexpected variant: {:?}", variant)
Some(span)
}
_ => None
};
// This is subtle and surprising, but sometimes we have to bitcast
@ -563,8 +539,16 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
// reference. It also occurs when testing libcore and in some
// other weird situations. Annoying.
let sym = instance.symbol_name(ccx.shared());
let llptrty = type_of::type_of(ccx, fn_ptr_ty);
let llfn = if let Some(llfn) = declare::get_declared_value(ccx, &sym) {
if let Some(span) = local_item {
if declare::get_defined_value(ccx, &sym).is_some() {
ccx.sess().span_fatal(span,
&format!("symbol `{}` is already defined", sym));
}
}
if common::val_ty(llfn) != llptrty {
if local_item.is_some() {
bug!("symbol `{}` previously declared as {:?}, now wanted as {:?}",
@ -581,7 +565,8 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
assert_eq!(common::val_ty(llfn), llptrty);
debug!("get_fn: not casting pointer!");
attributes::from_fn_attrs(ccx, attrs, llfn);
let attrs = ccx.tcx().get_attrs(def_id);
attributes::from_fn_attrs(ccx, &attrs, llfn);
if local_item.is_some() {
// FIXME(eddyb) Doubt all extern fn should allow unwinding.
attributes::unwind(llfn, true);

View File

@ -150,7 +150,7 @@ fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
return llfn;
}
let symbol = symbol_names::exported_name(ccx.shared(), instance);
let symbol = instance.symbol_name(ccx.shared());
// Compute the rust-call form of the closure call method.
let sig = &tcx.closure_type(closure_id, substs).sig;

View File

@ -19,8 +19,7 @@ use rustc::hir::def::Def;
use rustc::hir::def_id::DefId;
use rustc::hir::map as hir_map;
use {abi, adt, closure, debuginfo, expr, machine};
use base::{self, imported_name, push_ctxt};
use back::symbol_names;
use base::{self, push_ctxt};
use callee::Callee;
use collector;
use trans_item::TransItem;
@ -1018,6 +1017,8 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId)
return Datum::new(g, ty, Lvalue::new("static"));
}
let sym = instance.symbol_name(ccx.shared());
let g = if let Some(id) = ccx.tcx().map.as_local_node_id(def_id) {
let llty = type_of::type_of(ccx, ty);
match ccx.tcx().map.get(id) {
@ -1028,7 +1029,6 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId)
// we need to get the symbol from metadata instead of
// using the current crate's name/version
// information in the hash of the symbol
let sym = symbol_names::exported_name(ccx.shared(), instance);
debug!("making {}", sym);
// Create the global before evaluating the initializer;
@ -1043,9 +1043,8 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId)
}
hir_map::NodeForeignItem(&hir::ForeignItem {
ref attrs, name, span, node: hir::ForeignItemStatic(..), ..
ref attrs, span, node: hir::ForeignItemStatic(..), ..
}) => {
let ident = imported_name(name, attrs);
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
@ -1067,7 +1066,7 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId)
};
unsafe {
// Declare a symbol `foo` with the desired linkage.
let g1 = declare::declare_global(ccx, &ident, llty2);
let g1 = declare::declare_global(ccx, &sym, llty2);
llvm::SetLinkage(g1, linkage);
// Declare an internal global `extern_with_linkage_foo` which
@ -1077,10 +1076,10 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId)
// `extern_with_linkage_foo` will instead be initialized to
// zero.
let mut real_name = "_rust_extern_with_linkage_".to_string();
real_name.push_str(&ident);
real_name.push_str(&sym);
let g2 = declare::define_global(ccx, &real_name, llty).unwrap_or_else(||{
ccx.sess().span_fatal(span,
&format!("symbol `{}` is already defined", ident))
&format!("symbol `{}` is already defined", sym))
});
llvm::SetLinkage(g2, llvm::InternalLinkage);
llvm::LLVMSetInitializer(g2, g1);
@ -1088,7 +1087,7 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId)
}
} else {
// Generate an external declaration.
declare::declare_global(ccx, &ident, llty)
declare::declare_global(ccx, &sym, llty)
};
for attr in attrs {
@ -1105,8 +1104,7 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId)
} else {
// 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 name = symbol_names::exported_name(ccx.shared(), instance);
let g = declare::declare_global(ccx, &name, type_of::type_of(ccx, ty));
let g = declare::declare_global(ccx, &sym, type_of::type_of(ccx, ty));
// Thread-local statics in some other crate need to *always* be linked
// against in a thread-local fashion, so we need to be sure to apply the
// thread-local attribute locally if it was present remotely. If we

View File

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use back::symbol_names;
use llvm::ValueRef;
use llvm;
use rustc::hir::def_id::DefId;
@ -88,7 +87,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
monomorphizing.insert(fn_id, depth + 1);
}
let symbol = symbol_names::exported_name(ccx.shared(), instance);
let symbol = instance.symbol_name(ccx.shared());
debug!("monomorphize_fn mangled to {}", symbol);
assert!(declare::get_defined_value(ccx, &symbol).is_none());

View File

@ -14,7 +14,6 @@
//! item-path. This is used for unit testing the code that generates
//! paths etc in all kinds of annoying scenarios.
use back::symbol_names;
use rustc::hir;
use rustc::hir::intravisit::{self, Visitor};
use syntax::ast;
@ -53,7 +52,7 @@ impl<'a, 'tcx> SymbolNamesTest<'a, 'tcx> {
if attr.check_name(SYMBOL_NAME) {
// for now, can only use on monomorphic names
let instance = Instance::mono(self.ccx.shared(), def_id);
let name = symbol_names::exported_name(self.ccx.shared(), instance);
let name = instance.symbol_name(self.ccx.shared());
tcx.sess.span_err(attr.span, &format!("symbol-name({})", name));
} else if attr.check_name(ITEM_PATH) {
let path = tcx.item_path_str(def_id);

View File

@ -25,7 +25,7 @@ mod bar {
use foo::Foo;
impl Foo {
#[rustc_symbol_name] //~ ERROR _ZN5impl13bar26_$LT$impl$u20$foo..Foo$GT$3baz
#[rustc_symbol_name] //~ ERROR _ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz
#[rustc_item_path] //~ ERROR item-path(bar::<impl foo::Foo>::baz)
fn baz() { }
}