diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index 9b2d88e8ffd..d6f6f6944c4 100644 --- a/src/comp/driver/rustc.rs +++ b/src/comp/driver/rustc.rs @@ -60,12 +60,12 @@ impure fn compile_input(session.session sess, str input, str output, bool shared, bool optimize, - bool parse_only, + trans.output_type ot, vec[str] library_search_paths) { auto def = tup(0, 0); auto p = parser.new_parser(sess, env, def, input, 0u); auto crate = parse_input(sess, p, input); - if (parse_only) {ret;} + if (ot == trans.output_type_none) {ret;} crate = creader.read_crates(sess, crate, library_search_paths); crate = resolve.resolve_crate(sess, crate); capture.check_for_captures(sess, crate); @@ -74,7 +74,8 @@ impure fn compile_input(session.session sess, auto type_cache = typeck_result._1; // FIXME: uncomment once typestate_check works // crate = typestate_check.check_crate(crate); - trans.trans_crate(sess, crate, type_cache, output, shared, optimize); + trans.trans_crate(sess, crate, type_cache, output, shared, optimize, + ot); } impure fn pretty_print_input(session.session sess, @@ -137,7 +138,7 @@ impure fn main(vec[str] args) { let bool shared = false; let bool pretty = false; let bool ls = false; - let bool parse_only = false; + auto ot = trans.output_type_bitcode; let bool glue = false; // FIXME: Maybe we should support -O0, -O1, -Os, etc @@ -163,7 +164,9 @@ impure fn main(vec[str] args) { } else if (_str.eq(arg, "-ls")) { ls = true; } else if (_str.eq(arg, "-parse-only")) { - parse_only = true; + ot = trans.output_type_none; + } else if (_str.eq(arg, "-S")) { + ot = trans.output_type_assembly; } else if (_str.eq(arg, "-o")) { if (i+1u < len) { output_file = some(args.(i+1u)); @@ -207,10 +210,10 @@ impure fn main(vec[str] args) { if (glue) { alt (output_file) { case (none[str]) { - middle.trans.make_common_glue("glue.bc", optimize); + middle.trans.make_common_glue("glue.bc", optimize, ot); } case (some[str](?s)) { - middle.trans.make_common_glue(s, optimize); + middle.trans.make_common_glue(s, optimize, ot); } } ret; @@ -236,12 +239,12 @@ impure fn main(vec[str] args) { parts += vec(".bc"); auto ofile = _str.concat(parts); compile_input(sess, env, ifile, ofile, shared, - optimize, parse_only, + optimize, ot, library_search_paths); } case (some[str](?ofile)) { compile_input(sess, env, ifile, ofile, shared, - optimize, parse_only, + optimize, ot, library_search_paths); } } diff --git a/src/comp/lib/llvm.rs b/src/comp/lib/llvm.rs index 6770320598a..8d0910d54d9 100644 --- a/src/comp/lib/llvm.rs +++ b/src/comp/lib/llvm.rs @@ -815,6 +815,9 @@ native mod llvm = llvm_lib { fn LLVMRustCreateMemoryBufferWithContentsOfFile(sbuf Path) -> MemoryBufferRef; + fn LLVMRustWriteAssembly(PassManagerRef PM, ModuleRef M, + sbuf Triple, sbuf Output); + /** Returns a string describing the last error caused by an LLVMRust* call. */ fn LLVMRustGetLastError() -> sbuf; diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 71ad468c979..187265e96d6 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -6675,8 +6675,14 @@ fn trap(@block_ctxt bcx) { let vec[ValueRef] v = vec(); bcx.build.Call(bcx.fcx.ccx.intrinsics.get("llvm.trap"), v); } +tag output_type { + output_type_none; + output_type_bitcode; + output_type_assembly; +} -fn run_passes(ModuleRef llmod, bool opt) { +fn run_passes(ModuleRef llmod, bool opt, str output, + output_type ot) { auto pm = mk_pass_manager(); // TODO: run the linter here also, once there are llvm-c bindings for it. @@ -6741,7 +6747,18 @@ fn run_passes(ModuleRef llmod, bool opt) { llvm.LLVMAddConstantMergePass(pm.llpm); } llvm.LLVMAddVerifierPass(pm.llpm); + + if (ot == output_type_assembly) { + llvm.LLVMRustWriteAssembly(pm.llpm, llmod, + _str.buf(x86.get_target_triple()), + _str.buf(output)); + ret; + } + llvm.LLVMRunPassManager(pm.llpm, llmod); + + llvm.LLVMWriteBitcodeToFile(llmod, _str.buf(output)); + llvm.LLVMDisposeModule(llmod); } fn decl_no_op_type_glue(ModuleRef llmod, type_names tn) -> ValueRef { @@ -7073,7 +7090,8 @@ 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) { +fn make_common_glue(str output, bool optimize, + 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 // and it might be better to just check in a .ll file. @@ -7099,15 +7117,12 @@ fn make_common_glue(str output, bool optimize) { trans_exit_task_glue(glues, new_str_hash[ValueRef](), tn, llmod); - run_passes(llmod, optimize); - - llvm.LLVMWriteBitcodeToFile(llmod, _str.buf(output)); - llvm.LLVMDisposeModule(llmod); + run_passes(llmod, optimize, output, ot); } fn trans_crate(session.session sess, @ast.crate crate, &ty.type_cache type_cache, str output, bool shared, - bool optimize) { + bool optimize, output_type ot) { auto llmod = llvm.LLVMModuleCreateWithNameInContext(_str.buf("rust_out"), llvm.LLVMGetGlobalContext()); @@ -7170,10 +7185,7 @@ fn trans_crate(session.session sess, @ast.crate crate, // Translate the metadata. middle.metadata.write_metadata(cx, crate); - run_passes(llmod, optimize); - - llvm.LLVMWriteBitcodeToFile(llmod, _str.buf(output)); - llvm.LLVMDisposeModule(llmod); + run_passes(llmod, optimize, output, ot); } // diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index ac9b48cda8f..81b8cbc9e0c 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -12,10 +12,18 @@ // //===----------------------------------------------------------------------===// +#include "llvm/PassManager.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetSelect.h" +#include "llvm/Target/TargetRegistry.h" #include "llvm-c/Core.h" #include "llvm-c/Object.h" #include +using namespace llvm; + static char *LLVMRustError; extern "C" LLVMMemoryBufferRef @@ -33,3 +41,24 @@ extern "C" void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM); void (*RustHackToFetchPassesO)(LLVMPassManagerRef PM) = LLVMAddBasicAliasAnalysisPass; + +extern "C" void LLVMRustWriteAssembly(LLVMPassManagerRef PMR, LLVMModuleRef M, + const char *triple, const char *path) { + InitializeAllTargets(); + InitializeAllAsmPrinters(); + std::string Err; + const Target *TheTarget = TargetRegistry::lookupTarget(triple, Err); + std::string FeaturesStr; + TargetMachine &Target = *TheTarget->createTargetMachine(triple, FeaturesStr); + bool NoVerify = false; + CodeGenOpt::Level OLvl = CodeGenOpt::Default; + TargetMachine::CodeGenFileType FileType = TargetMachine::CGFT_AssemblyFile; + PassManager *PM = unwrap(PMR); + std::string ErrorInfo; + raw_fd_ostream OS(path, ErrorInfo, + raw_fd_ostream::F_Binary); + formatted_raw_ostream FOS(OS); + bool foo = Target.addPassesToEmitFile(*PM, FOS, FileType, OLvl, NoVerify); + assert(!foo); + PM->run(*unwrap(M)); +} diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in index 58f395c09e1..f95bb90b0f3 100644 --- a/src/rustllvm/rustllvm.def.in +++ b/src/rustllvm/rustllvm.def.in @@ -1,4 +1,5 @@ LLVMRustCreateMemoryBufferWithContentsOfFile +LLVMRustWriteAssembly LLVMRustGetLastError LLVMCreateObjectFile LLVMDisposeObjectFile