Compute a salt from arguments passed via -Cmetadata.

This commit is contained in:
Michael Woerister 2016-02-12 08:41:30 -05:00 committed by Niko Matsakis
parent c7e54d7279
commit 32a2e9a8e1
11 changed files with 67 additions and 18 deletions

View File

@ -166,7 +166,7 @@ impl<'doc> Doc<'doc> {
}
}
pub fn get<'a>(&'a self, tag: usize) -> Doc<'a> {
pub fn get(&self, tag: usize) -> Doc<'doc> {
reader::get_doc(*self, tag)
}
@ -174,7 +174,7 @@ impl<'doc> Doc<'doc> {
self.start == self.end
}
pub fn as_str_slice<'a>(&'a self) -> &'a str {
pub fn as_str_slice(&self) -> &'doc str {
str::from_utf8(&self.data[self.start..self.end]).unwrap()
}

View File

@ -206,6 +206,7 @@ pub trait CrateStore<'tcx> : Any {
fn crate_attrs(&self, cnum: ast::CrateNum) -> Vec<ast::Attribute>;
fn crate_name(&self, cnum: ast::CrateNum) -> InternedString;
fn crate_hash(&self, cnum: ast::CrateNum) -> Svh;
fn crate_disambiguator(&self, cnum: ast::CrateNum) -> InternedString;
fn crate_struct_field_attrs(&self, cnum: ast::CrateNum)
-> FnvHashMap<DefId, Vec<ast::Attribute>>;
fn plugin_registrar_fn(&self, cnum: ast::CrateNum) -> Option<DefId>;
@ -385,6 +386,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
{ unimplemented!() }
fn crate_name(&self, cnum: ast::CrateNum) -> InternedString { unimplemented!() }
fn crate_hash(&self, cnum: ast::CrateNum) -> Svh { unimplemented!() }
fn crate_disambiguator(&self, cnum: ast::CrateNum) -> InternedString { unimplemented!() }
fn crate_struct_field_attrs(&self, cnum: ast::CrateNum)
-> FnvHashMap<DefId, Vec<ast::Attribute>>
{ unimplemented!() }

View File

@ -64,7 +64,12 @@ pub struct Session {
pub plugin_attributes: RefCell<Vec<(String, AttributeType)>>,
pub crate_types: RefCell<Vec<config::CrateType>>,
pub dependency_formats: RefCell<dependency_format::Dependencies>,
pub crate_metadata: RefCell<Vec<String>>,
// The crate_disambiguator is constructed out of all the `-C metadata`
// arguments passed to the compiler. Its value together with the crate-name
// forms a unique global identifier for the crate. It is used to allow
// multiple crates with the same name to coexist. See the
// trans::back::symbol_names module for more information.
pub crate_disambiguator: RefCell<String>,
pub features: RefCell<feature_gate::Features>,
/// The maximum recursion limit for potentially infinitely recursive
@ -481,7 +486,7 @@ pub fn build_session_(sopts: config::Options,
plugin_attributes: RefCell::new(Vec::new()),
crate_types: RefCell::new(Vec::new()),
dependency_formats: RefCell::new(FnvHashMap()),
crate_metadata: RefCell::new(Vec::new()),
crate_disambiguator: RefCell::new(String::new()),
features: RefCell::new(feature_gate::Features::new()),
recursion_limit: Cell::new(64),
next_node_id: Cell::new(1),

View File

@ -66,7 +66,7 @@ impl Svh {
&self.hash
}
pub fn calculate(metadata: &Vec<String>, krate: &hir::Crate) -> Svh {
pub fn calculate(crate_disambiguator: &str, krate: &hir::Crate) -> Svh {
// FIXME (#14132): This is better than it used to be, but it still not
// ideal. We now attempt to hash only the relevant portions of the
// Crate AST as well as the top-level crate attributes. (However,
@ -78,9 +78,9 @@ impl Svh {
// avoid collisions.
let mut state = SipHasher::new();
for data in metadata {
data.hash(&mut state);
}
"crate_disambiguator".hash(&mut state);
crate_disambiguator.len().hash(&mut state);
crate_disambiguator.hash(&mut state);
{
let mut visit = svh_visitor::make(&mut state, krate);

View File

@ -22,6 +22,7 @@ use rustc::middle::privacy::AccessLevels;
use rustc::middle::ty::TyCtxt;
use rustc::util::common::time;
use rustc::util::nodemap::NodeSet;
use rustc_back::sha2::{Sha256, Digest};
use rustc_borrowck as borrowck;
use rustc_resolve as resolve;
use rustc_metadata::macro_import;
@ -500,7 +501,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
})?;
*sess.crate_types.borrow_mut() = collect_crate_types(sess, &krate.attrs);
*sess.crate_metadata.borrow_mut() = collect_crate_metadata(sess, &krate.attrs);
*sess.crate_disambiguator.borrow_mut() = compute_crate_disambiguator(sess);
time(time_passes, "recursion limit", || {
middle::recursion_limit::update_recursion_limit(sess, &krate);
@ -1121,8 +1122,34 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<c
.collect()
}
pub fn collect_crate_metadata(session: &Session, _attrs: &[ast::Attribute]) -> Vec<String> {
session.opts.cg.metadata.clone()
pub fn compute_crate_disambiguator(session: &Session) -> String {
let mut hasher = Sha256::new();
let mut metadata = session.opts.cg.metadata.clone();
// We don't want the crate_disambiguator to dependent on the order
// -C metadata arguments, so sort them:
metadata.sort();
// Every distinct -C metadata value is only incorporated once:
metadata.dedup();
hasher.input_str("metadata");
for s in &metadata {
// Also incorporate the length of a metadata string, so that we generate
// different values for `-Cmetadata=ab -Cmetadata=c` and
// `-Cmetadata=a -Cmetadata=bc`
hasher.input_str(&format!("{}", s.len())[..]);
hasher.input_str(&s[..]);
}
let mut hash = hasher.result_str();
// If this is an executable, add a special suffix, so that we don't get
// symbol conflicts when linking against a library of the same name.
if session.crate_types.borrow().contains(&config::CrateTypeExecutable) {
hash.push_str("-exe");
}
hash
}
pub fn build_output_filenames(input: &Input,

View File

@ -568,8 +568,6 @@ impl RustcDefaultCalls {
continue;
}
let crate_types = driver::collect_crate_types(sess, attrs);
let metadata = driver::collect_crate_metadata(sess, attrs);
*sess.crate_metadata.borrow_mut() = metadata;
for &style in &crate_types {
let fname = link::filename_for_input(sess, style, &id, &t_outputs);
println!("{}",

View File

@ -73,6 +73,7 @@ pub const tag_crate_dep: usize = 0x35;
pub const tag_crate_hash: usize = 0x103; // top-level only
pub const tag_crate_crate_name: usize = 0x104; // top-level only
pub const tag_crate_disambiguator: usize = 0x113; // top-level only
pub const tag_crate_dep_crate_name: usize = 0x36;
pub const tag_crate_dep_hash: usize = 0x37;

View File

@ -345,6 +345,12 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
decoder::get_crate_hash(cdata.data())
}
fn crate_disambiguator(&self, cnum: ast::CrateNum) -> token::InternedString
{
let cdata = self.get_crate_data(cnum);
token::intern_and_get_ident(decoder::get_crate_disambiguator(cdata.data()))
}
fn crate_struct_field_attrs(&self, cnum: ast::CrateNum)
-> FnvHashMap<DefId, Vec<ast::Attribute>>
{

View File

@ -1295,6 +1295,13 @@ pub fn maybe_get_crate_name(data: &[u8]) -> Option<String> {
})
}
pub fn get_crate_disambiguator<'a>(data: &'a [u8]) -> &'a str {
let crate_doc = rbml::Doc::new(data);
let salt_doc = reader::get_doc(crate_doc, tag_crate_disambiguator);
let slice: &'a str = salt_doc.as_str_slice();
slice
}
pub fn get_crate_triple(data: &[u8]) -> Option<String> {
let cratedoc = rbml::Doc::new(data);
let triple_doc = reader::maybe_get_doc(cratedoc, tag_crate_triple);

View File

@ -1877,6 +1877,10 @@ fn encode_crate_name(rbml_w: &mut Encoder, crate_name: &str) {
rbml_w.wr_tagged_str(tag_crate_crate_name, crate_name);
}
fn encode_crate_disambiguator(rbml_w: &mut Encoder, crate_disambiguator: &str) {
rbml_w.wr_tagged_str(tag_crate_disambiguator, crate_disambiguator);
}
fn encode_crate_triple(rbml_w: &mut Encoder, triple: &str) {
rbml_w.wr_tagged_str(tag_crate_triple, triple);
}
@ -1987,6 +1991,7 @@ fn encode_metadata_inner(rbml_w: &mut Encoder,
encode_crate_name(rbml_w, &ecx.link_meta.crate_name);
encode_crate_triple(rbml_w, &ecx.tcx.sess.opts.target_triple);
encode_hash(rbml_w, &ecx.link_meta.crate_hash);
encode_crate_disambiguator(rbml_w, &ecx.tcx.sess.crate_disambiguator.borrow());
encode_dylib_dependency_formats(rbml_w, &ecx);
let mut i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();

View File

@ -189,7 +189,7 @@ pub fn build_link_meta(sess: &Session,
-> LinkMeta {
let r = LinkMeta {
crate_name: name.to_owned(),
crate_hash: Svh::calculate(&sess.opts.cg.metadata, krate),
crate_hash: Svh::calculate(&sess.crate_disambiguator.borrow()[..], krate),
};
info!("{:?}", r);
return r;
@ -201,7 +201,7 @@ fn truncated_hash_result(symbol_hasher: &mut Sha256) -> String {
output[.. 8].to_hex().to_string()
}
pub fn def_to_string(_tcx: &ty::ctxt, did: DefId) -> String {
pub fn def_to_string(_tcx: &TyCtxt, did: DefId) -> String {
format!("{}:{}", did.krate, did.index.as_usize())
}
@ -218,9 +218,7 @@ fn symbol_hash<'tcx>(tcx: &TyCtxt<'tcx>,
symbol_hasher.input_str(&link_meta.crate_name);
symbol_hasher.input_str("-");
symbol_hasher.input_str(link_meta.crate_hash.as_str());
for meta in tcx.sess.crate_metadata.borrow().iter() {
symbol_hasher.input_str(&meta[..]);
}
symbol_hasher.input_str(&tcx.sess.crate_disambiguator.borrow()[..]);
symbol_hasher.input_str("-");
symbol_hasher.input(&tcx.sess.cstore.encode_type(tcx, t, def_to_string));
// Prefix with 'h' so that it never blends into adjacent digits