From e0479c902b0b5a5c521ce4d3bc38c937a80faf21 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 25 Apr 2011 14:08:12 -0700 Subject: [PATCH] rustc: Add a -save-temps option to save bitcode and write output simultaneously; document command line switches --- src/comp/driver/rustc.rs | 20 +++++++++++---- src/comp/middle/trans.rs | 55 +++++++++++++++++++++++++++++++++++----- 2 files changed, 64 insertions(+), 11 deletions(-) diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index eabf03102e2..890e69da269 100644 --- a/src/comp/driver/rustc.rs +++ b/src/comp/driver/rustc.rs @@ -62,6 +62,7 @@ fn compile_input(session.session sess, bool shared, bool optimize, bool verify, + bool save_temps, trans.output_type ot, vec[str] library_search_paths) { auto def = tup(0, 0); @@ -80,7 +81,7 @@ fn compile_input(session.session sess, // FIXME: uncomment once typestate_check works // crate = typestate_check.check_crate(crate); trans.trans_crate(sess, crate, ty_cx, type_cache, output, shared, - optimize, verify, ot); + optimize, verify, save_temps, ot); } fn pretty_print_input(session.session sess, @@ -111,6 +112,11 @@ options: -ls list the symbols defined by a crate file -L add a directory to the library search path -noverify suppress LLVM verification step (slight speedup) + -parse-only parse only; do not compile, assemble, or link + -O optimize + -S compile only; do not assemble or link + -c compile and assemble, but do not link + -save-temps write intermediate files in addition to normal output -h display this message\n\n"); } @@ -146,6 +152,7 @@ fn main(vec[str] args) { auto ot = trans.output_type_bitcode; let bool glue = false; let bool verify = true; + let bool save_temps = false; // FIXME: Maybe we should support -O0, -O1, -Os, etc let bool optimize = false; @@ -183,6 +190,8 @@ fn main(vec[str] args) { usage(sess, args.(0)); sess.err("-o requires an argument"); } + } else if (_str.eq(arg, "-save-temps")) { + save_temps = true; } else if (_str.eq(arg, "-L")) { if (i+1u < len) { library_search_paths += vec(args.(i+1u)); @@ -221,10 +230,11 @@ fn main(vec[str] args) { alt (output_file) { case (none[str]) { middle.trans.make_common_glue("glue.bc", optimize, verify, - ot); + save_temps, ot); } case (some[str](?s)) { - middle.trans.make_common_glue(s, optimize, verify, ot); + middle.trans.make_common_glue(s, optimize, verify, save_temps, + ot); } } ret; @@ -250,12 +260,12 @@ fn main(vec[str] args) { parts += vec(".bc"); auto ofile = _str.concat(parts); compile_input(sess, env, ifile, ofile, shared, - optimize, verify, ot, + optimize, verify, save_temps, ot, library_search_paths); } case (some[str](?ofile)) { compile_input(sess, env, ifile, ofile, shared, - optimize, verify, ot, + optimize, verify, save_temps, ot, library_search_paths); } } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 4a1242abb22..40294862229 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -6980,6 +6980,19 @@ tag output_type { output_type_object; } +// Decides what to call an intermediate file, given the name of the output and +// the extension to use. +fn mk_intermediate_name(str output_path, str extension) -> str { + auto dot_pos = _str.index(output_path, '.' as u8); + auto stem; + if (dot_pos < 0) { + stem = output_path; + } else { + stem = _str.substr(output_path, 0u, dot_pos as uint); + } + ret stem + "." + extension; +} + fn is_object_or_assembly(output_type ot) -> bool { if (ot == output_type_assembly) { ret true; @@ -6990,12 +7003,29 @@ fn is_object_or_assembly(output_type ot) -> bool { ret false; } -fn run_passes(ModuleRef llmod, bool opt, bool verify, str output, - output_type ot) { +fn run_passes(ModuleRef llmod, bool opt, bool verify, bool save_temps, + str output, output_type ot) { auto pm = mk_pass_manager(); // 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) { + case (output_type_bitcode) { + if (opt) { + auto filename = mk_intermediate_name(output, "no-opt.bc"); + llvm.LLVMWriteBitcodeToFile(llmod, _str.buf(filename)); + } + } + case (_) { + auto filename = mk_intermediate_name(output, "bc"); + llvm.LLVMWriteBitcodeToFile(llmod, _str.buf(filename)); + } + } + } + // FIXME: This is mostly a copy of the bits of opt's -O2 that are // available in the C api. // FIXME2: We might want to add optmization levels like -O1, -O2, -Os, etc @@ -7054,12 +7084,25 @@ fn run_passes(ModuleRef llmod, bool opt, bool verify, str output, llvm.LLVMAddStripDeadPrototypesPass(pm.llpm); llvm.LLVMAddDeadTypeEliminationPass(pm.llpm); llvm.LLVMAddConstantMergePass(pm.llpm); + + // Generate a post-optimization intermediate file if -save-temps was + // specified. + if (save_temps) { + alt (ot) { + case (output_type_bitcode) { /* nothing to do */ } + case (_) { + auto filename = mk_intermediate_name(output, "opt.bc"); + llvm.LLVMWriteBitcodeToFile(llmod, _str.buf(filename)); + } + } + } } if (verify) { llvm.LLVMAddVerifierPass(pm.llpm); } + // TODO: Write .s if -c was specified and -save-temps was on. if (is_object_or_assembly(ot)) { let int LLVMAssemblyFile = 0; let int LLVMObjectFile = 1; @@ -7414,7 +7457,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, +fn make_common_glue(str output, bool optimize, bool verify, bool save_temps, output_type ot) { // FIXME: part of this is repetitive and is probably a good idea // to autogen it, but things like the memcpy implementation are not @@ -7441,7 +7484,7 @@ fn make_common_glue(str output, bool optimize, bool verify, trans_exit_task_glue(glues, new_str_hash[ValueRef](), tn, llmod); - run_passes(llmod, optimize, verify, output, ot); + run_passes(llmod, optimize, verify, save_temps, output, ot); } fn create_module_map(@crate_ctxt ccx) -> ValueRef { @@ -7494,7 +7537,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 shared, - bool optimize, bool verify, output_type ot) { + bool optimize, bool verify, bool save_temps, output_type ot) { auto llmod = llvm.LLVMModuleCreateWithNameInContext(_str.buf("rust_out"), llvm.LLVMGetGlobalContext()); @@ -7557,7 +7600,7 @@ fn trans_crate(session.session sess, @ast.crate crate, ty.ctxt tcx, // Translate the metadata. middle.metadata.write_metadata(cx.ccx, crate); - run_passes(llmod, optimize, verify, output, ot); + run_passes(llmod, optimize, verify, save_temps, output, ot); } //