Merge remote branch 'graydon/master'

This commit is contained in:
Josh Matthews 2011-06-08 03:59:34 -04:00
commit b5c73605ea
30 changed files with 1637 additions and 1517 deletions

View File

@ -144,9 +144,9 @@ COMPILER_INPUTS := $(wildcard $(addprefix $(S)src/comp/, \
######################################################################
LREQ := rt/$(CFG_RUNTIME) rustllvm/$(CFG_RUSTLLVM)
SREQ0 := stage0/rustc$(X) $(LREQ) stage1/glue.o stage1/$(CFG_STDLIB)
SREQ1 := stage1/rustc$(X) $(LREQ) stage2/glue.o stage2/$(CFG_STDLIB)
SREQ2 := stage2/rustc$(X) $(LREQ) stage3/glue.o stage3/$(CFG_STDLIB)
SREQ0 := stage0/rustc$(X) $(LREQ) rt/main.a stage1/glue.o stage1/$(CFG_STDLIB)
SREQ1 := stage1/rustc$(X) $(LREQ) rt/main.a stage2/glue.o stage2/$(CFG_STDLIB)
SREQ2 := stage2/rustc$(X) $(LREQ) rt/main.a stage3/glue.o stage3/$(CFG_STDLIB)
######################################################################

View File

@ -28,6 +28,8 @@ clean:
$(Q)rm -f stage3/rustc$(X) stage3/$(CFG_STDLIB) stage3/glue*
$(Q)rm -f rustllvm/$(CFG_RUSTLLVM) rustllvm/rustllvmbits.a
$(Q)rm -f rt/$(CFG_RUNTIME)
$(Q)rm -f rt/main.o
$(Q)rm -f rt/main.a
$(Q)rm -Rf $(PKG_NAME)-*.tar.gz dist
$(Q)rm -f $(foreach ext,o a d bc s exe,$(wildcard stage*/*.$(ext)))
$(Q)rm -Rf $(foreach ext,out out.tmp \

View File

@ -76,6 +76,18 @@ rt/%.o: rt/%.s $(MKFILES)
@$(call E, compile: $@)
$(Q)$(call CFG_COMPILE_C, $@, $(RUNTIME_INCS)) $<
ifdef CFG_WINDOWSY
rt/main.ll: rt/main.ll.in
sed 's/MAIN/WinMain@16/' < $^ > $@
else
rt/main.ll: rt/main.ll.in
sed 's/MAIN/main/' < $^ > $@
endif
rt/main.a: rt/main.o
rm -f $@
ar crs $@ $^
rt/%.o: rt/%.ll $(MKFILES)
@$(call E, llc: $@)
$(Q)$(LLC) -filetype=obj -relocation-model=pic -march=x86 -o $@ $<

View File

@ -44,7 +44,7 @@ stage1/%.o: stage1/%.s
stage1/%$(X): stage1/%.o $(SREQ0)
@$(call E, link [gcc]: $@)
$(Q)gcc $(CFG_GCCISH_CFLAGS) stage1/glue.o -o $@ $< \
-Lstage1 -Lrustllvm -Lrt -lrustrt -lrustllvm -lstd -lm
-Lstage1 -Lrustllvm -Lrt rt/main.a -lrustrt -lrustllvm -lstd -lm
@# dsymutil sometimes fails or prints a warning, but the
@# program still runs. Since it simplifies debugging other
@# programs, I\'ll live with the noise.

View File

@ -44,7 +44,7 @@ stage2/%.o: stage2/%.s
stage2/%$(X): stage2/%.o $(SREQ1)
@$(call E, link [gcc]: $@)
$(Q)gcc $(CFG_GCCISH_CFLAGS) stage2/glue.o -o $@ $< \
-Lstage2 -Lrustllvm -Lrt -lrustrt -lrustllvm -lstd -lm
-Lstage2 -Lrustllvm -Lrt rt/main.a -lrustrt -lrustllvm -lstd -lm
@# dsymutil sometimes fails or prints a warning, but the
@# program still runs. Since it simplifies debugging other
@# programs, I\'ll live with the noise.

View File

@ -23,7 +23,7 @@ stage3/rustc.o: $(COMPILER_CRATE) $(COMPILER_INPUTS) $(SREQ2)
$(STAGE2) -c -o $@ $<
stage3/glue.o: stage2/rustc$(X) stage2/$(CFG_STDLIB) stage2/intrinsics.bc \
rustllvm/$(CFG_RUSTLLVM) rt/$(CFG_RUNTIME)
rustllvm/$(CFG_RUSTLLVM) rt/$(CFG_RUNTIME)
@$(call E, generate: $@)
$(STAGE2) -c -o $@ --glue
@ -44,7 +44,7 @@ stage3/%.o: stage3/%.s
stage3/%$(X): stage3/%.o $(SREQ2)
@$(call E, link [gcc]: $@)
$(Q)gcc $(CFG_GCCISH_CFLAGS) stage3/glue.o -o $@ $< \
-Lstage3 -Lrustllvm -Lrt -lrustrt -lrustllvm -lstd -lm
-Lstage3 -Lrustllvm -Lrt rt/main.a -lrustrt -lrustllvm -lstd -lm
@# dsymutil sometimes fails or prints a warning, but the
@# program still runs. Since it simplifies debugging other
@# programs, I\'ll live with the noise.

View File

@ -185,7 +185,7 @@ compile-check: tidy \
%.stage0$(X): %.stage0.o $(SREQ0)
@$(call E, link [gcc]: $@)
$(Q)gcc $(CFG_GCCISH_CFLAGS) stage1/glue.o -o $@ $< \
-Lstage1 -Lrt -lrustrt -lstd -lm
-Lstage1 -Lrt rt/main.a -lrustrt -lstd -lm
@# dsymutil sometimes fails or prints a warning, but the
@# program still runs. Since it simplifies debugging other
@# programs, I\'ll live with the noise.
@ -194,7 +194,7 @@ compile-check: tidy \
%.stage1$(X): %.stage1.o $(SREQ1)
@$(call E, link [gcc]: $@)
$(Q)gcc $(CFG_GCCISH_CFLAGS) stage2/glue.o -o $@ $< \
-Lstage2 -Lrt -lrustrt -lstd -lm
-Lstage2 -Lrt rt/main.a -lrustrt -lstd -lm
@# dsymutil sometimes fails or prints a warning, but the
@# program still runs. Since it simplifies debugging other
@# programs, I\'ll live with the noise.
@ -203,7 +203,7 @@ compile-check: tidy \
%.stage2$(X): %.stage2.o $(SREQ2)
@$(call E, link [gcc]: $@)
$(Q)gcc $(CFG_GCCISH_CFLAGS) stage3/glue.o -o $@ $< \
-Lstage3 -Lrt -lrustrt -lstd -lm
-Lstage3 -Lrt rt/main.a -lrustrt -lstd -lm
@# dsymutil sometimes fails or prints a warning, but the
@# program still runs. Since it simplifies debugging other
@# programs, I\'ll live with the noise.

View File

@ -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:
//

View File

@ -125,7 +125,7 @@ fn pretty_print_input(session::session sess, eval::env env, str input,
pp_mode ppm) {
auto def = tup(ast::local_crate, 0);
auto p = front::parser::new_parser(sess, env, def, input, 0u, 0u);
auto crate = front::parser::parse_crate_from_source_file(p);
auto crate = parse_input(sess, p, input);
auto mode;
alt (ppm) {

View File

@ -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 {

View File

@ -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);
}

View File

@ -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)) {}

View File

@ -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];

View File

@ -230,17 +230,6 @@ mod Encode {
}
case (ty::ty_type) {w.write_char('Y');}
case (ty::ty_task) {w.write_char('a');}
// These two don't appear in crate metadata, but are here because
// `hash_ty()` uses this function.
case (ty::ty_bound_param(?id)) {
w.write_char('o');
w.write_str(common::uistr(id));
}
case (ty::ty_local(?def)) {
w.write_char('L');
w.write_str(cx.ds(def));
}
}
}

View File

@ -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,70 +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 {
// 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(&@crate_ctxt ccx, &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);
@ -955,10 +904,6 @@ fn type_of_inner(&@crate_ctxt cx, &span sp, &ty::t t) -> TypeRef {
case (ty::ty_param(_)) {
llty = T_i8();
}
case (ty::ty_bound_param(_)) {
cx.tcx.sess.span_err(sp,
"trans::type_of called on ty_bound_param");
}
case (ty::ty_type) { llty = T_ptr(T_tydesc(cx.tn)); }
}
@ -1350,7 +1295,6 @@ fn static_size_of_tag(&@crate_ctxt cx, &span sp, &ty::t t) -> uint {
auto tup_ty = simplify_type(cx, ty::mk_imm_tup(cx.tcx, variant.args));
// Perform any type parameter substitutions.
tup_ty = ty::bind_params_in_type(cx.tcx, tup_ty);
tup_ty = ty::substitute_type_params(cx.tcx, subtys, tup_ty);
// Here we possibly do a recursive call.
@ -1424,10 +1368,8 @@ fn dynamic_size_of(&@block_ctxt cx, ty::t t) -> result {
let vec[ty::t] raw_tys = variant.args;
let vec[ty::t] tys = [];
for (ty::t raw_ty in raw_tys) {
auto t = ty::bind_params_in_type(cx.fcx.lcx.ccx.tcx,
raw_ty);
t = ty::substitute_type_params(cx.fcx.lcx.ccx.tcx, tps,
t);
auto t = ty::substitute_type_params(cx.fcx.lcx.ccx.tcx,
tps, raw_ty);
tys += [t];
}
@ -1604,9 +1546,8 @@ fn GEP_tag(@block_ctxt cx,
auto i = 0;
let vec[ty::t] true_arg_tys = [];
for (ty::t aty in arg_tys) {
auto arg_ty = ty::bind_params_in_type(cx.fcx.lcx.ccx.tcx, aty);
arg_ty = ty::substitute_type_params(cx.fcx.lcx.ccx.tcx, ty_substs,
arg_ty);
auto arg_ty = ty::substitute_type_params(cx.fcx.lcx.ccx.tcx,
ty_substs, aty);
true_arg_tys += [arg_ty];
if (i == ix) {
elem_ty = arg_ty;
@ -1914,10 +1855,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),
@ -1948,10 +1889,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);
@ -2794,10 +2737,8 @@ fn iter_structural_ty_full(&@block_ctxt cx,
auto llfldp_b = rslt.val;
variant_cx = rslt.bcx;
auto ty_subst = ty::bind_params_in_type(
cx.fcx.lcx.ccx.tcx, a.ty);
ty_subst = ty::substitute_type_params(
cx.fcx.lcx.ccx.tcx, tps, ty_subst);
auto ty_subst = ty::substitute_type_params(
cx.fcx.lcx.ccx.tcx, tps, a.ty);
auto llfld_a =
load_if_immediate(variant_cx,
@ -3684,13 +3625,11 @@ fn autoderef(&@block_ctxt cx, ValueRef v, &ty::t t) -> result {
v1 = load_if_immediate(cx, v1, t1);
}
case (_) {
ret res(cx, v1);
}
case (_) { break; }
}
}
fail; // fools the return-checker
ret res(cx, v1);
}
fn autoderefed_ty(&@crate_ctxt ccx, &ty::t t) -> ty::t {
@ -3701,13 +3640,11 @@ fn autoderefed_ty(&@crate_ctxt ccx, &ty::t t) -> ty::t {
case (ty::ty_box(?mt)) {
t1 = mt.ty;
}
case (_) {
ret t1;
}
case (_) { break; }
}
}
fail; // fools the return-checker
ret t1;
}
fn trans_binary(&@block_ctxt cx, ast::binop op,
@ -3873,7 +3810,7 @@ fn trans_if(&@block_ctxt cx, &@ast::expr cond,
}
// FIXME: This isn't quite right, particularly re: dynamic types
auto expr_ty = ty::ann_to_type(cx.fcx.lcx.ccx.tcx.node_types,
auto expr_ty = ty::ann_to_type(cx.fcx.lcx.ccx.tcx,
ann);
if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, expr_ty)) {
expr_llty = T_typaram_ptr(cx.fcx.lcx.ccx.tn);
@ -4107,7 +4044,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
@ -4257,7 +4195,7 @@ fn trans_pat_match(&@block_ctxt cx, &@ast::pat pat, ValueRef llval,
case (ast::pat_lit(?lt, ?ann)) {
auto lllit = trans_lit(cx.fcx.lcx.ccx, *lt, ann);
auto lltype = ty::ann_to_type(cx.fcx.lcx.ccx.tcx.node_types, ann);
auto lltype = ty::ann_to_type(cx.fcx.lcx.ccx.tcx, ann);
auto lleq = trans_compare(cx, ast::eq, lltype, llval, lllit);
auto matched_cx = new_sub_block_ctxt(lleq.bcx, "matched_cx");
@ -4295,7 +4233,7 @@ fn trans_pat_match(&@block_ctxt cx, &@ast::pat pat, ValueRef llval,
cx.build.CondBr(lleq, matched_cx.llbb, next_cx.llbb);
auto ty_params =
ty::ann_to_type_params(cx.fcx.lcx.ccx.tcx.node_types, ann);
ty::ann_to_type_params(cx.fcx.lcx.ccx.tcx, ann);
if (vec::len[@ast::pat](subpats) > 0u) {
auto llblobptr = matched_cx.build.GEP(lltagptr,
@ -4356,7 +4294,7 @@ fn trans_pat_binding(&@block_ctxt cx, &@ast::pat pat,
auto llblobptr = cx.build.GEP(lltagptr, [C_int(0), C_int(1)]);
auto ty_param_substs =
ty::ann_to_type_params(cx.fcx.lcx.ccx.tcx.node_types, ann);
ty::ann_to_type_params(cx.fcx.lcx.ccx.tcx, ann);
auto this_cx = cx;
auto i = 0;
@ -4405,7 +4343,7 @@ fn trans_alt(&@block_ctxt cx, &@ast::expr expr,
"non-exhaustive match failure");
// FIXME: This isn't quite right, particularly re: dynamic types
auto expr_ty = ty::ann_to_type(cx.fcx.lcx.ccx.tcx.node_types, ann);
auto expr_ty = ty::ann_to_type(cx.fcx.lcx.ccx.tcx, ann);
auto expr_llty;
if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, expr_ty)) {
expr_llty = T_typaram_ptr(cx.fcx.lcx.ccx.tn);
@ -4470,8 +4408,8 @@ fn lval_generic_fn(&@block_ctxt cx,
lv = trans_external_path(cx, fn_id, tpt);
}
auto tys = ty::ann_to_type_params(cx.fcx.lcx.ccx.tcx.node_types, ann);
auto monoty = ty::ann_to_type(cx.fcx.lcx.ccx.tcx.node_types, ann);
auto tys = ty::ann_to_type_params(cx.fcx.lcx.ccx.tcx, ann);
auto monoty = ty::ann_to_type(cx.fcx.lcx.ccx.tcx, ann);
if (vec::len[ty::t](tys) != 0u) {
auto bcx = lv.res.bcx;
@ -4806,7 +4744,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,
@ -5358,7 +5297,8 @@ fn trans_call(&@block_ctxt cx, &@ast::expr f,
}
auto ret_ty = ty::ann_to_type(cx.fcx.lcx.ccx.tcx.node_types, ann);
auto ret_ty = ty::ann_to_type(cx.fcx.lcx.ccx.tcx, ann);
auto args_res = trans_args(f_res.res.bcx,
llenv, f_res.llobj,
f_res.generic,
@ -5824,13 +5764,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
@ -6226,8 +6170,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);
@ -6240,9 +6184,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);
@ -6253,7 +6197,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)];
@ -6272,19 +6216,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.
@ -6720,7 +6664,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);
@ -6907,7 +6851,7 @@ fn is_terminated(&@block_ctxt cx) -> bool {
}
fn arg_tys_of_fn(&@crate_ctxt ccx, ast::ann ann) -> vec[ty::arg] {
alt (ty::struct(ccx.tcx, ty::ann_to_type(ccx.tcx.node_types, ann))) {
alt (ty::struct(ccx.tcx, ty::ann_to_type(ccx.tcx, ann))) {
case (ty::ty_fn(_, ?arg_tys, _, _)) {
ret arg_tys;
}
@ -6924,7 +6868,7 @@ fn ret_ty_of_fn_ty(&@crate_ctxt ccx, ty::t t) -> ty::t {
fn ret_ty_of_fn(&@crate_ctxt ccx, ast::ann ann) -> ty::t {
ret ret_ty_of_fn_ty(ccx, ty::ann_to_type(ccx.tcx.node_types, ann));
ret ret_ty_of_fn_ty(ccx, ty::ann_to_type(ccx.tcx, ann));
}
fn populate_fn_ctxt_from_llself(@fn_ctxt fcx, val_self_pair llself) {
@ -7095,7 +7039,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.ccx, 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);
@ -7107,7 +7051,8 @@ fn create_vtbl(@local_ctxt cx,
methods += [llfn];
}
auto vtbl = C_struct(methods);
auto vtbl_name = mangle_name_by_path(cx.ccx, 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);
@ -7124,7 +7069,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.ccx, 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);
@ -7517,23 +7462,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(ccx, 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,
@ -7564,7 +7515,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);
@ -7592,14 +7543,15 @@ 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(ccx, 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);
@ -7937,7 +7889,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));
@ -7956,8 +7908,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);
}
@ -7996,51 +7948,6 @@ fn create_typedefs(&@crate_ctxt cx) {
llvm::LLVMAddTypeName(cx.llmod, str::buf("tydesc"), T_tydesc(cx.tn));
}
fn trans_main_fn(@local_ctxt cx, ValueRef crate_map) {
auto T_main_args = [T_int(), T_int()];
auto T_rust_start_args = [T_int(), T_int(), T_int(), T_int()];
auto main_name;
if (str::eq(std::os::target_os(), "win32")) {
main_name = "WinMain@16";
} else {
main_name = "main";
}
auto llmain =
decl_cdecl_fn(cx.ccx.llmod, main_name, T_fn(T_main_args, T_int()));
auto llrust_start = decl_cdecl_fn(cx.ccx.llmod, "rust_start",
T_fn(T_rust_start_args, T_int()));
auto llargc = llvm::LLVMGetParam(llmain, 0u);
auto llargv = llvm::LLVMGetParam(llmain, 1u);
auto llrust_main = alt (cx.ccx.main_fn) {
case (none) {
cx.ccx.sess.err("missing 'main' function");
// FIXME: shouldn't sess.err's ! result unify with f?
C_nil()
}
case (some(?f)) { f }
};
//
// Emit the moral equivalent of:
//
// main(int argc, char **argv) {
// rust_start(&_rust.main, argc, argv);
// }
//
let BasicBlockRef llbb =
llvm::LLVMAppendBasicBlock(llmain, str::buf(""));
auto b = new_builder(llbb);
auto start_args = [p2i(llrust_main), llargc, llargv, p2i(crate_map)];
b.Ret(b.Call(llrust_start, start_args));
}
fn declare_intrinsics(ModuleRef llmod) -> hashmap[str,ValueRef] {
let vec[TypeRef] T_memmove32_args = [T_ptr(T_i8()), T_ptr(T_i8()),
@ -8211,8 +8118,6 @@ fn create_module_map(&@crate_ctxt ccx) -> ValueRef {
auto maptype = T_array(elttype, ccx.module_data.size() + 1u);
auto map = llvm::LLVMAddGlobal(ccx.llmod, maptype,
str::buf("_rust_mod_map"));
llvm::LLVMSetLinkage(map, lib::llvm::LLVMInternalLinkage
as llvm::Linkage);
let vec[ValueRef] elts = [];
for each (@tup(str, ValueRef) item in ccx.module_data.items()) {
auto elt = C_struct([p2i(C_cstr(ccx, item._0)), p2i(item._1)]);
@ -8224,15 +8129,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 = [];
@ -8245,7 +8141,13 @@ fn create_crate_map(&@crate_ctxt ccx) -> ValueRef {
i += 1;
}
vec::push[ValueRef](subcrates, C_int(0));
auto sym_name = "_rust_crate_map_" + crate_name(ccx, "__none__");
auto mapname;
if (ccx.sess.get_opts().shared) {
mapname = ccx.crate_meta_name;
} else {
mapname = "toplevel";
}
auto sym_name = "_rust_crate_map_" + mapname;
auto arrtype = T_array(T_int(), vec::len[ValueRef](subcrates));
auto maptype = T_struct([T_int(), arrtype]);
auto map = llvm::LLVMAddGlobal(ccx.llmod, maptype, str::buf(sym_name));
@ -8279,7 +8181,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,
@ -8291,6 +8193,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](),
@ -8302,7 +8208,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,
@ -8322,9 +8228,17 @@ fn trans_crate(&session::session sess, &@ast::crate crate,
trans_constants(ccx, crate);
trans_mod(cx, crate.node.module);
auto crate_map = create_crate_map(ccx);
if (!sess.get_opts().shared) {
trans_main_fn(cx, crate_map);
}
auto gvar = llvm::LLVMAddGlobal(cx.ccx.llmod, T_ptr(T_int()),
str::buf("_rust_fetch_this_object_hack"));
auto gvar2 = llvm::LLVMAddGlobal(cx.ccx.llmod, T_ptr(T_ptr(T_int())),
str::buf("_rust_fetch_this_object_hack2"));
llvm::LLVMSetInitializer(gvar2, gvar);
llvm::LLVMSetGlobalConstant(gvar, True);
llvm::LLVMSetGlobalConstant(gvar2, True);
}
emit_tydescs(ccx);

View File

@ -482,7 +482,7 @@ fn controlflow_def_id(&crate_ctxt ccx, &def_id d) -> controlflow {
If it has a function type with a ! annotation,
the answer is noreturn. */
fn controlflow_expr(&crate_ctxt ccx, @expr e) -> controlflow {
alt (ty::struct(ccx.tcx, ty::ann_to_type(ccx.tcx.node_types,
alt (ty::struct(ccx.tcx, ty::ann_to_type(ccx.tcx,
expr_ann(e)))) {
case (ty::ty_fn(_,_,_,?cf)) {
ret cf;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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(_, _)) {}
}

View File

@ -945,7 +945,7 @@ fn print_decl(&ps s, &@ast::decl decl) {
case (mo_untyped) { /* no-op */ }
case (mo_typed(?tcx)) {
auto lty =
ty::ann_to_type(tcx.node_types, loc.ann);
ty::ann_to_type(tcx, loc.ann);
word_space(s, ty::ty_to_str(tcx, lty));
}
case (mo_identified) { /* no-op */ }

View File

@ -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);

View File

@ -38,3 +38,7 @@ fn truncate[T](&smallintmap[T] m, uint len) {
m.v = vec::slice_mut[option::t[T]](m.v, 0u, len);
}
fn max_key[T](&smallintmap[T] m) -> uint {
ret vec::len[option::t[T]](m.v);
}

View File

@ -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.

View File

@ -20,6 +20,12 @@ fn make_set(&ufind ufnd) -> uint {
ret idx;
}
/// Creates sets as necessary to ensure that least `n` sets are present in the
/// data structure.
fn grow(&ufind ufnd, uint n) {
while (set_count(ufnd) < n) { make_set(ufnd); }
}
fn find(&ufind ufnd, uint n) -> uint {
alt (ufnd.nodes.(n)) {
case (none) { ret n; }
@ -37,12 +43,17 @@ fn union(&ufind ufnd, uint m, uint n) {
}
}
fn set_count(&ufind ufnd) -> uint {
ret vec::len[node](ufnd.nodes);
}
// Removes all sets with IDs greater than or equal to the given value.
fn prune(&ufind ufnd, uint n) {
// TODO: Use "slice" once we get rid of "mutable?"
while (n != 0u) {
auto len = vec::len[node](ufnd.nodes);
while (len != n) {
vec::pop[node](ufnd.nodes);
n -= 1u;
len -= 1u;
}
}

View File

@ -12,6 +12,11 @@ fn ne(uint x, uint y) -> bool { ret x != y; }
fn ge(uint x, uint y) -> bool { ret x >= y; }
fn gt(uint x, uint y) -> bool { ret x > y; }
fn max(uint x, uint y) -> uint {
if (x > y) { ret x; }
ret y;
}
iter range(uint lo, uint hi) -> uint {
auto lo_ = lo;
while (lo_ < hi) {

View File

@ -210,7 +210,7 @@ fn unshift[T](&mutable array[T] v, &T t) {
v = res;
}
fn grow[T](&array[T] v, uint n, &T initval) {
fn grow[T](&mutable array[T] v, uint n, &T initval) {
let uint i = n;
while (i > 0u) {
i -= 1u;
@ -218,7 +218,7 @@ fn grow[T](&array[T] v, uint n, &T initval) {
}
}
fn grow_set[T](&vec[mutable T] v, uint index, &T initval, &T val) {
fn grow_set[T](&mutable vec[mutable T] v, uint index, &T initval, &T val) {
auto length = vec::len(v);
if (index >= length) {
grow(v, index - length + 1u, initval);
@ -393,6 +393,12 @@ fn reversed[T](vec[T] v) -> vec[T] {
ret res;
}
/// Truncates the vector to length `new_len`.
/// FIXME: This relies on a typechecker bug (covariance vs. invariance).
fn truncate[T](&mutable vec[mutable? T] v, uint new_len) {
v = slice[T](v, 0u, new_len);
}
// Local Variables:
// mode: rust;
// fill-column: 78;

24
src/rt/main.ll.in Normal file
View File

@ -0,0 +1,24 @@
%0 = type { i32, [1 x i32] }
%1 = type { i32, i32 }
%2 = type { i32, %3 }
%3 = type { %tydesc*, %4, i1, {} }
%4 = type { i1*, i1* }
%5 = type { i32, i32, i32, i32, [0 x %6*] }
%6 = type { i32, i32, i32, i32, [0 x i8] }
@_rust_crate_map_toplevel = external global %0
declare fastcc void @_rust_main(i1* nocapture, %task*, %2* nocapture, %5*);
declare i32 @rust_start(i32, i32, i32, i32)
%tydesc = type { %tydesc**, i32, i32, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*, i8*, i8)* }
%task = type { i32, i32, i32, i32, i32, i32, i32, i32 }
@_rust_fetch_this_object_hack = global i32 0
define i32 @"MAIN"(i32, i32) {
%3 = tail call i32 @rust_start(i32 ptrtoint (void (i1*, %task*, %2*, %5*)* @_rust_main to i32), i32 %0, i32 %1, i32 ptrtoint (%0* @_rust_crate_map_toplevel to i32))
ret i32 %3
}

View File

@ -1,3 +1,8 @@
S 2011-06-07 a4ca75e
linux-i386 3de95184c59f5b0554df3da995090aaba26a190f
macos-i386 1537f2e01c746dc6ca2a9bfb4b2e81256bb01e96
winnt-i386 538765c5c4c31dfe8d6e998ef7503beb5cfa1525
S 2011-06-03 f29d046
linux-i386 76e4ee5b9148aae30ebfaabb12791bfee4fa8727
macos-i386 e146fa18f4b0f22fe4fd7fd104242837569d7702

View File

@ -1,5 +1,4 @@
// error-pattern:unknown syntax expander
fn main() {
#iamnotanextensionthatexists("");
}
}

View File

@ -1,6 +1,6 @@
// xfail-stage0
// error-pattern:Ambiguous type
// error-pattern:cannot determine a type
fn main() -> () {
auto foo = [];
}