Refactored ast_map and friends, mainly to have Paths without storing them.

This commit is contained in:
Eduard Burtescu 2014-02-14 07:07:09 +02:00
parent 22c34f3c4c
commit a02b10a062
92 changed files with 1987 additions and 2573 deletions

View file

@ -38,11 +38,12 @@ use serialize::hex::ToHex;
use extra::tempfile::TempDir;
use syntax::abi;
use syntax::ast;
use syntax::ast_map::{PathMod, PathName, PathPrettyName};
use syntax::ast_map::{PathElem, PathElems, PathName};
use syntax::ast_map;
use syntax::attr;
use syntax::attr::AttrMetaMethods;
use syntax::crateid::CrateId;
use syntax::parse::token;
#[deriving(Clone, Eq, TotalOrd, TotalEq)]
pub enum OutputType {
@ -531,11 +532,8 @@ fn truncated_hash_result(symbol_hasher: &mut Sha256) -> ~str {
// This calculates STH for a symbol, as defined above
pub fn symbol_hash(tcx: ty::ctxt,
symbol_hasher: &mut Sha256,
t: ty::t,
link_meta: &LinkMeta)
-> ~str {
fn symbol_hash(tcx: ty::ctxt, symbol_hasher: &mut Sha256,
t: ty::t, link_meta: &LinkMeta) -> ~str {
// NB: do *not* use abbrevs here as we want the symbol names
// to be independent of one another in the crate.
@ -551,13 +549,10 @@ pub fn symbol_hash(tcx: ty::ctxt,
hash
}
pub fn get_symbol_hash(ccx: &CrateContext, t: ty::t) -> ~str {
{
let type_hashcodes = ccx.type_hashcodes.borrow();
match type_hashcodes.get().find(&t) {
Some(h) => return h.to_str(),
None => {}
}
fn get_symbol_hash(ccx: &CrateContext, t: ty::t) -> ~str {
match ccx.type_hashcodes.borrow().get().find(&t) {
Some(h) => return h.to_str(),
None => {}
}
let mut type_hashcodes = ccx.type_hashcodes.borrow_mut();
@ -615,8 +610,9 @@ pub fn sanitize(s: &str) -> ~str {
return result;
}
pub fn mangle(sess: Session, ss: ast_map::Path,
hash: Option<&str>, vers: Option<&str>) -> ~str {
pub fn mangle<PI: Iterator<PathElem>>(mut path: PI,
hash: Option<&str>,
vers: Option<&str>) -> ~str {
// Follow C++ namespace-mangling style, see
// http://en.wikipedia.org/wiki/Name_mangling for more info.
//
@ -625,7 +621,7 @@ pub fn mangle(sess: Session, ss: ast_map::Path,
// when using unix's linker. Perhaps one day when we just use a linker from LLVM
// we won't need to do this name mangling. The problem with name mangling is
// that it seriously limits the available characters. For example we can't
// have things like @T or ~[T] in symbol names when one would theoretically
// have things like &T or ~[T] in symbol names when one would theoretically
// want them for things like impls of traits on that type.
//
// To be able to work on all platforms and get *some* reasonable output, we
@ -633,41 +629,19 @@ pub fn mangle(sess: Session, ss: ast_map::Path,
let mut n = ~"_ZN"; // _Z == Begin name-sequence, N == nested
let push = |n: &mut ~str, s: &str| {
fn push(n: &mut ~str, s: &str) {
let sani = sanitize(s);
n.push_str(format!("{}{}", sani.len(), sani));
};
}
// First, connect each component with <len, name> pairs.
for s in ss.iter() {
match *s {
PathName(s) | PathMod(s) | PathPrettyName(s, _) => {
push(&mut n, sess.str_of(s))
}
}
for e in path {
push(&mut n, token::get_name(e.name()).get().as_slice())
}
// next, if any identifiers are "pretty" and need extra information tacked
// on, then use the hash to generate two unique characters. For now
// hopefully 2 characters is enough to avoid collisions.
static EXTRA_CHARS: &'static str =
"abcdefghijklmnopqrstuvwxyz\
ABCDEFGHIJKLMNOPQRSTUVWXYZ\
0123456789";
let mut hash = match hash { Some(s) => s.to_owned(), None => ~"" };
for s in ss.iter() {
match *s {
PathPrettyName(_, extra) => {
let hi = (extra >> 32) as u32 as uint;
let lo = extra as u32 as uint;
hash.push_char(EXTRA_CHARS[hi % EXTRA_CHARS.len()] as char);
hash.push_char(EXTRA_CHARS[lo % EXTRA_CHARS.len()] as char);
}
_ => {}
}
}
if hash.len() > 0 {
push(&mut n, hash);
match hash {
Some(s) => push(&mut n, s),
None => {}
}
match vers {
Some(s) => push(&mut n, s),
@ -678,10 +652,7 @@ pub fn mangle(sess: Session, ss: ast_map::Path,
n
}
pub fn exported_name(sess: Session,
path: ast_map::Path,
hash: &str,
vers: &str) -> ~str {
pub fn exported_name(path: PathElems, hash: &str, vers: &str) -> ~str {
// The version will get mangled to have a leading '_', but it makes more
// sense to lead with a 'v' b/c this is a version...
let vers = if vers.len() > 0 && !char::is_XID_start(vers.char_at(0)) {
@ -690,53 +661,56 @@ pub fn exported_name(sess: Session,
vers.to_owned()
};
mangle(sess, path, Some(hash), Some(vers.as_slice()))
mangle(path, Some(hash), Some(vers.as_slice()))
}
pub fn mangle_exported_name(ccx: &CrateContext,
path: ast_map::Path,
t: ty::t) -> ~str {
let hash = get_symbol_hash(ccx, t);
return exported_name(ccx.sess, path,
hash,
ccx.link_meta.crateid.version_or_default());
pub fn mangle_exported_name(ccx: &CrateContext, path: PathElems,
t: ty::t, id: ast::NodeId) -> ~str {
let mut hash = get_symbol_hash(ccx, t);
// Paths can be completely identical for different nodes,
// e.g. `fn foo() { { fn a() {} } { fn a() {} } }`, so we
// generate unique characters from the node id. For now
// hopefully 3 characters is enough to avoid collisions.
static EXTRA_CHARS: &'static str =
"abcdefghijklmnopqrstuvwxyz\
ABCDEFGHIJKLMNOPQRSTUVWXYZ\
0123456789";
let id = id as uint;
let extra1 = id % EXTRA_CHARS.len();
let id = id / EXTRA_CHARS.len();
let extra2 = id % EXTRA_CHARS.len();
let id = id / EXTRA_CHARS.len();
let extra3 = id % EXTRA_CHARS.len();
hash.push_char(EXTRA_CHARS[extra1] as char);
hash.push_char(EXTRA_CHARS[extra2] as char);
hash.push_char(EXTRA_CHARS[extra3] as char);
exported_name(path, hash, ccx.link_meta.crateid.version_or_default())
}
pub fn mangle_internal_name_by_type_only(ccx: &CrateContext,
t: ty::t,
name: &str) -> ~str {
let s = ppaux::ty_to_short_str(ccx.tcx, t);
let path = [PathName(token::intern(name)),
PathName(token::intern(s))];
let hash = get_symbol_hash(ccx, t);
return mangle(ccx.sess,
~[PathName(ccx.sess.ident_of(name)),
PathName(ccx.sess.ident_of(s))],
Some(hash.as_slice()),
None);
mangle(ast_map::Values(path.iter()), Some(hash.as_slice()), None)
}
pub fn mangle_internal_name_by_type_and_seq(ccx: &CrateContext,
t: ty::t,
name: &str) -> ~str {
let s = ppaux::ty_to_str(ccx.tcx, t);
let path = [PathName(token::intern(s)),
gensym_name(name)];
let hash = get_symbol_hash(ccx, t);
let (_, name) = gensym_name(name);
return mangle(ccx.sess,
~[PathName(ccx.sess.ident_of(s)), name],
Some(hash.as_slice()),
None);
mangle(ast_map::Values(path.iter()), Some(hash.as_slice()), None)
}
pub fn mangle_internal_name_by_path_and_seq(ccx: &CrateContext,
mut path: ast_map::Path,
flav: &str) -> ~str {
let (_, name) = gensym_name(flav);
path.push(name);
mangle(ccx.sess, path, None, None)
}
pub fn mangle_internal_name_by_path(ccx: &CrateContext,
path: ast_map::Path) -> ~str {
mangle(ccx.sess, path, None, None)
pub fn mangle_internal_name_by_path_and_seq(path: PathElems, flav: &str) -> ~str {
mangle(path.chain(Some(gensym_name(flav)).move_iter()), None, None)
}
pub fn output_lib_filename(lm: &LinkMeta) -> ~str {