use session::Session;
use middle::cstore::{self, CrateStore, LinkMeta};
use middle::cstore::{LinkagePreference, NativeLibraryKind};
-use middle::def_id::DefId;
use middle::dependency_format::Linkage;
-use middle::ty::TyCtxt;
use trans::CrateTranslation;
use util::common::time;
use util::fs::fix_windows_verbatim_for_gcc;
use flate;
use syntax::ast;
use syntax::codemap::Span;
-use syntax::parse::token::InternedString;
use syntax::attr::AttrMetaMethods;
use rustc_front::hir;
RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET + 8;
-/*
- * Name mangling and its relationship to metadata. This is complex. Read
- * carefully.
- *
- * The semantic model of Rust linkage is, broadly, that "there's no global
- * namespace" between crates. Our aim is to preserve the illusion of this
- * model despite the fact that it's not *quite* possible to implement on
- * modern linkers. We initially didn't use system linkers at all, but have
- * been convinced of their utility.
- *
- * There are a few issues to handle:
- *
- * - Linkers operate on a flat namespace, so we have to flatten names.
- * We do this using the C++ namespace-mangling technique. Foo::bar
- * symbols and such.
- *
- * - Symbols with the same name but different types need to get different
- * linkage-names. We do this by hashing a string-encoding of the type into
- * a fixed-size (currently 16-byte hex) cryptographic hash function (CHF:
- * we use SHA256) to "prevent collisions". This is not airtight but 16 hex
- * digits on uniform probability means you're going to need 2**32 same-name
- * symbols in the same process before you're even hitting birthday-paradox
- * collision probability.
- *
- * - Symbols in different crates but with same names "within" the crate need
- * to get different linkage-names.
- *
- * - The hash shown in the filename needs to be predictable and stable for
- * build tooling integration. It also needs to be using a hash function
- * which is easy to use from Python, make, etc.
- *
- * So here is what we do:
- *
- * - Consider the package id; every crate has one (specified with crate_id
- * attribute). If a package id isn't provided explicitly, we infer a
- * versionless one from the output name. The version will end up being 0.0
- * in this case. CNAME and CVERS are taken from this package id. For
- * example, github.com/mozilla/CNAME#CVERS.
- *
- * - Define CMH as SHA256(crateid).
- *
- * - Define CMH8 as the first 8 characters of CMH.
- *
- * - Compile our crate to lib CNAME-CMH8-CVERS.so
- *
- * - Define STH(sym) as SHA256(CMH, type_str(sym))
- *
- * - Suffix a mangled sym with ::STH@CVERS, so that it is unique in the
- * name, non-name metadata, and type sense, and versioned in the way
- * system linkers understand.
- */
-
pub fn find_crate_name(sess: Option<&Session>,
attrs: &[ast::Attribute],
input: &Input) -> String {
return r;
}
-pub fn def_to_string(_tcx: &TyCtxt, did: DefId) -> String {
- format!("{}:{}", did.krate, did.index.as_usize())
-}
-
-// Name sanitation. LLVM will happily accept identifiers with weird names, but
-// gas doesn't!
-// gas accepts the following characters in symbols: a-z, A-Z, 0-9, ., _, $
-pub fn sanitize(s: &str) -> String {
- let mut result = String::new();
- for c in s.chars() {
- match c {
- // Escape these with $ sequences
- '@' => result.push_str("$SP$"),
- '*' => result.push_str("$BP$"),
- '&' => result.push_str("$RF$"),
- '<' => result.push_str("$LT$"),
- '>' => result.push_str("$GT$"),
- '(' => result.push_str("$LP$"),
- ')' => result.push_str("$RP$"),
- ',' => result.push_str("$C$"),
-
- // '.' doesn't occur in types and functions, so reuse it
- // for ':' and '-'
- '-' | ':' => result.push('.'),
-
- // These are legal symbols
- 'a' ... 'z'
- | 'A' ... 'Z'
- | '0' ... '9'
- | '_' | '.' | '$' => result.push(c),
-
- _ => {
- result.push('$');
- for c in c.escape_unicode().skip(1) {
- match c {
- '{' => {},
- '}' => result.push('$'),
- c => result.push(c),
- }
- }
- }
- }
- }
-
- // Underscore-qualify anything that didn't start as an ident.
- if !result.is_empty() &&
- result.as_bytes()[0] != '_' as u8 &&
- ! (result.as_bytes()[0] as char).is_xid_start() {
- return format!("_{}", &result[..]);
- }
-
- return result;
-}
-
-pub fn mangle<PI: Iterator<Item=InternedString>>(path: PI, hash: Option<&str>) -> String {
- // Follow C++ namespace-mangling style, see
- // http://en.wikipedia.org/wiki/Name_mangling for more info.
- //
- // It turns out that on OSX you can actually have arbitrary symbols in
- // function names (at least when given to LLVM), but this is not possible
- // 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 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
- // use C++ name-mangling.
-
- let mut n = String::from("_ZN"); // _Z == Begin name-sequence, N == nested
-
- fn push(n: &mut String, s: &str) {
- let sani = sanitize(s);
- n.push_str(&format!("{}{}", sani.len(), sani));
- }
-
- // First, connect each component with <len, name> pairs.
- for data in path {
- push(&mut n, &data);
- }
-
- if let Some(s) = hash {
- push(&mut n, s)
- }
-
- n.push('E'); // End name-sequence.
- n
-}
-
pub fn get_linker(sess: &Session) -> (String, Command) {
if let Some(ref linker) = sess.opts.cg.linker {
(linker.clone(), Command::new(linker))
use std::fmt::Write;
use syntax::ast;
-use syntax::parse::token;
+use syntax::parse::token::{self, InternedString};
use serialize::hex::ToHex;
-use super::link;
pub fn def_id_to_string<'tcx>(tcx: &ty::TyCtxt<'tcx>, def_id: DefId) -> String {
path.push(token::intern_and_get_ident(suffix));
}
- link::mangle(path.into_iter(), Some(&hash[..]))
+ mangle(path.into_iter(), Some(&hash[..]))
}
pub fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
let path = [token::intern(&t.to_string()).as_str(),
gensym_name(suffix).as_str()];
let hash = get_symbol_hash(ccx, &Vec::new(), cstore::LOCAL_CRATE, &[t]);
- link::mangle(path.iter().cloned(), Some(&hash[..]))
+ mangle(path.iter().cloned(), Some(&hash[..]))
+}
+
+// Name sanitation. LLVM will happily accept identifiers with weird names, but
+// gas doesn't!
+// gas accepts the following characters in symbols: a-z, A-Z, 0-9, ., _, $
+pub fn sanitize(s: &str) -> String {
+ let mut result = String::new();
+ for c in s.chars() {
+ match c {
+ // Escape these with $ sequences
+ '@' => result.push_str("$SP$"),
+ '*' => result.push_str("$BP$"),
+ '&' => result.push_str("$RF$"),
+ '<' => result.push_str("$LT$"),
+ '>' => result.push_str("$GT$"),
+ '(' => result.push_str("$LP$"),
+ ')' => result.push_str("$RP$"),
+ ',' => result.push_str("$C$"),
+
+ // '.' doesn't occur in types and functions, so reuse it
+ // for ':' and '-'
+ '-' | ':' => result.push('.'),
+
+ // These are legal symbols
+ 'a' ... 'z'
+ | 'A' ... 'Z'
+ | '0' ... '9'
+ | '_' | '.' | '$' => result.push(c),
+
+ _ => {
+ result.push('$');
+ for c in c.escape_unicode().skip(1) {
+ match c {
+ '{' => {},
+ '}' => result.push('$'),
+ c => result.push(c),
+ }
+ }
+ }
+ }
+ }
+
+ // Underscore-qualify anything that didn't start as an ident.
+ if !result.is_empty() &&
+ result.as_bytes()[0] != '_' as u8 &&
+ ! (result.as_bytes()[0] as char).is_xid_start() {
+ return format!("_{}", &result[..]);
+ }
+
+ return result;
+}
+
+pub fn mangle<PI: Iterator<Item=InternedString>>(path: PI, hash: Option<&str>) -> String {
+ // Follow C++ namespace-mangling style, see
+ // http://en.wikipedia.org/wiki/Name_mangling for more info.
+ //
+ // It turns out that on OSX you can actually have arbitrary symbols in
+ // function names (at least when given to LLVM), but this is not possible
+ // 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 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
+ // use C++ name-mangling.
+
+ let mut n = String::from("_ZN"); // _Z == Begin name-sequence, N == nested
+
+ fn push(n: &mut String, s: &str) {
+ let sani = sanitize(s);
+ n.push_str(&format!("{}{}", sani.len(), sani));
+ }
+
+ // First, connect each component with <len, name> pairs.
+ for data in path {
+ push(&mut n, &data);
+ }
+
+ if let Some(s) = hash {
+ push(&mut n, s)
+ }
+
+ n.push('E'); // End name-sequence.
+ n
}