From 650855322bd1e1cf1a7175a1ccc4e29a739426a7 Mon Sep 17 00:00:00 2001 From: Sander Maijers Date: Fri, 13 May 2016 19:18:59 +0200 Subject: [PATCH 01/18] IntelliJ support, ordering, cleanup --- .gitignore | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 972f527046b2c..390a0deeb9deb 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,6 @@ *.elc *.epub *.exe -*.pdb *.fn *.html *.kdev4 @@ -29,6 +28,7 @@ *.orig *.out *.patch +*.pdb *.pdf *.pg *.pot @@ -50,6 +50,10 @@ .cproject .hg/ .hgignore +.idea +__pycache__/ +*.py[cod] +*$py.class .project .settings/ .valgrindrc @@ -64,6 +68,7 @@ /llvm/ /mingw-build/ /nd/ +/obj/ /rt/ /rustllvm/ /src/libunicode/DerivedCoreProperties.txt @@ -72,13 +77,10 @@ /src/libunicode/PropList.txt /src/libunicode/Scripts.txt /src/libunicode/UnicodeData.txt -/stage0/ -/stage1/ -/stage2/ -/stage3/ +/stage[0-9]+/ +/target /test/ /tmp/ -/obj/ TAGS TAGS.emacs TAGS.vi @@ -88,11 +90,9 @@ config.mk config.stamp keywords.md lexer.ml -src/.DS_Store src/etc/dl src/librustc_llvm/llvmdeps.rs tmp.*.rs version.md version.ml version.texi -/target From 391ae7f37aee43000f0244e696fe178521fae2ce Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 15 May 2016 15:29:44 +0200 Subject: [PATCH 02/18] Add lifetime's bounds in doc generation --- src/librustdoc/clean/mod.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7305b0f1fb8bc..b167c47c2657f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -795,7 +795,17 @@ impl Clean for hir::Lifetime { impl Clean for hir::LifetimeDef { fn clean(&self, _: &DocContext) -> Lifetime { - Lifetime(self.lifetime.name.to_string()) + if self.bounds.len() > 0 { + let mut s = format!("{}: {}", + self.lifetime.name.to_string(), + self.bounds[0].name.to_string()); + for bound in self.bounds.iter().skip(1) { + s.push_str(&format!(" + {}", bound.name.to_string())); + } + Lifetime(s) + } else { + Lifetime(self.lifetime.name.to_string()) + } } } From bbb78440b4317d4873162fda230392a34da8d175 Mon Sep 17 00:00:00 2001 From: Timothy McRoy Date: Sun, 15 May 2016 15:30:59 -0500 Subject: [PATCH 03/18] Add descriptive error explanation for E0502 --- src/librustc_borrowck/diagnostics.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs index cdbad685008f2..f316cd325ce1c 100644 --- a/src/librustc_borrowck/diagnostics.rs +++ b/src/librustc_borrowck/diagnostics.rs @@ -501,6 +501,33 @@ fn foo(a: &mut i32) { ``` "##, +E0502: r##" +This error indicates that you are trying to borrow a variable as mutable when it +has already been borrowed as immutable. + +Example of erroneous code: + +```compile_fail +fn bar(x: &mut i32) {} +fn foo(a: &mut i32) { + let ref y = a; // a is borrowed as immutable. + bar(a); // error: cannot borrow `*a` as mutable because `a` is also borrowed + // as immutable +} +``` +To fix this error, ensure that you don't have any other references to the +variable before trying to access it mutably: +``` +fn bar(x: &mut i32) {} +fn foo(a: &mut i32) { + bar(a); + let ref y = a; // ok! +} +``` +For more information on the rust ownership system, take a look at +https://doc.rust-lang.org/stable/book/references-and-borrowing.html. +"##, + E0504: r##" This error occurs when an attempt is made to move a borrowed variable into a closure. From 899cbb3dfa1982e2e38858c36235b6b56fa4960f Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 10 May 2016 23:21:18 +0300 Subject: [PATCH 04/18] 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 1bea01c4849e7..2e4cbfd86279b 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use hir::def_id::DefIndex; +use hir::svh::Svh; use lint; use middle::cstore::CrateStore; use middle::dependency_format; @@ -310,6 +312,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 63c6af704bbfe..c78a3a0be74de 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}; @@ -578,9 +579,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(), @@ -598,12 +600,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 e233dda7e91ee..0d11998f21c58 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -613,14 +613,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 65c3aa12ba6c8..096cba84670f2 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -2436,6 +2436,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 222832f782721b827079e30d1c0abf238f1245e5 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 10 May 2016 23:24:17 +0300 Subject: [PATCH 05/18] 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 8e582a626799c46267e297d70322a8483f9a0915 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 12 May 2016 01:22:56 +0300 Subject: [PATCH 06/18] 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 096cba84670f2..fb395d3eb9808 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -2430,47 +2430,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(), @@ -2827,7 +2786,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 60c6af84ebbb6..4b42dad964d69 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -503,6 +503,10 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { Substs::new(VecPerParamSpace::empty(), scheme.generics.regions.map(|_| ty::ReStatic))) } + + pub fn symbol_hasher(&self) -> &RefCell { + &self.symbol_hasher + } } impl<'tcx> LocalCrateContext<'tcx> { 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 92dca9217443d3e2369609c417ee0436e1808d70 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 12 May 2016 01:25:20 +0300 Subject: [PATCH 07/18] trans: force absolute item paths within symbols. --- src/librustc/ty/item_path.rs | 30 +++++++++++++++++++++++-- src/librustc_trans/back/symbol_names.rs | 5 ++++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 5246c6739d960..9aaffd76d3984 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() } diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index dffd0beafe51b..27b695b913785 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -265,7 +265,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 3e01c103eb8f8734ad452ef016584d00c182feef Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 12 May 2016 19:52:38 +0300 Subject: [PATCH 08/18] 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 c0af457ed236c..07f7052c0ed6d 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -210,6 +210,7 @@ pub trait CrateStore<'tcx> : Any { 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; @@ -394,6 +395,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 8d464099783a6..7e039867a7877 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -252,6 +252,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 { let cdata = self.get_crate_data(def.krate); diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 0d11998f21c58..834ea7c027bd1 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1603,6 +1603,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 020f12d753e63..e43c9cdfe4abb 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1344,6 +1344,8 @@ fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, 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 27b695b913785..49c7225306b25 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}; @@ -188,89 +189,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 fb395d3eb9808..b83fe32256754 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; @@ -2630,10 +2630,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: @@ -2651,7 +2648,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() } @@ -2770,8 +2778,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()); @@ -2786,8 +2795,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 2d08063d5d9f72c3384e24433b5cb00589485e21 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 12 May 2016 19:57:23 +0300 Subject: [PATCH 09/18] trans: move the MSVC linker to compute symbols on-demand. --- src/librustc_trans/back/link.rs | 13 +--- src/librustc_trans/back/linker.rs | 121 ++++++++++++++++++++---------- src/librustc_trans/base.rs | 3 + src/librustc_trans/lib.rs | 1 + 4 files changed, 91 insertions(+), 47 deletions(-) diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 00d9658cb5943..c54432c6e5838 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; @@ -634,13 +634,9 @@ fn link_natively(sess: &Session, dylib: bool, } { - 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, dylib, tmpdir, - objects, out_filename, trans, outputs); + objects, out_filename, outputs); if !sess.target.target.options.no_compiler_rt { linker.link_staticlib("compiler-rt"); } @@ -709,7 +705,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. @@ -728,7 +723,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 dylib { - cmd.export_symbols(sess, trans, tmpdir); + cmd.export_symbols(tmpdir); } // 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 8055e97034e3f..858fe65c0fc7f 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -9,19 +9,91 @@ // except according to those terms. use std::ffi::OsString; +use std::fmt::Write as FmtWrite; use std::fs::{self, File}; use std::io::{self, BufWriter}; 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::CrateTypeDylib; 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 enum LinkerInfo { + Gnu, + Msvc { + dylib_exports: String + } +} + +impl<'a, 'tcx> LinkerInfo { + pub fn new(scx: &SharedCrateContext<'a, 'tcx>, + reachable: &[String]) -> LinkerInfo { + if scx.sess().target.target.options.is_like_msvc { + let mut exports = String::new(); + if scx.sess().crate_types.borrow().contains(&CrateTypeDylib) { + for sym in reachable { + writeln!(exports, " {}", sym).unwrap(); + } + + // Take a look at how all upstream crates are linked into this + // dynamic library. For all statically linked libraries we take all + // their reachable symbols and emit them as well. + let cstore = &scx.sess().cstore; + let formats = scx.sess().dependency_formats.borrow(); + let symbols = formats[&CrateTypeDylib].iter(); + let symbols = symbols.enumerate().filter_map(|(i, f)| { + if *f == Linkage::Static { + Some((i + 1) as ast::CrateNum) + } else { + None + } + }).flat_map(|cnum| { + cstore.reachable_ids(cnum) + }).map(|did| -> String { + Instance::mono(scx.tcx(), did).symbol_name(scx) + }); + for symbol in symbols { + writeln!(exports, " {}", symbol).unwrap(); + } + } + LinkerInfo::Msvc { + dylib_exports: exports + } + } else { + LinkerInfo::Gnu + } + } + + pub fn to_linker(&'a self, + cmd: &'a mut Command, + sess: &'a Session) -> Box { + match *self { + LinkerInfo::Gnu => { + Box::new(GnuLinker { + cmd: cmd, + sess: sess + }) as Box + } + LinkerInfo::Msvc { ref dylib_exports } => { + Box::new(MsvcLinker { + cmd: cmd, + sess: sess, + dylib_exports: dylib_exports + }) as Box + } + } + } +} /// Linker abstraction used by back::link to build up the command to invoke a /// linker. @@ -53,13 +125,12 @@ 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); + fn export_symbols(&mut self, tmpdir: &Path); } pub struct GnuLinker<'a> { - pub cmd: &'a mut Command, - pub sess: &'a Session, + cmd: &'a mut Command, + sess: &'a Session, } impl<'a> GnuLinker<'a> { @@ -198,14 +269,15 @@ impl<'a> Linker for GnuLinker<'a> { self.cmd.arg("-Wl,-Bdynamic"); } - fn export_symbols(&mut self, _: &Session, _: &CrateTranslation, _: &Path) { + fn export_symbols(&mut self, _: &Path) { // noop, visibility in object files takes care of this } } pub struct MsvcLinker<'a> { - pub cmd: &'a mut Command, - pub sess: &'a Session, + cmd: &'a mut Command, + sess: &'a Session, + dylib_exports: &'a str } impl<'a> Linker for MsvcLinker<'a> { @@ -322,8 +394,7 @@ impl<'a> Linker for MsvcLinker<'a> { // crates. Upstream rlibs may be linked statically to this dynamic library, // 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) { + fn export_symbols(&mut self, tmpdir: &Path) { let path = tmpdir.join("lib.def"); let res = (|| -> io::Result<()> { let mut f = BufWriter::new(File::create(&path)?); @@ -332,37 +403,11 @@ impl<'a> Linker for MsvcLinker<'a> { // straight to exports. writeln!(f, "LIBRARY")?; writeln!(f, "EXPORTS")?; - - // Write out all our local symbols - for sym in trans.reachable.iter() { - writeln!(f, " {}", sym)?; - } - - // Take a look at how all upstream crates are linked into this - // dynamic library. For all statically linked libraries we take all - // their reachable symbols and emit them as well. - let cstore = &sess.cstore; - let formats = sess.dependency_formats.borrow(); - let symbols = formats[&CrateTypeDylib].iter(); - let symbols = symbols.enumerate().filter_map(|(i, f)| { - if *f == Linkage::Static { - Some((i + 1) as ast::CrateNum) - } else { - None - } - }).flat_map(|cnum| { - cstore.reachable_ids(cnum) - }).map(|did| { - cstore.item_symbol(did) - }); - for symbol in symbols { - writeln!(f, " {}", symbol)?; - } - + f.write(self.dylib_exports.as_bytes())?; 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); diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index b83fe32256754..78c8e204f0d77 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; @@ -2816,6 +2817,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, @@ -2823,6 +2825,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 4c6c881430328f71ebf67f373d610fd9b017dbae Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 12 May 2016 19:58:11 +0300 Subject: [PATCH 10/18] 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 | 10 +--------- 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(+), 96 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 07f7052c0ed6d..17b5778994789 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -33,9 +33,8 @@ 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 util::nodemap::{FnvHashMap, NodeSet, DefIdMap}; use std::any::Any; -use std::cell::RefCell; use std::rc::Rc; use std::path::PathBuf; use syntax::ast; @@ -174,7 +173,6 @@ pub trait CrateStore<'tcx> : Any { 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; @@ -276,7 +274,6 @@ pub trait CrateStore<'tcx> : Any { 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>, @@ -354,7 +351,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> @@ -478,7 +474,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 7e039867a7877..6461869344d65 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -23,7 +23,7 @@ use rustc::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; use rustc::hir::map as hir_map; 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; @@ -105,12 +105,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { decoder::get_item_attrs(&cdata, def_id.index) } - fn item_symbol(&self, def: DefId) -> String - { - 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> { let cdata = self.get_crate_data(def.krate); @@ -517,7 +511,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>, @@ -527,7 +520,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 834ea7c027bd1..2c1114e3ee713 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -186,10 +186,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 translated_def_id(cdata: Cmd, d: rbml::Doc) -> DefId { let id = reader::doc_as_u64(d); let index = DefIndex::new((id & 0xFFFF_FFFF) as usize); @@ -609,10 +605,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 e43c9cdfe4abb..80c139b1be124 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -33,7 +33,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; @@ -58,7 +58,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>, @@ -204,20 +203,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) { @@ -512,10 +497,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); @@ -704,10 +685,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); } } @@ -885,7 +862,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); @@ -922,9 +898,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); @@ -1355,8 +1328,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)); @@ -1377,7 +1348,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 78c8e204f0d77..2bce2ebee76b1 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; @@ -2338,15 +2337,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); - } - } _ => {} } } @@ -2431,16 +2421,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) } @@ -2464,7 +2444,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 4b42dad964d69..c087b9fa7b4d0 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 } @@ -714,10 +708,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 b5a5be7210fa55ee254a604121bd8fe21e728767 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 12 May 2016 23:37:41 +0300 Subject: [PATCH 11/18] trans: save metadata even with -Z no-trans. --- src/librustc/session/config.rs | 2 +- src/librustc_driver/lib.rs | 4 -- src/librustc_trans/back/linker.rs | 1 - src/librustc_trans/base.rs | 69 ++++++++++++++++++------------- src/librustc_trans/context.rs | 4 ++ 5 files changed, 46 insertions(+), 34 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 7d1d5dba39839..08e422e47877b 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1103,7 +1103,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 2a4b30e016f28..45a665c99b8cd 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -504,10 +504,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/linker.rs b/src/librustc_trans/back/linker.rs index 858fe65c0fc7f..59e74c4efc753 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -9,7 +9,6 @@ // except according to those terms. use std::ffi::OsString; -use std::fmt::Write as FmtWrite; use std::fs::{self, File}; use std::io::{self, BufWriter}; use std::io::prelude::*; diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 2bce2ebee76b1..36c6428a45b4e 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -2425,11 +2425,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() @@ -2445,9 +2442,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)); @@ -2634,10 +2631,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 } @@ -2681,6 +2680,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 || @@ -2688,6 +2700,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); @@ -2717,13 +2747,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 ---"); @@ -2753,10 +2776,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); @@ -2790,12 +2809,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 c087b9fa7b4d0..64041b496ffe2 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -501,6 +501,10 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { pub fn symbol_hasher(&self) -> &RefCell { &self.symbol_hasher } + + pub fn mir_map(&self) -> &MirMap<'tcx> { + &self.mir_map + } } impl<'tcx> LocalCrateContext<'tcx> { From 3d67a1abf40664578060d84924d507097b98cc51 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 10 May 2016 14:17:57 -0700 Subject: [PATCH 12/18] rustc: Add a new crate type, cdylib This commit is an implementation of [RFC 1510] which adds a new crate type, `cdylib`, to the compiler. This new crate type differs from the existing `dylib` crate type in a few key ways: * No metadata is present in the final artifact * Symbol visibility rules are the same as executables, that is only reachable `extern` functions are visible symbols * LTO is allowed * All libraries are always linked statically This commit is relatively simple by just plubming the compiler with another crate type which takes different branches here and there. The only major change is an implementation of the `Linker::export_symbols` function on Unix which now actually does something. This helps restrict the public symbols from a cdylib on Unix. With this PR a "hello world" `cdylib` is 7.2K while the same `dylib` is 2.4MB, which is some nice size savings! [RFC 1510]: https://github.com/rust-lang/rfcs/pull/1510 Closes #33132 --- src/librustc/middle/dependency_format.rs | 7 +- src/librustc/middle/reachable.rs | 2 +- src/librustc/middle/weak_lang_items.rs | 1 + src/librustc/session/config.rs | 5 +- src/librustc_driver/driver.rs | 3 + src/librustc_metadata/creader.rs | 1 + src/librustc_trans/back/link.rs | 80 +++++---- src/librustc_trans/back/linker.rs | 162 +++++++++++------- src/librustc_trans/back/lto.rs | 7 +- src/test/compile-fail/auxiliary/cdylib-dep.rs | 11 ++ .../cdylib-deps-must-be-static.rs | 16 ++ src/test/run-make/cdylib/Makefile | 10 ++ src/test/run-make/cdylib/bar.rs | 13 ++ src/test/run-make/cdylib/foo.c | 20 +++ src/test/run-make/cdylib/foo.rs | 23 +++ 15 files changed, 253 insertions(+), 108 deletions(-) create mode 100644 src/test/compile-fail/auxiliary/cdylib-dep.rs create mode 100644 src/test/compile-fail/cdylib-deps-must-be-static.rs create mode 100644 src/test/run-make/cdylib/Makefile create mode 100644 src/test/run-make/cdylib/bar.rs create mode 100644 src/test/run-make/cdylib/foo.c create mode 100644 src/test/run-make/cdylib/foo.rs diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index fe22cfdb43f73..0b398fd0d47c5 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -115,9 +115,10 @@ fn calculate_type(sess: &session::Session, // got long ago), so don't bother with anything. config::CrateTypeRlib => return Vec::new(), - // Staticlibs must have all static dependencies. If any fail to be - // found, we generate some nice pretty errors. - config::CrateTypeStaticlib => { + // Staticlibs and cdylibs must have all static dependencies. If any fail + // to be found, we generate some nice pretty errors. + config::CrateTypeStaticlib | + config::CrateTypeCdylib => { match attempt_static(sess) { Some(v) => return v, None => {} diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index bca5af69edfd0..55d75ace08151 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -145,7 +145,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { // Creates a new reachability computation context. fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ReachableContext<'a, 'tcx> { let any_library = tcx.sess.crate_types.borrow().iter().any(|ty| { - *ty != config::CrateTypeExecutable + *ty == config::CrateTypeRlib || *ty == config::CrateTypeDylib }); ReachableContext { tcx: tcx, diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index b7dfc86720458..325887684914b 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -70,6 +70,7 @@ fn verify(sess: &Session, items: &lang_items::LanguageItems) { let needs_check = sess.crate_types.borrow().iter().any(|kind| { match *kind { config::CrateTypeDylib | + config::CrateTypeCdylib | config::CrateTypeExecutable | config::CrateTypeStaticlib => true, config::CrateTypeRlib => false, diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 08e422e47877b..0984c5e820984 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -300,6 +300,7 @@ pub enum CrateType { CrateTypeDylib, CrateTypeRlib, CrateTypeStaticlib, + CrateTypeCdylib, } #[derive(Clone)] @@ -1326,6 +1327,7 @@ pub fn parse_crate_types_from_list(list_list: Vec) -> Result CrateTypeRlib, "staticlib" => CrateTypeStaticlib, "dylib" => CrateTypeDylib, + "cdylib" => CrateTypeCdylib, "bin" => CrateTypeExecutable, _ => { return Err(format!("unknown crate type: `{}`", @@ -1413,7 +1415,8 @@ impl fmt::Display for CrateType { CrateTypeExecutable => "bin".fmt(f), CrateTypeDylib => "dylib".fmt(f), CrateTypeRlib => "rlib".fmt(f), - CrateTypeStaticlib => "staticlib".fmt(f) + CrateTypeStaticlib => "staticlib".fmt(f), + CrateTypeCdylib => "cdylib".fmt(f), } } } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 46356add8c682..05d84d9fd7846 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -1175,6 +1175,9 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec { Some(config::CrateTypeDylib) } + Some(ref n) if *n == "cdylib" => { + Some(config::CrateTypeCdylib) + } Some(ref n) if *n == "lib" => { Some(config::default_lib_output()) } diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index c78a3a0be74de..7e1bd50a795c1 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -747,6 +747,7 @@ impl<'a> CrateReader<'a> { match *ct { config::CrateTypeExecutable => need_exe_alloc = true, config::CrateTypeDylib | + config::CrateTypeCdylib | config::CrateTypeStaticlib => need_lib_alloc = true, config::CrateTypeRlib => {} } diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index c54432c6e5838..4101874c6fd50 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -228,6 +228,7 @@ pub fn invalid_output_for_target(sess: &Session, crate_type: config::CrateType) -> bool { match (sess.target.target.options.dynamic_linking, sess.target.target.options.executables, crate_type) { + (false, _, config::CrateTypeCdylib) | (false, _, config::CrateTypeDylib) => true, (_, false, config::CrateTypeExecutable) => true, _ => false @@ -250,6 +251,7 @@ pub fn filename_for_input(sess: &Session, config::CrateTypeRlib => { outputs.out_directory.join(&format!("lib{}.rlib", libname)) } + config::CrateTypeCdylib | config::CrateTypeDylib => { let (prefix, suffix) = (&sess.target.target.options.dll_prefix, &sess.target.target.options.dll_suffix); @@ -278,9 +280,10 @@ pub fn each_linked_rlib(sess: &Session, f: &mut FnMut(ast::CrateNum, &Path)) { let crates = sess.cstore.used_crates(LinkagePreference::RequireStatic).into_iter(); let fmts = sess.dependency_formats.borrow(); - let fmts = fmts.get(&config::CrateTypeExecutable).or_else(|| { - fmts.get(&config::CrateTypeStaticlib) - }).unwrap_or_else(|| { + let fmts = fmts.get(&config::CrateTypeExecutable) + .or_else(|| fmts.get(&config::CrateTypeStaticlib)) + .or_else(|| fmts.get(&config::CrateTypeCdylib)); + let fmts = fmts.unwrap_or_else(|| { bug!("could not find formats for rlibs") }); for (cnum, path) in crates { @@ -335,13 +338,9 @@ fn link_binary_output(sess: &Session, config::CrateTypeStaticlib => { link_staticlib(sess, &objects, &out_filename, tmpdir.path()); } - config::CrateTypeExecutable => { - link_natively(sess, false, &objects, &out_filename, trans, outputs, - tmpdir.path()); - } - config::CrateTypeDylib => { - link_natively(sess, true, &objects, &out_filename, trans, outputs, - tmpdir.path()); + _ => { + link_natively(sess, crate_type, &objects, &out_filename, trans, + outputs, tmpdir.path()); } } @@ -609,13 +608,14 @@ fn link_staticlib(sess: &Session, objects: &[PathBuf], out_filename: &Path, // // This will invoke the system linker/cc to create the resulting file. This // links to all upstream files as well. -fn link_natively(sess: &Session, dylib: bool, - objects: &[PathBuf], out_filename: &Path, +fn link_natively(sess: &Session, + crate_type: config::CrateType, + objects: &[PathBuf], + out_filename: &Path, trans: &CrateTranslation, outputs: &OutputFilenames, tmpdir: &Path) { - info!("preparing dylib? ({}) from {:?} to {:?}", dylib, objects, - out_filename); + info!("preparing {:?} from {:?} to {:?}", crate_type, objects, out_filename); // The invocations of cc share some flags across platforms let (pname, mut cmd) = get_linker(sess); @@ -624,10 +624,10 @@ fn link_natively(sess: &Session, dylib: bool, let root = sess.target_filesearch(PathKind::Native).get_lib_path(); cmd.args(&sess.target.target.options.pre_link_args); - let pre_link_objects = if dylib { - &sess.target.target.options.pre_link_objects_dll - } else { + let pre_link_objects = if crate_type == config::CrateTypeExecutable { &sess.target.target.options.pre_link_objects_exe + } else { + &sess.target.target.options.pre_link_objects_dll }; for obj in pre_link_objects { cmd.arg(root.join(obj)); @@ -635,7 +635,7 @@ fn link_natively(sess: &Session, dylib: bool, { let mut linker = trans.linker_info.to_linker(&mut cmd, &sess); - link_args(&mut *linker, sess, dylib, tmpdir, + link_args(&mut *linker, sess, crate_type, tmpdir, objects, out_filename, outputs); if !sess.target.target.options.no_compiler_rt { linker.link_staticlib("compiler-rt"); @@ -701,7 +701,7 @@ fn link_natively(sess: &Session, dylib: bool, fn link_args(cmd: &mut Linker, sess: &Session, - dylib: bool, + crate_type: config::CrateType, tmpdir: &Path, objects: &[PathBuf], out_filename: &Path, @@ -722,26 +722,28 @@ 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 dylib { - cmd.export_symbols(tmpdir); + if crate_type != config::CrateTypeExecutable { + cmd.export_symbols(tmpdir, crate_type); } // When linking a dynamic library, we put the metadata into a section of the // executable. This metadata is in a separate object file from the main // object file, so we link that in here. - if dylib { + if crate_type == config::CrateTypeDylib { cmd.add_object(&outputs.with_extension("metadata.o")); } // Try to strip as much out of the generated object by removing unused // sections if possible. See more comments in linker.rs if !sess.opts.cg.link_dead_code { - cmd.gc_sections(dylib); + let keep_metadata = crate_type == config::CrateTypeDylib; + cmd.gc_sections(keep_metadata); } let used_link_args = sess.cstore.used_link_args(); - if !dylib && t.options.position_independent_executables { + if crate_type == config::CrateTypeExecutable && + t.options.position_independent_executables { let empty_vec = Vec::new(); let empty_str = String::new(); let args = sess.opts.cg.link_args.as_ref().unwrap_or(&empty_vec); @@ -796,12 +798,12 @@ fn link_args(cmd: &mut Linker, // in this DAG so far because they're only dylibs and dylibs can only depend // on other dylibs (e.g. other native deps). add_local_native_libraries(cmd, sess); - add_upstream_rust_crates(cmd, sess, dylib, tmpdir); + add_upstream_rust_crates(cmd, sess, crate_type, tmpdir); add_upstream_native_libraries(cmd, sess); // # Telling the linker what we're doing - if dylib { + if crate_type != config::CrateTypeExecutable { cmd.build_dylib(out_filename); } @@ -899,8 +901,10 @@ fn add_local_native_libraries(cmd: &mut Linker, sess: &Session) { // Rust crates are not considered at all when creating an rlib output. All // dependencies will be linked when producing the final output (instead of // the intermediate rlib version) -fn add_upstream_rust_crates(cmd: &mut Linker, sess: &Session, - dylib: bool, tmpdir: &Path) { +fn add_upstream_rust_crates(cmd: &mut Linker, + sess: &Session, + crate_type: config::CrateType, + tmpdir: &Path) { // All of the heavy lifting has previously been accomplished by the // dependency_format module of the compiler. This is just crawling the // output of that module, adding crates as necessary. @@ -910,11 +914,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker, sess: &Session, // involves just passing the right -l flag. let formats = sess.dependency_formats.borrow(); - let data = if dylib { - formats.get(&config::CrateTypeDylib).unwrap() - } else { - formats.get(&config::CrateTypeExecutable).unwrap() - }; + let data = formats.get(&crate_type).unwrap(); // Invoke get_used_crates to ensure that we get a topological sorting of // crates. @@ -929,7 +929,8 @@ fn add_upstream_rust_crates(cmd: &mut Linker, sess: &Session, Linkage::NotLinked | Linkage::IncludedFromDylib => {} Linkage::Static => { - add_static_crate(cmd, sess, tmpdir, dylib, &src.rlib.unwrap().0) + add_static_crate(cmd, sess, tmpdir, crate_type, + &src.rlib.unwrap().0) } Linkage::Dynamic => { add_dynamic_crate(cmd, sess, &src.dylib.unwrap().0) @@ -974,9 +975,12 @@ fn add_upstream_rust_crates(cmd: &mut Linker, sess: &Session, // (aka we're making an executable), we can just pass the rlib blindly to // the linker (fast) because it's fine if it's not actually included as // we're at the end of the dependency chain. - fn add_static_crate(cmd: &mut Linker, sess: &Session, tmpdir: &Path, - dylib: bool, cratepath: &Path) { - if !sess.lto() && !dylib { + fn add_static_crate(cmd: &mut Linker, + sess: &Session, + tmpdir: &Path, + crate_type: config::CrateType, + cratepath: &Path) { + if !sess.lto() && crate_type != config::CrateTypeDylib { cmd.link_rlib(&fix_windows_verbatim_for_gcc(cratepath)); return } @@ -1012,7 +1016,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker, sess: &Session, if any_objects { archive.build(); - if dylib { + if crate_type == config::CrateTypeDylib { cmd.link_whole_rlib(&fix_windows_verbatim_for_gcc(&dst)); } else { cmd.link_rlib(&fix_windows_verbatim_for_gcc(&dst)); diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index 59e74c4efc753..aee5a4ebea1bf 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -21,75 +21,71 @@ use monomorphize::Instance; use back::archive; use middle::dependency_format::Linkage; use session::Session; -use session::config::CrateTypeDylib; +use session::config::{CrateType, CrateTypeCdylib, CrateTypeDylib}; use session::config; use syntax::ast; /// For all the linkers we support, and information they might /// need out of the shared crate context before we get rid of it. -pub enum LinkerInfo { - Gnu, - Msvc { - dylib_exports: String - } +pub struct LinkerInfo { + dylib_exports: Vec, + cdylib_exports: Vec +} + +fn exported_symbols<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, + reachable: &[String], + crate_type: CrateType) + -> Vec { + if !scx.sess().crate_types.borrow().contains(&crate_type) { + return vec![]; + } + + let mut symbols = reachable.to_vec(); + + // Take a look at how all upstream crates are linked into this + // dynamic library. For all statically linked libraries we take all + // their reachable symbols and emit them as well. + 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 { + None + } + }).flat_map(|cnum| { + cstore.reachable_ids(cnum) + }).map(|did| -> String { + Instance::mono(scx, did).symbol_name(scx) + })); + symbols } impl<'a, 'tcx> LinkerInfo { pub fn new(scx: &SharedCrateContext<'a, 'tcx>, reachable: &[String]) -> LinkerInfo { - if scx.sess().target.target.options.is_like_msvc { - let mut exports = String::new(); - if scx.sess().crate_types.borrow().contains(&CrateTypeDylib) { - for sym in reachable { - writeln!(exports, " {}", sym).unwrap(); - } - - // Take a look at how all upstream crates are linked into this - // dynamic library. For all statically linked libraries we take all - // their reachable symbols and emit them as well. - let cstore = &scx.sess().cstore; - let formats = scx.sess().dependency_formats.borrow(); - let symbols = formats[&CrateTypeDylib].iter(); - let symbols = symbols.enumerate().filter_map(|(i, f)| { - if *f == Linkage::Static { - Some((i + 1) as ast::CrateNum) - } else { - None - } - }).flat_map(|cnum| { - cstore.reachable_ids(cnum) - }).map(|did| -> String { - Instance::mono(scx.tcx(), did).symbol_name(scx) - }); - for symbol in symbols { - writeln!(exports, " {}", symbol).unwrap(); - } - } - LinkerInfo::Msvc { - dylib_exports: exports - } - } else { - LinkerInfo::Gnu + LinkerInfo { + dylib_exports: exported_symbols(scx, reachable, CrateTypeDylib), + cdylib_exports: exported_symbols(scx, reachable, CrateTypeCdylib) } } pub fn to_linker(&'a self, cmd: &'a mut Command, sess: &'a Session) -> Box { - match *self { - LinkerInfo::Gnu => { - Box::new(GnuLinker { - cmd: cmd, - sess: sess - }) as Box - } - LinkerInfo::Msvc { ref dylib_exports } => { - Box::new(MsvcLinker { - cmd: cmd, - sess: sess, - dylib_exports: dylib_exports - }) as 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 } } } @@ -113,7 +109,7 @@ pub trait Linker { fn framework_path(&mut self, path: &Path); fn output_filename(&mut self, path: &Path); fn add_object(&mut self, path: &Path); - fn gc_sections(&mut self, is_dylib: bool); + fn gc_sections(&mut self, keep_metadata: bool); fn position_independent_executable(&mut self); fn optimize(&mut self); fn debuginfo(&mut self); @@ -124,12 +120,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, tmpdir: &Path); + fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType); } pub struct GnuLinker<'a> { cmd: &'a mut Command, sess: &'a Session, + info: &'a LinkerInfo } impl<'a> GnuLinker<'a> { @@ -183,7 +180,7 @@ impl<'a> Linker for GnuLinker<'a> { } } - fn gc_sections(&mut self, is_dylib: bool) { + fn gc_sections(&mut self, keep_metadata: bool) { // The dead_strip option to the linker specifies that functions and data // unreachable by the entry point will be removed. This is quite useful // with Rust's compilation model of compiling libraries at a time into @@ -209,7 +206,7 @@ impl<'a> Linker for GnuLinker<'a> { // eliminate the metadata. If we're building an executable, however, // --gc-sections drops the size of hello world from 1.8MB to 597K, a 67% // reduction. - } else if !is_dylib { + } else if !keep_metadata { self.cmd.arg("-Wl,--gc-sections"); } } @@ -268,15 +265,43 @@ impl<'a> Linker for GnuLinker<'a> { self.cmd.arg("-Wl,-Bdynamic"); } - fn export_symbols(&mut self, _: &Path) { - // noop, visibility in object files takes care of this + fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) { + let path = tmpdir.join("list"); + let prefix = if self.sess.target.target.options.is_like_osx { + "_" + } else { + "" + }; + let res = (|| -> io::Result<()> { + let mut f = BufWriter::new(File::create(&path)?); + let symbols = if crate_type == CrateType::CrateTypeCdylib { + &self.info.cdylib_exports + } else { + &self.info.dylib_exports + }; + for sym in symbols { + writeln!(f, "{}{}", prefix, sym)?; + } + Ok(()) + })(); + if let Err(e) = res { + 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 { + arg.push("-Wl,-exported_symbols_list,"); + } else { + arg.push("-Wl,--retain-symbols-file="); + } + arg.push(&path); + self.cmd.arg(arg); } } pub struct MsvcLinker<'a> { cmd: &'a mut Command, sess: &'a Session, - dylib_exports: &'a str + info: &'a LinkerInfo } impl<'a> Linker for MsvcLinker<'a> { @@ -291,7 +316,9 @@ impl<'a> Linker for MsvcLinker<'a> { self.cmd.arg(arg); } - fn gc_sections(&mut self, _is_dylib: bool) { self.cmd.arg("/OPT:REF,ICF"); } + fn gc_sections(&mut self, _keep_metadata: bool) { + self.cmd.arg("/OPT:REF,ICF"); + } fn link_dylib(&mut self, lib: &str) { self.cmd.arg(&format!("{}.lib", lib)); @@ -393,7 +420,9 @@ impl<'a> Linker for MsvcLinker<'a> { // crates. Upstream rlibs may be linked statically to this dynamic library, // in which case they may continue to transitively be used and hence need // their symbols exported. - fn export_symbols(&mut self, tmpdir: &Path) { + fn export_symbols(&mut self, + tmpdir: &Path, + crate_type: CrateType) { let path = tmpdir.join("lib.def"); let res = (|| -> io::Result<()> { let mut f = BufWriter::new(File::create(&path)?); @@ -402,7 +431,14 @@ impl<'a> Linker for MsvcLinker<'a> { // straight to exports. writeln!(f, "LIBRARY")?; writeln!(f, "EXPORTS")?; - f.write(self.dylib_exports.as_bytes())?; + 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 { diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index 649d37e802d14..31bc11fb215b0 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -30,7 +30,8 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, output_names: &config::OutputFilenames) { if sess.opts.cg.prefer_dynamic { sess.struct_err("cannot prefer dynamic linking when performing LTO") - .note("only 'staticlib' and 'bin' outputs are supported with LTO") + .note("only 'staticlib', 'bin', and 'cdylib' outputs are \ + supported with LTO") .emit(); sess.abort_if_errors(); } @@ -38,7 +39,9 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, // Make sure we actually can run LTO for crate_type in sess.crate_types.borrow().iter() { match *crate_type { - config::CrateTypeExecutable | config::CrateTypeStaticlib => {} + config::CrateTypeExecutable | + config::CrateTypeCdylib | + config::CrateTypeStaticlib => {} _ => { sess.fatal("lto can only be run for executables and \ static library outputs"); diff --git a/src/test/compile-fail/auxiliary/cdylib-dep.rs b/src/test/compile-fail/auxiliary/cdylib-dep.rs new file mode 100644 index 0000000000000..a3d0222a14c97 --- /dev/null +++ b/src/test/compile-fail/auxiliary/cdylib-dep.rs @@ -0,0 +1,11 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "dylib"] diff --git a/src/test/compile-fail/cdylib-deps-must-be-static.rs b/src/test/compile-fail/cdylib-deps-must-be-static.rs new file mode 100644 index 0000000000000..c0a2dcba5c0a3 --- /dev/null +++ b/src/test/compile-fail/cdylib-deps-must-be-static.rs @@ -0,0 +1,16 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern: dependency `cdylib_dep` not found in rlib format +// aux-build:cdylib-dep.rs + +#![crate_type = "cdylib"] + +extern crate cdylib_dep; diff --git a/src/test/run-make/cdylib/Makefile b/src/test/run-make/cdylib/Makefile new file mode 100644 index 0000000000000..8d53b5dc210d1 --- /dev/null +++ b/src/test/run-make/cdylib/Makefile @@ -0,0 +1,10 @@ +include ../tools.mk + +all: + $(RUSTC) bar.rs -O + $(RUSTC) foo.rs -O + $(CC) $(CFLAGS) foo.c -lfoo -o $(call RUN_BINFILE,foo) -L $(TMPDIR) + $(call RUN,foo) + rm $(call DYLIB,foo) + $(RUSTC) foo.rs -C lto + $(call RUN,foo) diff --git a/src/test/run-make/cdylib/bar.rs b/src/test/run-make/cdylib/bar.rs new file mode 100644 index 0000000000000..fcb1efe397d4a --- /dev/null +++ b/src/test/run-make/cdylib/bar.rs @@ -0,0 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] + +pub fn bar() {} diff --git a/src/test/run-make/cdylib/foo.c b/src/test/run-make/cdylib/foo.c new file mode 100644 index 0000000000000..1c950427c658b --- /dev/null +++ b/src/test/run-make/cdylib/foo.c @@ -0,0 +1,20 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#include + +extern void foo(); +extern unsigned bar(unsigned a, unsigned b); + +int main() { + foo(); + assert(bar(1, 2) == 3); + return 0; +} diff --git a/src/test/run-make/cdylib/foo.rs b/src/test/run-make/cdylib/foo.rs new file mode 100644 index 0000000000000..cdac6d1903525 --- /dev/null +++ b/src/test/run-make/cdylib/foo.rs @@ -0,0 +1,23 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "cdylib"] + +extern crate bar; + +#[no_mangle] +pub extern fn foo() { + bar::bar(); +} + +#[no_mangle] +pub extern fn bar(a: u32, b: u32) -> u32 { + a + b +} From 067284b2917561f5bff1db4c521347d897dcaf3b Mon Sep 17 00:00:00 2001 From: Wang Xuerui Date: Mon, 16 May 2016 16:59:27 +0800 Subject: [PATCH 13/18] syntax_ext: format: nest_level's are no more `nest_level` is long dead since cac7a2053aba7be214d5e58e13867089638a8f50 (PR #14831), so is `check_positional_ok()`. Let's bid them farewell. --- src/libsyntax_ext/format.rs | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 6c61d6b914c56..7d57614fd7982 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -68,7 +68,6 @@ struct Context<'a, 'b:'a> { name_positions: HashMap, /// Updated as arguments are consumed or methods are entered - nest_level: usize, next_arg: usize, } @@ -164,9 +163,7 @@ impl<'a, 'b> Context<'a, 'b> { let pos = match arg.position { parse::ArgumentNext => { let i = self.next_arg; - if self.check_positional_ok() { - self.next_arg += 1; - } + self.next_arg += 1; Exact(i) } parse::ArgumentIs(i) => Exact(i), @@ -189,25 +186,13 @@ impl<'a, 'b> Context<'a, 'b> { self.verify_arg_type(Named(s.to_string()), Unsigned); } parse::CountIsNextParam => { - if self.check_positional_ok() { - let next_arg = self.next_arg; - self.verify_arg_type(Exact(next_arg), Unsigned); - self.next_arg += 1; - } + let next_arg = self.next_arg; + self.verify_arg_type(Exact(next_arg), Unsigned); + self.next_arg += 1; } } } - fn check_positional_ok(&mut self) -> bool { - if self.nest_level != 0 { - self.ecx.span_err(self.fmtsp, "cannot use implicit positional \ - arguments nested inside methods"); - false - } else { - true - } - } - fn describe_num_args(&self) -> String { match self.args.len() { 0 => "no arguments given".to_string(), @@ -655,7 +640,6 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span, name_positions: HashMap::new(), name_types: HashMap::new(), name_ordering: name_ordering, - nest_level: 0, next_arg: 0, literal: String::new(), pieces: Vec::new(), From 2ea6c70a1ad43ae8af0e108ddcee4fc06ea9c77c Mon Sep 17 00:00:00 2001 From: Wang Xuerui Date: Mon, 16 May 2016 17:16:32 +0800 Subject: [PATCH 14/18] syntax_ext: format: remove reference to methods in comment --- src/libsyntax_ext/format.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 7d57614fd7982..abfa65580646d 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -67,7 +67,7 @@ struct Context<'a, 'b:'a> { name_positions: HashMap, - /// Updated as arguments are consumed or methods are entered + /// Updated as arguments are consumed next_arg: usize, } From dc1ebae5e134f2496978291443bb1a175cb929d1 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Mon, 16 May 2016 20:05:43 +0300 Subject: [PATCH 15/18] Mark the metadata symbol as reachable to fix OSX not finding dylibs. --- src/librustc_trans/back/linker.rs | 5 +++++ src/librustc_trans/base.rs | 4 +--- src/librustc_trans/context.rs | 6 ++++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index aee5a4ebea1bf..62435572278a1 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -42,6 +42,11 @@ fn exported_symbols<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, let mut symbols = reachable.to_vec(); + // Make sure to keep the metadata in dylibs (cdylibs don't have it). + if crate_type == CrateTypeDylib { + symbols.push(scx.metadata_symbol_name()); + } + // Take a look at how all upstream crates are linked into this // dynamic library. For all statically linked libraries we take all // their reachable symbols and emit them as well. diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 36c6428a45b4e..361eb701b63fa 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -2450,9 +2450,7 @@ fn write_metadata(cx: &SharedCrateContext, let llmeta = C_bytes_in_context(cx.metadata_llcx(), &compressed[..]); let llconst = C_struct_in_context(cx.metadata_llcx(), &[llmeta], false); - let name = format!("rust_metadata_{}_{}", - cx.link_meta().crate_name, - cx.link_meta().crate_hash); + let name = cx.metadata_symbol_name(); let buf = CString::new(name).unwrap(); let llglobal = unsafe { llvm::LLVMAddGlobal(cx.metadata_llmod(), val_ty(llconst).to_ref(), buf.as_ptr()) diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 64041b496ffe2..1ddcbc79aed5f 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -505,6 +505,12 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { 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, + self.link_meta().crate_hash) + } } impl<'tcx> LocalCrateContext<'tcx> { From b2613028feeb2c266befe121ff4d16b87c328f9d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 16 May 2016 22:36:13 +0200 Subject: [PATCH 16/18] Fix selected item background style --- src/librustdoc/html/static/rustdoc.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index d256e939afcfc..a52a914fea680 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -640,6 +640,10 @@ span.since { margin-right: 5px; } +:target > code { + background: #FDFFD3; +} + /* Media Queries */ @media (max-width: 700px) { From f3c63d21c1af1da00bcf36e6e6490425ff3edbbc Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Mon, 16 May 2016 16:57:33 -0400 Subject: [PATCH 17/18] Add missing code fence to `diagnostics.rs` Closes #33662 --- src/librustc_borrowck/diagnostics.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs index cdbad685008f2..b5d8192b4dd2c 100644 --- a/src/librustc_borrowck/diagnostics.rs +++ b/src/librustc_borrowck/diagnostics.rs @@ -391,6 +391,7 @@ fn you_know_nothing(jon_snow: &mut i32) { // but it is already borrowed }; } +``` In here, `jon_snow` is already borrowed by the `nights_watch` closure, so it cannot be borrowed by the `starks` closure at the same time. To fix this issue, From 07e8975ac8bded08721ec7c4830e23d07d7285af Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 17 May 2016 08:52:03 +0300 Subject: [PATCH 18/18] Use the original crate name in absolute paths. --- src/librustc/ty/item_path.rs | 6 +++++- src/librustc_trans/back/symbol_names.rs | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 9aaffd76d3984..ee9983038b162 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -101,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 49c7225306b25..170c8f75b5056 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -121,7 +121,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));