From 7462da5c38db350292d1eae8961ea714232c612d Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 10 May 2016 23:21:18 +0300 Subject: [PATCH 1/8] rustc: use a simpler scheme for plugin registrar symbol names. --- src/librustc/session/mod.rs | 10 ++++++++++ src/librustc_metadata/creader.rs | 14 +++++++++----- src/librustc_metadata/decoder.rs | 8 -------- src/librustc_plugin/load.rs | 3 ++- src/librustc_trans/base.rs | 6 ++++++ 5 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 907241d1746d6..ab9187a835dad 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -9,6 +9,8 @@ // except according to those terms. use dep_graph::DepGraph; +use hir::def_id::DefIndex; +use hir::svh::Svh; use lint; use middle::cstore::CrateStore; use middle::dependency_format; @@ -312,6 +314,14 @@ impl Session { pub fn nonzeroing_move_hints(&self) -> bool { self.opts.debugging_opts.enable_nonzeroing_move_hints } + + /// Returns the symbol name for the registrar function, + /// given the crate Svh and the function DefIndex. + pub fn generate_plugin_registrar_symbol(&self, svh: &Svh, index: DefIndex) + -> String { + format!("__rustc_plugin_registrar__{}_{}", svh, index.as_usize()) + } + pub fn sysroot<'a>(&'a self) -> &'a Path { match self.opts.maybe_sysroot { Some (ref sysroot) => sysroot, diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index ad6bb2dbac221..2025045cc8f56 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -17,6 +17,7 @@ use cstore::{self, CStore, CrateSource, MetadataBlob}; use decoder; use loader::{self, CratePaths}; +use rustc::hir::def_id::DefIndex; use rustc::hir::svh::Svh; use rustc::dep_graph::{DepGraph, DepNode}; use rustc::session::{config, Session}; @@ -610,9 +611,10 @@ impl<'a> CrateReader<'a> { macros } - /// Look for a plugin registrar. Returns library path and symbol name. + /// Look for a plugin registrar. Returns library path, crate + /// SVH and DefIndex of the registrar function. pub fn find_plugin_registrar(&mut self, span: Span, name: &str) - -> Option<(PathBuf, String)> { + -> Option<(PathBuf, Svh, DefIndex)> { let ekrate = self.read_extension_crate(span, &CrateInfo { name: name.to_string(), ident: name.to_string(), @@ -630,12 +632,14 @@ impl<'a> CrateReader<'a> { span_fatal!(self.sess, span, E0456, "{}", &message[..]); } + let svh = decoder::get_crate_hash(ekrate.metadata.as_slice()); let registrar = - decoder::get_plugin_registrar_fn(ekrate.metadata.as_slice()) - .map(|id| decoder::get_symbol_from_buf(ekrate.metadata.as_slice(), id)); + decoder::get_plugin_registrar_fn(ekrate.metadata.as_slice()); match (ekrate.dylib.as_ref(), registrar) { - (Some(dylib), Some(reg)) => Some((dylib.to_path_buf(), reg)), + (Some(dylib), Some(reg)) => { + Some((dylib.to_path_buf(), svh, reg)) + } (None, Some(_)) => { span_err!(self.sess, span, E0457, "plugin `{}` only found in rlib format, but must be available \ diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index b6f35074b7dc7..7f79df97852b6 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -644,14 +644,6 @@ pub fn get_symbol(cdata: Cmd, id: DefIndex) -> String { return item_symbol(cdata.lookup_item(id)); } -/// If you have a crate_metadata, call get_symbol instead -pub fn get_symbol_from_buf(data: &[u8], id: DefIndex) -> String { - let index = load_index(data); - let pos = index.lookup_item(data, id).unwrap(); - let doc = reader::doc_at(data, pos as usize).unwrap().doc; - item_symbol(doc) -} - /// Iterates over the language items in the given crate. pub fn each_lang_item(cdata: Cmd, mut f: F) -> bool where F: FnMut(DefIndex, usize) -> bool, diff --git a/src/librustc_plugin/load.rs b/src/librustc_plugin/load.rs index 036e46c380398..11e1841f7493e 100644 --- a/src/librustc_plugin/load.rs +++ b/src/librustc_plugin/load.rs @@ -101,7 +101,8 @@ impl<'a> PluginLoader<'a> { fn load_plugin(&mut self, span: Span, name: &str, args: Vec>) { let registrar = self.reader.find_plugin_registrar(span, name); - if let Some((lib, symbol)) = registrar { + if let Some((lib, svh, index)) = registrar { + let symbol = self.sess.generate_plugin_registrar_symbol(&svh, index); let fun = self.dylink_registrar(span, lib, symbol); self.plugins.push(PluginRegistrar { fun: fun, diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 992e07fa7449d..451bfbc83bc1d 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -2443,6 +2443,12 @@ pub fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, -> String { let id = ccx.tcx().map.as_local_node_id(instance.def).unwrap(); + if ccx.sess().plugin_registrar_fn.get() == Some(id) { + let svh = &ccx.link_meta().crate_hash; + let idx = instance.def.index; + return ccx.sess().generate_plugin_registrar_symbol(svh, idx); + } + match ccx.external_srcs().borrow().get(&id) { Some(&did) => { let sym = ccx.sess().cstore.item_symbol(did); From 39184741bce5087337c3a8ee185b4c0a251d3e24 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 10 May 2016 23:24:17 +0300 Subject: [PATCH 2/8] trans: remove unused symbol_names::exported_name_with_suffix. --- src/librustc_trans/back/symbol_names.rs | 30 +++++-------------------- 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index 0cf82d66b2b68..0495cf5eb6718 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -116,7 +116,7 @@ pub fn def_id_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> def_path_to_string(tcx, &def_path) } -pub fn def_path_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_path: &DefPath) -> String { +fn def_path_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_path: &DefPath) -> String { let mut s = String::with_capacity(def_path.data.len() * 16); s.push_str(&tcx.crate_name(def_path.krate)); @@ -187,14 +187,13 @@ fn get_symbol_hash<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } } -fn exported_name_with_opt_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - instance: &Instance<'tcx>, - suffix: Option<&str>) - -> String { +pub fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, + instance: &Instance<'tcx>) + -> String { let &Instance { def: mut def_id, ref substs } = instance; - debug!("exported_name_with_opt_suffix(def_id={:?}, substs={:?}, suffix={:?})", - def_id, substs, suffix); + debug!("exported_name(def_id={:?}, substs={:?})", + def_id, substs); if let Some(node_id) = ccx.tcx().map.as_local_node_id(def_id) { if let Some(&src_def_id) = ccx.external_srcs().borrow().get(&node_id) { @@ -242,10 +241,6 @@ fn exported_name_with_opt_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, }; ccx.tcx().push_item_path(&mut buffer, def_id); - if let Some(suffix) = suffix { - buffer.push(suffix); - } - mangle(buffer.names.into_iter(), Some(&hash[..])) } @@ -264,19 +259,6 @@ impl ItemPathBuffer for SymbolPathBuffer { } } -pub fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - instance: &Instance<'tcx>) - -> String { - exported_name_with_opt_suffix(ccx, instance, None) -} - -pub fn exported_name_with_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - instance: &Instance<'tcx>, - suffix: &str) - -> String { - exported_name_with_opt_suffix(ccx, instance, Some(suffix)) -} - /// Only symbols that are invisible outside their compilation unit should use a /// name generated by this function. pub fn internal_name_from_type_and_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, From 14133d33bcc2e6e3939fa4b485294334366bf162 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Wed, 25 May 2016 01:34:17 +0300 Subject: [PATCH 3/8] trans: move exported_name's logic into symbol_names. --- src/librustc_trans/back/symbol_names.rs | 64 +++++++++++++++++-------- src/librustc_trans/base.rs | 44 +---------------- src/librustc_trans/callee.rs | 5 +- src/librustc_trans/closure.rs | 2 +- src/librustc_trans/consts.rs | 9 ++-- src/librustc_trans/context.rs | 4 ++ src/librustc_trans/monomorphize.rs | 2 +- src/librustc_trans/symbol_names_test.rs | 2 +- 8 files changed, 62 insertions(+), 70 deletions(-) diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index 0495cf5eb6718..dffd0beafe51b 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -97,17 +97,18 @@ //! virtually impossible. Thus, symbol hash generation exclusively relies on //! DefPaths which are much more robust in the face of changes to the code base. -use common::{CrateContext, gensym_name}; +use common::{CrateContext, SharedCrateContext, gensym_name}; use monomorphize::Instance; use util::sha2::{Digest, Sha256}; -use rustc::middle::cstore; +use rustc::middle::{cstore, weak_lang_items}; use rustc::hir::def_id::DefId; use rustc::ty::{self, TyCtxt, TypeFoldable}; -use rustc::ty::item_path::{ItemPathBuffer, RootMode}; +use rustc::ty::item_path::{self, ItemPathBuffer, RootMode}; use rustc::hir::map::definitions::{DefPath, DefPathData}; use std::fmt::Write; +use syntax::attr; use syntax::parse::token::{self, InternedString}; use serialize::hex::ToHex; @@ -134,7 +135,7 @@ fn def_path_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_path: &DefPath) s } -fn get_symbol_hash<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, +fn get_symbol_hash<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, // path to the item this name is for def_path: &DefPath, @@ -152,9 +153,9 @@ fn get_symbol_hash<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, debug!("get_symbol_hash(def_path={:?}, parameters={:?})", def_path, parameters); - let tcx = ccx.tcx(); + let tcx = scx.tcx(); - let mut hash_state = ccx.symbol_hasher().borrow_mut(); + let mut hash_state = scx.symbol_hasher().borrow_mut(); hash_state.reset(); @@ -187,22 +188,47 @@ fn get_symbol_hash<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } } -pub fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - instance: &Instance<'tcx>) +pub fn exported_name<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, + instance: Instance<'tcx>) -> String { - let &Instance { def: mut def_id, ref substs } = instance; + let Instance { def: def_id, ref substs } = instance; debug!("exported_name(def_id={:?}, substs={:?})", def_id, substs); - if let Some(node_id) = ccx.tcx().map.as_local_node_id(def_id) { - if let Some(&src_def_id) = ccx.external_srcs().borrow().get(&node_id) { - def_id = src_def_id; + let node_id = scx.tcx().map.as_local_node_id(instance.def); + + 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); } } - let def_path = ccx.tcx().def_path(def_id); - assert_eq!(def_path.krate, def_id.krate); + // 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 @@ -211,11 +237,11 @@ pub fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let mut ty_def_id = def_id; let instance_ty; loop { - let key = ccx.tcx().def_key(ty_def_id); + let key = scx.tcx().def_key(ty_def_id); match key.disambiguated_data.data { DefPathData::TypeNs(_) | DefPathData::ValueNs(_) => { - instance_ty = ccx.tcx().lookup_item_type(ty_def_id); + instance_ty = scx.tcx().lookup_item_type(ty_def_id); break; } _ => { @@ -232,9 +258,9 @@ pub fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, // Erase regions because they may not be deterministic when hashed // and should not matter anyhow. - let instance_ty = ccx.tcx().erase_regions(&instance_ty.ty); + let instance_ty = scx.tcx().erase_regions(&instance_ty.ty); - let hash = get_symbol_hash(ccx, &def_path, instance_ty, substs.types.as_slice()); + 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()) @@ -271,7 +297,7 @@ pub fn internal_name_from_type_and_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx> data: vec![], krate: cstore::LOCAL_CRATE, }; - let hash = get_symbol_hash(ccx, &def_path, t, &[]); + let hash = get_symbol_hash(ccx.shared(), &def_path, t, &[]); mangle(path.iter().cloned(), Some(&hash[..])) } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 451bfbc83bc1d..f6a2b82fb1668 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -2437,47 +2437,6 @@ pub fn create_entry_wrapper(ccx: &CrateContext, sp: Span, main_llfn: ValueRef) { } } -pub fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - instance: Instance<'tcx>, - attrs: &[ast::Attribute]) - -> String { - let id = ccx.tcx().map.as_local_node_id(instance.def).unwrap(); - - if ccx.sess().plugin_registrar_fn.get() == Some(id) { - let svh = &ccx.link_meta().crate_hash; - let idx = instance.def.index; - return ccx.sess().generate_plugin_registrar_symbol(svh, idx); - } - - match ccx.external_srcs().borrow().get(&id) { - Some(&did) => { - let sym = ccx.sess().cstore.item_symbol(did); - debug!("found item {} in other crate...", sym); - return sym; - } - None => {} - } - - match attr::find_export_name_attr(ccx.sess().diagnostic(), attrs) { - // Use provided name - Some(name) => name.to_string(), - _ => { - if attr::contains_name(attrs, "no_mangle") { - // Don't mangle - ccx.tcx().map.name(id).as_str().to_string() - } else { - match weak_lang_items::link_name(attrs) { - Some(name) => name.to_string(), - None => { - // Usual name mangling - symbol_names::exported_name(ccx, &instance) - } - } - } - } - } -} - pub fn imported_name(name: ast::Name, attrs: &[ast::Attribute]) -> InternedString { match attr::first_attr_value_str_by_name(attrs, "link_name") { Some(ln) => ln.clone(), @@ -2840,7 +2799,8 @@ 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| { - sess.cstore.item_symbol(did) + let instance = Instance::mono(shared_ccx.tcx(), did); + symbol_names::exported_name(&shared_ccx, instance) })); } diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index c0c5ea818b2d7..bdeb1a6270f95 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -512,7 +512,7 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, Some(hir_map::NodeImplItem(&hir::ImplItem { ref attrs, id, span, node: hir::ImplItemKind::Method(..), .. })) => { - let sym = exported_name(ccx, instance, attrs); + let sym = symbol_names::exported_name(ccx.shared(), instance); if declare::get_defined_value(ccx, &sym).is_some() { ccx.sess().span_fatal(span, @@ -530,7 +530,8 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, None => { attrs = ccx.sess().cstore.item_attrs(def_id); - (ccx.sess().cstore.item_symbol(def_id), &attrs[..], None) + let sym = symbol_names::exported_name(ccx.shared(), instance); + (sym, &attrs[..], None) } ref variant => { diff --git a/src/librustc_trans/closure.rs b/src/librustc_trans/closure.rs index 1c393f8091eee..8d273dfe1953c 100644 --- a/src/librustc_trans/closure.rs +++ b/src/librustc_trans/closure.rs @@ -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, &instance); + let symbol = symbol_names::exported_name(ccx.shared(), instance); // Compute the rust-call form of the closure call method. let sig = &tcx.closure_type(closure_id, substs).sig; diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index 3e876eb3d7de0..6dca7fe5ed92c 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -19,7 +19,8 @@ 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, exported_name, imported_name, push_ctxt}; +use base::{self, imported_name, push_ctxt}; +use back::symbol_names; use callee::Callee; use collector; use trans_item::TransItem; @@ -1021,13 +1022,13 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId) let llty = type_of::type_of(ccx, ty); match ccx.tcx().map.get(id) { hir_map::NodeItem(&hir::Item { - ref attrs, span, node: hir::ItemStatic(..), .. + span, node: hir::ItemStatic(..), .. }) => { // If this static came from an external crate, then // 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 = exported_name(ccx, instance, attrs); + let sym = symbol_names::exported_name(ccx.shared(), instance); debug!("making {}", sym); // Create the global before evaluating the initializer; @@ -1104,7 +1105,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 = ccx.sess().cstore.item_symbol(def_id); + let name = symbol_names::exported_name(ccx.shared(), instance); let g = declare::declare_global(ccx, &name, 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 diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 4d6c4cdcc6b07..95d56432e1e34 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -504,6 +504,10 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { scheme.generics.regions.map(|_| ty::ReStatic))) } + pub fn symbol_hasher(&self) -> &RefCell { + &self.symbol_hasher + } + pub fn metadata_symbol_name(&self) -> String { format!("rust_metadata_{}_{}", self.link_meta().crate_name, diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index dfaf84ecef023..e781468f96c93 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -88,7 +88,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, monomorphizing.insert(fn_id, depth + 1); } - let symbol = symbol_names::exported_name(ccx, &instance); + let symbol = symbol_names::exported_name(ccx.shared(), instance); debug!("monomorphize_fn mangled to {}", symbol); assert!(declare::get_defined_value(ccx, &symbol).is_none()); diff --git a/src/librustc_trans/symbol_names_test.rs b/src/librustc_trans/symbol_names_test.rs index 284a227276dd0..6777e98d4b81a 100644 --- a/src/librustc_trans/symbol_names_test.rs +++ b/src/librustc_trans/symbol_names_test.rs @@ -53,7 +53,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, &instance); + let name = symbol_names::exported_name(self.ccx.shared(), instance); 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); From a6a5e4884a6c5be54acd53773e68faf02d79f52f Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 12 May 2016 01:25:20 +0300 Subject: [PATCH 4/8] trans: force absolute item paths within symbols. --- src/librustc/ty/item_path.rs | 36 ++++++++++++++++++++++--- src/librustc_trans/back/symbol_names.rs | 11 ++++++-- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 5246c6739d960..ee9983038b162 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -14,12 +14,38 @@ use hir::def_id::{DefId, CRATE_DEF_INDEX}; use ty::{self, Ty, TyCtxt}; use syntax::ast; +use std::cell::Cell; + +thread_local! { + static FORCE_ABSOLUTE: Cell = Cell::new(false) +} + +/// Enforces that item_path_str always returns an absolute path. +/// This is useful when building symbols that contain types, +/// where we want the crate name to be part of the symbol. +pub fn with_forced_absolute_paths R, R>(f: F) -> R { + FORCE_ABSOLUTE.with(|force| { + let old = force.get(); + force.set(true); + let result = f(); + force.set(old); + result + }) +} + impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Returns a string identifying this def-id. This string is /// suitable for user output. It is relative to the current crate - /// root. + /// root, unless with_forced_absolute_paths was used. pub fn item_path_str(self, def_id: DefId) -> String { - let mut buffer = LocalPathBuffer::new(RootMode::Local); + let mode = FORCE_ABSOLUTE.with(|force| { + if force.get() { + RootMode::Absolute + } else { + RootMode::Local + } + }); + let mut buffer = LocalPathBuffer::new(mode); self.push_item_path(&mut buffer, def_id); buffer.into_string() } @@ -75,7 +101,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { RootMode::Absolute => { // In absolute mode, just write the crate name // unconditionally. - buffer.push(&self.crate_name(cnum)); + if cnum == LOCAL_CRATE { + buffer.push(&self.crate_name(cnum)); + } else { + buffer.push(&self.sess.cstore.original_crate_name(cnum)); + } } } } diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index dffd0beafe51b..4c166029c3e7b 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -120,7 +120,11 @@ pub fn def_id_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> fn def_path_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_path: &DefPath) -> String { let mut s = String::with_capacity(def_path.data.len() * 16); - s.push_str(&tcx.crate_name(def_path.krate)); + if def_path.krate == cstore::LOCAL_CRATE { + s.push_str(&tcx.crate_name(def_path.krate)); + } else { + s.push_str(&tcx.sess.cstore.original_crate_name(def_path.krate)); + } s.push_str("/"); s.push_str(&tcx.crate_disambiguator(def_path.krate)); @@ -265,7 +269,10 @@ pub fn exported_name<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, let mut buffer = SymbolPathBuffer { names: Vec::with_capacity(def_path.data.len()) }; - ccx.tcx().push_item_path(&mut buffer, def_id); + + item_path::with_forced_absolute_paths(|| { + scx.tcx().push_item_path(&mut buffer, def_id); + }); mangle(buffer.names.into_iter(), Some(&hash[..])) } From c9a10bd26b1305e507b7a5a23ccb0a2a64b8dbba Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 12 May 2016 19:52:38 +0300 Subject: [PATCH 5/8] trans: move exported_symbol to Instance::symbol_name. --- src/librustc/middle/cstore.rs | 2 + src/librustc_metadata/csearch.rs | 5 + src/librustc_metadata/decoder.rs | 10 ++ src/librustc_metadata/encoder.rs | 2 + src/librustc_trans/back/symbol_names.rs | 148 +++++++++++--------- src/librustc_trans/base.rs | 28 ++-- src/librustc_trans/callee.rs | 47 +++---- src/librustc_trans/closure.rs | 2 +- src/librustc_trans/consts.rs | 20 ++- src/librustc_trans/monomorphize.rs | 3 +- src/librustc_trans/symbol_names_test.rs | 3 +- src/test/compile-fail/symbol-names/impl1.rs | 2 +- 12 files changed, 146 insertions(+), 126 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index e5a8c1d1b4e6f..61978ca71d2fa 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -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") } diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index b87b5492f0440..5d5820251491a 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -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)); diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 7f79df97852b6..2c4edcea611d8 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -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) { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 928601095b078..5476b21dd8c11 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -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, _) => { diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index 4c166029c3e7b..170c8f75b5056 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -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); + 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; - 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(); - } + // 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 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(); - } + 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 is_foreign { + if let Some(name) = attr::first_attr_value_str_by_name(&attrs, "link_name") { + return name.to_string(); } - _ => { - // 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); - }); + // 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); + // 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 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()) - }; + 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); - }); + item_path::with_forced_absolute_paths(|| { + scx.tcx().push_item_path(&mut buffer, def_id); + }); - mangle(buffer.names.into_iter(), Some(&hash[..])) + mangle(buffer.names.into_iter(), Some(&hash[..])) + } } struct SymbolPathBuffer { diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index f6a2b82fb1668..94ef80d3b8587 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -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::>(); 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) })); } diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index bdeb1a6270f95..e7fa871d23db5 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -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); diff --git a/src/librustc_trans/closure.rs b/src/librustc_trans/closure.rs index 8d273dfe1953c..5e0d34c2a674d 100644 --- a/src/librustc_trans/closure.rs +++ b/src/librustc_trans/closure.rs @@ -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; diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index 6dca7fe5ed92c..bf7d1ef4d0636 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -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 diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index e781468f96c93..b0f8edac0a623 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -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()); diff --git a/src/librustc_trans/symbol_names_test.rs b/src/librustc_trans/symbol_names_test.rs index 6777e98d4b81a..11e9e9f3204a2 100644 --- a/src/librustc_trans/symbol_names_test.rs +++ b/src/librustc_trans/symbol_names_test.rs @@ -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); diff --git a/src/test/compile-fail/symbol-names/impl1.rs b/src/test/compile-fail/symbol-names/impl1.rs index 39bee26da20b8..93fa48b880fdf 100644 --- a/src/test/compile-fail/symbol-names/impl1.rs +++ b/src/test/compile-fail/symbol-names/impl1.rs @@ -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::::baz) fn baz() { } } From b03bde9c2af8b004b5c8eba5a797b079190718c3 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Wed, 25 May 2016 01:45:25 +0300 Subject: [PATCH 6/8] trans: move the linker support to compute symbols on-demand. --- src/librustc_trans/back/link.rs | 13 ++-- src/librustc_trans/back/linker.rs | 116 ++++++++++++++++++++---------- src/librustc_trans/base.rs | 3 + src/librustc_trans/lib.rs | 1 + 4 files changed, 88 insertions(+), 45 deletions(-) diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 53cc03198292e..0a7c3b6fc8f49 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -9,7 +9,7 @@ // except according to those terms. use super::archive::{ArchiveBuilder, ArchiveConfig}; -use super::linker::{Linker, GnuLinker, MsvcLinker}; +use super::linker::Linker; use super::rpath::RPathConfig; use super::rpath; use super::msvc; @@ -637,13 +637,9 @@ fn link_natively(sess: &Session, } { - let mut linker = if sess.target.target.options.is_like_msvc { - Box::new(MsvcLinker { cmd: &mut cmd, sess: &sess }) as Box - } else { - Box::new(GnuLinker { cmd: &mut cmd, sess: &sess }) as Box - }; + let mut linker = trans.linker_info.to_linker(&mut cmd, &sess); link_args(&mut *linker, sess, crate_type, tmpdir, - objects, out_filename, trans, outputs); + objects, out_filename, outputs); if !sess.target.target.options.no_compiler_rt { linker.link_staticlib("compiler-rt"); } @@ -712,7 +708,6 @@ fn link_args(cmd: &mut Linker, tmpdir: &Path, objects: &[PathBuf], out_filename: &Path, - trans: &CrateTranslation, outputs: &OutputFilenames) { // The default library location, we need this to find the runtime. @@ -731,7 +726,7 @@ fn link_args(cmd: &mut Linker, // If we're building a dynamic library then some platforms need to make sure // that all symbols are exported correctly from the dynamic library. if crate_type != config::CrateTypeExecutable { - cmd.export_symbols(sess, trans, tmpdir, crate_type); + cmd.export_symbols(tmpdir, crate_type); } // When linking a dynamic library, we put the metadata into a section of the diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index 50f6366e85c86..cb990ead8e81e 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -15,13 +15,50 @@ use std::io::prelude::*; use std::path::{Path, PathBuf}; use std::process::Command; +use context::SharedCrateContext; +use monomorphize::Instance; + use back::archive; use middle::dependency_format::Linkage; use session::Session; use session::config::CrateType; use session::config; use syntax::ast; -use CrateTranslation; + +/// For all the linkers we support, and information they might +/// need out of the shared crate context before we get rid of it. +pub struct LinkerInfo { + dylib_exports: Vec, + cdylib_exports: Vec +} + +impl<'a, 'tcx> LinkerInfo { + pub fn new(scx: &SharedCrateContext<'a, 'tcx>, + reachable: &[String]) -> LinkerInfo { + LinkerInfo { + dylib_exports: exported_symbols(scx, reachable, CrateType::CrateTypeDylib), + cdylib_exports: exported_symbols(scx, reachable, CrateType::CrateTypeCdylib) + } + } + + pub fn to_linker(&'a self, + cmd: &'a mut Command, + sess: &'a Session) -> Box { + if sess.target.target.options.is_like_msvc { + Box::new(MsvcLinker { + cmd: cmd, + sess: sess, + info: self + }) as Box + } else { + Box::new(GnuLinker { + cmd: cmd, + sess: sess, + info: self + }) as Box + } + } +} /// Linker abstraction used by back::link to build up the command to invoke a /// linker. @@ -53,16 +90,13 @@ pub trait Linker { fn hint_dynamic(&mut self); fn whole_archives(&mut self); fn no_whole_archives(&mut self); - fn export_symbols(&mut self, - sess: &Session, - trans: &CrateTranslation, - tmpdir: &Path, - crate_type: CrateType); + fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType); } pub struct GnuLinker<'a> { - pub cmd: &'a mut Command, - pub sess: &'a Session, + cmd: &'a mut Command, + sess: &'a Session, + info: &'a LinkerInfo } impl<'a> GnuLinker<'a> { @@ -201,11 +235,7 @@ impl<'a> Linker for GnuLinker<'a> { self.cmd.arg("-Wl,-Bdynamic"); } - fn export_symbols(&mut self, - sess: &Session, - trans: &CrateTranslation, - tmpdir: &Path, - crate_type: CrateType) { + fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) { // If we're compiling a dylib, then we let symbol visibility in object // files to take care of whether they're exported or not. // @@ -225,13 +255,13 @@ impl<'a> Linker for GnuLinker<'a> { }; let res = (|| -> io::Result<()> { let mut f = BufWriter::new(File::create(&path)?); - for sym in exported_symbols(sess, trans, crate_type) { + for sym in &self.info.cdylib_exports { writeln!(f, "{}{}", prefix, sym)?; } Ok(()) })(); if let Err(e) = res { - sess.fatal(&format!("failed to write lib.def file: {}", e)); + self.sess.fatal(&format!("failed to write lib.def file: {}", e)); } let mut arg = OsString::new(); if self.sess.target.target.options.is_like_osx { @@ -245,8 +275,9 @@ impl<'a> Linker for GnuLinker<'a> { } pub struct MsvcLinker<'a> { - pub cmd: &'a mut Command, - pub sess: &'a Session, + cmd: &'a mut Command, + sess: &'a Session, + info: &'a LinkerInfo } impl<'a> Linker for MsvcLinker<'a> { @@ -366,8 +397,6 @@ impl<'a> Linker for MsvcLinker<'a> { // in which case they may continue to transitively be used and hence need // their symbols exported. fn export_symbols(&mut self, - sess: &Session, - trans: &CrateTranslation, tmpdir: &Path, crate_type: CrateType) { let path = tmpdir.join("lib.def"); @@ -378,15 +407,18 @@ impl<'a> Linker for MsvcLinker<'a> { // straight to exports. writeln!(f, "LIBRARY")?; writeln!(f, "EXPORTS")?; - - for sym in exported_symbols(sess, trans, crate_type) { - writeln!(f, " {}", sym)?; + let symbols = if crate_type == CrateType::CrateTypeCdylib { + &self.info.cdylib_exports + } else { + &self.info.dylib_exports + }; + for symbol in symbols { + writeln!(f, " {}", symbol)?; } - Ok(()) })(); if let Err(e) = res { - sess.fatal(&format!("failed to write lib.def file: {}", e)); + self.sess.fatal(&format!("failed to write lib.def file: {}", e)); } let mut arg = OsString::from("/DEF:"); arg.push(path); @@ -394,10 +426,23 @@ impl<'a> Linker for MsvcLinker<'a> { } } -fn exported_symbols(sess: &Session, - trans: &CrateTranslation, - crate_type: CrateType) -> Vec { - let mut symbols = trans.reachable.iter().cloned().collect::>(); +fn exported_symbols(scx: &SharedCrateContext, + reachable: &[String], + crate_type: CrateType) + -> Vec { + if !scx.sess().crate_types.borrow().contains(&crate_type) { + return vec![]; + } + + // See explanation in GnuLinker::export_symbols, for + // why we don't ever need dylib symbols on non-MSVC. + if crate_type == CrateType::CrateTypeDylib { + if !scx.sess().target.target.options.is_like_msvc { + return vec![]; + } + } + + let mut symbols = reachable.to_vec(); // If we're producing anything other than a dylib then the `reachable` array // above is the exhaustive set of symbols we should be exporting. @@ -409,10 +454,10 @@ fn exported_symbols(sess: &Session, return symbols } - let cstore = &sess.cstore; - let formats = sess.dependency_formats.borrow(); - let upstream_symbols = formats[&crate_type].iter(); - symbols.extend(upstream_symbols.enumerate().filter_map(|(i, f)| { + let cstore = &scx.sess().cstore; + let formats = scx.sess().dependency_formats.borrow(); + let deps = formats[&crate_type].iter(); + symbols.extend(deps.enumerate().filter_map(|(i, f)| { if *f == Linkage::Static { Some((i + 1) as ast::CrateNum) } else { @@ -420,9 +465,8 @@ fn exported_symbols(sess: &Session, } }).flat_map(|cnum| { cstore.reachable_ids(cnum) - }).map(|did| { - cstore.item_symbol(did) + }).map(|did| -> String { + Instance::mono(scx, did).symbol_name(scx) })); - - return symbols + symbols } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 94ef80d3b8587..84dd633a45265 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -31,6 +31,7 @@ use super::CrateTranslation; use super::ModuleTranslation; use back::link; +use back::linker::LinkerInfo; use lint; use llvm::{BasicBlockRef, Linkage, ValueRef, Vector, get_param}; use llvm; @@ -2828,6 +2829,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; let no_builtins = attr::contains_name(&krate.attrs, "no_builtins"); + let linker_info = LinkerInfo::new(&shared_ccx, &reachable_symbols); CrateTranslation { modules: modules, metadata_module: metadata_module, @@ -2835,6 +2837,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, metadata: metadata, reachable: reachable_symbols, no_builtins: no_builtins, + linker_info: linker_info } } diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index bccb5aa050b51..0188a6d54de2d 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -145,6 +145,7 @@ pub struct CrateTranslation { pub metadata: Vec, pub reachable: Vec, pub no_builtins: bool, + pub linker_info: back::linker::LinkerInfo } __build_diagnostic_array! { librustc_trans, DIAGNOSTICS } From 04464db954e457f7f9d0bdc80ec365ddeb75c9cd Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 12 May 2016 19:58:11 +0300 Subject: [PATCH 7/8] trans: remove item_symbols from metadata and CrateContext. --- src/librustc/middle/cstore.rs | 7 +------ src/librustc_metadata/common.rs | 2 +- src/librustc_metadata/csearch.rs | 11 +---------- src/librustc_metadata/decoder.rs | 8 -------- src/librustc_metadata/encoder.rs | 32 +------------------------------- src/librustc_trans/base.rs | 21 --------------------- src/librustc_trans/callee.rs | 5 ----- src/librustc_trans/consts.rs | 7 ++----- src/librustc_trans/context.rs | 10 ---------- 9 files changed, 6 insertions(+), 97 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 61978ca71d2fa..3ede60beb7443 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -34,8 +34,7 @@ use mir::mir_map::MirMap; use session::Session; use session::config::PanicStrategy; use session::search_paths::PathKind; -use util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap}; -use std::cell::RefCell; +use util::nodemap::{FnvHashMap, NodeSet, DefIdMap}; use std::rc::Rc; use std::path::PathBuf; use syntax::ast; @@ -169,7 +168,6 @@ pub trait CrateStore<'tcx> { fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::GenericPredicates<'tcx>; fn item_attrs(&self, def_id: DefId) -> Vec; - fn item_symbol(&self, def: DefId) -> String; fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef<'tcx>; fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx>; fn method_arg_names(&self, did: DefId) -> Vec; @@ -275,7 +273,6 @@ pub trait CrateStore<'tcx> { fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option; fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, reexports: &def::ExportMap, - item_symbols: &RefCell>, link_meta: &LinkMeta, reachable: &NodeSet, mir_map: &MirMap<'tcx>, @@ -353,7 +350,6 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::GenericPredicates<'tcx> { bug!("item_super_predicates") } fn item_attrs(&self, def_id: DefId) -> Vec { bug!("item_attrs") } - fn item_symbol(&self, def: DefId) -> String { bug!("item_symbol") } fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef<'tcx> { bug!("trait_def") } fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx> @@ -483,7 +479,6 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option { None } fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, reexports: &def::ExportMap, - item_symbols: &RefCell>, link_meta: &LinkMeta, reachable: &NodeSet, mir_map: &MirMap<'tcx>, diff --git a/src/librustc_metadata/common.rs b/src/librustc_metadata/common.rs index 2b972af07ff91..74f97de265898 100644 --- a/src/librustc_metadata/common.rs +++ b/src/librustc_metadata/common.rs @@ -33,7 +33,7 @@ pub const tag_items_data_item_family: usize = 0x24; pub const tag_items_data_item_type: usize = 0x25; -pub const tag_items_data_item_symbol: usize = 0x26; +// GAP 0x26 pub const tag_items_data_item_variant: usize = 0x27; diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index 5d5820251491a..5d42f8c1d6f6a 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -25,7 +25,7 @@ use rustc::hir::map as hir_map; use rustc::hir::map::DefKey; use rustc::mir::repr::Mir; use rustc::mir::mir_map::MirMap; -use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap}; +use rustc::util::nodemap::{FnvHashMap, NodeSet, DefIdMap}; use rustc::session::config::PanicStrategy; use std::cell::RefCell; @@ -115,13 +115,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { decoder::get_item_attrs(&cdata, def_id.index) } - fn item_symbol(&self, def: DefId) -> String - { - self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_symbol(&cdata, def.index) - } - fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::TraitDef<'tcx> { self.dep_graph.read(DepNode::MetaData(def)); @@ -569,7 +562,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, reexports: &def::ExportMap, - item_symbols: &RefCell>, link_meta: &LinkMeta, reachable: &NodeSet, mir_map: &MirMap<'tcx>, @@ -579,7 +571,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { diag: tcx.sess.diagnostic(), tcx: tcx, reexports: reexports, - item_symbols: item_symbols, link_meta: link_meta, cstore: self, reachable: reachable, diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 2c4edcea611d8..d1153fe2d0603 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -213,10 +213,6 @@ fn item_sort(item: rbml::Doc) -> Option { }) } -fn item_symbol(item: rbml::Doc) -> String { - reader::get_doc(item, tag_items_data_item_symbol).as_str().to_string() -} - fn untranslated_def_id(d: rbml::Doc) -> DefId { let id = reader::doc_as_u64(d); let index = DefIndex::new((id & 0xFFFF_FFFF) as usize); @@ -640,10 +636,6 @@ pub fn get_impl_trait<'a, 'tcx>(cdata: Cmd, } } -pub fn get_symbol(cdata: Cmd, id: DefIndex) -> String { - return item_symbol(cdata.lookup_item(id)); -} - /// Iterates over the language items in the given crate. pub fn each_lang_item(cdata: Cmd, mut f: F) -> bool where F: FnMut(DefIndex, usize) -> bool, diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 5476b21dd8c11..2bc953039adb2 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -34,7 +34,7 @@ use rustc::ty::util::IntTypeExt; use rustc::hir::svh::Svh; use rustc::mir::mir_map::MirMap; use rustc::session::config::{self, PanicStrategy}; -use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet}; +use rustc::util::nodemap::{FnvHashMap, NodeSet}; use rustc_serialize::Encodable; use std::cell::RefCell; @@ -59,7 +59,6 @@ pub struct EncodeContext<'a, 'tcx: 'a> { pub diag: &'a Handler, pub tcx: TyCtxt<'a, 'tcx, 'tcx>, pub reexports: &'a def::ExportMap, - pub item_symbols: &'a RefCell>, pub link_meta: &'a LinkMeta, pub cstore: &'a cstore::CStore, pub type_abbrevs: tyencode::abbrev_map<'tcx>, @@ -213,20 +212,6 @@ fn encode_region(ecx: &EncodeContext, rbml_w.end_tag(); } -fn encode_symbol(ecx: &EncodeContext, - rbml_w: &mut Encoder, - id: NodeId) { - match ecx.item_symbols.borrow().get(&id) { - Some(x) => { - debug!("encode_symbol(id={}, str={})", id, *x); - rbml_w.wr_tagged_str(tag_items_data_item_symbol, x); - } - None => { - bug!("encode_symbol: id not found {}", id); - } - } -} - fn encode_disr_val(_: &EncodeContext, rbml_w: &mut Encoder, disr_val: ty::Disr) { @@ -518,10 +503,6 @@ fn encode_info_for_struct_ctor<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, encode_name(rbml_w, name); encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(struct_id)); - if ecx.item_symbols.borrow().contains_key(&ctor_id) { - encode_symbol(ecx, rbml_w, ctor_id); - } - let stab = ecx.tcx.lookup_stability(ecx.tcx.map.local_def_id(ctor_id)); let depr= ecx.tcx.lookup_deprecation(ecx.tcx.map.local_def_id(ctor_id)); encode_stability(rbml_w, stab); @@ -710,10 +691,6 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, } encode_constness(rbml_w, sig.constness); encode_defaultness(rbml_w, impl_item.defaultness); - if !any_types { - let m_id = ecx.local_id(m.def_id); - encode_symbol(ecx, rbml_w, m_id); - } encode_method_argument_names(rbml_w, &sig.decl); } } @@ -894,7 +871,6 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, encode_family(rbml_w, 'c'); } encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id); - encode_symbol(ecx, rbml_w, item.id); encode_name(rbml_w, item.name); encode_visibility(rbml_w, vis); encode_stability(rbml_w, stab); @@ -931,9 +907,6 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item)); encode_mir(ecx, rbml_w, item.id); } - if tps_len == 0 { - encode_symbol(ecx, rbml_w, item.id); - } encode_constness(rbml_w, constness); encode_visibility(rbml_w, vis); encode_stability(rbml_w, stab); @@ -1365,8 +1338,6 @@ fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, if abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic { encode_inlined_item(ecx, rbml_w, InlinedItemRef::Foreign(nitem)); encode_mir(ecx, rbml_w, nitem.id); - } else { - encode_symbol(ecx, rbml_w, nitem.id); } encode_attributes(rbml_w, &nitem.attrs); let stab = ecx.tcx.lookup_stability(ecx.tcx.map.local_def_id(nitem.id)); @@ -1387,7 +1358,6 @@ fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, let depr = ecx.tcx.lookup_deprecation(ecx.tcx.map.local_def_id(nitem.id)); encode_stability(rbml_w, stab); encode_deprecation(rbml_w, depr); - encode_symbol(ecx, rbml_w, nitem.id); encode_name(rbml_w, nitem.name); } } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 84dd633a45265..c4afb348a0fa8 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -38,7 +38,6 @@ use llvm; use rustc::cfg; use rustc::hir::def_id::DefId; use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem}; -use middle::weak_lang_items; use rustc::hir::pat_util::simple_name; use rustc::ty::subst::{self, Substs}; use rustc::traits; @@ -2345,15 +2344,6 @@ pub fn trans_item(ccx: &CrateContext, item: &hir::Item) { set_global_section(ccx, g, item); update_linkage(ccx, g, Some(item.id), OriginalTranslation); } - hir::ItemForeignMod(ref m) => { - if m.abi == Abi::RustIntrinsic || m.abi == Abi::PlatformIntrinsic { - return; - } - for fi in &m.items { - let lname = imported_name(fi.name, &fi.attrs).to_string(); - ccx.item_symbols().borrow_mut().insert(fi.id, lname); - } - } _ => {} } } @@ -2438,16 +2428,6 @@ pub fn create_entry_wrapper(ccx: &CrateContext, sp: Span, main_llfn: ValueRef) { } } -pub fn imported_name(name: ast::Name, attrs: &[ast::Attribute]) -> InternedString { - match attr::first_attr_value_str_by_name(attrs, "link_name") { - Some(ln) => ln.clone(), - None => match weak_lang_items::link_name(attrs) { - Some(name) => name, - None => name.as_str(), - } - } -} - fn contains_null(s: &str) -> bool { s.bytes().any(|b| b == 0) } @@ -2471,7 +2451,6 @@ pub fn write_metadata<'a, 'tcx>(cx: &SharedCrateContext<'a, 'tcx>, let cstore = &cx.tcx().sess.cstore; let metadata = cstore.encode_metadata(cx.tcx(), cx.export_map(), - cx.item_symbols(), cx.link_meta(), reachable, mir_map, diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index e7fa871d23db5..d7f565a9cd449 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -575,11 +575,6 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, llfn }; - // Always insert into item_symbols, in case this item is exported. - if let Some(id) = local_item { - ccx.item_symbols().borrow_mut().insert(id, sym); - } - ccx.instances().borrow_mut().insert(instance, llfn); immediate_rvalue(llfn, fn_ptr_ty) diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index bf7d1ef4d0636..bd36c18a47ee2 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -1033,13 +1033,10 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId) // Create the global before evaluating the initializer; // this is necessary to allow recursive statics. - let g = declare::define_global(ccx, &sym, llty).unwrap_or_else(|| { + declare::define_global(ccx, &sym, llty).unwrap_or_else(|| { ccx.sess().span_fatal(span, &format!("symbol `{}` is already defined", sym)) - }); - - ccx.item_symbols().borrow_mut().insert(id, sym); - g + }) } hir_map::NodeForeignItem(&hir::ForeignItem { diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 95d56432e1e34..1c081bb49bca1 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -71,7 +71,6 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> { export_map: ExportMap, reachable: NodeSet, - item_symbols: RefCell>, link_meta: LinkMeta, symbol_hasher: RefCell, tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -395,7 +394,6 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { metadata_llcx: metadata_llcx, export_map: export_map, reachable: reachable, - item_symbols: RefCell::new(NodeMap()), link_meta: link_meta, symbol_hasher: RefCell::new(symbol_hasher), tcx: tcx, @@ -439,10 +437,6 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { &self.reachable } - pub fn item_symbols<'a>(&'a self) -> &'a RefCell> { - &self.item_symbols - } - pub fn trait_cache(&self) -> &RefCell>> { &self.trait_cache } @@ -720,10 +714,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { &self.shared.reachable } - pub fn item_symbols<'a>(&'a self) -> &'a RefCell> { - &self.shared.item_symbols - } - pub fn link_meta<'a>(&'a self) -> &'a LinkMeta { &self.shared.link_meta } From a619901e3dafbfb01e10c53cdb5f9fea52a1ef6d Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Wed, 25 May 2016 08:46:36 +0300 Subject: [PATCH 8/8] trans: save metadata even with -Z no-trans. --- src/librustc/session/config.rs | 2 +- src/librustc_driver/lib.rs | 4 -- src/librustc_trans/back/link.rs | 5 ++ src/librustc_trans/base.rs | 69 +++++++++++++++++----------- src/librustc_trans/context.rs | 4 ++ src/tools/compiletest/src/runtest.rs | 7 +++ 6 files changed, 58 insertions(+), 33 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index da5555dbd6453..05ed02211097c 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1104,7 +1104,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let no_analysis = debugging_opts.no_analysis; let mut output_types = HashMap::new(); - if !debugging_opts.parse_only && !no_trans { + if !debugging_opts.parse_only { for list in matches.opt_strs("emit") { for output_type in list.split(',') { let mut parts = output_type.splitn(2, '='); diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 06133c508d9f0..bd6b0599e7832 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -511,10 +511,6 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { control.after_write_deps.stop = Compilation::Stop; } - if sess.opts.no_trans { - control.after_analysis.stop = Compilation::Stop; - } - if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe) { control.after_llvm.stop = Compilation::Stop; } diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 0a7c3b6fc8f49..4640377cf8600 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -188,6 +188,11 @@ pub fn link_binary(sess: &Session, let mut out_filenames = Vec::new(); for &crate_type in sess.crate_types.borrow().iter() { + // Ignore executable crates if we have -Z no-trans, as they will error. + if sess.opts.no_trans && crate_type == config::CrateTypeExecutable { + continue; + } + if invalid_output_for_target(sess, crate_type) { bug!("invalid output type `{:?}` for target os `{}`", crate_type, sess.opts.target_triple); diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index c4afb348a0fa8..03e12c1c8a7b0 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -2432,11 +2432,8 @@ fn contains_null(s: &str) -> bool { s.bytes().any(|b| b == 0) } -pub fn write_metadata<'a, 'tcx>(cx: &SharedCrateContext<'a, 'tcx>, - krate: &hir::Crate, - reachable: &NodeSet, - mir_map: &MirMap<'tcx>) - -> Vec { +fn write_metadata(cx: &SharedCrateContext, + reachable_ids: &NodeSet) -> Vec { use flate; let any_library = cx.sess() @@ -2452,9 +2449,9 @@ pub fn write_metadata<'a, 'tcx>(cx: &SharedCrateContext<'a, 'tcx>, let metadata = cstore.encode_metadata(cx.tcx(), cx.export_map(), cx.link_meta(), - reachable, - mir_map, - krate); + reachable_ids, + cx.mir_map(), + cx.tcx().map.krate()); let mut compressed = cstore.metadata_encoding_version().to_vec(); compressed.extend_from_slice(&flate::deflate_bytes(&metadata)); @@ -2639,10 +2636,12 @@ pub fn filter_reachable_ids(scx: &SharedCrateContext) -> NodeSet { 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, + node: hir::ImplItemKind::Method(..), .. }) => { + let def_id = scx.tcx().map.local_def_id(id); + let scheme = scx.tcx().lookup_item_type(def_id); + scheme.generics.types.is_empty() + } _ => false } @@ -2686,6 +2685,19 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, check_overflow, check_dropflag); + let reachable_symbol_ids = filter_reachable_ids(&shared_ccx); + + // Translate the metadata. + let metadata = time(tcx.sess.time_passes(), "write metadata", || { + write_metadata(&shared_ccx, &reachable_symbol_ids) + }); + + let metadata_module = ModuleTranslation { + llcx: shared_ccx.metadata_llcx(), + llmod: shared_ccx.metadata_llmod(), + }; + let no_builtins = attr::contains_name(&krate.attrs, "no_builtins"); + let codegen_units = collect_and_partition_translation_items(&shared_ccx); let codegen_unit_count = codegen_units.len(); assert!(tcx.sess.opts.cg.codegen_units == codegen_unit_count || @@ -2693,6 +2705,24 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let crate_context_list = CrateContextList::new(&shared_ccx, codegen_units); + let modules = crate_context_list.iter() + .map(|ccx| ModuleTranslation { llcx: ccx.llcx(), llmod: ccx.llmod() }) + .collect(); + + // Skip crate items and just output metadata in -Z no-trans mode. + if tcx.sess.opts.no_trans { + let linker_info = LinkerInfo::new(&shared_ccx, &[]); + return CrateTranslation { + modules: modules, + metadata_module: metadata_module, + link: link_meta, + metadata: metadata, + reachable: vec![], + no_builtins: no_builtins, + linker_info: linker_info + }; + } + { let ccx = crate_context_list.get_ccx(0); @@ -2722,13 +2752,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } - let reachable_symbol_ids = filter_reachable_ids(&shared_ccx); - - // Translate the metadata. - let metadata = time(tcx.sess.time_passes(), "write metadata", || { - write_metadata(&shared_ccx, krate, &reachable_symbol_ids, mir_map) - }); - if shared_ccx.sess().trans_stats() { let stats = shared_ccx.stats(); println!("--- trans stats ---"); @@ -2758,10 +2781,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } - let modules = crate_context_list.iter() - .map(|ccx| ModuleTranslation { llcx: ccx.llcx(), llmod: ccx.llmod() }) - .collect(); - let sess = shared_ccx.sess(); let mut reachable_symbols = reachable_symbol_ids.iter().map(|&id| { let def_id = shared_ccx.tcx().map.local_def_id(id); @@ -2802,12 +2821,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, create_imps(&crate_context_list); } - let metadata_module = ModuleTranslation { - llcx: shared_ccx.metadata_llcx(), - llmod: shared_ccx.metadata_llmod(), - }; - let no_builtins = attr::contains_name(&krate.attrs, "no_builtins"); - let linker_info = LinkerInfo::new(&shared_ccx, &reachable_symbols); CrateTranslation { modules: modules, diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 1c081bb49bca1..1ddcbc79aed5f 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -502,6 +502,10 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { &self.symbol_hasher } + pub fn mir_map(&self) -> &MirMap<'tcx> { + &self.mir_map + } + pub fn metadata_symbol_name(&self) -> String { format!("rust_metadata_{}_{}", self.link_meta().crate_name, diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index e6dc3a9d360ff..4040b55ff98cb 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -371,9 +371,16 @@ actual:\n\ } else { &*self.config.target }; + + let out_dir = self.output_base_name().with_extension("pretty-out"); + let _ = fs::remove_dir_all(&out_dir); + self.create_dir_racy(&out_dir); + // FIXME (#9639): This needs to handle non-utf8 paths let mut args = vec!("-".to_owned(), "-Zno-trans".to_owned(), + "--out-dir".to_owned(), + out_dir.to_str().unwrap().to_owned(), format!("--target={}", target), "-L".to_owned(), self.config.build_base.to_str().unwrap().to_owned(),