Skip to content

Make the macro system more modular. #451

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 64 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
2e4f7a2
Make the macro system more modular.
paulstansifer Jun 3, 2011
72e11fd
"macro" -> "syntax extension" for now
paulstansifer Jun 4, 2011
9a65c16
rustc: Typecheck patterns from the top down; remove pushdown_pat
pcwalton Jun 3, 2011
c974cc3
Removing redundant "fail"s.
lkuper Jun 3, 2011
c94c9e8
Temporarily xfail compile-fail/pattern-tyvar
marijnh Jun 3, 2011
b3d6ead
Accept *foo as a pointer to foo.
cixtor Jun 3, 2011
d258852
Boilerplate for pointers. Sorry for missing this on the first patch.
cixtor Jun 3, 2011
92e246a
Parse pointers in metadata.
cixtor Jun 3, 2011
99ccd02
Tidy up printing of ty_fn.
graydon Jun 3, 2011
60d730f
Add spans to fields, args, methods. Improve pp of same.
graydon Jun 3, 2011
884acab
rustc: Add a "smallintmap" implementation
pcwalton Jun 3, 2011
86c3e16
Comments and cleanup.
lkuper Jun 4, 2011
c66ffa0
More comments.
lkuper Jun 4, 2011
7d02fb4
Make pp more conservative about inserting trailing comments mid-list.
graydon Jun 4, 2011
c41eada
Remove zerobreak between foo and ( on a call expr. Never looks right.
graydon Jun 4, 2011
1c5f6c9
Register new snapshots.
graydon Jun 4, 2011
b55a99c
rustc: Introduce ext module. Move some things from parser to ext.
brson Jun 4, 2011
462e47e
rustc: Pass the correct span to syntax extensions
brson Jun 4, 2011
cd88b51
rustc: Return the correct span from parse_seq
brson Jun 4, 2011
3e72b23
rustc: Use spans on extfmt error messages
brson Jun 4, 2011
fe51cee
rustc: Add a span_unimpl method to ext_ctxt
brson Jun 4, 2011
457b6ba
rustc: Report unimplemented #fmt features with spans
brson Jun 4, 2011
dac75ff
rustc: Use spans for #env errors
brson Jun 4, 2011
a77cc7f
rustc: Add a next_ann method to ext_ctxt
brson Jun 4, 2011
81899ce
rustc: Generate extension annotations from ext_ctxt instead of parser
brson Jun 4, 2011
6b2a8cd
rustc: Hide the parser from syntax extensions
brson Jun 4, 2011
6689e57
rustc: Reenable debug logging in extfmt
brson Jun 4, 2011
5a9aa5f
stdlib: Use spans for #fmt errors originating in std
brson Jun 4, 2011
ba0044a
Remove redundant 'fail' exprs and dead code; use sess.bug or
lkuper Jun 5, 2011
103317d
Adding comments; removing dead code.
lkuper Jun 5, 2011
bcfa0d1
rustc: Make resolve::unresolved return !. Remove redundant fails
brson Jun 5, 2011
3d165ba
Change unsafe aliases
marijnh Jun 6, 2011
bc8fcf1
First take on an alias-safety checker
marijnh Jun 6, 2011
543717e
Implement enough support for pointer to get an identity function work…
cixtor Jun 6, 2011
70b1d6e
Begin tidying up name-mangling rules.
graydon Jun 6, 2011
7458a07
Add multiline, whitespace-eating strings.
jdm Jun 7, 2011
5251ea5
Don't put a copy of main (the C one) in each binary we produce. This …
cixtor Jun 7, 2011
1d2f0e5
Removing dead code and redundant fails; changing fails to sess.bug
lkuper Jun 7, 2011
9a2546f
For consistency, use ctxt instead of ty_ctxt outside of unify.
lkuper Jun 7, 2011
bc0ea91
Update the snapshot.
cixtor Jun 8, 2011
7d47d93
More work on proper linkage name-mangling. Almost right, aside from v…
graydon Jun 8, 2011
4b3755b
rustc: Use a set-based approach to unification; remove ty_bound_param…
pcwalton May 21, 2011
2200d6e
rustc: Print out a real error message on unresolved types. Puts out b…
pcwalton Jun 8, 2011
fa306d7
Add optional message to fail.
jdm Jun 8, 2011
64c0631
authors: Add Josh Matthews to AUTHORS
pcwalton Jun 8, 2011
04ffefb
Use main.o directly now that stage0 is ok with it.
cixtor Jun 8, 2011
9bedc39
Don't force the fetch of main.o from main.a, we are not using main.a …
cixtor Jun 8, 2011
dc39dd4
rustc: Remove all traces of the unification cache
pcwalton Jun 8, 2011
b33bf32
Update rust to build with newer llvm versions.
cixtor May 24, 2011
ba6f670
rustc: Remove pushdown. 15 second improvement.
pcwalton Jun 8, 2011
0dafbf6
test: Add a test case for issue #362, "ret none".
pcwalton Jun 8, 2011
1a880df
Register new snapshots.
graydon Jun 8, 2011
bc59dfa
rustc: Add some miscellaneous demands that pushdown had previously ca…
pcwalton Jun 8, 2011
1689650
rustc: Use cnames in ty_to_str again; debugging code crept in
pcwalton Jun 8, 2011
53248ce
Tidy up 'export meta' situation now that snapshot understands it.
graydon Jun 8, 2011
1a72745
rustc: Don't generate so many variables when typechecking functions; …
pcwalton Jun 9, 2011
9eb4081
rustc: Make resolve_all_vars() check to see whether the type actually…
pcwalton Jun 9, 2011
dbb3471
rustc: Fix error pattern in compile-fail/arg-count-mismatch.rs
pcwalton Jun 9, 2011
7b09e2d
rustc: Don't eagerly resolve type variables after unification
pcwalton Jun 9, 2011
da4e3b9
Add new visitor framework
marijnh Jun 8, 2011
5335ffd
Some more workarounds to please the alias checker
marijnh Jun 9, 2011
25b0338
Add vec::member
marijnh Jun 9, 2011
c70792d
A revised, improved alias-checker
marijnh Jun 7, 2011
b33fb68
Properly handle lifetime of aliases in nested blocks
marijnh Jun 9, 2011
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Jason Orendorff <[email protected]>
Jeff Balogh <[email protected]>
Jeff Muizelaar <[email protected]>
Jeffrey Yasskin <[email protected]>
Josh Matthews <[email protected]>
Kelly Wilson <[email protected]>
Lindsey Kuper <[email protected]>
Marijn Haverbeke <[email protected]>
Expand Down
6 changes: 3 additions & 3 deletions Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -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.o stage1/glue.o stage1/$(CFG_STDLIB)
SREQ1 := stage1/rustc$(X) $(LREQ) rt/main.o stage2/glue.o stage2/$(CFG_STDLIB)
SREQ2 := stage2/rustc$(X) $(LREQ) rt/main.o stage3/glue.o stage3/$(CFG_STDLIB)


######################################################################
Expand Down
1 change: 1 addition & 0 deletions mk/clean.mk
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ 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 -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 \
Expand Down
8 changes: 8 additions & 0 deletions mk/rt.mk
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ 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/%.o: rt/%.ll $(MKFILES)
@$(call E, llc: $@)
$(Q)$(LLC) -filetype=obj -relocation-model=pic -march=x86 -o $@ $<
Expand Down
2 changes: 1 addition & 1 deletion mk/stage1.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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.o -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.
Expand Down
2 changes: 1 addition & 1 deletion mk/stage2.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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.o -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.
Expand Down
4 changes: 2 additions & 2 deletions mk/stage3.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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.o -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.
Expand Down
6 changes: 3 additions & 3 deletions mk/tests.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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.o -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.
Expand All @@ -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.o -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.
Expand All @@ -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.o -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.
Expand Down
248 changes: 245 additions & 3 deletions src/comp/back/link.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -143,7 +153,6 @@ mod write {
True, // unit-at-a-time
True, // unroll loops
True, // simplify lib calls
True, // have exceptions
threshold); // inline threshold
}

Expand Down Expand Up @@ -218,3 +227,236 @@ 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) {
auto m = m_;
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:
//
Loading