More work on proper linkage name-mangling. Almost right, aside from version numbers.
This commit is contained in:
parent
7034a28241
commit
721c5bbee8
@ -1,8 +1,18 @@
|
||||
import driver::session;
|
||||
import lib::llvm::llvm;
|
||||
import middle::trans;
|
||||
import middle::metadata;
|
||||
import middle::ty;
|
||||
import std::str;
|
||||
import std::fs;
|
||||
import std::vec;
|
||||
import std::option;
|
||||
import option::some;
|
||||
import option::none;
|
||||
import std::sha1::sha1;
|
||||
import std::sort;
|
||||
import trans::crate_ctxt;
|
||||
import front::ast;
|
||||
|
||||
import lib::llvm::llvm::ModuleRef;
|
||||
import lib::llvm::llvm::ValueRef;
|
||||
@ -49,7 +59,7 @@ fn link_intrinsics(session::session sess, ModuleRef llmod) {
|
||||
|
||||
auto linkres = llvm::LLVMLinkModules(llmod, llintrinsicsmod);
|
||||
llvm::LLVMDisposeModule(llintrinsicsmod);
|
||||
|
||||
|
||||
if (linkres == False) {
|
||||
llvm_err(sess, "couldn't link the module with the intrinsics");
|
||||
fail;
|
||||
@ -58,7 +68,7 @@ fn link_intrinsics(session::session sess, ModuleRef llmod) {
|
||||
|
||||
mod write {
|
||||
fn is_object_or_assembly_or_exe(output_type ot) -> bool {
|
||||
if ( (ot == output_type_assembly) ||
|
||||
if ( (ot == output_type_assembly) ||
|
||||
(ot == output_type_object) ||
|
||||
(ot == output_type_exe) ) {
|
||||
ret true;
|
||||
@ -218,3 +228,235 @@ mod write {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 SHA1) 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 dirrerent crates but with same names "within" the crate need
|
||||
* to get different linkage-names.
|
||||
*
|
||||
* So here is what we do:
|
||||
*
|
||||
* - Separate the meta tags into two sets: exported and local. Only work with
|
||||
* the exported ones when considering linkage.
|
||||
*
|
||||
* - Consider two exported tags as special (and madatory): name and vers.
|
||||
* Every crate gets them; if it doesn't name them explicitly we infer them
|
||||
* as basename(crate) and "0.1", respectively. Call these CNAME, CVERS.
|
||||
*
|
||||
* - Define CMETA as all the non-name, non-vers exported meta tags in the
|
||||
* crate (in sorted order).
|
||||
*
|
||||
* - Define CMH as hash(CMETA).
|
||||
*
|
||||
* - Compile our crate to lib CNAME-CMH-CVERS.so
|
||||
*
|
||||
* - Define STH(sym) as hash(CNAME, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
iter crate_export_metas(ast::crate c) -> @ast::meta_item {
|
||||
for (@ast::crate_directive cdir in c.node.directives) {
|
||||
alt (cdir.node) {
|
||||
case (ast::cdir_meta(?v, ?mis)) {
|
||||
if (v == ast::export_meta) {
|
||||
for (@ast::meta_item mi in mis) {
|
||||
put mi;
|
||||
}
|
||||
}
|
||||
}
|
||||
case (_) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
fn get_crate_meta(&session::session sess,
|
||||
&ast::crate c, str k, str default,
|
||||
bool warn_default) -> str {
|
||||
let vec[@ast::meta_item] v = [];
|
||||
for each (@ast::meta_item mi in crate_export_metas(c)) {
|
||||
if (mi.node.name == k) {
|
||||
v += [mi];
|
||||
}
|
||||
}
|
||||
alt (vec::len(v)) {
|
||||
case (0u) {
|
||||
if (warn_default) {
|
||||
sess.warn(#fmt("missing meta '%s', using '%s' as default",
|
||||
k, default));
|
||||
}
|
||||
ret default;
|
||||
}
|
||||
case (1u) {
|
||||
ret v.(0).node.value;
|
||||
}
|
||||
case (_) {
|
||||
sess.span_err(v.(1).span, #fmt("duplicate meta '%s'", k));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This calculates CMH as defined above
|
||||
fn crate_meta_extras_hash(sha1 sha, &ast::crate crate) -> str {
|
||||
fn lteq(&@ast::meta_item ma,
|
||||
&@ast::meta_item mb) -> bool {
|
||||
ret ma.node.name <= mb.node.name;
|
||||
}
|
||||
|
||||
fn len_and_str(&str s) -> str {
|
||||
ret #fmt("%u_%s", str::byte_len(s), s);
|
||||
}
|
||||
|
||||
let vec[mutable @ast::meta_item] v = [mutable];
|
||||
for each (@ast::meta_item mi in crate_export_metas(crate)) {
|
||||
if (mi.node.name != "name" &&
|
||||
mi.node.name != "vers") {
|
||||
v += [mutable mi];
|
||||
}
|
||||
}
|
||||
sort::quick_sort(lteq, v);
|
||||
sha.reset();
|
||||
for (@ast::meta_item m in v) {
|
||||
sha.input_str(len_and_str(m.node.name));
|
||||
sha.input_str(len_and_str(m.node.value));
|
||||
}
|
||||
ret truncated_sha1_result(sha);
|
||||
}
|
||||
|
||||
fn crate_meta_name(&session::session sess, &ast::crate crate,
|
||||
&str output) -> str {
|
||||
auto os = str::split(fs::basename(output), '.' as u8);
|
||||
assert vec::len(os) >= 2u;
|
||||
vec::pop(os);
|
||||
ret get_crate_meta(sess, crate, "name", str::connect(os, "."),
|
||||
sess.get_opts().shared);
|
||||
}
|
||||
|
||||
fn crate_meta_vers(&session::session sess, &ast::crate crate) -> str {
|
||||
ret get_crate_meta(sess, crate, "vers", "0.0",
|
||||
sess.get_opts().shared);
|
||||
}
|
||||
|
||||
fn truncated_sha1_result(sha1 sha) -> str {
|
||||
ret str::substr(sha.result_str(), 0u, 16u);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// This calculates STH for a symbol, as defined above
|
||||
fn symbol_hash(ty::ctxt tcx, sha1 sha, &ty::t t,
|
||||
str crate_meta_name,
|
||||
str crate_meta_extras_hash) -> str {
|
||||
// NB: do *not* use abbrevs here as we want the symbol names
|
||||
// to be independent of one another in the crate.
|
||||
auto cx = @rec(ds=metadata::def_to_str, tcx=tcx,
|
||||
abbrevs=metadata::ac_no_abbrevs);
|
||||
sha.reset();
|
||||
sha.input_str(crate_meta_name);
|
||||
sha.input_str("-");
|
||||
sha.input_str(crate_meta_name);
|
||||
sha.input_str("-");
|
||||
sha.input_str(metadata::Encode::ty_str(cx, t));
|
||||
auto hash = truncated_sha1_result(sha);
|
||||
// Prefix with _ so that it never blends into adjacent digits
|
||||
ret "_" + hash;
|
||||
}
|
||||
|
||||
fn get_symbol_hash(&@crate_ctxt ccx, &ty::t t) -> str {
|
||||
auto hash = "";
|
||||
alt (ccx.type_sha1s.find(t)) {
|
||||
case (some(?h)) { hash = h; }
|
||||
case (none) {
|
||||
hash = symbol_hash(ccx.tcx, ccx.sha, t,
|
||||
ccx.crate_meta_name,
|
||||
ccx.crate_meta_extras_hash);
|
||||
ccx.type_sha1s.insert(t, hash);
|
||||
}
|
||||
}
|
||||
ret hash;
|
||||
}
|
||||
|
||||
|
||||
fn mangle(&vec[str] ss) -> str {
|
||||
|
||||
// Follow C++ namespace-mangling style
|
||||
|
||||
auto n = "_ZN"; // Begin name-sequence.
|
||||
|
||||
for (str s in ss) {
|
||||
n += #fmt("%u%s", str::byte_len(s), s);
|
||||
}
|
||||
|
||||
n += "E"; // End name-sequence.
|
||||
ret n;
|
||||
}
|
||||
|
||||
|
||||
fn exported_name(&vec[str] path, &str hash, &str vers) -> str {
|
||||
// FIXME: versioning isn't working yet
|
||||
ret mangle(path + [hash]); // + "@" + vers;
|
||||
}
|
||||
|
||||
fn mangle_exported_name(&@crate_ctxt ccx, &vec[str] path,
|
||||
&ty::t t) -> str {
|
||||
auto hash = get_symbol_hash(ccx, t);
|
||||
ret exported_name(path, hash, ccx.crate_meta_vers);
|
||||
}
|
||||
|
||||
fn mangle_internal_name_by_type_only(&@crate_ctxt ccx, &ty::t t,
|
||||
&str name) -> str {
|
||||
auto f = metadata::def_to_str;
|
||||
auto cx = @rec(ds=f, tcx=ccx.tcx, abbrevs=metadata::ac_no_abbrevs);
|
||||
auto s = ty::ty_to_short_str(ccx.tcx, t);
|
||||
|
||||
auto hash = get_symbol_hash(ccx, t);
|
||||
ret mangle([name, s, hash]);
|
||||
}
|
||||
|
||||
fn mangle_internal_name_by_path_and_seq(&@crate_ctxt ccx, &vec[str] path,
|
||||
&str flav) -> str {
|
||||
ret mangle(path + [ccx.names.next(flav)]);
|
||||
}
|
||||
|
||||
fn mangle_internal_name_by_path(&@crate_ctxt ccx, &vec[str] path) -> str {
|
||||
ret mangle(path);
|
||||
}
|
||||
|
||||
fn mangle_internal_name_by_seq(&@crate_ctxt ccx, &str flav) -> str {
|
||||
ret ccx.names.next(flav);
|
||||
}
|
||||
|
||||
//
|
||||
// Local Variables:
|
||||
// mode: rust
|
||||
// fill-column: 78;
|
||||
// indent-tabs-mode: nil
|
||||
// c-basic-offset: 4
|
||||
// buffer-file-coding-system: utf-8-unix
|
||||
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
|
||||
// End:
|
||||
//
|
||||
|
@ -6,6 +6,9 @@ import std::uint;
|
||||
import std::term;
|
||||
import std::io;
|
||||
import std::map;
|
||||
import std::option;
|
||||
import std::option::some;
|
||||
import std::option::none;
|
||||
|
||||
tag os {
|
||||
os_win32;
|
||||
@ -48,9 +51,16 @@ fn span_to_str(span sp, codemap::codemap cm) -> str {
|
||||
lo.col, hi.line, hi.col));
|
||||
}
|
||||
|
||||
fn emit_diagnostic(span sp, str msg, str kind, u8 color,
|
||||
fn emit_diagnostic(option::t[span] sp, str msg, str kind, u8 color,
|
||||
codemap::codemap cm) {
|
||||
io::stdout().write_str(span_to_str(sp, cm) + ": ");
|
||||
auto ss = "<input>:0:0:0:0";
|
||||
alt (sp) {
|
||||
case (some(?ssp)) {
|
||||
ss = span_to_str(ssp, cm);
|
||||
}
|
||||
case (none) {}
|
||||
}
|
||||
io::stdout().write_str(ss + ": ");
|
||||
|
||||
if (term::color_supported()) {
|
||||
term::fg(io::stdout().get_buf_writer(), color);
|
||||
@ -85,12 +95,12 @@ state obj session(ast::crate_num cnum,
|
||||
|
||||
fn span_err(span sp, str msg) -> ! {
|
||||
// FIXME: Use constants, but rustboot doesn't know how to export them.
|
||||
emit_diagnostic(sp, msg, "error", 9u8, cm);
|
||||
emit_diagnostic(some(sp), msg, "error", 9u8, cm);
|
||||
fail;
|
||||
}
|
||||
|
||||
fn err(str msg) -> ! {
|
||||
log_err #fmt("error: %s", msg);
|
||||
emit_diagnostic(none[span], msg, "error", 9u8, cm);
|
||||
fail;
|
||||
}
|
||||
|
||||
@ -103,29 +113,32 @@ state obj session(ast::crate_num cnum,
|
||||
|
||||
fn span_warn(span sp, str msg) {
|
||||
// FIXME: Use constants, but rustboot doesn't know how to export them.
|
||||
emit_diagnostic(sp, msg, "warning", 11u8, cm);
|
||||
emit_diagnostic(some(sp), msg, "warning", 11u8, cm);
|
||||
}
|
||||
|
||||
fn warn(str msg) {
|
||||
emit_diagnostic(none[span], msg, "warning", 11u8, cm);
|
||||
}
|
||||
|
||||
fn span_note(span sp, str msg) {
|
||||
// FIXME: Use constants, but rustboot doesn't know how to export them.
|
||||
emit_diagnostic(sp, msg, "note", 10u8, cm);
|
||||
emit_diagnostic(some(sp), msg, "note", 10u8, cm);
|
||||
}
|
||||
|
||||
fn span_bug(span sp, str msg) -> ! {
|
||||
self.span_err(sp, #fmt("internal compiler error %s", msg));
|
||||
}
|
||||
|
||||
fn bug(str msg) -> ! {
|
||||
log_err #fmt("error: internal compiler error %s", msg);
|
||||
fail;
|
||||
self.err(#fmt("internal compiler error %s", msg));
|
||||
}
|
||||
|
||||
fn span_unimpl(span sp, str msg) -> ! {
|
||||
// FIXME: Use constants, but rustboot doesn't know how to export them.
|
||||
emit_diagnostic(sp, "internal compiler error: unimplemented " + msg,
|
||||
"error", 9u8, cm);
|
||||
fail;
|
||||
self.span_bug(sp, "unimplemented " + msg);
|
||||
}
|
||||
|
||||
|
||||
fn unimpl(str msg) -> ! {
|
||||
log_err #fmt("error: unimplemented %s", msg);
|
||||
fail;
|
||||
self.bug("unimplemented " + msg);
|
||||
}
|
||||
|
||||
fn get_external_crate(int num) -> crate_metadata {
|
||||
|
@ -71,6 +71,11 @@ type crate = spanned[crate_];
|
||||
type crate_ = rec(vec[@crate_directive] directives,
|
||||
_mod module);
|
||||
|
||||
tag meta_visibility {
|
||||
export_meta;
|
||||
local_meta;
|
||||
}
|
||||
|
||||
tag crate_directive_ {
|
||||
cdir_expr(@expr);
|
||||
// FIXME: cdir_let should be eliminated
|
||||
@ -80,7 +85,7 @@ tag crate_directive_ {
|
||||
cdir_src_mod(ident, option::t[filename]);
|
||||
cdir_dir_mod(ident, option::t[filename], vec[@crate_directive]);
|
||||
cdir_view_item(@view_item);
|
||||
cdir_meta(vec[@meta_item]);
|
||||
cdir_meta(meta_visibility, vec[@meta_item]);
|
||||
cdir_syntax(path);
|
||||
cdir_auth(path, _auth);
|
||||
}
|
||||
|
@ -418,8 +418,13 @@ fn eval_crate_directive(ctx cx,
|
||||
vec::push[@ast::view_item](view_items, vi);
|
||||
}
|
||||
|
||||
case (ast::cdir_meta(?mi)) {
|
||||
cx.sess.add_metadata(mi);
|
||||
case (ast::cdir_meta(?vi, ?mi)) {
|
||||
// FIXME: we should actually record, for documentation-sake,
|
||||
// the metadata that's not exported. It would be nice to have
|
||||
// compiled-in to the target crate, not just in theh AST.
|
||||
if (vi == ast::export_meta) {
|
||||
cx.sess.add_metadata(mi);
|
||||
}
|
||||
}
|
||||
|
||||
case (ast::cdir_syntax(?pth)) {}
|
||||
|
@ -2362,10 +2362,14 @@ fn parse_crate_directive(&parser p) -> ast::crate_directive
|
||||
expect(p, token::SEMI);
|
||||
ret spanned(lo, hi, ast::cdir_auth(n, a));
|
||||
} else if (eat_word(p, "meta")) {
|
||||
auto mv = ast::local_meta;
|
||||
if (eat_word(p, "export")) {
|
||||
mv = ast::export_meta;
|
||||
}
|
||||
auto mis = parse_meta(p);
|
||||
auto hi = p.get_hi_pos();
|
||||
expect(p, token::SEMI);
|
||||
ret spanned(lo, hi, ast::cdir_meta(mis));
|
||||
ret spanned(lo, hi, ast::cdir_meta(mv, mis));
|
||||
} else if (eat_word(p, "mod")) {
|
||||
auto id = parse_ident(p);
|
||||
auto file_opt = none[filename];
|
||||
|
@ -6,7 +6,7 @@
|
||||
// particular definition to the LLVM IR output we're producing.
|
||||
//
|
||||
// Hopefully useful general knowledge about trans:
|
||||
//
|
||||
//
|
||||
// * There's no way to find out the ty::t type of a ValueRef. Doing so
|
||||
// would be "trying to get the eggs out of an omelette" (credit:
|
||||
// pcwalton). You can, instead, find out its TypeRef by calling val_ty,
|
||||
@ -24,6 +24,7 @@ import std::map::hashmap;
|
||||
import std::option;
|
||||
import std::option::some;
|
||||
import std::option::none;
|
||||
import std::fs;
|
||||
|
||||
import front::ast;
|
||||
import front::creader;
|
||||
@ -62,6 +63,15 @@ import lib::llvm::False;
|
||||
import lib::llvm::True;
|
||||
import lib::llvm::Bool;
|
||||
|
||||
import link::mangle_internal_name_by_type_only;
|
||||
import link::mangle_internal_name_by_seq;
|
||||
import link::mangle_internal_name_by_path;
|
||||
import link::mangle_internal_name_by_path_and_seq;
|
||||
import link::mangle_exported_name;
|
||||
import link::crate_meta_name;
|
||||
import link::crate_meta_vers;
|
||||
import link::crate_meta_extras_hash;
|
||||
|
||||
state obj namegen(mutable int i) {
|
||||
fn next(str prefix) -> str {
|
||||
i += 1;
|
||||
@ -119,6 +129,9 @@ state type crate_ctxt = rec(session::session sess,
|
||||
@ast::native_item] native_items,
|
||||
hashmap[ast::def_id, str] item_symbols,
|
||||
mutable option::t[ValueRef] main_fn,
|
||||
str crate_meta_name,
|
||||
str crate_meta_vers,
|
||||
str crate_meta_extras_hash,
|
||||
// TODO: hashmap[tup(tag_id,subtys), @tag_info]
|
||||
hashmap[ty::t, uint] tag_sizes,
|
||||
hashmap[ast::def_id, ValueRef] discrims,
|
||||
@ -166,14 +179,14 @@ type fn_ctxt = rec(
|
||||
ValueRef lltaskptr,
|
||||
ValueRef llenv,
|
||||
ValueRef llretptr,
|
||||
|
||||
|
||||
// The next three elements: "hoisted basic blocks" containing
|
||||
// administrative activities that have to happen in only one place in the
|
||||
// function, due to LLVM's quirks.
|
||||
|
||||
// A block for all the function's allocas, so that LLVM will coalesce them
|
||||
// into a single alloca call.
|
||||
mutable BasicBlockRef llallocas,
|
||||
mutable BasicBlockRef llallocas,
|
||||
|
||||
// A block containing code that copies incoming arguments to space already
|
||||
// allocated by code in the llallocas block. (LLVM requires that
|
||||
@ -313,73 +326,6 @@ fn extend_path(@local_ctxt cx, &str name) -> @local_ctxt {
|
||||
ret @rec(path = cx.path + [name] with *cx);
|
||||
}
|
||||
|
||||
fn get_type_sha1(&@crate_ctxt ccx, &ty::t t) -> str {
|
||||
auto hash = "";
|
||||
alt (ccx.type_sha1s.find(t)) {
|
||||
case (some(?h)) { hash = h; }
|
||||
case (none) {
|
||||
ccx.sha.reset();
|
||||
auto f = metadata::def_to_str;
|
||||
// NB: do *not* use abbrevs here as we want the symbol names
|
||||
// to be independent of one another in the crate.
|
||||
auto cx = @rec(ds=f,
|
||||
tcx=ccx.tcx,
|
||||
abbrevs=metadata::ac_no_abbrevs);
|
||||
|
||||
ccx.sha.input_str(metadata::Encode::ty_str(cx, t));
|
||||
hash = str::substr(ccx.sha.result_str(), 0u, 16u);
|
||||
// Prefix with _ so that it never blends into adjacent digits
|
||||
hash = "_" + hash;
|
||||
ccx.type_sha1s.insert(t, hash);
|
||||
}
|
||||
}
|
||||
ret hash;
|
||||
}
|
||||
|
||||
fn mangle(&vec[str] ss) -> str {
|
||||
|
||||
if (vec::len(ss) > 0u && str::eq(vec::top(ss), "main")) {
|
||||
ret "_rust_main";
|
||||
}
|
||||
// Follow C++ namespace-mangling style
|
||||
|
||||
auto n = "_ZN"; // Begin name-sequence.
|
||||
|
||||
for (str s in ss) {
|
||||
n += #fmt("%u%s", str::byte_len(s), s);
|
||||
}
|
||||
|
||||
n += "E"; // End name-sequence.
|
||||
ret n;
|
||||
}
|
||||
|
||||
fn mangle_name_by_type(&@crate_ctxt ccx, &vec[str] path, &ty::t t) -> str {
|
||||
auto hash = get_type_sha1(ccx, t);
|
||||
ret mangle(path + [hash]);
|
||||
}
|
||||
|
||||
fn mangle_name_by_type_only(&@crate_ctxt ccx, &ty::t t, &str name) -> str {
|
||||
auto f = metadata::def_to_str;
|
||||
auto cx = @rec(ds=f, tcx=ccx.tcx, abbrevs=metadata::ac_no_abbrevs);
|
||||
auto s = ty::ty_to_short_str(ccx.tcx, t);
|
||||
|
||||
auto hash = get_type_sha1(ccx, t);
|
||||
ret mangle([name, s, hash]);
|
||||
}
|
||||
|
||||
fn mangle_name_by_path_and_seq(&@crate_ctxt ccx, &vec[str] path,
|
||||
&str flav) -> str {
|
||||
ret mangle(path + [ccx.names.next(flav)]);
|
||||
}
|
||||
|
||||
fn mangle_name_by_path(&vec[str] path) -> str {
|
||||
ret mangle(path);
|
||||
}
|
||||
|
||||
fn mangle_name_by_seq(&@crate_ctxt ccx, &str flav) -> str {
|
||||
ret ccx.names.next(flav);
|
||||
}
|
||||
|
||||
fn res(@block_ctxt bcx, ValueRef val) -> result {
|
||||
ret rec(bcx = bcx,
|
||||
val = val);
|
||||
@ -1917,10 +1863,10 @@ fn declare_tydesc(&@local_ctxt cx, &span sp, &ty::t t,
|
||||
|
||||
auto name;
|
||||
if (cx.ccx.sess.get_opts().debuginfo) {
|
||||
name = mangle_name_by_type_only(cx.ccx, t, "tydesc");
|
||||
name = mangle_internal_name_by_type_only(cx.ccx, t, "tydesc");
|
||||
name = sanitize(name);
|
||||
} else {
|
||||
name = mangle_name_by_seq(cx.ccx, "tydesc");
|
||||
name = mangle_internal_name_by_seq(cx.ccx, "tydesc");
|
||||
}
|
||||
|
||||
auto gvar = llvm::LLVMAddGlobal(ccx.llmod, T_tydesc(ccx.tn),
|
||||
@ -1951,10 +1897,12 @@ fn declare_generic_glue(&@local_ctxt cx,
|
||||
&str name) -> ValueRef {
|
||||
auto fn_nm;
|
||||
if (cx.ccx.sess.get_opts().debuginfo) {
|
||||
fn_nm = mangle_name_by_type_only(cx.ccx, t, "glue_" + name);
|
||||
fn_nm = mangle_internal_name_by_type_only(cx.ccx, t,
|
||||
"glue_" + name);
|
||||
fn_nm = sanitize(fn_nm);
|
||||
} else {
|
||||
fn_nm = mangle_name_by_seq(cx.ccx, "glue_" + name);
|
||||
fn_nm = mangle_internal_name_by_seq(cx.ccx,
|
||||
"glue_" + name);
|
||||
}
|
||||
auto llfn = decl_fastcall_fn(cx.ccx.llmod, fn_nm, llfnty);
|
||||
set_glue_inlining(cx, llfn, t);
|
||||
@ -4106,7 +4054,8 @@ fn trans_for_each(&@block_ctxt cx,
|
||||
|
||||
// Step 2: Declare foreach body function.
|
||||
|
||||
let str s = mangle_name_by_path_and_seq(lcx.ccx, lcx.path, "foreach");
|
||||
let str s = mangle_internal_name_by_path_and_seq(lcx.ccx, lcx.path,
|
||||
"foreach");
|
||||
|
||||
// The 'env' arg entering the body function is a fake env member (as in
|
||||
// the env-part of the normal rust calling convention) that actually
|
||||
@ -4805,7 +4754,8 @@ fn trans_bind_thunk(&@local_ctxt cx,
|
||||
// Construct a thunk-call with signature incoming_fty, and that copies
|
||||
// args forward into a call to outgoing_fty:
|
||||
|
||||
let str s = mangle_name_by_path_and_seq(cx.ccx, cx.path, "thunk");
|
||||
let str s = mangle_internal_name_by_path_and_seq(cx.ccx, cx.path,
|
||||
"thunk");
|
||||
let TypeRef llthunk_ty = get_pair_fn_ty(type_of(cx.ccx, sp,
|
||||
incoming_fty));
|
||||
let ValueRef llthunk = decl_internal_fastcall_fn(cx.ccx.llmod,
|
||||
@ -5823,13 +5773,17 @@ fn load_if_immediate(&@block_ctxt cx, ValueRef v, &ty::t t) -> ValueRef {
|
||||
|
||||
fn trans_log(int lvl, &@block_ctxt cx, &@ast::expr e) -> result {
|
||||
auto lcx = cx.fcx.lcx;
|
||||
auto modname = str::connect(lcx.module_path, "::");
|
||||
auto modname = link::mangle_internal_name_by_path(lcx.ccx,
|
||||
lcx.module_path);
|
||||
auto global;
|
||||
if (lcx.ccx.module_data.contains_key(modname)) {
|
||||
global = lcx.ccx.module_data.get(modname);
|
||||
} else {
|
||||
global = llvm::LLVMAddGlobal(lcx.ccx.llmod, T_int(),
|
||||
str::buf("_rust_mod_log_" + modname));
|
||||
auto s =
|
||||
link::mangle_internal_name_by_path_and_seq(lcx.ccx,
|
||||
lcx.module_path,
|
||||
"loglevel");
|
||||
global = llvm::LLVMAddGlobal(lcx.ccx.llmod, T_int(), str::buf(s));
|
||||
llvm::LLVMSetGlobalConstant(global, False);
|
||||
llvm::LLVMSetInitializer(global, C_null(T_int()));
|
||||
llvm::LLVMSetLinkage(global, lib::llvm::LLVMInternalLinkage
|
||||
@ -6225,8 +6179,8 @@ fn trans_spawn(&@block_ctxt cx,
|
||||
ret res(bcx, new_task);
|
||||
}
|
||||
|
||||
fn mk_spawn_wrapper(&@block_ctxt cx,
|
||||
&@ast::expr func,
|
||||
fn mk_spawn_wrapper(&@block_ctxt cx,
|
||||
&@ast::expr func,
|
||||
&ty::t args_ty) -> result {
|
||||
auto llmod = cx.fcx.lcx.ccx.llmod;
|
||||
let TypeRef args_ty_tref = type_of(cx.fcx.lcx.ccx, cx.sp, args_ty);
|
||||
@ -6239,9 +6193,9 @@ fn mk_spawn_wrapper(&@block_ctxt cx,
|
||||
|
||||
// TODO: construct a name based on tname
|
||||
let str wrap_name =
|
||||
mangle_name_by_path_and_seq(cx.fcx.lcx.ccx,
|
||||
cx.fcx.lcx.path,
|
||||
"spawn_wrapper");
|
||||
mangle_internal_name_by_path_and_seq(cx.fcx.lcx.ccx,
|
||||
cx.fcx.lcx.path,
|
||||
"spawn_wrapper");
|
||||
auto llfndecl = decl_fastcall_fn(llmod, wrap_name,
|
||||
wrapper_fn_type);
|
||||
|
||||
@ -6252,7 +6206,7 @@ fn mk_spawn_wrapper(&@block_ctxt cx,
|
||||
// 3u to skip the three implicit args
|
||||
let ValueRef arg = llvm::LLVMGetParam(fcx.llfn, 3u);
|
||||
|
||||
let vec[ValueRef] child_args =
|
||||
let vec[ValueRef] child_args =
|
||||
[llvm::LLVMGetParam(fcx.llfn, 0u),
|
||||
llvm::LLVMGetParam(fcx.llfn, 1u),
|
||||
llvm::LLVMGetParam(fcx.llfn, 2u)];
|
||||
@ -6271,19 +6225,19 @@ fn mk_spawn_wrapper(&@block_ctxt cx,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Find the function
|
||||
auto fnptr = trans_lval(fbcx, func).res;
|
||||
fbcx = fnptr.bcx;
|
||||
|
||||
|
||||
auto llfnptr = fbcx.build.GEP(fnptr.val,
|
||||
[C_int(0), C_int(0)]);
|
||||
auto llfn = fbcx.build.Load(llfnptr);
|
||||
|
||||
|
||||
fbcx.build.FastCall(llfn,
|
||||
child_args);
|
||||
fbcx.build.RetVoid();
|
||||
|
||||
|
||||
finish_fn(fcx, fbcx.llbb);
|
||||
|
||||
// TODO: make sure we clean up everything we need to.
|
||||
@ -6719,7 +6673,7 @@ fn new_local_ctxt(&@crate_ctxt ccx) -> @local_ctxt {
|
||||
let vec[ast::ty_param] obj_typarams = [];
|
||||
let vec[ast::obj_field] obj_fields = [];
|
||||
ret @rec(path=pth,
|
||||
module_path=[crate_name(ccx, "main")],
|
||||
module_path=[ccx.crate_meta_name],
|
||||
obj_typarams = obj_typarams,
|
||||
obj_fields = obj_fields,
|
||||
ccx = ccx);
|
||||
@ -7094,7 +7048,7 @@ fn create_vtbl(@local_ctxt cx,
|
||||
|
||||
let @local_ctxt mcx = @rec(path = cx.path + ["method",
|
||||
m.node.ident] with *cx);
|
||||
let str s = mangle_name_by_path(mcx.path);
|
||||
let str s = mangle_internal_name_by_path(mcx.ccx, mcx.path);
|
||||
let ValueRef llfn = decl_internal_fastcall_fn(cx.ccx.llmod, s,
|
||||
llfnty);
|
||||
cx.ccx.item_ids.insert(m.node.id, llfn);
|
||||
@ -7106,7 +7060,8 @@ fn create_vtbl(@local_ctxt cx,
|
||||
methods += [llfn];
|
||||
}
|
||||
auto vtbl = C_struct(methods);
|
||||
auto vtbl_name = mangle_name_by_path(cx.path + ["vtbl"]);
|
||||
auto vtbl_name = mangle_internal_name_by_path(cx.ccx,
|
||||
cx.path + ["vtbl"]);
|
||||
auto gvar = llvm::LLVMAddGlobal(cx.ccx.llmod, val_ty(vtbl),
|
||||
str::buf(vtbl_name));
|
||||
llvm::LLVMSetInitializer(gvar, vtbl);
|
||||
@ -7123,7 +7078,7 @@ fn trans_dtor(@local_ctxt cx,
|
||||
&@ast::method dtor) -> ValueRef {
|
||||
|
||||
auto llfnty = T_dtor(cx.ccx, dtor.span, llself_ty);
|
||||
let str s = mangle_name_by_path(cx.path + ["drop"]);
|
||||
let str s = mangle_internal_name_by_path(cx.ccx, cx.path + ["drop"]);
|
||||
let ValueRef llfn = decl_internal_fastcall_fn(cx.ccx.llmod, s, llfnty);
|
||||
cx.ccx.item_ids.insert(dtor.node.id, llfn);
|
||||
cx.ccx.item_symbols.insert(dtor.node.id, s);
|
||||
@ -7516,25 +7471,29 @@ fn decl_fn_and_pair(&@crate_ctxt ccx, &span sp,
|
||||
}
|
||||
}
|
||||
|
||||
let bool is_main = (str::eq(vec::top(path), "main") &&
|
||||
!ccx.sess.get_opts().shared);
|
||||
|
||||
// Declare the function itself.
|
||||
let str s = mangle_name_by_path(path);
|
||||
let str s =
|
||||
if (is_main) { "_rust_main" }
|
||||
else { mangle_internal_name_by_path(ccx, path) };
|
||||
|
||||
let ValueRef llfn = decl_internal_fastcall_fn(ccx.llmod, s, llfty);
|
||||
|
||||
// Declare the global constant pair that points to it.
|
||||
let str ps = mangle_name_by_type(ccx, path, node_ann_type(ccx, ann));
|
||||
|
||||
let str ps = mangle_exported_name(ccx, path, node_ann_type(ccx, ann));
|
||||
register_fn_pair(ccx, ps, llpairty, llfn, id);
|
||||
|
||||
if (str::eq(vec::top(path), "main") &&
|
||||
!ccx.sess.get_opts().shared) {
|
||||
if (is_main) {
|
||||
if (ccx.main_fn != none[ValueRef]) {
|
||||
ccx.sess.span_err(sp, "multiple 'main' functions");
|
||||
}
|
||||
log #fmt("registering %s as main function for crate", ps);
|
||||
llvm::LLVMSetLinkage(llfn, lib::llvm::LLVMExternalLinkage
|
||||
as llvm::Linkage);
|
||||
ccx.main_fn = some(llfn);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn register_fn_pair(&@crate_ctxt cx, str ps, TypeRef llpairty, ValueRef llfn,
|
||||
@ -7565,7 +7524,7 @@ fn native_fn_ty_param_count(&@crate_ctxt cx, &ast::def_id id) -> uint {
|
||||
alt (native_item.node) {
|
||||
case (ast::native_item_ty(_,_)) {
|
||||
cx.sess.bug("decl_native_fn_and_pair(): native fn isn't " +
|
||||
"actually a fn?!");
|
||||
"actually a fn");
|
||||
}
|
||||
case (ast::native_item_fn(_, _, _, ?tps, _, _)) {
|
||||
count = vec::len[ast::ty_param](tps);
|
||||
@ -7594,13 +7553,13 @@ fn decl_native_fn_and_pair(&@crate_ctxt ccx,
|
||||
// Declare the wrapper.
|
||||
auto t = node_ann_type(ccx, ann);
|
||||
auto wrapper_type = native_fn_wrapper_type(ccx, sp, num_ty_param, t);
|
||||
let str s = mangle_name_by_path(path);
|
||||
let str s = mangle_internal_name_by_path(ccx, path);
|
||||
let ValueRef wrapper_fn = decl_internal_fastcall_fn(ccx.llmod, s,
|
||||
wrapper_type);
|
||||
|
||||
// Declare the global constant pair that points to it.
|
||||
auto wrapper_pair_type = T_fn_pair(ccx.tn, wrapper_type);
|
||||
let str ps = mangle_name_by_type(ccx, path, node_ann_type(ccx, ann));
|
||||
let str ps = mangle_exported_name(ccx, path, node_ann_type(ccx, ann));
|
||||
|
||||
register_fn_pair(ccx, ps, wrapper_pair_type, wrapper_fn, id);
|
||||
|
||||
@ -7938,7 +7897,7 @@ fn trans_constant(&@crate_ctxt ccx, @walk_ctxt wcx, &@ast::item it) {
|
||||
auto discrim_val = C_int(i as int);
|
||||
|
||||
auto p = wcx.path + [ident, variant.node.name, "discrim"];
|
||||
auto s = mangle_name_by_type(ccx, p, ty::mk_int(ccx.tcx));
|
||||
auto s = mangle_exported_name(ccx, p, ty::mk_int(ccx.tcx));
|
||||
auto discrim_gvar = llvm::LLVMAddGlobal(ccx.llmod, T_int(),
|
||||
str::buf(s));
|
||||
|
||||
@ -7957,8 +7916,8 @@ fn trans_constant(&@crate_ctxt ccx, @walk_ctxt wcx, &@ast::item it) {
|
||||
// with consts.
|
||||
auto v = C_int(1);
|
||||
ccx.item_ids.insert(cid, v);
|
||||
auto s = mangle_name_by_type(ccx, wcx.path + [name],
|
||||
node_ann_type(ccx, ann));
|
||||
auto s = mangle_exported_name(ccx, wcx.path + [name],
|
||||
node_ann_type(ccx, ann));
|
||||
ccx.item_symbols.insert(cid, s);
|
||||
}
|
||||
|
||||
@ -8178,15 +8137,6 @@ fn create_module_map(&@crate_ctxt ccx) -> ValueRef {
|
||||
ret map;
|
||||
}
|
||||
|
||||
fn crate_name(&@crate_ctxt ccx, &str deflt) -> str {
|
||||
for (@ast::meta_item item in ccx.sess.get_metadata()) {
|
||||
if (str::eq(item.node.name, "name")) {
|
||||
ret item.node.value;
|
||||
}
|
||||
}
|
||||
ret deflt;
|
||||
}
|
||||
|
||||
// FIXME use hashed metadata instead of crate names once we have that
|
||||
fn create_crate_map(&@crate_ctxt ccx) -> ValueRef {
|
||||
let vec[ValueRef] subcrates = [];
|
||||
@ -8199,10 +8149,9 @@ fn create_crate_map(&@crate_ctxt ccx) -> ValueRef {
|
||||
i += 1;
|
||||
}
|
||||
vec::push[ValueRef](subcrates, C_int(0));
|
||||
auto cname = crate_name(ccx, "__none__");
|
||||
auto mapname;
|
||||
if (ccx.sess.get_opts().shared) {
|
||||
mapname = cname;
|
||||
mapname = ccx.crate_meta_name;
|
||||
} else {
|
||||
mapname = "toplevel";
|
||||
}
|
||||
@ -8240,7 +8189,7 @@ fn trans_crate(&session::session sess, &@ast::crate crate,
|
||||
auto sha1s = map::mk_hashmap[ty::t,str](hasher, eqer);
|
||||
auto abbrevs = map::mk_hashmap[ty::t,metadata::ty_abbrev](hasher, eqer);
|
||||
auto short_names = map::mk_hashmap[ty::t,str](hasher, eqer);
|
||||
|
||||
auto sha = std::sha1::mk_sha1();
|
||||
auto ccx = @rec(sess = sess,
|
||||
llmod = llmod,
|
||||
td = td,
|
||||
@ -8252,6 +8201,10 @@ fn trans_crate(&session::session sess, &@ast::crate crate,
|
||||
native_items = new_def_hash[@ast::native_item](),
|
||||
item_symbols = new_def_hash[str](),
|
||||
mutable main_fn = none[ValueRef],
|
||||
crate_meta_name = crate_meta_name(sess, *crate, output),
|
||||
crate_meta_vers = crate_meta_vers(sess, *crate),
|
||||
crate_meta_extras_hash =
|
||||
crate_meta_extras_hash(sha, *crate),
|
||||
tag_sizes = tag_sizes,
|
||||
discrims = new_def_hash[ValueRef](),
|
||||
discrim_symbols = new_def_hash[str](),
|
||||
@ -8263,7 +8216,7 @@ fn trans_crate(&session::session sess, &@ast::crate crate,
|
||||
lltypes = lltypes,
|
||||
glues = glues,
|
||||
names = namegen(0),
|
||||
sha = std::sha1::mk_sha1(),
|
||||
sha = sha,
|
||||
type_sha1s = sha1s,
|
||||
type_abbrevs = abbrevs,
|
||||
type_short_names = short_names,
|
||||
|
@ -68,7 +68,7 @@ fn walk_crate_directive(&ast_visitor v, @ast::crate_directive cd) {
|
||||
case (ast::cdir_view_item(?vi)) {
|
||||
walk_view_item(v, vi);
|
||||
}
|
||||
case (ast::cdir_meta(_)) {}
|
||||
case (ast::cdir_meta(_,_)) {}
|
||||
case (ast::cdir_syntax(_)) {}
|
||||
case (ast::cdir_auth(_, _)) {}
|
||||
}
|
||||
|
@ -19,6 +19,20 @@ fn dirname(path p) -> path {
|
||||
ret str::substr(p, 0u, i as uint);
|
||||
}
|
||||
|
||||
fn basename(path p) -> path {
|
||||
let int i = str::rindex(p, os_fs::path_sep as u8);
|
||||
if (i == -1) {
|
||||
i = str::rindex(p, os_fs::alt_path_sep as u8);
|
||||
if (i == -1) {
|
||||
ret p;
|
||||
}
|
||||
}
|
||||
auto len = str::byte_len(p);
|
||||
if ((i+1) as uint >= len) { ret p; }
|
||||
|
||||
ret str::slice(p, i+1 as uint, len);
|
||||
}
|
||||
|
||||
// FIXME: Need some typestate to avoid bounds check when len(pre) == 0
|
||||
fn connect(path pre, path post) -> path {
|
||||
auto len = str::byte_len(pre);
|
||||
|
@ -1,8 +1,10 @@
|
||||
meta (name = "std",
|
||||
desc = "Rust standard library",
|
||||
vers = "0.1",
|
||||
uuid = "122bed0b-c19b-4b82-b0b7-7ae8aead7297",
|
||||
url = "http://rust-lang.org/src/std",
|
||||
ver = "0.0.1");
|
||||
url = "http://rust-lang.org/src/std");
|
||||
|
||||
meta (comment = "Rust standard library",
|
||||
license = "BSD");
|
||||
|
||||
// Built-in types support modules.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user