From b1d6f12a050ea0c99f13a1eb58c06577559cc76a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Tue, 7 Jun 2011 16:41:19 -0400 Subject: [PATCH] Don't put a copy of main (the C one) in each binary we produce. This is a step in getting a driver that works on all linux systems. Sorry for the linker hacks, I will remove them after snapshotting a new compiler. --- Makefile.in | 6 +-- mk/clean.mk | 2 + mk/rt.mk | 12 ++++++ mk/stage1.mk | 2 +- mk/stage2.mk | 2 +- mk/stage3.mk | 4 +- mk/tests.mk | 6 +-- src/comp/middle/trans.rs | 85 ++++++++++++++-------------------------- src/rt/main.ll.in | 24 ++++++++++++ 9 files changed, 77 insertions(+), 66 deletions(-) create mode 100644 src/rt/main.ll.in diff --git a/Makefile.in b/Makefile.in index ecff84dc4c0..362b97ea036 100644 --- a/Makefile.in +++ b/Makefile.in @@ -144,9 +144,9 @@ COMPILER_INPUTS := $(wildcard $(addprefix $(S)src/comp/, \ ###################################################################### LREQ := rt/$(CFG_RUNTIME) rustllvm/$(CFG_RUSTLLVM) -SREQ0 := stage0/rustc$(X) $(LREQ) stage1/glue.o stage1/$(CFG_STDLIB) -SREQ1 := stage1/rustc$(X) $(LREQ) stage2/glue.o stage2/$(CFG_STDLIB) -SREQ2 := stage2/rustc$(X) $(LREQ) stage3/glue.o stage3/$(CFG_STDLIB) +SREQ0 := stage0/rustc$(X) $(LREQ) rt/main.a stage1/glue.o stage1/$(CFG_STDLIB) +SREQ1 := stage1/rustc$(X) $(LREQ) rt/main.a stage2/glue.o stage2/$(CFG_STDLIB) +SREQ2 := stage2/rustc$(X) $(LREQ) rt/main.a stage3/glue.o stage3/$(CFG_STDLIB) ###################################################################### diff --git a/mk/clean.mk b/mk/clean.mk index 3f19953929e..305b06b5e0a 100644 --- a/mk/clean.mk +++ b/mk/clean.mk @@ -28,6 +28,8 @@ clean: $(Q)rm -f stage3/rustc$(X) stage3/$(CFG_STDLIB) stage3/glue* $(Q)rm -f rustllvm/$(CFG_RUSTLLVM) rustllvm/rustllvmbits.a $(Q)rm -f rt/$(CFG_RUNTIME) + $(Q)rm -f rt/main.o + $(Q)rm -f rt/main.a $(Q)rm -Rf $(PKG_NAME)-*.tar.gz dist $(Q)rm -f $(foreach ext,o a d bc s exe,$(wildcard stage*/*.$(ext))) $(Q)rm -Rf $(foreach ext,out out.tmp \ diff --git a/mk/rt.mk b/mk/rt.mk index 8139f9e4e79..1cc6dfb57f4 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -76,6 +76,18 @@ rt/%.o: rt/%.s $(MKFILES) @$(call E, compile: $@) $(Q)$(call CFG_COMPILE_C, $@, $(RUNTIME_INCS)) $< +ifdef CFG_WINDOWSY +rt/main.ll: rt/main.ll.in + sed 's/MAIN/WinMain@16/' < $^ > $@ +else +rt/main.ll: rt/main.ll.in + sed 's/MAIN/main/' < $^ > $@ +endif + +rt/main.a: rt/main.o + rm -f $@ + ar crs $@ $^ + rt/%.o: rt/%.ll $(MKFILES) @$(call E, llc: $@) $(Q)$(LLC) -filetype=obj -relocation-model=pic -march=x86 -o $@ $< diff --git a/mk/stage1.mk b/mk/stage1.mk index f2ca6321d94..c98882e41a8 100644 --- a/mk/stage1.mk +++ b/mk/stage1.mk @@ -44,7 +44,7 @@ stage1/%.o: stage1/%.s stage1/%$(X): stage1/%.o $(SREQ0) @$(call E, link [gcc]: $@) $(Q)gcc $(CFG_GCCISH_CFLAGS) stage1/glue.o -o $@ $< \ - -Lstage1 -Lrustllvm -Lrt -lrustrt -lrustllvm -lstd -lm + -Lstage1 -Lrustllvm -Lrt rt/main.a -lrustrt -lrustllvm -lstd -lm @# dsymutil sometimes fails or prints a warning, but the @# program still runs. Since it simplifies debugging other @# programs, I\'ll live with the noise. diff --git a/mk/stage2.mk b/mk/stage2.mk index e084a19a8d3..0d87400c1e2 100644 --- a/mk/stage2.mk +++ b/mk/stage2.mk @@ -44,7 +44,7 @@ stage2/%.o: stage2/%.s stage2/%$(X): stage2/%.o $(SREQ1) @$(call E, link [gcc]: $@) $(Q)gcc $(CFG_GCCISH_CFLAGS) stage2/glue.o -o $@ $< \ - -Lstage2 -Lrustllvm -Lrt -lrustrt -lrustllvm -lstd -lm + -Lstage2 -Lrustllvm -Lrt rt/main.a -lrustrt -lrustllvm -lstd -lm @# dsymutil sometimes fails or prints a warning, but the @# program still runs. Since it simplifies debugging other @# programs, I\'ll live with the noise. diff --git a/mk/stage3.mk b/mk/stage3.mk index dc2792446e2..77d09440883 100644 --- a/mk/stage3.mk +++ b/mk/stage3.mk @@ -23,7 +23,7 @@ stage3/rustc.o: $(COMPILER_CRATE) $(COMPILER_INPUTS) $(SREQ2) $(STAGE2) -c -o $@ $< stage3/glue.o: stage2/rustc$(X) stage2/$(CFG_STDLIB) stage2/intrinsics.bc \ - rustllvm/$(CFG_RUSTLLVM) rt/$(CFG_RUNTIME) + rustllvm/$(CFG_RUSTLLVM) rt/$(CFG_RUNTIME) @$(call E, generate: $@) $(STAGE2) -c -o $@ --glue @@ -44,7 +44,7 @@ stage3/%.o: stage3/%.s stage3/%$(X): stage3/%.o $(SREQ2) @$(call E, link [gcc]: $@) $(Q)gcc $(CFG_GCCISH_CFLAGS) stage3/glue.o -o $@ $< \ - -Lstage3 -Lrustllvm -Lrt -lrustrt -lrustllvm -lstd -lm + -Lstage3 -Lrustllvm -Lrt rt/main.a -lrustrt -lrustllvm -lstd -lm @# dsymutil sometimes fails or prints a warning, but the @# program still runs. Since it simplifies debugging other @# programs, I\'ll live with the noise. diff --git a/mk/tests.mk b/mk/tests.mk index 5e30b352dfa..db7a3dd4d33 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -185,7 +185,7 @@ compile-check: tidy \ %.stage0$(X): %.stage0.o $(SREQ0) @$(call E, link [gcc]: $@) $(Q)gcc $(CFG_GCCISH_CFLAGS) stage1/glue.o -o $@ $< \ - -Lstage1 -Lrt -lrustrt -lstd -lm + -Lstage1 -Lrt rt/main.a -lrustrt -lstd -lm @# dsymutil sometimes fails or prints a warning, but the @# program still runs. Since it simplifies debugging other @# programs, I\'ll live with the noise. @@ -194,7 +194,7 @@ compile-check: tidy \ %.stage1$(X): %.stage1.o $(SREQ1) @$(call E, link [gcc]: $@) $(Q)gcc $(CFG_GCCISH_CFLAGS) stage2/glue.o -o $@ $< \ - -Lstage2 -Lrt -lrustrt -lstd -lm + -Lstage2 -Lrt rt/main.a -lrustrt -lstd -lm @# dsymutil sometimes fails or prints a warning, but the @# program still runs. Since it simplifies debugging other @# programs, I\'ll live with the noise. @@ -203,7 +203,7 @@ compile-check: tidy \ %.stage2$(X): %.stage2.o $(SREQ2) @$(call E, link [gcc]: $@) $(Q)gcc $(CFG_GCCISH_CFLAGS) stage3/glue.o -o $@ $< \ - -Lstage3 -Lrt -lrustrt -lstd -lm + -Lstage3 -Lrt rt/main.a -lrustrt -lstd -lm @# dsymutil sometimes fails or prints a warning, but the @# program still runs. Since it simplifies debugging other @# programs, I\'ll live with the noise. diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 4230032f7ee..a65b1403b38 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -338,6 +338,9 @@ fn get_type_sha1(&@crate_ctxt ccx, &ty::t t) -> str { fn mangle(&vec[str] ss) -> str { + if (vec::len(ss) > 0u && str::eq(vec::top(ss), "main")) { + ret "_rust_main"; + } // Follow C++ namespace-mangling style auto n = "_ZN"; // Begin name-sequence. @@ -369,7 +372,7 @@ fn mangle_name_by_path_and_seq(&@crate_ctxt ccx, &vec[str] path, ret mangle(path + [ccx.names.next(flav)]); } -fn mangle_name_by_path(&@crate_ctxt ccx, &vec[str] path) -> str { +fn mangle_name_by_path(&vec[str] path) -> str { ret mangle(path); } @@ -7095,7 +7098,7 @@ fn create_vtbl(@local_ctxt cx, let @local_ctxt mcx = @rec(path = cx.path + ["method", m.node.ident] with *cx); - let str s = mangle_name_by_path(mcx.ccx, mcx.path); + let str s = mangle_name_by_path(mcx.path); let ValueRef llfn = decl_internal_fastcall_fn(cx.ccx.llmod, s, llfnty); cx.ccx.item_ids.insert(m.node.id, llfn); @@ -7107,7 +7110,7 @@ fn create_vtbl(@local_ctxt cx, methods += [llfn]; } auto vtbl = C_struct(methods); - auto vtbl_name = mangle_name_by_path(cx.ccx, cx.path + ["vtbl"]); + auto vtbl_name = mangle_name_by_path(cx.path + ["vtbl"]); auto gvar = llvm::LLVMAddGlobal(cx.ccx.llmod, val_ty(vtbl), str::buf(vtbl_name)); llvm::LLVMSetInitializer(gvar, vtbl); @@ -7124,7 +7127,7 @@ fn trans_dtor(@local_ctxt cx, &@ast::method dtor) -> ValueRef { auto llfnty = T_dtor(cx.ccx, dtor.span, llself_ty); - let str s = mangle_name_by_path(cx.ccx, cx.path + ["drop"]); + let str s = mangle_name_by_path(cx.path + ["drop"]); let ValueRef llfn = decl_internal_fastcall_fn(cx.ccx.llmod, s, llfnty); cx.ccx.item_ids.insert(dtor.node.id, llfn); cx.ccx.item_symbols.insert(dtor.node.id, s); @@ -7518,7 +7521,7 @@ fn decl_fn_and_pair(&@crate_ctxt ccx, &span sp, } // Declare the function itself. - let str s = mangle_name_by_path(ccx, path); + let str s = mangle_name_by_path(path); let ValueRef llfn = decl_internal_fastcall_fn(ccx.llmod, s, llfty); // Declare the global constant pair that points to it. @@ -7532,6 +7535,8 @@ fn decl_fn_and_pair(&@crate_ctxt ccx, &span sp, 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); } } @@ -7593,7 +7598,7 @@ fn decl_native_fn_and_pair(&@crate_ctxt ccx, // Declare the wrapper. auto t = node_ann_type(ccx, ann); auto wrapper_type = native_fn_wrapper_type(ccx, sp, num_ty_param, t); - let str s = mangle_name_by_path(ccx, path); + let str s = mangle_name_by_path(path); let ValueRef wrapper_fn = decl_internal_fastcall_fn(ccx.llmod, s, wrapper_type); @@ -7996,51 +8001,6 @@ fn create_typedefs(&@crate_ctxt cx) { llvm::LLVMAddTypeName(cx.llmod, str::buf("tydesc"), T_tydesc(cx.tn)); } -fn trans_main_fn(@local_ctxt cx, ValueRef crate_map) { - auto T_main_args = [T_int(), T_int()]; - auto T_rust_start_args = [T_int(), T_int(), T_int(), T_int()]; - - auto main_name; - if (str::eq(std::os::target_os(), "win32")) { - main_name = "WinMain@16"; - } else { - main_name = "main"; - } - - auto llmain = - decl_cdecl_fn(cx.ccx.llmod, main_name, T_fn(T_main_args, T_int())); - - auto llrust_start = decl_cdecl_fn(cx.ccx.llmod, "rust_start", - T_fn(T_rust_start_args, T_int())); - - auto llargc = llvm::LLVMGetParam(llmain, 0u); - auto llargv = llvm::LLVMGetParam(llmain, 1u); - auto llrust_main = alt (cx.ccx.main_fn) { - case (none) { - cx.ccx.sess.err("missing 'main' function"); - // FIXME: shouldn't sess.err's ! result unify with f? - C_nil() - } - case (some(?f)) { f } - }; - - // - // Emit the moral equivalent of: - // - // main(int argc, char **argv) { - // rust_start(&_rust.main, argc, argv); - // } - // - - let BasicBlockRef llbb = - llvm::LLVMAppendBasicBlock(llmain, str::buf("")); - auto b = new_builder(llbb); - - auto start_args = [p2i(llrust_main), llargc, llargv, p2i(crate_map)]; - - b.Ret(b.Call(llrust_start, start_args)); -} - fn declare_intrinsics(ModuleRef llmod) -> hashmap[str,ValueRef] { let vec[TypeRef] T_memmove32_args = [T_ptr(T_i8()), T_ptr(T_i8()), @@ -8211,8 +8171,6 @@ fn create_module_map(&@crate_ctxt ccx) -> ValueRef { auto maptype = T_array(elttype, ccx.module_data.size() + 1u); auto map = llvm::LLVMAddGlobal(ccx.llmod, maptype, str::buf("_rust_mod_map")); - llvm::LLVMSetLinkage(map, lib::llvm::LLVMInternalLinkage - as llvm::Linkage); let vec[ValueRef] elts = []; for each (@tup(str, ValueRef) item in ccx.module_data.items()) { auto elt = C_struct([p2i(C_cstr(ccx, item._0)), p2i(item._1)]); @@ -8245,7 +8203,14 @@ fn create_crate_map(&@crate_ctxt ccx) -> ValueRef { i += 1; } vec::push[ValueRef](subcrates, C_int(0)); - auto sym_name = "_rust_crate_map_" + crate_name(ccx, "__none__"); + auto cname = crate_name(ccx, "__none__"); + auto mapname; + if (ccx.sess.get_opts().shared) { + mapname = cname; + } else { + mapname = "toplevel"; + } + auto sym_name = "_rust_crate_map_" + mapname; auto arrtype = T_array(T_int(), vec::len[ValueRef](subcrates)); auto maptype = T_struct([T_int(), arrtype]); auto map = llvm::LLVMAddGlobal(ccx.llmod, maptype, str::buf(sym_name)); @@ -8322,9 +8287,17 @@ fn trans_crate(&session::session sess, &@ast::crate crate, trans_constants(ccx, crate); trans_mod(cx, crate.node.module); auto crate_map = create_crate_map(ccx); + if (!sess.get_opts().shared) { - trans_main_fn(cx, crate_map); - } + auto gvar = llvm::LLVMAddGlobal(cx.ccx.llmod, T_ptr(T_int()), + str::buf("_rust_fetch_this_object_hack")); + + auto gvar2 = llvm::LLVMAddGlobal(cx.ccx.llmod, T_ptr(T_ptr(T_int())), + str::buf("_rust_fetch_this_object_hack2")); + llvm::LLVMSetInitializer(gvar2, gvar); + llvm::LLVMSetGlobalConstant(gvar, True); + llvm::LLVMSetGlobalConstant(gvar2, True); + } emit_tydescs(ccx); diff --git a/src/rt/main.ll.in b/src/rt/main.ll.in new file mode 100644 index 00000000000..d956fb86817 --- /dev/null +++ b/src/rt/main.ll.in @@ -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 +}