Skip to content

Commit b5c7360

Browse files
committed
Merge remote branch 'graydon/master'
2 parents a078844 + 0857d22 commit b5c7360

30 files changed

+1619
-1499
lines changed

Makefile.in

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,9 @@ COMPILER_INPUTS := $(wildcard $(addprefix $(S)src/comp/, \
144144
######################################################################
145145

146146
LREQ := rt/$(CFG_RUNTIME) rustllvm/$(CFG_RUSTLLVM)
147-
SREQ0 := stage0/rustc$(X) $(LREQ) stage1/glue.o stage1/$(CFG_STDLIB)
148-
SREQ1 := stage1/rustc$(X) $(LREQ) stage2/glue.o stage2/$(CFG_STDLIB)
149-
SREQ2 := stage2/rustc$(X) $(LREQ) stage3/glue.o stage3/$(CFG_STDLIB)
147+
SREQ0 := stage0/rustc$(X) $(LREQ) rt/main.a stage1/glue.o stage1/$(CFG_STDLIB)
148+
SREQ1 := stage1/rustc$(X) $(LREQ) rt/main.a stage2/glue.o stage2/$(CFG_STDLIB)
149+
SREQ2 := stage2/rustc$(X) $(LREQ) rt/main.a stage3/glue.o stage3/$(CFG_STDLIB)
150150

151151

152152
######################################################################

mk/clean.mk

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ clean:
2828
$(Q)rm -f stage3/rustc$(X) stage3/$(CFG_STDLIB) stage3/glue*
2929
$(Q)rm -f rustllvm/$(CFG_RUSTLLVM) rustllvm/rustllvmbits.a
3030
$(Q)rm -f rt/$(CFG_RUNTIME)
31+
$(Q)rm -f rt/main.o
32+
$(Q)rm -f rt/main.a
3133
$(Q)rm -Rf $(PKG_NAME)-*.tar.gz dist
3234
$(Q)rm -f $(foreach ext,o a d bc s exe,$(wildcard stage*/*.$(ext)))
3335
$(Q)rm -Rf $(foreach ext,out out.tmp \

mk/rt.mk

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,18 @@ rt/%.o: rt/%.s $(MKFILES)
7676
@$(call E, compile: $@)
7777
$(Q)$(call CFG_COMPILE_C, $@, $(RUNTIME_INCS)) $<
7878

79+
ifdef CFG_WINDOWSY
80+
rt/main.ll: rt/main.ll.in
81+
sed 's/MAIN/WinMain@16/' < $^ > $@
82+
else
83+
rt/main.ll: rt/main.ll.in
84+
sed 's/MAIN/main/' < $^ > $@
85+
endif
86+
87+
rt/main.a: rt/main.o
88+
rm -f $@
89+
ar crs $@ $^
90+
7991
rt/%.o: rt/%.ll $(MKFILES)
8092
@$(call E, llc: $@)
8193
$(Q)$(LLC) -filetype=obj -relocation-model=pic -march=x86 -o $@ $<

mk/stage1.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ stage1/%.o: stage1/%.s
4444
stage1/%$(X): stage1/%.o $(SREQ0)
4545
@$(call E, link [gcc]: $@)
4646
$(Q)gcc $(CFG_GCCISH_CFLAGS) stage1/glue.o -o $@ $< \
47-
-Lstage1 -Lrustllvm -Lrt -lrustrt -lrustllvm -lstd -lm
47+
-Lstage1 -Lrustllvm -Lrt rt/main.a -lrustrt -lrustllvm -lstd -lm
4848
@# dsymutil sometimes fails or prints a warning, but the
4949
@# program still runs. Since it simplifies debugging other
5050
@# programs, I\'ll live with the noise.

mk/stage2.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ stage2/%.o: stage2/%.s
4444
stage2/%$(X): stage2/%.o $(SREQ1)
4545
@$(call E, link [gcc]: $@)
4646
$(Q)gcc $(CFG_GCCISH_CFLAGS) stage2/glue.o -o $@ $< \
47-
-Lstage2 -Lrustllvm -Lrt -lrustrt -lrustllvm -lstd -lm
47+
-Lstage2 -Lrustllvm -Lrt rt/main.a -lrustrt -lrustllvm -lstd -lm
4848
@# dsymutil sometimes fails or prints a warning, but the
4949
@# program still runs. Since it simplifies debugging other
5050
@# programs, I\'ll live with the noise.

mk/stage3.mk

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ stage3/rustc.o: $(COMPILER_CRATE) $(COMPILER_INPUTS) $(SREQ2)
2323
$(STAGE2) -c -o $@ $<
2424

2525
stage3/glue.o: stage2/rustc$(X) stage2/$(CFG_STDLIB) stage2/intrinsics.bc \
26-
rustllvm/$(CFG_RUSTLLVM) rt/$(CFG_RUNTIME)
26+
rustllvm/$(CFG_RUSTLLVM) rt/$(CFG_RUNTIME)
2727
@$(call E, generate: $@)
2828
$(STAGE2) -c -o $@ --glue
2929

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

mk/tests.mk

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ compile-check: tidy \
185185
%.stage0$(X): %.stage0.o $(SREQ0)
186186
@$(call E, link [gcc]: $@)
187187
$(Q)gcc $(CFG_GCCISH_CFLAGS) stage1/glue.o -o $@ $< \
188-
-Lstage1 -Lrt -lrustrt -lstd -lm
188+
-Lstage1 -Lrt rt/main.a -lrustrt -lstd -lm
189189
@# dsymutil sometimes fails or prints a warning, but the
190190
@# program still runs. Since it simplifies debugging other
191191
@# programs, I\'ll live with the noise.
@@ -194,7 +194,7 @@ compile-check: tidy \
194194
%.stage1$(X): %.stage1.o $(SREQ1)
195195
@$(call E, link [gcc]: $@)
196196
$(Q)gcc $(CFG_GCCISH_CFLAGS) stage2/glue.o -o $@ $< \
197-
-Lstage2 -Lrt -lrustrt -lstd -lm
197+
-Lstage2 -Lrt rt/main.a -lrustrt -lstd -lm
198198
@# dsymutil sometimes fails or prints a warning, but the
199199
@# program still runs. Since it simplifies debugging other
200200
@# programs, I\'ll live with the noise.
@@ -203,7 +203,7 @@ compile-check: tidy \
203203
%.stage2$(X): %.stage2.o $(SREQ2)
204204
@$(call E, link [gcc]: $@)
205205
$(Q)gcc $(CFG_GCCISH_CFLAGS) stage3/glue.o -o $@ $< \
206-
-Lstage3 -Lrt -lrustrt -lstd -lm
206+
-Lstage3 -Lrt rt/main.a -lrustrt -lstd -lm
207207
@# dsymutil sometimes fails or prints a warning, but the
208208
@# program still runs. Since it simplifies debugging other
209209
@# programs, I\'ll live with the noise.

src/comp/back/link.rs

Lines changed: 244 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
11
import driver::session;
22
import lib::llvm::llvm;
33
import middle::trans;
4+
import middle::metadata;
5+
import middle::ty;
46
import std::str;
57
import std::fs;
8+
import std::vec;
9+
import std::option;
10+
import option::some;
11+
import option::none;
12+
import std::sha1::sha1;
13+
import std::sort;
14+
import trans::crate_ctxt;
15+
import front::ast;
616

717
import lib::llvm::llvm::ModuleRef;
818
import lib::llvm::llvm::ValueRef;
@@ -49,7 +59,7 @@ fn link_intrinsics(session::session sess, ModuleRef llmod) {
4959

5060
auto linkres = llvm::LLVMLinkModules(llmod, llintrinsicsmod);
5161
llvm::LLVMDisposeModule(llintrinsicsmod);
52-
62+
5363
if (linkres == False) {
5464
llvm_err(sess, "couldn't link the module with the intrinsics");
5565
fail;
@@ -58,7 +68,7 @@ fn link_intrinsics(session::session sess, ModuleRef llmod) {
5868

5969
mod write {
6070
fn is_object_or_assembly_or_exe(output_type ot) -> bool {
61-
if ( (ot == output_type_assembly) ||
71+
if ( (ot == output_type_assembly) ||
6272
(ot == output_type_object) ||
6373
(ot == output_type_exe) ) {
6474
ret true;
@@ -218,3 +228,235 @@ mod write {
218228
}
219229
}
220230

231+
/*
232+
* Name mangling and its relationship to metadata. This is complex. Read
233+
* carefully.
234+
*
235+
* The semantic model of Rust linkage is, broadly, that "there's no global
236+
* namespace" between crates. Our aim is to preserve the illusion of this
237+
* model despite the fact that it's not *quite* possible to implement on
238+
* modern linkers. We initially didn't use system linkers at all, but have
239+
* been convinced of their utility.
240+
*
241+
* There are a few issues to handle:
242+
*
243+
* - Linkers operate on a flat namespace, so we have to flatten names.
244+
* We do this using the C++ namespace-mangling technique. Foo::bar
245+
* symbols and such.
246+
*
247+
* - Symbols with the same name but different types need to get different
248+
* linkage-names. We do this by hashing a string-encoding of the type into
249+
* a fixed-size (currently 16-byte hex) cryptographic hash function (CHF:
250+
* we use SHA1) to "prevent collisions". This is not airtight but 16 hex
251+
* digits on uniform probability means you're going to need 2**32 same-name
252+
* symbols in the same process before you're even hitting birthday-paradox
253+
* collision probability.
254+
*
255+
* - Symbols in dirrerent crates but with same names "within" the crate need
256+
* to get different linkage-names.
257+
*
258+
* So here is what we do:
259+
*
260+
* - Separate the meta tags into two sets: exported and local. Only work with
261+
* the exported ones when considering linkage.
262+
*
263+
* - Consider two exported tags as special (and madatory): name and vers.
264+
* Every crate gets them; if it doesn't name them explicitly we infer them
265+
* as basename(crate) and "0.1", respectively. Call these CNAME, CVERS.
266+
*
267+
* - Define CMETA as all the non-name, non-vers exported meta tags in the
268+
* crate (in sorted order).
269+
*
270+
* - Define CMH as hash(CMETA).
271+
*
272+
* - Compile our crate to lib CNAME-CMH-CVERS.so
273+
*
274+
* - Define STH(sym) as hash(CNAME, CMH, type_str(sym))
275+
*
276+
* - Suffix a mangled sym with ::STH@CVERS, so that it is unique in the
277+
* name, non-name metadata, and type sense, and versioned in the way
278+
* system linkers understand.
279+
*
280+
*/
281+
282+
283+
iter crate_export_metas(ast::crate c) -> @ast::meta_item {
284+
for (@ast::crate_directive cdir in c.node.directives) {
285+
alt (cdir.node) {
286+
case (ast::cdir_meta(?v, ?mis)) {
287+
if (v == ast::export_meta) {
288+
for (@ast::meta_item mi in mis) {
289+
put mi;
290+
}
291+
}
292+
}
293+
case (_) {}
294+
}
295+
}
296+
}
297+
fn get_crate_meta(&session::session sess,
298+
&ast::crate c, str k, str default,
299+
bool warn_default) -> str {
300+
let vec[@ast::meta_item] v = [];
301+
for each (@ast::meta_item mi in crate_export_metas(c)) {
302+
if (mi.node.name == k) {
303+
v += [mi];
304+
}
305+
}
306+
alt (vec::len(v)) {
307+
case (0u) {
308+
if (warn_default) {
309+
sess.warn(#fmt("missing meta '%s', using '%s' as default",
310+
k, default));
311+
}
312+
ret default;
313+
}
314+
case (1u) {
315+
ret v.(0).node.value;
316+
}
317+
case (_) {
318+
sess.span_err(v.(1).span, #fmt("duplicate meta '%s'", k));
319+
}
320+
}
321+
}
322+
323+
// This calculates CMH as defined above
324+
fn crate_meta_extras_hash(sha1 sha, &ast::crate crate) -> str {
325+
fn lteq(&@ast::meta_item ma,
326+
&@ast::meta_item mb) -> bool {
327+
ret ma.node.name <= mb.node.name;
328+
}
329+
330+
fn len_and_str(&str s) -> str {
331+
ret #fmt("%u_%s", str::byte_len(s), s);
332+
}
333+
334+
let vec[mutable @ast::meta_item] v = [mutable];
335+
for each (@ast::meta_item mi in crate_export_metas(crate)) {
336+
if (mi.node.name != "name" &&
337+
mi.node.name != "vers") {
338+
v += [mutable mi];
339+
}
340+
}
341+
sort::quick_sort(lteq, v);
342+
sha.reset();
343+
for (@ast::meta_item m in v) {
344+
sha.input_str(len_and_str(m.node.name));
345+
sha.input_str(len_and_str(m.node.value));
346+
}
347+
ret truncated_sha1_result(sha);
348+
}
349+
350+
fn crate_meta_name(&session::session sess, &ast::crate crate,
351+
&str output) -> str {
352+
auto os = str::split(fs::basename(output), '.' as u8);
353+
assert vec::len(os) >= 2u;
354+
vec::pop(os);
355+
ret get_crate_meta(sess, crate, "name", str::connect(os, "."),
356+
sess.get_opts().shared);
357+
}
358+
359+
fn crate_meta_vers(&session::session sess, &ast::crate crate) -> str {
360+
ret get_crate_meta(sess, crate, "vers", "0.0",
361+
sess.get_opts().shared);
362+
}
363+
364+
fn truncated_sha1_result(sha1 sha) -> str {
365+
ret str::substr(sha.result_str(), 0u, 16u);
366+
}
367+
368+
369+
370+
// This calculates STH for a symbol, as defined above
371+
fn symbol_hash(ty::ctxt tcx, sha1 sha, &ty::t t,
372+
str crate_meta_name,
373+
str crate_meta_extras_hash) -> str {
374+
// NB: do *not* use abbrevs here as we want the symbol names
375+
// to be independent of one another in the crate.
376+
auto cx = @rec(ds=metadata::def_to_str, tcx=tcx,
377+
abbrevs=metadata::ac_no_abbrevs);
378+
sha.reset();
379+
sha.input_str(crate_meta_name);
380+
sha.input_str("-");
381+
sha.input_str(crate_meta_name);
382+
sha.input_str("-");
383+
sha.input_str(metadata::Encode::ty_str(cx, t));
384+
auto hash = truncated_sha1_result(sha);
385+
// Prefix with _ so that it never blends into adjacent digits
386+
ret "_" + hash;
387+
}
388+
389+
fn get_symbol_hash(&@crate_ctxt ccx, &ty::t t) -> str {
390+
auto hash = "";
391+
alt (ccx.type_sha1s.find(t)) {
392+
case (some(?h)) { hash = h; }
393+
case (none) {
394+
hash = symbol_hash(ccx.tcx, ccx.sha, t,
395+
ccx.crate_meta_name,
396+
ccx.crate_meta_extras_hash);
397+
ccx.type_sha1s.insert(t, hash);
398+
}
399+
}
400+
ret hash;
401+
}
402+
403+
404+
fn mangle(&vec[str] ss) -> str {
405+
406+
// Follow C++ namespace-mangling style
407+
408+
auto n = "_ZN"; // Begin name-sequence.
409+
410+
for (str s in ss) {
411+
n += #fmt("%u%s", str::byte_len(s), s);
412+
}
413+
414+
n += "E"; // End name-sequence.
415+
ret n;
416+
}
417+
418+
419+
fn exported_name(&vec[str] path, &str hash, &str vers) -> str {
420+
// FIXME: versioning isn't working yet
421+
ret mangle(path + [hash]); // + "@" + vers;
422+
}
423+
424+
fn mangle_exported_name(&@crate_ctxt ccx, &vec[str] path,
425+
&ty::t t) -> str {
426+
auto hash = get_symbol_hash(ccx, t);
427+
ret exported_name(path, hash, ccx.crate_meta_vers);
428+
}
429+
430+
fn mangle_internal_name_by_type_only(&@crate_ctxt ccx, &ty::t t,
431+
&str name) -> str {
432+
auto f = metadata::def_to_str;
433+
auto cx = @rec(ds=f, tcx=ccx.tcx, abbrevs=metadata::ac_no_abbrevs);
434+
auto s = ty::ty_to_short_str(ccx.tcx, t);
435+
436+
auto hash = get_symbol_hash(ccx, t);
437+
ret mangle([name, s, hash]);
438+
}
439+
440+
fn mangle_internal_name_by_path_and_seq(&@crate_ctxt ccx, &vec[str] path,
441+
&str flav) -> str {
442+
ret mangle(path + [ccx.names.next(flav)]);
443+
}
444+
445+
fn mangle_internal_name_by_path(&@crate_ctxt ccx, &vec[str] path) -> str {
446+
ret mangle(path);
447+
}
448+
449+
fn mangle_internal_name_by_seq(&@crate_ctxt ccx, &str flav) -> str {
450+
ret ccx.names.next(flav);
451+
}
452+
453+
//
454+
// Local Variables:
455+
// mode: rust
456+
// fill-column: 78;
457+
// indent-tabs-mode: nil
458+
// c-basic-offset: 4
459+
// buffer-file-coding-system: utf-8-unix
460+
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
461+
// End:
462+
//

src/comp/driver/rustc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ fn pretty_print_input(session::session sess, eval::env env, str input,
125125
pp_mode ppm) {
126126
auto def = tup(ast::local_crate, 0);
127127
auto p = front::parser::new_parser(sess, env, def, input, 0u, 0u);
128-
auto crate = front::parser::parse_crate_from_source_file(p);
128+
auto crate = parse_input(sess, p, input);
129129

130130
auto mode;
131131
alt (ppm) {

0 commit comments

Comments
 (0)