mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 09:14:20 +00:00
Merge remote branch 'graydon/master'
This commit is contained in:
commit
b5c73605ea
@ -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)
|
||||
|
||||
|
||||
######################################################################
|
||||
|
@ -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 \
|
||||
|
12
mk/rt.mk
12
mk/rt.mk
@ -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 $@ $<
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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:
|
||||
//
|
||||
|
@ -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) {
|
||||
|
@ -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];
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
@ -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(_, _)) {}
|
||||
}
|
||||
|
@ -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 */ }
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
24
src/rt/main.ll.in
Normal 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
|
||||
}
|
@ -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
|
||||
|
@ -1,5 +1,4 @@
|
||||
|
||||
// error-pattern:unknown syntax expander
|
||||
fn main() {
|
||||
#iamnotanextensionthatexists("");
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// xfail-stage0
|
||||
|
||||
// error-pattern:Ambiguous type
|
||||
// error-pattern:cannot determine a type
|
||||
fn main() -> () {
|
||||
auto foo = [];
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user