提交 5229e0ef 编写于 作者: B bors

Auto merge of #33602 - eddyb:no-trans--check, r=michaelwoerister

Save metadata even with -Z no-trans (e.g. for multi-crate cargo check).

Removes the item symbol map in metadata, as we can now generate them in a deterministic manner.
The `-Z no-trans` change lets the LLVM passes and linking run, but with just metadata and no code.
It fails while trying to link a binary because there's no `main` function, which is correct but not good UX.

There's also no way to easily throw away all of the artifacts to rebuild with actual code generation.
We might want `cargo check` to do that using cargo-internal information and then it would just work.

cc @alexcrichton @nikomatsakis @Aatch @michaelwoerister
......@@ -34,8 +34,7 @@
use session::Session;
use session::config::PanicStrategy;
use session::search_paths::PathKind;
use util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap};
use std::cell::RefCell;
use util::nodemap::{FnvHashMap, NodeSet, DefIdMap};
use std::rc::Rc;
use std::path::PathBuf;
use syntax::ast;
......@@ -169,7 +168,6 @@ fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> ty::GenericPredicates<'tcx>;
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>;
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<String>;
......@@ -205,6 +203,7 @@ fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
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;
......@@ -274,7 +273,6 @@ fn encode_type<'a>(&self,
fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<ast::CrateNum>;
fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
reexports: &def::ExportMap,
item_symbols: &RefCell<NodeMap<String>>,
link_meta: &LinkMeta,
reachable: &NodeSet,
mir_map: &MirMap<'tcx>,
......@@ -352,7 +350,6 @@ fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
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<ast::Attribute> { 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>
......@@ -399,6 +396,7 @@ fn is_impl(&self, did: DefId) -> bool { bug!("is_impl") }
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") }
......@@ -481,7 +479,6 @@ fn used_crate_source(&self, cnum: ast::CrateNum) -> CrateSource { bug!("used_cra
fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<ast::CrateNum> { None }
fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
reexports: &def::ExportMap,
item_symbols: &RefCell<NodeMap<String>>,
link_meta: &LinkMeta,
reachable: &NodeSet,
mir_map: &MirMap<'tcx>,
......
......@@ -1104,7 +1104,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
let no_analysis = debugging_opts.no_analysis;
let mut output_types = HashMap::new();
if !debugging_opts.parse_only && !no_trans {
if !debugging_opts.parse_only {
for list in matches.opt_strs("emit") {
for output_type in list.split(',') {
let mut parts = output_type.splitn(2, '=');
......
......@@ -9,6 +9,8 @@
// except according to those terms.
use dep_graph::DepGraph;
use hir::def_id::DefIndex;
use hir::svh::Svh;
use lint;
use middle::cstore::CrateStore;
use middle::dependency_format;
......@@ -312,6 +314,14 @@ pub fn print_enum_sizes(&self) -> bool {
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,
......
......@@ -14,12 +14,38 @@
use ty::{self, Ty, TyCtxt};
use syntax::ast;
use std::cell::Cell;
thread_local! {
static FORCE_ABSOLUTE: Cell<bool> = 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<F: FnOnce() -> R, R>(f: F) -> R {
FORCE_ABSOLUTE.with(|force| {
let old = force.get();
force.set(true);
let result = f();
force.set(old);
result
})
}
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
/// Returns a string identifying this def-id. This string is
/// suitable for user output. It is relative to the current crate
/// root.
/// root, unless with_forced_absolute_paths was used.
pub fn item_path_str(self, def_id: DefId) -> String {
let mut buffer = LocalPathBuffer::new(RootMode::Local);
let mode = FORCE_ABSOLUTE.with(|force| {
if force.get() {
RootMode::Absolute
} else {
RootMode::Local
}
});
let mut buffer = LocalPathBuffer::new(mode);
self.push_item_path(&mut buffer, def_id);
buffer.into_string()
}
......@@ -75,7 +101,11 @@ pub fn push_krate_path<T>(self, buffer: &mut T, cnum: ast::CrateNum)
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));
}
}
}
}
......
......@@ -511,10 +511,6 @@ fn build_controller(&mut self,
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;
}
......
......@@ -33,7 +33,7 @@
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;
......
......@@ -17,6 +17,7 @@
use decoder;
use loader::{self, CratePaths};
use rustc::hir::def_id::DefIndex;
use rustc::hir::svh::Svh;
use rustc::dep_graph::{DepGraph, DepNode};
use rustc::session::{config, Session};
......@@ -610,9 +611,10 @@ pub fn read_exported_macros(&mut self, item: &ast::Item) -> Vec<ast::MacroDef> {
macros
}
/// Look for a plugin registrar. Returns library path and symbol name.
/// Look for a plugin registrar. Returns library path, crate
/// SVH and DefIndex of the registrar function.
pub fn find_plugin_registrar(&mut self, span: Span, name: &str)
-> Option<(PathBuf, String)> {
-> Option<(PathBuf, Svh, DefIndex)> {
let ekrate = self.read_extension_crate(span, &CrateInfo {
name: name.to_string(),
ident: name.to_string(),
......@@ -630,12 +632,14 @@ pub fn find_plugin_registrar(&mut self, span: Span, name: &str)
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 \
......
......@@ -25,7 +25,7 @@
use rustc::hir::map::DefKey;
use rustc::mir::repr::Mir;
use rustc::mir::mir_map::MirMap;
use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap};
use rustc::util::nodemap::{FnvHashMap, NodeSet, DefIdMap};
use rustc::session::config::PanicStrategy;
use std::cell::RefCell;
......@@ -115,13 +115,6 @@ fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>
decoder::get_item_attrs(&cdata, def_id.index)
}
fn item_symbol(&self, def: DefId) -> String
{
self.dep_graph.read(DepNode::MetaData(def));
let cdata = self.get_crate_data(def.krate);
decoder::get_symbol(&cdata, def.index)
}
fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::TraitDef<'tcx>
{
self.dep_graph.read(DepNode::MetaData(def));
......@@ -284,6 +277,11 @@ fn is_extern_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId) -> bool {
decoder::is_extern_item(&cdata, did.index, tcx)
}
fn is_foreign_item(&self, did: DefId) -> bool {
let cdata = self.get_crate_data(did.krate);
decoder::is_foreign_item(&cdata, did.index)
}
fn is_static_method(&self, def: DefId) -> bool
{
self.dep_graph.read(DepNode::MetaData(def));
......@@ -564,7 +562,6 @@ fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<ast::CrateNum>
fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
reexports: &def::ExportMap,
item_symbols: &RefCell<NodeMap<String>>,
link_meta: &LinkMeta,
reachable: &NodeSet,
mir_map: &MirMap<'tcx>,
......@@ -574,7 +571,6 @@ fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
diag: tcx.sess.diagnostic(),
tcx: tcx,
reexports: reexports,
item_symbols: item_symbols,
link_meta: link_meta,
cstore: self,
reachable: reachable,
......
......@@ -213,10 +213,6 @@ fn item_sort(item: rbml::Doc) -> Option<char> {
})
}
fn item_symbol(item: rbml::Doc) -> String {
reader::get_doc(item, tag_items_data_item_symbol).as_str().to_string()
}
fn untranslated_def_id(d: rbml::Doc) -> DefId {
let id = reader::doc_as_u64(d);
let index = DefIndex::new((id & 0xFFFF_FFFF) as usize);
......@@ -640,18 +636,6 @@ pub fn get_impl_trait<'a, 'tcx>(cdata: Cmd,
}
}
pub fn get_symbol(cdata: Cmd, id: DefIndex) -> String {
return item_symbol(cdata.lookup_item(id));
}
/// 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<F>(cdata: Cmd, mut f: F) -> bool where
F: FnMut(DefIndex, usize) -> bool,
......@@ -1642,6 +1626,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) {
......
......@@ -34,7 +34,7 @@
use rustc::hir::svh::Svh;
use rustc::mir::mir_map::MirMap;
use rustc::session::config::{self, PanicStrategy};
use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet};
use rustc::util::nodemap::{FnvHashMap, NodeSet};
use rustc_serialize::Encodable;
use std::cell::RefCell;
......@@ -59,7 +59,6 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
pub diag: &'a Handler,
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
pub reexports: &'a def::ExportMap,
pub item_symbols: &'a RefCell<NodeMap<String>>,
pub link_meta: &'a LinkMeta,
pub cstore: &'a cstore::CStore,
pub type_abbrevs: tyencode::abbrev_map<'tcx>,
......@@ -213,20 +212,6 @@ fn encode_region(ecx: &EncodeContext,
rbml_w.end_tag();
}
fn encode_symbol(ecx: &EncodeContext,
rbml_w: &mut Encoder,
id: NodeId) {
match ecx.item_symbols.borrow().get(&id) {
Some(x) => {
debug!("encode_symbol(id={}, str={})", id, *x);
rbml_w.wr_tagged_str(tag_items_data_item_symbol, x);
}
None => {
bug!("encode_symbol: id not found {}", id);
}
}
}
fn encode_disr_val(_: &EncodeContext,
rbml_w: &mut Encoder,
disr_val: ty::Disr) {
......@@ -518,10 +503,6 @@ fn encode_info_for_struct_ctor<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
encode_name(rbml_w, name);
encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(struct_id));
if ecx.item_symbols.borrow().contains_key(&ctor_id) {
encode_symbol(ecx, rbml_w, ctor_id);
}
let stab = ecx.tcx.lookup_stability(ecx.tcx.map.local_def_id(ctor_id));
let depr= ecx.tcx.lookup_deprecation(ecx.tcx.map.local_def_id(ctor_id));
encode_stability(rbml_w, stab);
......@@ -710,10 +691,6 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
}
encode_constness(rbml_w, sig.constness);
encode_defaultness(rbml_w, impl_item.defaultness);
if !any_types {
let m_id = ecx.local_id(m.def_id);
encode_symbol(ecx, rbml_w, m_id);
}
encode_method_argument_names(rbml_w, &sig.decl);
}
}
......@@ -894,7 +871,6 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
encode_family(rbml_w, 'c');
}
encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id);
encode_symbol(ecx, rbml_w, item.id);
encode_name(rbml_w, item.name);
encode_visibility(rbml_w, vis);
encode_stability(rbml_w, stab);
......@@ -931,9 +907,6 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
encode_mir(ecx, rbml_w, item.id);
}
if tps_len == 0 {
encode_symbol(ecx, rbml_w, item.id);
}
encode_constness(rbml_w, constness);
encode_visibility(rbml_w, vis);
encode_stability(rbml_w, stab);
......@@ -1354,6 +1327,8 @@ fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
let _task = index.record(def_id, rbml_w);
rbml_w.start_tag(tag_items_data_item);
encode_def_id_and_key(ecx, rbml_w, def_id);
let parent_id = ecx.tcx.map.get_parent(nitem.id);
encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id));
encode_visibility(rbml_w, &nitem.vis);
match nitem.node {
hir::ForeignItemFn(ref fndecl, _) => {
......@@ -1363,8 +1338,6 @@ fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
if abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
encode_inlined_item(ecx, rbml_w, InlinedItemRef::Foreign(nitem));
encode_mir(ecx, rbml_w, nitem.id);
} else {
encode_symbol(ecx, rbml_w, nitem.id);
}
encode_attributes(rbml_w, &nitem.attrs);
let stab = ecx.tcx.lookup_stability(ecx.tcx.map.local_def_id(nitem.id));
......@@ -1385,7 +1358,6 @@ fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
let depr = ecx.tcx.lookup_deprecation(ecx.tcx.map.local_def_id(nitem.id));
encode_stability(rbml_w, stab);
encode_deprecation(rbml_w, depr);
encode_symbol(ecx, rbml_w, nitem.id);
encode_name(rbml_w, nitem.name);
}
}
......
......@@ -101,7 +101,8 @@ fn new(sess: &'a Session, cstore: &'a CStore, crate_name: &str) -> PluginLoader<
fn load_plugin(&mut self, span: Span, name: &str, args: Vec<P<ast::MetaItem>>) {
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,
......
......@@ -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;
......@@ -188,6 +188,11 @@ pub fn link_binary(sess: &Session,
let mut out_filenames = Vec::new();
for &crate_type in sess.crate_types.borrow().iter() {
// Ignore executable crates if we have -Z no-trans, as they will error.
if sess.opts.no_trans && crate_type == config::CrateTypeExecutable {
continue;
}
if invalid_output_for_target(sess, crate_type) {
bug!("invalid output type `{:?}` for target os `{}`",
crate_type, sess.opts.target_triple);
......@@ -637,13 +642,9 @@ fn link_natively(sess: &Session,
}
{
let mut linker = if sess.target.target.options.is_like_msvc {
Box::new(MsvcLinker { cmd: &mut cmd, sess: &sess }) as Box<Linker>
} else {
Box::new(GnuLinker { cmd: &mut cmd, sess: &sess }) as Box<Linker>
};
let mut linker = trans.linker_info.to_linker(&mut cmd, &sess);
link_args(&mut *linker, sess, crate_type, tmpdir,
objects, out_filename, trans, outputs);
objects, out_filename, outputs);
if !sess.target.target.options.no_compiler_rt {
linker.link_staticlib("compiler-rt");
}
......@@ -712,7 +713,6 @@ fn link_args(cmd: &mut Linker,
tmpdir: &Path,
objects: &[PathBuf],
out_filename: &Path,
trans: &CrateTranslation,
outputs: &OutputFilenames) {
// The default library location, we need this to find the runtime.
......@@ -731,7 +731,7 @@ fn link_args(cmd: &mut Linker,
// If we're building a dynamic library then some platforms need to make sure
// that all symbols are exported correctly from the dynamic library.
if crate_type != config::CrateTypeExecutable {
cmd.export_symbols(sess, trans, tmpdir, crate_type);
cmd.export_symbols(tmpdir, crate_type);
}
// When linking a dynamic library, we put the metadata into a section of the
......
......@@ -15,13 +15,50 @@
use std::path::{Path, PathBuf};
use std::process::Command;
use context::SharedCrateContext;
use monomorphize::Instance;
use back::archive;
use middle::dependency_format::Linkage;
use session::Session;
use session::config::CrateType;
use session::config;
use syntax::ast;
use CrateTranslation;
/// For all the linkers we support, and information they might
/// need out of the shared crate context before we get rid of it.
pub struct LinkerInfo {
dylib_exports: Vec<String>,
cdylib_exports: Vec<String>
}
impl<'a, 'tcx> LinkerInfo {
pub fn new(scx: &SharedCrateContext<'a, 'tcx>,
reachable: &[String]) -> LinkerInfo {
LinkerInfo {
dylib_exports: exported_symbols(scx, reachable, CrateType::CrateTypeDylib),
cdylib_exports: exported_symbols(scx, reachable, CrateType::CrateTypeCdylib)
}
}
pub fn to_linker(&'a self,
cmd: &'a mut Command,
sess: &'a Session) -> Box<Linker+'a> {
if sess.target.target.options.is_like_msvc {
Box::new(MsvcLinker {
cmd: cmd,
sess: sess,
info: self
}) as Box<Linker>
} else {
Box::new(GnuLinker {
cmd: cmd,
sess: sess,
info: self
}) as Box<Linker>
}
}
}
/// Linker abstraction used by back::link to build up the command to invoke a
/// linker.
......@@ -53,16 +90,13 @@ pub trait Linker {
fn hint_dynamic(&mut self);
fn whole_archives(&mut self);
fn no_whole_archives(&mut self);
fn export_symbols(&mut self,
sess: &Session,
trans: &CrateTranslation,
tmpdir: &Path,
crate_type: CrateType);
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType);
}
pub struct GnuLinker<'a> {
pub cmd: &'a mut Command,
pub sess: &'a Session,
cmd: &'a mut Command,
sess: &'a Session,
info: &'a LinkerInfo
}
impl<'a> GnuLinker<'a> {
......@@ -201,11 +235,7 @@ fn hint_dynamic(&mut self) {
self.cmd.arg("-Wl,-Bdynamic");
}
fn export_symbols(&mut self,
sess: &Session,
trans: &CrateTranslation,
tmpdir: &Path,
crate_type: CrateType) {
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
// If we're compiling a dylib, then we let symbol visibility in object
// files to take care of whether they're exported or not.
//
......@@ -225,13 +255,13 @@ fn export_symbols(&mut self,
};
let res = (|| -> io::Result<()> {
let mut f = BufWriter::new(File::create(&path)?);
for sym in exported_symbols(sess, trans, crate_type) {
for sym in &self.info.cdylib_exports {
writeln!(f, "{}{}", prefix, sym)?;
}
Ok(())
})();
if let Err(e) = res {
sess.fatal(&format!("failed to write lib.def file: {}", e));
self.sess.fatal(&format!("failed to write lib.def file: {}", e));
}
let mut arg = OsString::new();
if self.sess.target.target.options.is_like_osx {
......@@ -245,8 +275,9 @@ fn export_symbols(&mut self,
}
pub struct MsvcLinker<'a> {
pub cmd: &'a mut Command,
pub sess: &'a Session,
cmd: &'a mut Command,
sess: &'a Session,
info: &'a LinkerInfo
}
impl<'a> Linker for MsvcLinker<'a> {
......@@ -366,8 +397,6 @@ fn hint_dynamic(&mut self) {}
// in which case they may continue to transitively be used and hence need
// their symbols exported.
fn export_symbols(&mut self,
sess: &Session,
trans: &CrateTranslation,
tmpdir: &Path,
crate_type: CrateType) {
let path = tmpdir.join("lib.def");
......@@ -378,15 +407,18 @@ fn export_symbols(&mut self,
// straight to exports.
writeln!(f, "LIBRARY")?;
writeln!(f, "EXPORTS")?;
for sym in exported_symbols(sess, trans, crate_type) {
writeln!(f, " {}", sym)?;
let symbols = if crate_type == CrateType::CrateTypeCdylib {
&self.info.cdylib_exports
} else {
&self.info.dylib_exports
};
for symbol in symbols {
writeln!(f, " {}", symbol)?;
}
Ok(())
})();
if let Err(e) = res {
sess.fatal(&format!("failed to write lib.def file: {}", e));
self.sess.fatal(&format!("failed to write lib.def file: {}", e));
}
let mut arg = OsString::from("/DEF:");
arg.push(path);
......@@ -394,10 +426,23 @@ fn export_symbols(&mut self,
}
}
fn exported_symbols(sess: &Session,
trans: &CrateTranslation,
crate_type: CrateType) -> Vec<String> {
let mut symbols = trans.reachable.iter().cloned().collect::<Vec<_>>();
fn exported_symbols(scx: &SharedCrateContext,
reachable: &[String],
crate_type: CrateType)
-> Vec<String> {
if !scx.sess().crate_types.borrow().contains(&crate_type) {
return vec![];
}
// See explanation in GnuLinker::export_symbols, for
// why we don't ever need dylib symbols on non-MSVC.
if crate_type == CrateType::CrateTypeDylib {
if !scx.sess().target.target.options.is_like_msvc {
return vec![];
}
}
let mut symbols = reachable.to_vec();
// If we're producing anything other than a dylib then the `reachable` array
// above is the exhaustive set of symbols we should be exporting.
......@@ -409,10 +454,10 @@ fn exported_symbols(sess: &Session,
return symbols
}
let cstore = &sess.cstore;
let formats = sess.dependency_formats.borrow();
let upstream_symbols = formats[&crate_type].iter();
symbols.extend(upstream_symbols.enumerate().filter_map(|(i, f)| {
let cstore = &scx.sess().cstore;
let formats = scx.sess().dependency_formats.borrow();
let deps = formats[&crate_type].iter();
symbols.extend(deps.enumerate().filter_map(|(i, f)| {
if *f == Linkage::Static {
Some((i + 1) as ast::CrateNum)
} else {
......@@ -420,9 +465,8 @@ fn exported_symbols(sess: &Session,
}
}).flat_map(|cnum| {
cstore.reachable_ids(cnum)
}).map(|did| {
cstore.item_symbol(did)
}).map(|did| -> String {
Instance::mono(scx, did).symbol_name(scx)
}));
return symbols
symbols
}
......@@ -97,17 +97,19 @@
//! 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::hir::map as hir_map;
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;
......@@ -116,10 +118,14 @@ 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));
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));
......@@ -134,7 +140,7 @@ pub fn def_path_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_path: &DefP
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 +158,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,66 +193,100 @@ fn truncated_hash_result(symbol_hasher: &mut Sha256) -> String {
}
}
fn exported_name_with_opt_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
instance: &Instance<'tcx>,
suffix: Option<&str>)
-> String {
let &Instance { def: mut 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!("symbol_name(def_id={:?}, substs={:?})",
def_id, substs);
debug!("exported_name_with_opt_suffix(def_id={:?}, substs={:?}, suffix={:?})",
def_id, substs, suffix);
let node_id = scx.tcx().map.as_local_node_id(def_id);
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;
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);
}
}
}
let def_path = ccx.tcx().def_path(def_id);
assert_eq!(def_path.krate, def_id.krate);
// 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 = ccx.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);
break;
// 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
}
_ => {
// 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);
});
} else {
scx.sess().cstore.is_foreign_item(def_id)
};
if let Some(name) = weak_lang_items::link_name(&attrs) {
return name.to_string();
}
if is_foreign {
if let Some(name) = attr::first_attr_value_str_by_name(&attrs, "link_name") {
return name.to_string();
}
// Don't mangle foreign items.
return scx.tcx().item_name(def_id).as_str().to_string();
}
}
// 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);
if let Some(name) = attr::find_export_name_attr(scx.sess().diagnostic(), &attrs) {
// Use provided name
return name.to_string();
}
let hash = get_symbol_hash(ccx, &def_path, instance_ty, substs.types.as_slice());
if attr::contains_name(&attrs, "no_mangle") {
// Don't mangle
return scx.tcx().item_name(def_id).as_str().to_string();
}
let mut buffer = SymbolPathBuffer {
names: Vec::with_capacity(def_path.data.len())
};
ccx.tcx().push_item_path(&mut buffer, def_id);
let def_path = scx.tcx().def_path(def_id);
// We want to compute the "type" of this item. Unfortunately, some
// kinds of items (e.g., closures) don't have an entry in the
// item-type array. So walk back up the find the closest parent
// that DOES have an entry.
let mut ty_def_id = def_id;
let instance_ty;
loop {
let key = scx.tcx().def_key(ty_def_id);
match key.disambiguated_data.data {
DefPathData::TypeNs(_) |
DefPathData::ValueNs(_) => {
instance_ty = scx.tcx().lookup_item_type(ty_def_id);
break;
}
_ => {
// if we're making a symbol for something, there ought
// to be a value or type-def or something in there
// *somewhere*
ty_def_id.index = key.parent.unwrap_or_else(|| {
bug!("finding type for {:?}, encountered def-id {:?} with no \
parent", def_id, ty_def_id);
});
}
}
}
if let Some(suffix) = suffix {
buffer.push(suffix);
}
// Erase regions because they may not be deterministic when hashed
// and should not matter anyhow.
let instance_ty = scx.tcx().erase_regions(&instance_ty.ty);
let hash = get_symbol_hash(scx, &def_path, instance_ty, substs.types.as_slice());
let mut buffer = SymbolPathBuffer {
names: Vec::with_capacity(def_path.data.len())
};
mangle(buffer.names.into_iter(), Some(&hash[..]))
item_path::with_forced_absolute_paths(|| {
scx.tcx().push_item_path(&mut buffer, def_id);
});
mangle(buffer.names.into_iter(), Some(&hash[..]))
}
}
struct SymbolPathBuffer {
......@@ -264,19 +304,6 @@ fn push(&mut self, text: &str) {
}
}
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>,
......@@ -289,7 +316,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[..]))
}
......
......@@ -30,14 +30,14 @@
use super::CrateTranslation;
use super::ModuleTranslation;
use back::{link, symbol_names};
use back::link;
use back::linker::LinkerInfo;
use lint;
use llvm::{BasicBlockRef, Linkage, ValueRef, Vector, get_param};
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;
......@@ -2344,15 +2344,6 @@ pub fn trans_item(ccx: &CrateContext, item: &hir::Item) {
set_global_section(ccx, g, item);
update_linkage(ccx, g, Some(item.id), OriginalTranslation);
}
hir::ItemForeignMod(ref m) => {
if m.abi == Abi::RustIntrinsic || m.abi == Abi::PlatformIntrinsic {
return;
}
for fi in &m.items {
let lname = imported_name(fi.name, &fi.attrs).to_string();
ccx.item_symbols().borrow_mut().insert(fi.id, lname);
}
}
_ => {}
}
}
......@@ -2437,60 +2428,12 @@ fn create_entry_fn(ccx: &CrateContext,
}
}
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();
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(),
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)
}
pub fn write_metadata<'a, 'tcx>(cx: &SharedCrateContext<'a, 'tcx>,
krate: &hir::Crate,
reachable: &NodeSet,
mir_map: &MirMap<'tcx>)
-> Vec<u8> {
fn write_metadata(cx: &SharedCrateContext,
reachable_ids: &NodeSet) -> Vec<u8> {
use flate;
let any_library = cx.sess()
......@@ -2505,11 +2448,10 @@ 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,
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));
......@@ -2670,10 +2612,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:
......@@ -2691,7 +2630,20 @@ 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::NodeImplItem(&hir::ImplItem {
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
}
}).collect()
}
......@@ -2733,6 +2685,19 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
check_overflow,
check_dropflag);
let reachable_symbol_ids = filter_reachable_ids(&shared_ccx);
// Translate the metadata.
let metadata = time(tcx.sess.time_passes(), "write metadata", || {
write_metadata(&shared_ccx, &reachable_symbol_ids)
});
let metadata_module = ModuleTranslation {
llcx: shared_ccx.metadata_llcx(),
llmod: shared_ccx.metadata_llmod(),
};
let no_builtins = attr::contains_name(&krate.attrs, "no_builtins");
let codegen_units = collect_and_partition_translation_items(&shared_ccx);
let codegen_unit_count = codegen_units.len();
assert!(tcx.sess.opts.cg.codegen_units == codegen_unit_count ||
......@@ -2740,6 +2705,24 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let crate_context_list = CrateContextList::new(&shared_ccx, codegen_units);
let modules = crate_context_list.iter()
.map(|ccx| ModuleTranslation { llcx: ccx.llcx(), llmod: ccx.llmod() })
.collect();
// Skip crate items and just output metadata in -Z no-trans mode.
if tcx.sess.opts.no_trans {
let linker_info = LinkerInfo::new(&shared_ccx, &[]);
return CrateTranslation {
modules: modules,
metadata_module: metadata_module,
link: link_meta,
metadata: metadata,
reachable: vec![],
no_builtins: no_builtins,
linker_info: linker_info
};
}
{
let ccx = crate_context_list.get_ccx(0);
......@@ -2769,13 +2752,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
}
let reachable_symbol_ids = filter_reachable_ids(&shared_ccx);
// Translate the metadata.
let metadata = time(tcx.sess.time_passes(), "write metadata", || {
write_metadata(&shared_ccx, krate, &reachable_symbol_ids, mir_map)
});
if shared_ccx.sess().trans_stats() {
let stats = shared_ccx.stats();
println!("--- trans stats ---");
......@@ -2805,13 +2781,10 @@ 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| {
shared_ccx.item_symbols().borrow()[id].to_string()
let mut reachable_symbols = reachable_symbol_ids.iter().map(|&id| {
let def_id = shared_ccx.tcx().map.local_def_id(id);
Instance::mono(&shared_ccx, def_id).symbol_name(&shared_ccx)
}).collect::<Vec<_>>();
if sess.entry_fn.borrow().is_some() {
reachable_symbols.push("main".to_string());
......@@ -2834,7 +2807,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| {
sess.cstore.item_symbol(did)
Instance::mono(&shared_ccx, did).symbol_name(&shared_ccx)
}));
}
......@@ -2848,12 +2821,7 @@ 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,
metadata_module: metadata_module,
......@@ -2861,6 +2829,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
}
}
......
......@@ -499,43 +499,20 @@ fn is_named_tuple_constructor(tcx: TyCtxt, def_id: DefId) -> bool {
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 = exported_name(ccx, instance, attrs);
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);
(ccx.sess().cstore.item_symbol(def_id), &attrs[..], None)
}
ref variant => {
bug!("get_fn: unexpected variant: {:?}", variant)
Some(span)
}
_ => None
};
// This is subtle and surprising, but sometimes we have to bitcast
......@@ -562,8 +539,16 @@ fn is_named_tuple_constructor(tcx: TyCtxt, def_id: DefId) -> bool {
// 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 {:?}",
......@@ -580,7 +565,8 @@ fn is_named_tuple_constructor(tcx: TyCtxt, def_id: DefId) -> bool {
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);
......@@ -589,11 +575,6 @@ fn is_named_tuple_constructor(tcx: TyCtxt, def_id: DefId) -> bool {
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)
......
......@@ -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 = instance.symbol_name(ccx.shared());
// Compute the rust-call form of the closure call method.
let sig = &tcx.closure_type(closure_id, substs).sig;
......
......@@ -19,7 +19,7 @@
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, push_ctxt};
use callee::Callee;
use collector;
use trans_item::TransItem;
......@@ -1017,34 +1017,31 @@ 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) {
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);
debug!("making {}", sym);
// 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 {
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
......@@ -1066,7 +1063,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
......@@ -1076,10 +1073,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);
......@@ -1087,7 +1084,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 {
......@@ -1104,8 +1101,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 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
......
......@@ -71,7 +71,6 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
export_map: ExportMap,
reachable: NodeSet,
item_symbols: RefCell<NodeMap<String>>,
link_meta: LinkMeta,
symbol_hasher: RefCell<Sha256>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
......@@ -395,7 +394,6 @@ pub fn new(tcx: TyCtxt<'b, 'tcx, '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 @@ pub fn reachable<'a>(&'a self) -> &'a NodeSet {
&self.reachable
}
pub fn item_symbols<'a>(&'a self) -> &'a RefCell<NodeMap<String>> {
&self.item_symbols
}
pub fn trait_cache(&self) -> &RefCell<DepTrackingMap<TraitSelectionCache<'tcx>>> {
&self.trait_cache
}
......@@ -504,6 +498,14 @@ pub fn empty_substs_for_scheme(&self, scheme: &ty::TypeScheme<'tcx>)
scheme.generics.regions.map(|_| ty::ReStatic)))
}
pub fn symbol_hasher(&self) -> &RefCell<Sha256> {
&self.symbol_hasher
}
pub fn mir_map(&self) -> &MirMap<'tcx> {
&self.mir_map
}
pub fn metadata_symbol_name(&self) -> String {
format!("rust_metadata_{}_{}",
self.link_meta().crate_name,
......@@ -716,10 +718,6 @@ pub fn reachable<'a>(&'a self) -> &'a NodeSet {
&self.shared.reachable
}
pub fn item_symbols<'a>(&'a self) -> &'a RefCell<NodeMap<String>> {
&self.shared.item_symbols
}
pub fn link_meta<'a>(&'a self) -> &'a LinkMeta {
&self.shared.link_meta
}
......
......@@ -145,6 +145,7 @@ pub struct CrateTranslation {
pub metadata: Vec<u8>,
pub reachable: Vec<String>,
pub no_builtins: bool,
pub linker_info: back::linker::LinkerInfo
}
__build_diagnostic_array! { librustc_trans, DIAGNOSTICS }
......@@ -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, &instance);
let symbol = instance.symbol_name(ccx.shared());
debug!("monomorphize_fn mangled to {}", symbol);
assert!(declare::get_defined_value(ccx, &symbol).is_none());
......
......@@ -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 @@ fn process_attrs(&mut self,
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 = 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);
......
......@@ -25,7 +25,7 @@ mod bar {
use foo::Foo;
impl Foo {
#[rustc_symbol_name] //~ ERROR _ZN5impl13bar26_$LT$impl$u20$foo..Foo$GT$3baz
#[rustc_symbol_name] //~ ERROR _ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz
#[rustc_item_path] //~ ERROR item-path(bar::<impl foo::Foo>::baz)
fn baz() { }
}
......
......@@ -371,9 +371,16 @@ fn make_typecheck_args(&self) -> ProcArgs {
} else {
&*self.config.target
};
let out_dir = self.output_base_name().with_extension("pretty-out");
let _ = fs::remove_dir_all(&out_dir);
self.create_dir_racy(&out_dir);
// FIXME (#9639): This needs to handle non-utf8 paths
let mut args = vec!("-".to_owned(),
"-Zno-trans".to_owned(),
"--out-dir".to_owned(),
out_dir.to_str().unwrap().to_owned(),
format!("--target={}", target),
"-L".to_owned(),
self.config.build_base.to_str().unwrap().to_owned(),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册