Merge remote branch 'graydon/master'
This commit is contained in:
commit
b5c73605ea
30 changed files with 1637 additions and 1517 deletions
|
@ -144,9 +144,9 @@ COMPILER_INPUTS := $(wildcard $(addprefix $(S)src/comp/, \
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
LREQ := rt/$(CFG_RUNTIME) rustllvm/$(CFG_RUSTLLVM)
|
LREQ := rt/$(CFG_RUNTIME) rustllvm/$(CFG_RUSTLLVM)
|
||||||
SREQ0 := stage0/rustc$(X) $(LREQ) stage1/glue.o stage1/$(CFG_STDLIB)
|
SREQ0 := stage0/rustc$(X) $(LREQ) rt/main.a stage1/glue.o stage1/$(CFG_STDLIB)
|
||||||
SREQ1 := stage1/rustc$(X) $(LREQ) stage2/glue.o stage2/$(CFG_STDLIB)
|
SREQ1 := stage1/rustc$(X) $(LREQ) rt/main.a stage2/glue.o stage2/$(CFG_STDLIB)
|
||||||
SREQ2 := stage2/rustc$(X) $(LREQ) stage3/glue.o stage3/$(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 stage3/rustc$(X) stage3/$(CFG_STDLIB) stage3/glue*
|
||||||
$(Q)rm -f rustllvm/$(CFG_RUSTLLVM) rustllvm/rustllvmbits.a
|
$(Q)rm -f rustllvm/$(CFG_RUSTLLVM) rustllvm/rustllvmbits.a
|
||||||
$(Q)rm -f rt/$(CFG_RUNTIME)
|
$(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 -Rf $(PKG_NAME)-*.tar.gz dist
|
||||||
$(Q)rm -f $(foreach ext,o a d bc s exe,$(wildcard stage*/*.$(ext)))
|
$(Q)rm -f $(foreach ext,o a d bc s exe,$(wildcard stage*/*.$(ext)))
|
||||||
$(Q)rm -Rf $(foreach ext,out out.tmp \
|
$(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: $@)
|
@$(call E, compile: $@)
|
||||||
$(Q)$(call CFG_COMPILE_C, $@, $(RUNTIME_INCS)) $<
|
$(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)
|
rt/%.o: rt/%.ll $(MKFILES)
|
||||||
@$(call E, llc: $@)
|
@$(call E, llc: $@)
|
||||||
$(Q)$(LLC) -filetype=obj -relocation-model=pic -march=x86 -o $@ $<
|
$(Q)$(LLC) -filetype=obj -relocation-model=pic -march=x86 -o $@ $<
|
||||||
|
|
|
@ -44,7 +44,7 @@ stage1/%.o: stage1/%.s
|
||||||
stage1/%$(X): stage1/%.o $(SREQ0)
|
stage1/%$(X): stage1/%.o $(SREQ0)
|
||||||
@$(call E, link [gcc]: $@)
|
@$(call E, link [gcc]: $@)
|
||||||
$(Q)gcc $(CFG_GCCISH_CFLAGS) stage1/glue.o -o $@ $< \
|
$(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
|
@# dsymutil sometimes fails or prints a warning, but the
|
||||||
@# program still runs. Since it simplifies debugging other
|
@# program still runs. Since it simplifies debugging other
|
||||||
@# programs, I\'ll live with the noise.
|
@# programs, I\'ll live with the noise.
|
||||||
|
|
|
@ -44,7 +44,7 @@ stage2/%.o: stage2/%.s
|
||||||
stage2/%$(X): stage2/%.o $(SREQ1)
|
stage2/%$(X): stage2/%.o $(SREQ1)
|
||||||
@$(call E, link [gcc]: $@)
|
@$(call E, link [gcc]: $@)
|
||||||
$(Q)gcc $(CFG_GCCISH_CFLAGS) stage2/glue.o -o $@ $< \
|
$(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
|
@# dsymutil sometimes fails or prints a warning, but the
|
||||||
@# program still runs. Since it simplifies debugging other
|
@# program still runs. Since it simplifies debugging other
|
||||||
@# programs, I\'ll live with the noise.
|
@# programs, I\'ll live with the noise.
|
||||||
|
|
|
@ -44,7 +44,7 @@ stage3/%.o: stage3/%.s
|
||||||
stage3/%$(X): stage3/%.o $(SREQ2)
|
stage3/%$(X): stage3/%.o $(SREQ2)
|
||||||
@$(call E, link [gcc]: $@)
|
@$(call E, link [gcc]: $@)
|
||||||
$(Q)gcc $(CFG_GCCISH_CFLAGS) stage3/glue.o -o $@ $< \
|
$(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
|
@# dsymutil sometimes fails or prints a warning, but the
|
||||||
@# program still runs. Since it simplifies debugging other
|
@# program still runs. Since it simplifies debugging other
|
||||||
@# programs, I\'ll live with the noise.
|
@# programs, I\'ll live with the noise.
|
||||||
|
|
|
@ -185,7 +185,7 @@ compile-check: tidy \
|
||||||
%.stage0$(X): %.stage0.o $(SREQ0)
|
%.stage0$(X): %.stage0.o $(SREQ0)
|
||||||
@$(call E, link [gcc]: $@)
|
@$(call E, link [gcc]: $@)
|
||||||
$(Q)gcc $(CFG_GCCISH_CFLAGS) stage1/glue.o -o $@ $< \
|
$(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
|
@# dsymutil sometimes fails or prints a warning, but the
|
||||||
@# program still runs. Since it simplifies debugging other
|
@# program still runs. Since it simplifies debugging other
|
||||||
@# programs, I\'ll live with the noise.
|
@# programs, I\'ll live with the noise.
|
||||||
|
@ -194,7 +194,7 @@ compile-check: tidy \
|
||||||
%.stage1$(X): %.stage1.o $(SREQ1)
|
%.stage1$(X): %.stage1.o $(SREQ1)
|
||||||
@$(call E, link [gcc]: $@)
|
@$(call E, link [gcc]: $@)
|
||||||
$(Q)gcc $(CFG_GCCISH_CFLAGS) stage2/glue.o -o $@ $< \
|
$(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
|
@# dsymutil sometimes fails or prints a warning, but the
|
||||||
@# program still runs. Since it simplifies debugging other
|
@# program still runs. Since it simplifies debugging other
|
||||||
@# programs, I\'ll live with the noise.
|
@# programs, I\'ll live with the noise.
|
||||||
|
@ -203,7 +203,7 @@ compile-check: tidy \
|
||||||
%.stage2$(X): %.stage2.o $(SREQ2)
|
%.stage2$(X): %.stage2.o $(SREQ2)
|
||||||
@$(call E, link [gcc]: $@)
|
@$(call E, link [gcc]: $@)
|
||||||
$(Q)gcc $(CFG_GCCISH_CFLAGS) stage3/glue.o -o $@ $< \
|
$(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
|
@# dsymutil sometimes fails or prints a warning, but the
|
||||||
@# program still runs. Since it simplifies debugging other
|
@# program still runs. Since it simplifies debugging other
|
||||||
@# programs, I\'ll live with the noise.
|
@# programs, I\'ll live with the noise.
|
||||||
|
|
|
@ -1,8 +1,18 @@
|
||||||
import driver::session;
|
import driver::session;
|
||||||
import lib::llvm::llvm;
|
import lib::llvm::llvm;
|
||||||
import middle::trans;
|
import middle::trans;
|
||||||
|
import middle::metadata;
|
||||||
|
import middle::ty;
|
||||||
import std::str;
|
import std::str;
|
||||||
import std::fs;
|
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::ModuleRef;
|
||||||
import lib::llvm::llvm::ValueRef;
|
import lib::llvm::llvm::ValueRef;
|
||||||
|
@ -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) {
|
pp_mode ppm) {
|
||||||
auto def = tup(ast::local_crate, 0);
|
auto def = tup(ast::local_crate, 0);
|
||||||
auto p = front::parser::new_parser(sess, env, def, input, 0u, 0u);
|
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;
|
auto mode;
|
||||||
alt (ppm) {
|
alt (ppm) {
|
||||||
|
|
|
@ -6,6 +6,9 @@ import std::uint;
|
||||||
import std::term;
|
import std::term;
|
||||||
import std::io;
|
import std::io;
|
||||||
import std::map;
|
import std::map;
|
||||||
|
import std::option;
|
||||||
|
import std::option::some;
|
||||||
|
import std::option::none;
|
||||||
|
|
||||||
tag os {
|
tag os {
|
||||||
os_win32;
|
os_win32;
|
||||||
|
@ -48,9 +51,16 @@ fn span_to_str(span sp, codemap::codemap cm) -> str {
|
||||||
lo.col, hi.line, hi.col));
|
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) {
|
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()) {
|
if (term::color_supported()) {
|
||||||
term::fg(io::stdout().get_buf_writer(), color);
|
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) -> ! {
|
fn span_err(span sp, str msg) -> ! {
|
||||||
// FIXME: Use constants, but rustboot doesn't know how to export them.
|
// 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;
|
fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn err(str msg) -> ! {
|
fn err(str msg) -> ! {
|
||||||
log_err #fmt("error: %s", msg);
|
emit_diagnostic(none[span], msg, "error", 9u8, cm);
|
||||||
fail;
|
fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,29 +113,32 @@ state obj session(ast::crate_num cnum,
|
||||||
|
|
||||||
fn span_warn(span sp, str msg) {
|
fn span_warn(span sp, str msg) {
|
||||||
// FIXME: Use constants, but rustboot doesn't know how to export them.
|
// 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) {
|
fn span_note(span sp, str msg) {
|
||||||
// FIXME: Use constants, but rustboot doesn't know how to export them.
|
// 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) -> ! {
|
fn bug(str msg) -> ! {
|
||||||
log_err #fmt("error: internal compiler error %s", msg);
|
self.err(#fmt("internal compiler error %s", msg));
|
||||||
fail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn span_unimpl(span sp, str msg) -> ! {
|
fn span_unimpl(span sp, str msg) -> ! {
|
||||||
// FIXME: Use constants, but rustboot doesn't know how to export them.
|
self.span_bug(sp, "unimplemented " + msg);
|
||||||
emit_diagnostic(sp, "internal compiler error: unimplemented " + msg,
|
|
||||||
"error", 9u8, cm);
|
|
||||||
fail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unimpl(str msg) -> ! {
|
fn unimpl(str msg) -> ! {
|
||||||
log_err #fmt("error: unimplemented %s", msg);
|
self.bug("unimplemented " + msg);
|
||||||
fail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_external_crate(int num) -> crate_metadata {
|
fn get_external_crate(int num) -> crate_metadata {
|
||||||
|
|
|
@ -71,6 +71,11 @@ type crate = spanned[crate_];
|
||||||
type crate_ = rec(vec[@crate_directive] directives,
|
type crate_ = rec(vec[@crate_directive] directives,
|
||||||
_mod module);
|
_mod module);
|
||||||
|
|
||||||
|
tag meta_visibility {
|
||||||
|
export_meta;
|
||||||
|
local_meta;
|
||||||
|
}
|
||||||
|
|
||||||
tag crate_directive_ {
|
tag crate_directive_ {
|
||||||
cdir_expr(@expr);
|
cdir_expr(@expr);
|
||||||
// FIXME: cdir_let should be eliminated
|
// FIXME: cdir_let should be eliminated
|
||||||
|
@ -80,7 +85,7 @@ tag crate_directive_ {
|
||||||
cdir_src_mod(ident, option::t[filename]);
|
cdir_src_mod(ident, option::t[filename]);
|
||||||
cdir_dir_mod(ident, option::t[filename], vec[@crate_directive]);
|
cdir_dir_mod(ident, option::t[filename], vec[@crate_directive]);
|
||||||
cdir_view_item(@view_item);
|
cdir_view_item(@view_item);
|
||||||
cdir_meta(vec[@meta_item]);
|
cdir_meta(meta_visibility, vec[@meta_item]);
|
||||||
cdir_syntax(path);
|
cdir_syntax(path);
|
||||||
cdir_auth(path, _auth);
|
cdir_auth(path, _auth);
|
||||||
}
|
}
|
||||||
|
|
|
@ -418,9 +418,14 @@ fn eval_crate_directive(ctx cx,
|
||||||
vec::push[@ast::view_item](view_items, vi);
|
vec::push[@ast::view_item](view_items, vi);
|
||||||
}
|
}
|
||||||
|
|
||||||
case (ast::cdir_meta(?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);
|
cx.sess.add_metadata(mi);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case (ast::cdir_syntax(?pth)) {}
|
case (ast::cdir_syntax(?pth)) {}
|
||||||
case (ast::cdir_auth(?pth, ?eff)) {}
|
case (ast::cdir_auth(?pth, ?eff)) {}
|
||||||
|
|
|
@ -2362,10 +2362,14 @@ fn parse_crate_directive(&parser p) -> ast::crate_directive
|
||||||
expect(p, token::SEMI);
|
expect(p, token::SEMI);
|
||||||
ret spanned(lo, hi, ast::cdir_auth(n, a));
|
ret spanned(lo, hi, ast::cdir_auth(n, a));
|
||||||
} else if (eat_word(p, "meta")) {
|
} 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 mis = parse_meta(p);
|
||||||
auto hi = p.get_hi_pos();
|
auto hi = p.get_hi_pos();
|
||||||
expect(p, token::SEMI);
|
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")) {
|
} else if (eat_word(p, "mod")) {
|
||||||
auto id = parse_ident(p);
|
auto id = parse_ident(p);
|
||||||
auto file_opt = none[filename];
|
auto file_opt = none[filename];
|
||||||
|
|
|
@ -230,17 +230,6 @@ mod Encode {
|
||||||
}
|
}
|
||||||
case (ty::ty_type) {w.write_char('Y');}
|
case (ty::ty_type) {w.write_char('Y');}
|
||||||
case (ty::ty_task) {w.write_char('a');}
|
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ import std::map::hashmap;
|
||||||
import std::option;
|
import std::option;
|
||||||
import std::option::some;
|
import std::option::some;
|
||||||
import std::option::none;
|
import std::option::none;
|
||||||
|
import std::fs;
|
||||||
|
|
||||||
import front::ast;
|
import front::ast;
|
||||||
import front::creader;
|
import front::creader;
|
||||||
|
@ -62,6 +63,15 @@ import lib::llvm::False;
|
||||||
import lib::llvm::True;
|
import lib::llvm::True;
|
||||||
import lib::llvm::Bool;
|
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) {
|
state obj namegen(mutable int i) {
|
||||||
fn next(str prefix) -> str {
|
fn next(str prefix) -> str {
|
||||||
i += 1;
|
i += 1;
|
||||||
|
@ -119,6 +129,9 @@ state type crate_ctxt = rec(session::session sess,
|
||||||
@ast::native_item] native_items,
|
@ast::native_item] native_items,
|
||||||
hashmap[ast::def_id, str] item_symbols,
|
hashmap[ast::def_id, str] item_symbols,
|
||||||
mutable option::t[ValueRef] main_fn,
|
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]
|
// TODO: hashmap[tup(tag_id,subtys), @tag_info]
|
||||||
hashmap[ty::t, uint] tag_sizes,
|
hashmap[ty::t, uint] tag_sizes,
|
||||||
hashmap[ast::def_id, ValueRef] discrims,
|
hashmap[ast::def_id, ValueRef] discrims,
|
||||||
|
@ -313,70 +326,6 @@ fn extend_path(@local_ctxt cx, &str name) -> @local_ctxt {
|
||||||
ret @rec(path = cx.path + [name] with *cx);
|
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 {
|
fn res(@block_ctxt bcx, ValueRef val) -> result {
|
||||||
ret rec(bcx = bcx,
|
ret rec(bcx = bcx,
|
||||||
val = val);
|
val = val);
|
||||||
|
@ -955,10 +904,6 @@ fn type_of_inner(&@crate_ctxt cx, &span sp, &ty::t t) -> TypeRef {
|
||||||
case (ty::ty_param(_)) {
|
case (ty::ty_param(_)) {
|
||||||
llty = T_i8();
|
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)); }
|
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));
|
auto tup_ty = simplify_type(cx, ty::mk_imm_tup(cx.tcx, variant.args));
|
||||||
|
|
||||||
// Perform any type parameter substitutions.
|
// 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);
|
tup_ty = ty::substitute_type_params(cx.tcx, subtys, tup_ty);
|
||||||
|
|
||||||
// Here we possibly do a recursive call.
|
// 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] raw_tys = variant.args;
|
||||||
let vec[ty::t] tys = [];
|
let vec[ty::t] tys = [];
|
||||||
for (ty::t raw_ty in raw_tys) {
|
for (ty::t raw_ty in raw_tys) {
|
||||||
auto t = ty::bind_params_in_type(cx.fcx.lcx.ccx.tcx,
|
auto t = ty::substitute_type_params(cx.fcx.lcx.ccx.tcx,
|
||||||
raw_ty);
|
tps, raw_ty);
|
||||||
t = ty::substitute_type_params(cx.fcx.lcx.ccx.tcx, tps,
|
|
||||||
t);
|
|
||||||
tys += [t];
|
tys += [t];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1604,9 +1546,8 @@ fn GEP_tag(@block_ctxt cx,
|
||||||
auto i = 0;
|
auto i = 0;
|
||||||
let vec[ty::t] true_arg_tys = [];
|
let vec[ty::t] true_arg_tys = [];
|
||||||
for (ty::t aty in arg_tys) {
|
for (ty::t aty in arg_tys) {
|
||||||
auto arg_ty = ty::bind_params_in_type(cx.fcx.lcx.ccx.tcx, aty);
|
auto arg_ty = ty::substitute_type_params(cx.fcx.lcx.ccx.tcx,
|
||||||
arg_ty = ty::substitute_type_params(cx.fcx.lcx.ccx.tcx, ty_substs,
|
ty_substs, aty);
|
||||||
arg_ty);
|
|
||||||
true_arg_tys += [arg_ty];
|
true_arg_tys += [arg_ty];
|
||||||
if (i == ix) {
|
if (i == ix) {
|
||||||
elem_ty = arg_ty;
|
elem_ty = arg_ty;
|
||||||
|
@ -1914,10 +1855,10 @@ fn declare_tydesc(&@local_ctxt cx, &span sp, &ty::t t,
|
||||||
|
|
||||||
auto name;
|
auto name;
|
||||||
if (cx.ccx.sess.get_opts().debuginfo) {
|
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);
|
name = sanitize(name);
|
||||||
} else {
|
} 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),
|
auto gvar = llvm::LLVMAddGlobal(ccx.llmod, T_tydesc(ccx.tn),
|
||||||
|
@ -1948,10 +1889,12 @@ fn declare_generic_glue(&@local_ctxt cx,
|
||||||
&str name) -> ValueRef {
|
&str name) -> ValueRef {
|
||||||
auto fn_nm;
|
auto fn_nm;
|
||||||
if (cx.ccx.sess.get_opts().debuginfo) {
|
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);
|
fn_nm = sanitize(fn_nm);
|
||||||
} else {
|
} 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);
|
auto llfn = decl_fastcall_fn(cx.ccx.llmod, fn_nm, llfnty);
|
||||||
set_glue_inlining(cx, llfn, t);
|
set_glue_inlining(cx, llfn, t);
|
||||||
|
@ -2794,10 +2737,8 @@ fn iter_structural_ty_full(&@block_ctxt cx,
|
||||||
auto llfldp_b = rslt.val;
|
auto llfldp_b = rslt.val;
|
||||||
variant_cx = rslt.bcx;
|
variant_cx = rslt.bcx;
|
||||||
|
|
||||||
auto ty_subst = ty::bind_params_in_type(
|
auto ty_subst = ty::substitute_type_params(
|
||||||
cx.fcx.lcx.ccx.tcx, a.ty);
|
cx.fcx.lcx.ccx.tcx, tps, a.ty);
|
||||||
ty_subst = ty::substitute_type_params(
|
|
||||||
cx.fcx.lcx.ccx.tcx, tps, ty_subst);
|
|
||||||
|
|
||||||
auto llfld_a =
|
auto llfld_a =
|
||||||
load_if_immediate(variant_cx,
|
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);
|
v1 = load_if_immediate(cx, v1, t1);
|
||||||
}
|
}
|
||||||
case (_) {
|
case (_) { break; }
|
||||||
ret res(cx, v1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fail; // fools the return-checker
|
ret res(cx, v1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn autoderefed_ty(&@crate_ctxt ccx, &ty::t t) -> ty::t {
|
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)) {
|
case (ty::ty_box(?mt)) {
|
||||||
t1 = mt.ty;
|
t1 = mt.ty;
|
||||||
}
|
}
|
||||||
case (_) {
|
case (_) { break; }
|
||||||
ret t1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fail; // fools the return-checker
|
ret t1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trans_binary(&@block_ctxt cx, ast::binop op,
|
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
|
// 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);
|
ann);
|
||||||
if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, expr_ty)) {
|
if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, expr_ty)) {
|
||||||
expr_llty = T_typaram_ptr(cx.fcx.lcx.ccx.tn);
|
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.
|
// 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' arg entering the body function is a fake env member (as in
|
||||||
// the env-part of the normal rust calling convention) that actually
|
// 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)) {
|
case (ast::pat_lit(?lt, ?ann)) {
|
||||||
auto lllit = trans_lit(cx.fcx.lcx.ccx, *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 lleq = trans_compare(cx, ast::eq, lltype, llval, lllit);
|
||||||
|
|
||||||
auto matched_cx = new_sub_block_ctxt(lleq.bcx, "matched_cx");
|
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);
|
cx.build.CondBr(lleq, matched_cx.llbb, next_cx.llbb);
|
||||||
|
|
||||||
auto ty_params =
|
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) {
|
if (vec::len[@ast::pat](subpats) > 0u) {
|
||||||
auto llblobptr = matched_cx.build.GEP(lltagptr,
|
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 llblobptr = cx.build.GEP(lltagptr, [C_int(0), C_int(1)]);
|
||||||
|
|
||||||
auto ty_param_substs =
|
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 this_cx = cx;
|
||||||
auto i = 0;
|
auto i = 0;
|
||||||
|
@ -4405,7 +4343,7 @@ fn trans_alt(&@block_ctxt cx, &@ast::expr expr,
|
||||||
"non-exhaustive match failure");
|
"non-exhaustive match failure");
|
||||||
|
|
||||||
// FIXME: This isn't quite right, particularly re: dynamic types
|
// 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;
|
auto expr_llty;
|
||||||
if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, expr_ty)) {
|
if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, expr_ty)) {
|
||||||
expr_llty = T_typaram_ptr(cx.fcx.lcx.ccx.tn);
|
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);
|
lv = trans_external_path(cx, fn_id, tpt);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto tys = ty::ann_to_type_params(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.node_types, ann);
|
auto monoty = ty::ann_to_type(cx.fcx.lcx.ccx.tcx, ann);
|
||||||
|
|
||||||
if (vec::len[ty::t](tys) != 0u) {
|
if (vec::len[ty::t](tys) != 0u) {
|
||||||
auto bcx = lv.res.bcx;
|
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
|
// Construct a thunk-call with signature incoming_fty, and that copies
|
||||||
// args forward into a call to outgoing_fty:
|
// 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,
|
let TypeRef llthunk_ty = get_pair_fn_ty(type_of(cx.ccx, sp,
|
||||||
incoming_fty));
|
incoming_fty));
|
||||||
let ValueRef llthunk = decl_internal_fastcall_fn(cx.ccx.llmod,
|
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,
|
auto args_res = trans_args(f_res.res.bcx,
|
||||||
llenv, f_res.llobj,
|
llenv, f_res.llobj,
|
||||||
f_res.generic,
|
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 {
|
fn trans_log(int lvl, &@block_ctxt cx, &@ast::expr e) -> result {
|
||||||
auto lcx = cx.fcx.lcx;
|
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;
|
auto global;
|
||||||
if (lcx.ccx.module_data.contains_key(modname)) {
|
if (lcx.ccx.module_data.contains_key(modname)) {
|
||||||
global = lcx.ccx.module_data.get(modname);
|
global = lcx.ccx.module_data.get(modname);
|
||||||
} else {
|
} else {
|
||||||
global = llvm::LLVMAddGlobal(lcx.ccx.llmod, T_int(),
|
auto s =
|
||||||
str::buf("_rust_mod_log_" + modname));
|
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::LLVMSetGlobalConstant(global, False);
|
||||||
llvm::LLVMSetInitializer(global, C_null(T_int()));
|
llvm::LLVMSetInitializer(global, C_null(T_int()));
|
||||||
llvm::LLVMSetLinkage(global, lib::llvm::LLVMInternalLinkage
|
llvm::LLVMSetLinkage(global, lib::llvm::LLVMInternalLinkage
|
||||||
|
@ -6240,7 +6184,7 @@ fn mk_spawn_wrapper(&@block_ctxt cx,
|
||||||
|
|
||||||
// TODO: construct a name based on tname
|
// TODO: construct a name based on tname
|
||||||
let str wrap_name =
|
let str wrap_name =
|
||||||
mangle_name_by_path_and_seq(cx.fcx.lcx.ccx,
|
mangle_internal_name_by_path_and_seq(cx.fcx.lcx.ccx,
|
||||||
cx.fcx.lcx.path,
|
cx.fcx.lcx.path,
|
||||||
"spawn_wrapper");
|
"spawn_wrapper");
|
||||||
auto llfndecl = decl_fastcall_fn(llmod, wrap_name,
|
auto llfndecl = decl_fastcall_fn(llmod, wrap_name,
|
||||||
|
@ -6720,7 +6664,7 @@ fn new_local_ctxt(&@crate_ctxt ccx) -> @local_ctxt {
|
||||||
let vec[ast::ty_param] obj_typarams = [];
|
let vec[ast::ty_param] obj_typarams = [];
|
||||||
let vec[ast::obj_field] obj_fields = [];
|
let vec[ast::obj_field] obj_fields = [];
|
||||||
ret @rec(path=pth,
|
ret @rec(path=pth,
|
||||||
module_path=[crate_name(ccx, "main")],
|
module_path=[ccx.crate_meta_name],
|
||||||
obj_typarams = obj_typarams,
|
obj_typarams = obj_typarams,
|
||||||
obj_fields = obj_fields,
|
obj_fields = obj_fields,
|
||||||
ccx = ccx);
|
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] {
|
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, _, _)) {
|
case (ty::ty_fn(_, ?arg_tys, _, _)) {
|
||||||
ret 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 {
|
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) {
|
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",
|
let @local_ctxt mcx = @rec(path = cx.path + ["method",
|
||||||
m.node.ident] with *cx);
|
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,
|
let ValueRef llfn = decl_internal_fastcall_fn(cx.ccx.llmod, s,
|
||||||
llfnty);
|
llfnty);
|
||||||
cx.ccx.item_ids.insert(m.node.id, llfn);
|
cx.ccx.item_ids.insert(m.node.id, llfn);
|
||||||
|
@ -7107,7 +7051,8 @@ fn create_vtbl(@local_ctxt cx,
|
||||||
methods += [llfn];
|
methods += [llfn];
|
||||||
}
|
}
|
||||||
auto vtbl = C_struct(methods);
|
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),
|
auto gvar = llvm::LLVMAddGlobal(cx.ccx.llmod, val_ty(vtbl),
|
||||||
str::buf(vtbl_name));
|
str::buf(vtbl_name));
|
||||||
llvm::LLVMSetInitializer(gvar, vtbl);
|
llvm::LLVMSetInitializer(gvar, vtbl);
|
||||||
|
@ -7124,7 +7069,7 @@ fn trans_dtor(@local_ctxt cx,
|
||||||
&@ast::method dtor) -> ValueRef {
|
&@ast::method dtor) -> ValueRef {
|
||||||
|
|
||||||
auto llfnty = T_dtor(cx.ccx, dtor.span, llself_ty);
|
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);
|
let ValueRef llfn = decl_internal_fastcall_fn(cx.ccx.llmod, s, llfnty);
|
||||||
cx.ccx.item_ids.insert(dtor.node.id, llfn);
|
cx.ccx.item_ids.insert(dtor.node.id, llfn);
|
||||||
cx.ccx.item_symbols.insert(dtor.node.id, s);
|
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.
|
// 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);
|
let ValueRef llfn = decl_internal_fastcall_fn(ccx.llmod, s, llfty);
|
||||||
|
|
||||||
// Declare the global constant pair that points to it.
|
// 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);
|
register_fn_pair(ccx, ps, llpairty, llfn, id);
|
||||||
|
|
||||||
if (str::eq(vec::top(path), "main") &&
|
if (is_main) {
|
||||||
!ccx.sess.get_opts().shared) {
|
|
||||||
if (ccx.main_fn != none[ValueRef]) {
|
if (ccx.main_fn != none[ValueRef]) {
|
||||||
ccx.sess.span_err(sp, "multiple 'main' functions");
|
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);
|
ccx.main_fn = some(llfn);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_fn_pair(&@crate_ctxt cx, str ps, TypeRef llpairty, ValueRef 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) {
|
alt (native_item.node) {
|
||||||
case (ast::native_item_ty(_,_)) {
|
case (ast::native_item_ty(_,_)) {
|
||||||
cx.sess.bug("decl_native_fn_and_pair(): native fn isn't " +
|
cx.sess.bug("decl_native_fn_and_pair(): native fn isn't " +
|
||||||
"actually a fn?!");
|
"actually a fn");
|
||||||
}
|
}
|
||||||
case (ast::native_item_fn(_, _, _, ?tps, _, _)) {
|
case (ast::native_item_fn(_, _, _, ?tps, _, _)) {
|
||||||
count = vec::len[ast::ty_param](tps);
|
count = vec::len[ast::ty_param](tps);
|
||||||
|
@ -7592,14 +7543,15 @@ fn decl_native_fn_and_pair(&@crate_ctxt ccx,
|
||||||
|
|
||||||
// Declare the wrapper.
|
// Declare the wrapper.
|
||||||
auto t = node_ann_type(ccx, ann);
|
auto t = node_ann_type(ccx, ann);
|
||||||
|
|
||||||
auto wrapper_type = native_fn_wrapper_type(ccx, sp, num_ty_param, t);
|
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,
|
let ValueRef wrapper_fn = decl_internal_fastcall_fn(ccx.llmod, s,
|
||||||
wrapper_type);
|
wrapper_type);
|
||||||
|
|
||||||
// Declare the global constant pair that points to it.
|
// Declare the global constant pair that points to it.
|
||||||
auto wrapper_pair_type = T_fn_pair(ccx.tn, wrapper_type);
|
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);
|
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 discrim_val = C_int(i as int);
|
||||||
|
|
||||||
auto p = wcx.path + [ident, variant.node.name, "discrim"];
|
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(),
|
auto discrim_gvar = llvm::LLVMAddGlobal(ccx.llmod, T_int(),
|
||||||
str::buf(s));
|
str::buf(s));
|
||||||
|
|
||||||
|
@ -7956,7 +7908,7 @@ fn trans_constant(&@crate_ctxt ccx, @walk_ctxt wcx, &@ast::item it) {
|
||||||
// with consts.
|
// with consts.
|
||||||
auto v = C_int(1);
|
auto v = C_int(1);
|
||||||
ccx.item_ids.insert(cid, v);
|
ccx.item_ids.insert(cid, v);
|
||||||
auto s = mangle_name_by_type(ccx, wcx.path + [name],
|
auto s = mangle_exported_name(ccx, wcx.path + [name],
|
||||||
node_ann_type(ccx, ann));
|
node_ann_type(ccx, ann));
|
||||||
ccx.item_symbols.insert(cid, s);
|
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));
|
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] {
|
fn declare_intrinsics(ModuleRef llmod) -> hashmap[str,ValueRef] {
|
||||||
|
|
||||||
let vec[TypeRef] T_memmove32_args = [T_ptr(T_i8()), T_ptr(T_i8()),
|
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 maptype = T_array(elttype, ccx.module_data.size() + 1u);
|
||||||
auto map = llvm::LLVMAddGlobal(ccx.llmod, maptype,
|
auto map = llvm::LLVMAddGlobal(ccx.llmod, maptype,
|
||||||
str::buf("_rust_mod_map"));
|
str::buf("_rust_mod_map"));
|
||||||
llvm::LLVMSetLinkage(map, lib::llvm::LLVMInternalLinkage
|
|
||||||
as llvm::Linkage);
|
|
||||||
let vec[ValueRef] elts = [];
|
let vec[ValueRef] elts = [];
|
||||||
for each (@tup(str, ValueRef) item in ccx.module_data.items()) {
|
for each (@tup(str, ValueRef) item in ccx.module_data.items()) {
|
||||||
auto elt = C_struct([p2i(C_cstr(ccx, item._0)), p2i(item._1)]);
|
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;
|
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
|
// FIXME use hashed metadata instead of crate names once we have that
|
||||||
fn create_crate_map(&@crate_ctxt ccx) -> ValueRef {
|
fn create_crate_map(&@crate_ctxt ccx) -> ValueRef {
|
||||||
let vec[ValueRef] subcrates = [];
|
let vec[ValueRef] subcrates = [];
|
||||||
|
@ -8245,7 +8141,13 @@ fn create_crate_map(&@crate_ctxt ccx) -> ValueRef {
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
vec::push[ValueRef](subcrates, C_int(0));
|
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 arrtype = T_array(T_int(), vec::len[ValueRef](subcrates));
|
||||||
auto maptype = T_struct([T_int(), arrtype]);
|
auto maptype = T_struct([T_int(), arrtype]);
|
||||||
auto map = llvm::LLVMAddGlobal(ccx.llmod, maptype, str::buf(sym_name));
|
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 sha1s = map::mk_hashmap[ty::t,str](hasher, eqer);
|
||||||
auto abbrevs = map::mk_hashmap[ty::t,metadata::ty_abbrev](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 short_names = map::mk_hashmap[ty::t,str](hasher, eqer);
|
||||||
|
auto sha = std::sha1::mk_sha1();
|
||||||
auto ccx = @rec(sess = sess,
|
auto ccx = @rec(sess = sess,
|
||||||
llmod = llmod,
|
llmod = llmod,
|
||||||
td = td,
|
td = td,
|
||||||
|
@ -8291,6 +8193,10 @@ fn trans_crate(&session::session sess, &@ast::crate crate,
|
||||||
native_items = new_def_hash[@ast::native_item](),
|
native_items = new_def_hash[@ast::native_item](),
|
||||||
item_symbols = new_def_hash[str](),
|
item_symbols = new_def_hash[str](),
|
||||||
mutable main_fn = none[ValueRef],
|
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,
|
tag_sizes = tag_sizes,
|
||||||
discrims = new_def_hash[ValueRef](),
|
discrims = new_def_hash[ValueRef](),
|
||||||
discrim_symbols = new_def_hash[str](),
|
discrim_symbols = new_def_hash[str](),
|
||||||
|
@ -8302,7 +8208,7 @@ fn trans_crate(&session::session sess, &@ast::crate crate,
|
||||||
lltypes = lltypes,
|
lltypes = lltypes,
|
||||||
glues = glues,
|
glues = glues,
|
||||||
names = namegen(0),
|
names = namegen(0),
|
||||||
sha = std::sha1::mk_sha1(),
|
sha = sha,
|
||||||
type_sha1s = sha1s,
|
type_sha1s = sha1s,
|
||||||
type_abbrevs = abbrevs,
|
type_abbrevs = abbrevs,
|
||||||
type_short_names = short_names,
|
type_short_names = short_names,
|
||||||
|
@ -8322,8 +8228,16 @@ fn trans_crate(&session::session sess, &@ast::crate crate,
|
||||||
trans_constants(ccx, crate);
|
trans_constants(ccx, crate);
|
||||||
trans_mod(cx, crate.node.module);
|
trans_mod(cx, crate.node.module);
|
||||||
auto crate_map = create_crate_map(ccx);
|
auto crate_map = create_crate_map(ccx);
|
||||||
|
|
||||||
if (!sess.get_opts().shared) {
|
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);
|
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,
|
If it has a function type with a ! annotation,
|
||||||
the answer is noreturn. */
|
the answer is noreturn. */
|
||||||
fn controlflow_expr(&crate_ctxt ccx, @expr e) -> controlflow {
|
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)))) {
|
expr_ann(e)))) {
|
||||||
case (ty::ty_fn(_,_,_,?cf)) {
|
case (ty::ty_fn(_,_,_,?cf)) {
|
||||||
ret 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)) {
|
case (ast::cdir_view_item(?vi)) {
|
||||||
walk_view_item(v, vi);
|
walk_view_item(v, vi);
|
||||||
}
|
}
|
||||||
case (ast::cdir_meta(_)) {}
|
case (ast::cdir_meta(_,_)) {}
|
||||||
case (ast::cdir_syntax(_)) {}
|
case (ast::cdir_syntax(_)) {}
|
||||||
case (ast::cdir_auth(_, _)) {}
|
case (ast::cdir_auth(_, _)) {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -945,7 +945,7 @@ fn print_decl(&ps s, &@ast::decl decl) {
|
||||||
case (mo_untyped) { /* no-op */ }
|
case (mo_untyped) { /* no-op */ }
|
||||||
case (mo_typed(?tcx)) {
|
case (mo_typed(?tcx)) {
|
||||||
auto lty =
|
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));
|
word_space(s, ty::ty_to_str(tcx, lty));
|
||||||
}
|
}
|
||||||
case (mo_identified) { /* no-op */ }
|
case (mo_identified) { /* no-op */ }
|
||||||
|
|
|
@ -19,6 +19,20 @@ fn dirname(path p) -> path {
|
||||||
ret str::substr(p, 0u, i as uint);
|
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
|
// FIXME: Need some typestate to avoid bounds check when len(pre) == 0
|
||||||
fn connect(path pre, path post) -> path {
|
fn connect(path pre, path post) -> path {
|
||||||
auto len = str::byte_len(pre);
|
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);
|
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",
|
meta (name = "std",
|
||||||
desc = "Rust standard library",
|
vers = "0.1",
|
||||||
uuid = "122bed0b-c19b-4b82-b0b7-7ae8aead7297",
|
uuid = "122bed0b-c19b-4b82-b0b7-7ae8aead7297",
|
||||||
url = "http://rust-lang.org/src/std",
|
url = "http://rust-lang.org/src/std");
|
||||||
ver = "0.0.1");
|
|
||||||
|
meta (comment = "Rust standard library",
|
||||||
|
license = "BSD");
|
||||||
|
|
||||||
// Built-in types support modules.
|
// Built-in types support modules.
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,12 @@ fn make_set(&ufind ufnd) -> uint {
|
||||||
ret idx;
|
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 {
|
fn find(&ufind ufnd, uint n) -> uint {
|
||||||
alt (ufnd.nodes.(n)) {
|
alt (ufnd.nodes.(n)) {
|
||||||
case (none) { ret 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.
|
// Removes all sets with IDs greater than or equal to the given value.
|
||||||
fn prune(&ufind ufnd, uint n) {
|
fn prune(&ufind ufnd, uint n) {
|
||||||
// TODO: Use "slice" once we get rid of "mutable?"
|
// 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);
|
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 ge(uint x, uint y) -> bool { ret x >= y; }
|
||||||
fn gt(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 {
|
iter range(uint lo, uint hi) -> uint {
|
||||||
auto lo_ = lo;
|
auto lo_ = lo;
|
||||||
while (lo_ < hi) {
|
while (lo_ < hi) {
|
||||||
|
|
|
@ -210,7 +210,7 @@ fn unshift[T](&mutable array[T] v, &T t) {
|
||||||
v = res;
|
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;
|
let uint i = n;
|
||||||
while (i > 0u) {
|
while (i > 0u) {
|
||||||
i -= 1u;
|
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);
|
auto length = vec::len(v);
|
||||||
if (index >= length) {
|
if (index >= length) {
|
||||||
grow(v, index - length + 1u, initval);
|
grow(v, index - length + 1u, initval);
|
||||||
|
@ -393,6 +393,12 @@ fn reversed[T](vec[T] v) -> vec[T] {
|
||||||
ret res;
|
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:
|
// Local Variables:
|
||||||
// mode: rust;
|
// mode: rust;
|
||||||
// fill-column: 78;
|
// 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
|
S 2011-06-03 f29d046
|
||||||
linux-i386 76e4ee5b9148aae30ebfaabb12791bfee4fa8727
|
linux-i386 76e4ee5b9148aae30ebfaabb12791bfee4fa8727
|
||||||
macos-i386 e146fa18f4b0f22fe4fd7fd104242837569d7702
|
macos-i386 e146fa18f4b0f22fe4fd7fd104242837569d7702
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
// error-pattern:unknown syntax expander
|
// error-pattern:unknown syntax expander
|
||||||
fn main() {
|
fn main() {
|
||||||
#iamnotanextensionthatexists("");
|
#iamnotanextensionthatexists("");
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// xfail-stage0
|
// xfail-stage0
|
||||||
|
|
||||||
// error-pattern:Ambiguous type
|
// error-pattern:cannot determine a type
|
||||||
fn main() -> () {
|
fn main() -> () {
|
||||||
auto foo = [];
|
auto foo = [];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue