diff --git a/Makefile.in b/Makefile.in index 676b4cfb7a015..a6b856622db5d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -38,7 +38,7 @@ CFG_STDLIB :=$(call CFG_LIB_NAME,std) ifdef CFG_OCAMLC_OPT $(info cfg: have ocaml native compiler) OPT=.opt -else +else ifdef CFG_OCAMLC $(info cfg: have only ocaml bytecode compiler) endif @@ -137,6 +137,12 @@ SREQ2 := stage2/rustc$(X) $(LREQ) stage3/glue.o stage3/$(CFG_STDLIB) export CFG_SRC_DIR +###################################################################### +# Subprograms +###################################################################### + +LLVM_AS := $(CFG_LLVM_BINDIR)/llvm-as + ###################################################################### # Single-target rules @@ -145,17 +151,21 @@ export CFG_SRC_DIR all: rt/$(CFG_RUNTIME) \ rustllvm/$(CFG_RUSTLLVM) \ stage0/$(CFG_STDLIB) \ + stage0/intrinsics.bc \ stage0/rustc$(X) \ $(GENERATED) \ $(DOCS) \ stage1/$(CFG_STDLIB) \ + stage1/intrinsics.bc \ stage1/glue.o \ stage1/rustc$(X) \ stage2/$(CFG_STDLIB) \ + stage2/intrinsics.bc \ stage2/glue.o \ stage2/rustc$(X) \ stage3/$(CFG_STDLIB) \ stage3/glue.o \ + stage3/intrinsics.bc \ stage3/rustc$(X) @@ -172,6 +182,7 @@ config.mk: $(S)configure $(S)Makefile.in # Additional makefiles ###################################################################### +include $(CFG_SRC_DIR)/mk/intrinsics.mk include $(CFG_SRC_DIR)/mk/stage0.mk include $(CFG_SRC_DIR)/mk/stage1.mk include $(CFG_SRC_DIR)/mk/stage2.mk diff --git a/configure b/configure index a2d6063a9a4b6..84833f12bcb6b 100755 --- a/configure +++ b/configure @@ -122,6 +122,7 @@ need_cmd find need_cmd uname need_cmd date need_cmd tr +need_cmd sed msg "inspecting environment" @@ -185,13 +186,13 @@ putvar CFG_CONFIGURE_ARGS step_msg "looking for build programs" probe_need CFG_GCC gcc probe_need CFG_GIT git -probe_need CFG_OCAMLC ocamlc probe_need CFG_PERL perl probe_need CFG_PYTHON python probe_need CFG_CURL curl probe CFG_LLVM_CONFIG llvm-config probe CFG_VALGRIND valgrind +probe CFG_OCAMLC ocamlc probe CFG_OCAMLOPT ocamlopt probe CFG_OCAMLC_OPT ocamlc.opt probe CFG_OCAMLOPT_OPT ocamlopt.opt @@ -215,6 +216,10 @@ then --version \ | grep version \ | cut -d ' ' -f 5-) + CFG_LLVM_TRIPLE=$("$CFG_LLVM_BINDIR/llc" \ + --version \ + | grep Host: \ + | cut -d ' ' -f 4-) elif [ ! -z "$CFG_LLVM_CONFIG" ] then CFG_LLVM_VERSION=$(llvm-config --version) @@ -224,6 +229,7 @@ then CFG_LLVM_CXXFLAGS=$(llvm-config --cxxflags) CFG_LLVM_LDFLAGS=$(llvm-config --ldflags) CFG_LLVM_LIBS=$(llvm-config --libs) + CFG_LLVM_TRIPLE=$(llvm-config --host-target) else err "either the \"CFG_LLVM_ROOT\" environment variable must be set, or a \ \"llvm-config\" script must be present" @@ -244,6 +250,7 @@ putvar CFG_LLVM_LIBDIR putvar CFG_LLVM_CXXFLAGS putvar CFG_LLVM_LDFLAGS putvar CFG_LLVM_LIBS +putvar CFG_LLVM_TRIPLE # Munge any paths that appear in config.mk back to posix-y perl -i.bak -p -e 's@ ([a-zA-Z]):[/\\]@ /\1/@go;' \ diff --git a/mk/intrinsics.mk b/mk/intrinsics.mk new file mode 100644 index 0000000000000..77442ec530a49 --- /dev/null +++ b/mk/intrinsics.mk @@ -0,0 +1,19 @@ +###################################################################### +# intrinsics.bc rules +###################################################################### + +# TODO: Use clang to compile the C++. +INTRINSICS_LL_IN := $(S)src/rt/intrinsics/intrinsics.ll.in +INTRINSICS_LL := intrinsics/intrinsics.ll +INTRINSICS_BC := intrinsics/intrinsics.bc + +$(INTRINSICS_LL): $(INTRINSICS_LL_IN) $(MKFILES) + @$(call E, mkdir: intrinsics) + $(Q)mkdir -p intrinsics + @$(call E, sed: $@) + $(Q)sed s/@CFG_LLVM_TRIPLE@/$(CFG_LLVM_TRIPLE)/g $< > $@ + +$(INTRINSICS_BC): $(INTRINSICS_LL) $(MKFILES) + @$(call E, llvm-as: $@) + $(Q)$(LLVM_AS) -o $@ $< + diff --git a/mk/stage0.mk b/mk/stage0.mk index 493f9e0058585..e79ae8435f95d 100644 --- a/mk/stage0.mk +++ b/mk/stage0.mk @@ -10,3 +10,9 @@ stage0/glue.o: stage0/rustc$(X) stage0/$(CFG_STDLIB): stage0/rustc$(X) $(Q)touch $@ + +# TODO: Include as part of the snapshot. +stage0/intrinsics.bc: $(INTRINSICS_BC) + @$(call E, cp: $@) + $(Q)cp $< $@ + diff --git a/mk/stage1.mk b/mk/stage1.mk index e01942a5695d7..eb30e78251156 100644 --- a/mk/stage1.mk +++ b/mk/stage1.mk @@ -1,5 +1,6 @@ stage1/std.o: $(STDLIB_CRATE) $(STDLIB_INPUTS) \ - stage0/rustc$(X) stage0/$(CFG_STDLIB) $(LREQ) $(MKFILES) + stage0/rustc$(X) stage0/$(CFG_STDLIB) stage0/intrinsics.bc \ + $(LREQ) $(MKFILES) @$(call E, compile: $@) $(STAGE0) -c --shared -o $@ $< @@ -12,10 +13,15 @@ stage1/rustc.o: $(COMPILER_CRATE) $(COMPILER_INPUTS) $(SREQ0) @$(call E, compile: $@) $(STAGE0) -c -o $@ $< -stage1/glue.o: stage0/rustc$(X) stage0/$(CFG_STDLIB) $(LREQ) $(MKFILES) +stage1/glue.o: stage0/rustc$(X) stage0/$(CFG_STDLIB) stage0/intrinsics.bc \ + $(LREQ) $(MKFILES) @$(call E, generate: $@) $(STAGE0) -c -o $@ --glue +stage1/intrinsics.bc: $(INTRINSICS_BC) + @$(call E, cp: $@) + $(Q)cp $< $@ + # Due to make not wanting to run the same implicit rules twice on the same # rule tree (implicit-rule recursion prevention, see "Chains of Implicit # Rules" in GNU Make manual) we have to re-state the %.o and %.s patterns here diff --git a/mk/stage2.mk b/mk/stage2.mk index 600d55e4a74c5..74e76c3ce0380 100644 --- a/mk/stage2.mk +++ b/mk/stage2.mk @@ -1,4 +1,5 @@ -stage2/std.o: $(STDLIB_CRATE) $(STDLIB_INPUTS) stage1/rustc$(X) $(MKFILES) +stage2/std.o: $(STDLIB_CRATE) $(STDLIB_INPUTS) stage1/rustc$(X) \ + stage1/intrinsics.bc $(MKFILES) @$(call E, compile: $@) $(STAGE1) -c --shared -o $@ $< @@ -11,11 +12,15 @@ stage2/rustc.o: $(COMPILER_CRATE) $(COMPILER_INPUTS) $(SREQ1) @$(call E, compile: $@) $(STAGE1) -c -o $@ $< -stage2/glue.o: stage1/rustc$(X) stage1/$(CFG_STDLIB) \ - rustllvm/$(CFG_RUSTLLVM) rt/$(CFG_RUNTIME) +stage2/glue.o: stage1/rustc$(X) stage1/$(CFG_STDLIB) stage1/intrinsics.bc \ + rustllvm/$(CFG_RUSTLLVM) rt/$(CFG_RUNTIME) @$(call E, generate: $@) $(STAGE1) -c -o $@ --glue +stage2/intrinsics.bc: $(INTRINSICS_BC) + @$(call E, cp: $@) + $(Q)cp $< $@ + # Due to make not wanting to run the same implicit rules twice on the same # rule tree (implicit-rule recursion prevention, see "Chains of Implicit # Rules" in GNU Make manual) we have to re-state the %.o and %.s patterns here diff --git a/mk/stage3.mk b/mk/stage3.mk index 8f56637ef53c7..427f37f88ee4c 100644 --- a/mk/stage3.mk +++ b/mk/stage3.mk @@ -1,4 +1,5 @@ -stage3/std.o: $(STDLIB_CRATE) $(STDLIB_INPUTS) stage2/rustc$(X) $(MKFILES) +stage3/std.o: $(STDLIB_CRATE) $(STDLIB_INPUTS) stage2/rustc$(X) \ + stage2/intrinsics.bc $(MKFILES) @$(call E, compile: $@) $(STAGE2) -c --shared -o $@ $< @@ -11,11 +12,15 @@ stage3/rustc.o: $(COMPILER_CRATE) $(COMPILER_INPUTS) $(SREQ2) @$(call E, compile: $@) $(STAGE2) -c -o $@ $< -stage3/glue.o: stage2/rustc$(X) stage2/$(CFG_STDLIB) \ +stage3/glue.o: stage2/rustc$(X) stage2/$(CFG_STDLIB) stage2/intrinsics.bc \ rustllvm/$(CFG_RUSTLLVM) rt/$(CFG_RUNTIME) @$(call E, generate: $@) $(STAGE2) -c -o $@ --glue +stage3/intrinsics.bc: $(INTRINSICS_BC) + @$(call E, cp: $@) + $(Q)cp $< $@ + # Due to make not wanting to run the same implicit rules twice on the same # rule tree (implicit-rule recursion prevention, see "Chains of Implicit # Rules" in GNU Make manual) we have to re-state the %.o and %.s patterns here diff --git a/mk/tests.mk b/mk/tests.mk index 64185eeb52fe0..42eb05944df0d 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -139,10 +139,27 @@ ALL_TEST_SOURCES = $(TEST_CFAIL_SOURCES_STAGE0) \ unexport RUST_LOG -check_nocompile: $(TEST_CFAIL_OUTS_STAGE0) \ +check-nocompile: $(TEST_CFAIL_OUTS_STAGE0) \ $(TEST_CFAIL_OUTS_STAGE1) \ $(TEST_CFAIL_OUTS_STAGE2) +check-stage0: tidy \ + $(TEST_RPASS_EXES_STAGE0) $(TEST_RFAIL_EXES_STAGE0) \ + $(TEST_RPASS_OUTS_STAGE0) $(TEST_RFAIL_OUTS_STAGE0) \ + $(TEST_CFAIL_OUTS_STAGE0) \ + + +check-stage1: tidy \ + $(TEST_RPASS_EXES_STAGE1) $(TEST_RFAIL_EXES_STAGE1) \ + $(TEST_RPASS_OUTS_STAGE1) $(TEST_RFAIL_OUTS_STAGE1) \ + $(TEST_CFAIL_OUTS_STAGE1) \ + + +check-stage2: tidy \ + $(TEST_RPASS_EXES_STAGE2) $(TEST_RFAIL_EXES_STAGE2) \ + $(TEST_RPASS_OUTS_STAGE2) $(TEST_RFAIL_OUTS_STAGE2) \ + $(TEST_CFAIL_OUTS_STAGE2) \ + check: tidy \ $(TEST_RPASS_EXES_STAGE0) $(TEST_RFAIL_EXES_STAGE0) \ diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index 6a37dece84515..4276b55806120 100644 --- a/src/comp/driver/rustc.rs +++ b/src/comp/driver/rustc.rs @@ -14,6 +14,7 @@ import middle.typestate_check; import lib.llvm; import util.common; +import std.fs; import std.map.mk_hashmap; import std.option; import std.option.some; @@ -78,50 +79,39 @@ fn time[T](bool do_it, str what, fn()->T thunk) -> T { } fn compile_input(session.session sess, - eval.env env, - str input, str output, - bool shared, - bool optimize, - bool debuginfo, - bool verify, - bool save_temps, - trans.output_type ot, - bool time_passes, - bool run_typestate, - vec[str] library_search_paths) { + eval.env env, + str input, str output) { + auto time_passes = sess.get_opts().time_passes; auto def = tup(0, 0); auto p = parser.new_parser(sess, env, def, input, 0u); auto crate = time[@ast.crate](time_passes, "parsing", - bind parse_input(sess, p, input)); - if (ot == trans.output_type_none) {ret;} + bind parse_input(sess, p, input)); + if (sess.get_opts().output_type == trans.output_type_none) {ret;} crate = time[@ast.crate](time_passes, "external crate reading", - bind creader.read_crates(sess, crate, library_search_paths)); + bind creader.read_crates(sess, crate)); crate = time[@ast.crate](time_passes, "resolution", - bind resolve.resolve_crate(sess, crate)); + bind resolve.resolve_crate(sess, crate)); time[()](time_passes, "capture checking", - bind capture.check_for_captures(sess, crate)); + bind capture.check_for_captures(sess, crate)); auto ty_cx = ty.mk_ctxt(sess); auto typeck_result = time[typeck.typecheck_result](time_passes, "typechecking", - bind typeck.check_crate(ty_cx, crate)); + bind typeck.check_crate(ty_cx, crate)); crate = typeck_result._0; auto type_cache = typeck_result._1; - if (run_typestate) { + if (sess.get_opts().run_typestate) { crate = time[@ast.crate](time_passes, "typestate checking", bind typestate_check.check_crate(crate)); } auto llmod = time[llvm.ModuleRef](time_passes, "translation", - bind trans.trans_crate(sess, crate, ty_cx, type_cache, output, - debuginfo, shared)); + bind trans.trans_crate(sess, crate, ty_cx, type_cache, output)); time[()](time_passes, "LLVM passes", - bind trans.run_passes(llmod, optimize, debuginfo, - verify, save_temps, output, - ot)); + bind trans.run_passes(sess, llmod, output)); } fn pretty_print_input(session.session sess, @@ -133,7 +123,7 @@ fn pretty_print_input(session.session sess, pretty.pprust.print_file(crate.node.module, input, std.io.stdout()); } -fn usage(session.session sess, str argv0) { +fn usage(str argv0) { io.stdout().write_str(#fmt("usage: %s [options] \n", argv0) + " options: @@ -152,6 +142,7 @@ options: -c compile and assemble, but do not link --save-temps write intermediate files in addition to normal output --time-passes time the individual phases of the compiler + --sysroot override the system root (default: rustc's directory) --no-typestate don't run the typestate pass (unsafe!) -h display this message\n\n"); } @@ -163,35 +154,40 @@ fn get_os() -> session.os { if (_str.eq(s, "linux")) { ret session.os_linux; } } +fn get_default_sysroot(str binary) -> str { + auto dirname = fs.dirname(binary); + if (_str.eq(dirname, binary)) { ret "."; } + ret dirname; +} + fn main(vec[str] args) { // FIXME: don't hard-wire this. - auto target_cfg = rec(os = get_os(), - arch = session.arch_x86, - int_type = common.ty_i32, - uint_type = common.ty_u32, - float_type = common.ty_f64 ); - - auto crate_cache = common.new_int_hash[session.crate_metadata](); - auto target_crate_num = 0; - let vec[@ast.meta_item] md = vec(); - auto sess = session.session(target_crate_num, target_cfg, crate_cache, - md, front.codemap.new_codemap()); + let @session.config target_cfg = + @rec(os = get_os(), + arch = session.arch_x86, + int_type = common.ty_i32, + uint_type = common.ty_u32, + float_type = common.ty_f64); auto opts = vec(optflag("h"), optflag("glue"), optflag("pretty"), optflag("ls"), optflag("parse-only"), optflag("O"), optflag("shared"), optmulti("L"), optflag("S"), optflag("c"), optopt("o"), optopt("g"), - optflag("save-temps"), optflag("time-passes"), - optflag("no-typestate"), optflag("noverify")); + optflag("save-temps"), optopt("sysroot"), + optflag("time-passes"), optflag("no-typestate"), + optflag("noverify")); auto binary = _vec.shift[str](args); auto match; alt (GetOpts.getopts(args, opts)) { - case (GetOpts.failure(?f)) { sess.err(GetOpts.fail_str(f)); fail; } + case (GetOpts.failure(?f)) { + log_err #fmt("error: %s", GetOpts.fail_str(f)); + fail; + } case (GetOpts.success(?m)) { match = m; } } if (opt_present(match, "h")) { - usage(sess, binary); + usage(binary); ret; } @@ -201,13 +197,13 @@ fn main(vec[str] args) { auto shared = opt_present(match, "shared"); auto output_file = GetOpts.opt_maybe_str(match, "o"); auto library_search_paths = GetOpts.opt_strs(match, "L"); - auto ot = trans.output_type_bitcode; + auto output_type = trans.output_type_bitcode; if (opt_present(match, "parse-only")) { - ot = trans.output_type_none; + output_type = trans.output_type_none; } else if (opt_present(match, "S")) { - ot = trans.output_type_assembly; + output_type = trans.output_type_assembly; } else if (opt_present(match, "c")) { - ot = trans.output_type_object; + output_type = trans.output_type_object; } auto verify = !opt_present(match, "noverify"); auto save_temps = opt_present(match, "save-temps"); @@ -216,6 +212,33 @@ fn main(vec[str] args) { auto debuginfo = opt_present(match, "g"); auto time_passes = opt_present(match, "time-passes"); auto run_typestate = !opt_present(match, "no-typestate"); + auto sysroot_opt = GetOpts.opt_maybe_str(match, "sysroot"); + + auto sysroot; + alt (sysroot_opt) { + case (none[str]) { sysroot = get_default_sysroot(binary); } + case (some[str](?s)) { sysroot = s; } + } + + let @session.options sopts = + @rec(shared = shared, + optimize = optimize, + debuginfo = debuginfo, + verify = verify, + run_typestate = run_typestate, + save_temps = save_temps, + time_passes = time_passes, + output_type = output_type, + library_search_paths = library_search_paths, + sysroot = sysroot); + + auto crate_cache = common.new_int_hash[session.crate_metadata](); + auto target_crate_num = 0; + let vec[@ast.meta_item] md = vec(); + auto sess = + session.session(target_crate_num, target_cfg, sopts, + crate_cache, md, front.codemap.new_codemap()); + auto n_inputs = _vec.len[str](match.free); if (glue) { @@ -223,7 +246,7 @@ fn main(vec[str] args) { sess.err("No input files allowed with --glue."); } auto out = option.from_maybe[str]("glue.bc", output_file); - middle.trans.make_common_glue(out, optimize, verify, save_temps, ot); + middle.trans.make_common_glue(sess, out); ret; } @@ -244,18 +267,21 @@ fn main(vec[str] args) { case (none[str]) { let vec[str] parts = _str.split(ifile, '.' as u8); _vec.pop[str](parts); - parts += vec("bc"); + alt (output_type) { + case (trans.output_type_none) + { parts += vec("pp"); } + case (trans.output_type_bitcode) + { parts += vec("bc"); } + case (trans.output_type_assembly) + { parts += vec("s"); } + case (trans.output_type_object) + { parts += vec("o"); } + } auto ofile = _str.connect(parts, "."); - compile_input(sess, env, ifile, ofile, shared, - optimize, debuginfo, verify, - save_temps, ot, time_passes, - run_typestate, library_search_paths); + compile_input(sess, env, ifile, ofile); } case (some[str](?ofile)) { - compile_input(sess, env, ifile, ofile, shared, - optimize, debuginfo, verify, - save_temps, ot, time_passes, - run_typestate, library_search_paths); + compile_input(sess, env, ifile, ofile); } } } diff --git a/src/comp/driver/session.rs b/src/comp/driver/session.rs index 501b50b1ad6f7..6b3b55f44901d 100644 --- a/src/comp/driver/session.rs +++ b/src/comp/driver/session.rs @@ -19,11 +19,22 @@ tag arch { arch_arm; } -type cfg = rec(os os, - arch arch, - ty_mach int_type, - ty_mach uint_type, - ty_mach float_type); +type config = rec(os os, + arch arch, + ty_mach int_type, + ty_mach uint_type, + ty_mach float_type); + +type options = rec(bool shared, + bool optimize, + bool debuginfo, + bool verify, + bool run_typestate, + bool save_temps, + bool time_passes, + middle.trans.output_type output_type, + vec[str] library_search_paths, + str sysroot); type crate_metadata = rec(str name, vec[u8] data); @@ -47,13 +58,18 @@ fn emit_diagnostic(span sp, str msg, str kind, u8 color, codemap.codemap cm) { io.stdout().write_str(#fmt(" %s\n", msg)); } -state obj session(ast.crate_num cnum, cfg targ, +state obj session(ast.crate_num cnum, + @config targ_cfg, @options opts, map.hashmap[int, crate_metadata] crates, mutable vec[@ast.meta_item] metadata, codemap.codemap cm) { - fn get_targ_cfg() -> cfg { - ret targ; + fn get_targ_cfg() -> @config { + ret targ_cfg; + } + + fn get_opts() -> @options { + ret opts; } fn get_targ_crate_num() -> ast.crate_num { diff --git a/src/comp/front/creader.rs b/src/comp/front/creader.rs index c8b31159444f7..cdbafe5a09990 100644 --- a/src/comp/front/creader.rs +++ b/src/comp/front/creader.rs @@ -459,12 +459,11 @@ fn fold_view_item_use(&env e, &span sp, ast.ident ident, // Reads external crates referenced by "use" directives. fn read_crates(session.session sess, - @ast.crate crate, - vec[str] library_search_paths) -> @ast.crate { + @ast.crate crate) -> @ast.crate { auto e = @rec( sess=sess, crate_cache=@common.new_str_hash[int](), - library_search_paths=library_search_paths, + library_search_paths=sess.get_opts().library_search_paths, mutable next_crate_num=1 ); diff --git a/src/comp/front/extenv.rs b/src/comp/front/extenv.rs new file mode 100644 index 0000000000000..6dc9c5ec021f5 --- /dev/null +++ b/src/comp/front/extenv.rs @@ -0,0 +1,68 @@ +/* + * The compiler code necessary to support the #env extension. Eventually this + * should all get sucked into either the compiler syntax extension plugin + * interface. + */ + +import util.common; + +import std._str; +import std._vec; +import std.option; +import std.GenericOS; + +export expand_syntax_ext; + +// FIXME: Need to thread parser through here to handle errors correctly +fn expand_syntax_ext(parser.parser p, + common.span sp, + vec[@ast.expr] args, + option.t[str] body) -> @ast.expr { + + if (_vec.len[@ast.expr](args) != 1u) { + p.err("malformed #env call"); + } + + auto var = expr_to_str(p, args.(0)); + auto val = GenericOS.getenv(var); + ret make_new_str(sp, val); +} + +// FIXME: duplicate code copied from extfmt. + +fn expr_to_str(parser.parser p, + @ast.expr expr) -> str { + alt (expr.node) { + case (ast.expr_lit(?l, _)) { + alt (l.node) { + case (ast.lit_str(?s)) { + ret s; + } + } + } + } + p.err("malformed #env call"); + fail; +} + +fn make_new_lit(common.span sp, ast.lit_ lit) -> @ast.expr { + auto sp_lit = @rec(node=lit, span=sp); + auto expr = ast.expr_lit(sp_lit, ast.ann_none); + ret @rec(node=expr, span=sp); +} + +fn make_new_str(common.span sp, str s) -> @ast.expr { + auto lit = ast.lit_str(s); + ret make_new_lit(sp, lit); +} + +// +// 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: +// diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index e7a86d6efed1d..a7e355af5918e 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -948,6 +948,13 @@ fn expand_syntax_ext(parser p, ast.span sp, expanded, ast.ann_none); + ret newexpr; + } else if (_str.eq(extname, "env")) { + auto expanded = extenv.expand_syntax_ext(p, sp, args, body); + auto newexpr = ast.expr_ext(path, args, body, + expanded, + ast.ann_none); + ret newexpr; } else { p.err("unknown syntax extension"); diff --git a/src/comp/lib/llvm.rs b/src/comp/lib/llvm.rs index 070174bad3c68..5e758bc66768b 100644 --- a/src/comp/lib/llvm.rs +++ b/src/comp/lib/llvm.rs @@ -848,7 +848,9 @@ native mod llvm = llvm_lib { call. */ fn LLVMRustGetLastError() -> sbuf; - + /** Links LLVM modules together. `Src` is destroyed by this call and + must never be referenced again. */ + fn LLVMLinkModules(ModuleRef Dest, ModuleRef Src) -> Bool; } native mod rustllvm = llvm_lib { diff --git a/src/comp/middle/metadata.rs b/src/comp/middle/metadata.rs index 2b4ad2a2f64cf..5f222cd43d9f6 100644 --- a/src/comp/middle/metadata.rs +++ b/src/comp/middle/metadata.rs @@ -687,9 +687,9 @@ fn encode_metadata(@trans.crate_ctxt cx, @ast.crate crate) ret C_postr(string_w.get_str()); } -fn write_metadata(@trans.crate_ctxt cx, bool shared, @ast.crate crate) { +fn write_metadata(@trans.crate_ctxt cx, @ast.crate crate) { auto llmeta = C_postr(""); - if (shared) { + if (cx.sess.get_opts().shared) { llmeta = encode_metadata(cx, crate); } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 7e8e788efa8cc..3a654da8ae6ca 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -116,8 +116,7 @@ state type crate_ctxt = rec(session.session sess, std.sha1.sha1 sha, hashmap[ty.t, str] type_sha1s, hashmap[ty.t, metadata.ty_abbrev] type_abbrevs, - ty.ctxt tcx, - bool debuginfo); + ty.ctxt tcx); type local_ctxt = rec(vec[str] path, vec[str] module_path, @@ -1787,7 +1786,7 @@ fn declare_generic_glue(@local_ctxt cx, TypeRef llfnty, str name) -> ValueRef { auto fn_nm; - if (cx.ccx.debuginfo) { + if (cx.ccx.sess.get_opts().debuginfo) { fn_nm = mangle_name_by_type_only(cx.ccx, t, "glue_" + name); fn_nm = sanitize(fn_nm); } else { @@ -1972,9 +1971,7 @@ fn make_drop_glue(@block_ctxt cx, ValueRef v0, ty.t t) { C_int(abi.obj_body_elt_tydesc))); auto tydesc = cx.build.Load(tydescptr); - // FIXME: disabled for now. - // auto cx_ = maybe_call_dtor(cx, o); - auto cx_ = cx; + auto cx_ = maybe_call_dtor(cx, o); // Call through the obj's own fields-drop glue first. call_tydesc_glue_full(cx_, body, tydesc, @@ -2772,8 +2769,9 @@ fn maybe_call_dtor(@block_ctxt cx, ValueRef v) -> @block_ctxt { vtbl = cx.build.Load(vtbl); auto dtor_ptr = cx.build.GEP(vtbl, vec(C_int(0), C_int(0))); dtor_ptr = cx.build.Load(dtor_ptr); + auto self_t = llvm.LLVMGetElementType(val_ty(v)); dtor_ptr = cx.build.BitCast(dtor_ptr, - T_ptr(T_dtor(cx.fcx.lcx.ccx, val_ty(v)))); + T_ptr(T_dtor(cx.fcx.lcx.ccx, self_t))); auto dtor_cx = new_sub_block_ctxt(cx, "dtor"); auto after_cx = new_sub_block_ctxt(cx, "after_dtor"); @@ -2781,9 +2779,9 @@ fn maybe_call_dtor(@block_ctxt cx, ValueRef v) -> @block_ctxt { C_null(val_ty(dtor_ptr))); cx.build.CondBr(test, dtor_cx.llbb, after_cx.llbb); - // FIXME need to pass type params (?) + auto me = dtor_cx.build.Load(v); dtor_cx.build.FastCall(dtor_ptr, vec(C_null(T_ptr(T_nil())), - cx.fcx.lltaskptr, v)); + cx.fcx.lltaskptr, me)); dtor_cx.build.Br(after_cx.llbb); ret after_cx; } @@ -6358,6 +6356,8 @@ fn trans_obj(@local_ctxt cx, &ast._obj ob, ast.def_id oid, let TypeRef llbox_ty = T_opaque_obj_ptr(ccx.tn); + // FIXME we should probably also allocate a box for empty objs that have a + // dtor, since otherwise they are never dropped, and the dtor never runs if (_vec.len[ast.ty_param](ty_params) == 0u && _vec.len[ty.arg](arg_tys) == 0u) { // Store null into pair, if no args or typarams. @@ -7247,18 +7247,18 @@ fn is_object_or_assembly(output_type ot) -> bool { ret false; } -fn run_passes(ModuleRef llmod, bool opt, bool dbg, bool verify, - bool save_temps, str output, output_type ot) { +fn run_passes(session.session sess, ModuleRef llmod, str output) { auto pm = mk_pass_manager(); + auto opts = sess.get_opts(); // TODO: run the linter here also, once there are llvm-c bindings for it. // Generate a pre-optimization intermediate file if -save-temps was // specified. - if (save_temps) { - alt (ot) { + if (opts.save_temps) { + alt (opts.output_type) { case (output_type_bitcode) { - if (opt) { + if (opts.optimize) { auto filename = mk_intermediate_name(output, "no-opt.bc"); llvm.LLVMWriteBitcodeToFile(llmod, _str.buf(filename)); } @@ -7274,7 +7274,7 @@ fn run_passes(ModuleRef llmod, bool opt, bool dbg, bool verify, // available in the C api. // FIXME2: We might want to add optmization levels like -O1, -O2, -Os, etc // FIXME3: Should we expose and use the pass lists used by the opt tool? - if (opt) { + if (opts.optimize) { auto fpm = mk_pass_manager(); // createStandardFunctionPasses @@ -7330,25 +7330,25 @@ fn run_passes(ModuleRef llmod, bool opt, bool dbg, bool verify, llvm.LLVMAddConstantMergePass(pm.llpm); } - if (verify) { + if (opts.verify) { llvm.LLVMAddVerifierPass(pm.llpm); } // TODO: Write .s if -c was specified and -save-temps was on. - if (is_object_or_assembly(ot)) { + if (is_object_or_assembly(opts.output_type)) { let int LLVMAssemblyFile = 0; let int LLVMObjectFile = 1; let int LLVMNullFile = 2; auto FileType; - if (ot == output_type_object) { + if (opts.output_type == output_type_object) { FileType = LLVMObjectFile; } else { FileType = LLVMAssemblyFile; } // Write optimized bitcode if --save-temps was on. - if (save_temps) { - alt (ot) { + if (opts.save_temps) { + alt (opts.output_type) { case (output_type_bitcode) { /* nothing to do */ } case (_) { auto filename = mk_intermediate_name(output, "opt.bc"); @@ -7712,8 +7712,7 @@ fn make_glues(ModuleRef llmod, type_names tn) -> @glue_fns { vec_append_glue = make_vec_append_glue(llmod, tn)); } -fn make_common_glue(str output, bool optimize, bool verify, bool save_temps, - output_type ot) { +fn make_common_glue(session.session sess, str output) { // FIXME: part of this is repetitive and is probably a good idea // to autogen it, but things like the memcpy implementation are not // and it might be better to just check in a .ll file. @@ -7739,7 +7738,7 @@ fn make_common_glue(str output, bool optimize, bool verify, bool save_temps, trans_exit_task_glue(glues, new_str_hash[ValueRef](), tn, llmod); - run_passes(llmod, optimize, false, verify, save_temps, output, ot); + run_passes(sess, llmod, output); } fn create_module_map(@crate_ctxt ccx) -> ValueRef { @@ -7791,8 +7790,7 @@ fn create_crate_map(@crate_ctxt ccx) -> ValueRef { } fn trans_crate(session.session sess, @ast.crate crate, ty.ctxt tcx, - ty.type_cache type_cache, str output, - bool debuginfo, bool shared) + ty.type_cache type_cache, str output) -> ModuleRef { auto llmod = llvm.LLVMModuleCreateWithNameInContext(_str.buf("rust_out"), @@ -7842,8 +7840,7 @@ fn trans_crate(session.session sess, @ast.crate crate, ty.ctxt tcx, sha = std.sha1.mk_sha1(), type_sha1s = sha1s, type_abbrevs = abbrevs, - tcx = tcx, - debuginfo = debuginfo); + tcx = tcx); auto cx = new_local_ctxt(ccx); create_typedefs(ccx); @@ -7854,12 +7851,12 @@ fn trans_crate(session.session sess, @ast.crate crate, ty.ctxt tcx, trans_mod(cx, crate.node.module); trans_vec_append_glue(cx); auto crate_map = create_crate_map(ccx); - if (!shared) { + if (!sess.get_opts().shared) { trans_main_fn(cx, crate_ptr, crate_map); } // Translate the metadata. - middle.metadata.write_metadata(cx.ccx, shared, crate); + middle.metadata.write_metadata(cx.ccx, crate); ret llmod; } diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc index b506947a9c7c4..3074a84d07419 100644 --- a/src/comp/rustc.rc +++ b/src/comp/rustc.rc @@ -24,6 +24,7 @@ mod front { mod ast; mod creader; mod extfmt; + mod extenv; mod codemap; mod lexer; mod parser; diff --git a/src/rt/intrinsics/intrinsics.ll.in b/src/rt/intrinsics/intrinsics.ll.in index ebd5d15cff4a7..2a05555ef0261 100644 --- a/src/rt/intrinsics/intrinsics.ll.in +++ b/src/rt/intrinsics/intrinsics.ll.in @@ -1,6 +1,6 @@ ; ModuleID = 'intrinsics.cpp' target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32" -target triple = "$(LLVM_TRIPLE)" +target triple = "@CFG_LLVM_TRIPLE@" %0 = type { i32, i8**, i32 } %1 = type { %"struct.hash_map *>::map_entry"* } diff --git a/src/rt/memcheck.h b/src/rt/memcheck.h index bf95491b9b8cf..58480256e19dc 100644 --- a/src/rt/memcheck.h +++ b/src/rt/memcheck.h @@ -184,7 +184,7 @@ typedef /* Do a full memory leak check (like --leak-check=full) mid-execution. */ #define VALGRIND_DO_LEAK_CHECK \ - {unsigned long _qzz_res; \ + {unsigned long _qzz_res __attribute((unused)); \ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ VG_USERREQ__DO_LEAK_CHECK, \ 0, 0, 0, 0, 0); \ @@ -192,7 +192,7 @@ typedef /* Do a summary memory leak check (like --leak-check=summary) mid-execution. */ #define VALGRIND_DO_QUICK_LEAK_CHECK \ - {unsigned long _qzz_res; \ + {unsigned long _qzz_res __attribute((unused)); \ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ VG_USERREQ__DO_LEAK_CHECK, \ 1, 0, 0, 0, 0); \ @@ -207,7 +207,7 @@ typedef are. We also initialise '_qzz_leaked', etc because VG_USERREQ__COUNT_LEAKS doesn't mark the values returned as defined. */ \ - {unsigned long _qzz_res; \ + {unsigned long _qzz_res __attribute((unused)); \ unsigned long _qzz_leaked = 0, _qzz_dubious = 0; \ unsigned long _qzz_reachable = 0, _qzz_suppressed = 0; \ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ @@ -229,7 +229,7 @@ typedef are. We also initialise '_qzz_leaked', etc because VG_USERREQ__COUNT_LEAKS doesn't mark the values returned as defined. */ \ - {unsigned long _qzz_res; \ + {unsigned long _qzz_res __attribute((unused)); \ unsigned long _qzz_leaked = 0, _qzz_dubious = 0; \ unsigned long _qzz_reachable = 0, _qzz_suppressed = 0; \ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ diff --git a/src/rt/valgrind.h b/src/rt/valgrind.h index 0bae0aa130eec..737cc2a8b4224 100644 --- a/src/rt/valgrind.h +++ b/src/rt/valgrind.h @@ -4403,7 +4403,7 @@ vg_VALGRIND_DO_CLIENT_REQUEST_EXPR(uintptr_t _zzq_default, since it provides a way to make sure valgrind will retranslate the invalidated area. Returns no value. */ #define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \ - {unsigned int _qzz_res; \ + {unsigned int _qzz_res __attribute((unused)); \ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ VG_USERREQ__DISCARD_TRANSLATIONS, \ _qzz_addr, _qzz_len, 0, 0, 0); \ @@ -4652,7 +4652,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) Ignored if addr == 0. */ #define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \ - {unsigned int _qzz_res; \ + {unsigned int _qzz_res __attribute((unused)); \ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ VG_USERREQ__MALLOCLIKE_BLOCK, \ addr, sizeB, rzB, is_zeroed, 0); \ @@ -4662,7 +4662,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) Ignored if addr == 0. */ #define VALGRIND_FREELIKE_BLOCK(addr, rzB) \ - {unsigned int _qzz_res; \ + {unsigned int _qzz_res __attribute((unused)); \ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ VG_USERREQ__FREELIKE_BLOCK, \ addr, rzB, 0, 0, 0); \ @@ -4670,7 +4670,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) /* Create a memory pool. */ #define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \ - {unsigned int _qzz_res; \ + {unsigned int _qzz_res __attribute((unused)); \ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ VG_USERREQ__CREATE_MEMPOOL, \ pool, rzB, is_zeroed, 0, 0); \ @@ -4678,7 +4678,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) /* Destroy a memory pool. */ #define VALGRIND_DESTROY_MEMPOOL(pool) \ - {unsigned int _qzz_res; \ + {unsigned int _qzz_res __attribute((unused)); \ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ VG_USERREQ__DESTROY_MEMPOOL, \ pool, 0, 0, 0, 0); \ @@ -4686,7 +4686,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) /* Associate a piece of memory with a memory pool. */ #define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \ - {unsigned int _qzz_res; \ + {unsigned int _qzz_res __attribute((unused)); \ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ VG_USERREQ__MEMPOOL_ALLOC, \ pool, addr, size, 0, 0); \ @@ -4694,7 +4694,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) /* Disassociate a piece of memory from a memory pool. */ #define VALGRIND_MEMPOOL_FREE(pool, addr) \ - {unsigned int _qzz_res; \ + {unsigned int _qzz_res __attribute((unused)); \ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ VG_USERREQ__MEMPOOL_FREE, \ pool, addr, 0, 0, 0); \ @@ -4702,7 +4702,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) /* Disassociate any pieces outside a particular range. */ #define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \ - {unsigned int _qzz_res; \ + {unsigned int _qzz_res __attribute((unused)); \ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ VG_USERREQ__MEMPOOL_TRIM, \ pool, addr, size, 0, 0); \ @@ -4710,7 +4710,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) /* Resize and/or move a piece associated with a memory pool. */ #define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \ - {unsigned int _qzz_res; \ + {unsigned int _qzz_res __attribute((unused)); \ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ VG_USERREQ__MOVE_MEMPOOL, \ poolA, poolB, 0, 0, 0); \ @@ -4718,7 +4718,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) /* Resize and/or move a piece associated with a memory pool. */ #define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \ - {unsigned int _qzz_res; \ + {unsigned int _qzz_res __attribute((unused)); \ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ VG_USERREQ__MEMPOOL_CHANGE, \ pool, addrA, addrB, size, 0); \ @@ -4747,7 +4747,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) /* Unmark the piece of memory associated with a stack id as being a stack. */ #define VALGRIND_STACK_DEREGISTER(id) \ - {unsigned int _qzz_res; \ + {unsigned int _qzz_res __attribute((unused)); \ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ VG_USERREQ__STACK_DEREGISTER, \ id, 0, 0, 0, 0); \ @@ -4755,7 +4755,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) /* Change the start and end address of the stack id. */ #define VALGRIND_STACK_CHANGE(id, start, end) \ - {unsigned int _qzz_res; \ + {unsigned int _qzz_res __attribute((unused)); \ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ VG_USERREQ__STACK_CHANGE, \ id, start, end, 0, 0); \ @@ -4763,7 +4763,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) /* Load PDB debug info for Wine PE image_map. */ #define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \ - {unsigned int _qzz_res; \ + {unsigned int _qzz_res __attribute((unused)); \ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ VG_USERREQ__LOAD_PDB_DEBUGINFO, \ fd, ptr, total_size, delta, 0); \ @@ -4774,7 +4774,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) result will be dumped in there and is guaranteed to be zero terminated. If no info is found, the first byte is set to zero. */ #define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \ - {unsigned int _qzz_res; \ + {unsigned int _qzz_res __attribute((unused)); \ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ VG_USERREQ__MAP_IP_TO_SRCLOC, \ addr, buf64, 0, 0, 0); \ diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 6d342b0cad70c..01ea6677be126 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Linker.h" #include "llvm/PassManager.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/FormattedStream.h" @@ -25,12 +26,13 @@ using namespace llvm; -static char *LLVMRustError; +static const char *LLVMRustError; extern "C" LLVMMemoryBufferRef LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) { LLVMMemoryBufferRef MemBuf = NULL; - LLVMCreateMemoryBufferWithContentsOfFile(Path, &MemBuf, &LLVMRustError); + LLVMCreateMemoryBufferWithContentsOfFile(Path, &MemBuf, + const_cast(&LLVMRustError)); return MemBuf; } @@ -49,8 +51,24 @@ enum LLVMCodeGenFileType { LLVMNullFile // Do not emit any output. }; -extern "C" void LLVMRustWriteOutputFile(LLVMPassManagerRef PMR, LLVMModuleRef M, - const char *triple, const char *path, +extern "C" bool LLVMLinkModules(LLVMModuleRef Dest, LLVMModuleRef Src) { + static std::string err; + + // For some strange reason, unwrap() doesn't work here. "No matching + // function" error. + Module *DM = reinterpret_cast(Dest); + Module *SM = reinterpret_cast(Src); + if (Linker::LinkModules(DM, SM, &err)) { + LLVMRustError = err.c_str(); + return false; + } + return true; +} + +extern "C" void LLVMRustWriteOutputFile(LLVMPassManagerRef PMR, + LLVMModuleRef M, + const char *triple, + const char *path, LLVMCodeGenFileType FileType) { // Set compilation options. diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in index 0bd524c21cb66..74acb28bb9ccd 100644 --- a/src/rustllvm/rustllvm.def.in +++ b/src/rustllvm/rustllvm.def.in @@ -1,6 +1,7 @@ LLVMRustCreateMemoryBufferWithContentsOfFile LLVMRustWriteOutputFile LLVMRustGetLastError +LLVMLinkModules LLVMCreateObjectFile LLVMDisposeObjectFile LLVMGetSections diff --git a/src/snapshots.txt b/src/snapshots.txt index caa021e47bd4f..9187f59e51828 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -1,3 +1,8 @@ +S 2011-05-04 add7d34 + linux-i386 a85df9efb67bf83c5d71218a90d2a4935de2bec3 + macos-i386 68e40fddb4aa9ac86a0fa93e7c36d461698e204e + winnt-i386 fbc7bf335af774cc7f904ceba725f18acbb5fcd9 + S 2011-05-04 4642d7a linux-i386 631d4c375a8cc74de77c2f9aa79d3c404f8c353b macos-i386 61b5a0eebb4eea8242d5cbc4a9967882b6a99cb4