From b12de9881418ff9fff8318d0142fa101efd9dc08 Mon Sep 17 00:00:00 2001 From: Haitao Li Date: Mon, 7 Nov 2011 21:32:13 +0800 Subject: [PATCH] rustc: Add support of generating LLVM assembly rustc generates output files in LLVM bitcode format if "--emit-llvm" option is given. When used with the "-S" option, rustc generates LLVM intermediate language assembly files. Fixes Issue #476 --- src/comp/back/link.rs | 18 +++++++++++++----- src/comp/driver/rustc.rs | 3 +++ src/comp/lib/llvm.rs | 3 +++ src/rustllvm/RustWrapper.cpp | 12 ++++++++++++ src/rustllvm/rustllvm.def.in | 1 + 5 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/comp/back/link.rs b/src/comp/back/link.rs index 8d46774712ab..05cd3ba6d36e 100644 --- a/src/comp/back/link.rs +++ b/src/comp/back/link.rs @@ -30,6 +30,7 @@ tag output_type { output_type_none; output_type_bitcode; output_type_assembly; + output_type_llvm_assembly; output_type_object; output_type_exe; } @@ -254,12 +255,19 @@ mod write { if opts.time_llvm_passes { llvm::LLVMRustPrintPassTimings(); } ret; } - // If only a bitcode file is asked for by using the '--emit-llvm' - // flag, then output it here - llvm::LLVMRunPassManager(pm.llpm, llmod); - str::as_buf(output, - {|buf| llvm::LLVMWriteBitcodeToFile(llmod, buf) }); + if opts.output_type == output_type_llvm_assembly { + // Given options "-S --emit-llvm": output LLVM assembly + str::as_buf(output, {|buf_o| + llvm::LLVMRustAddPrintModulePass(pm.llpm, llmod, buf_o)}); + } else { + // If only a bitcode file is asked for by using the '--emit-llvm' + // flag, then output it here + llvm::LLVMRunPassManager(pm.llpm, llmod); + str::as_buf(output, + {|buf| llvm::LLVMWriteBitcodeToFile(llmod, buf) }); + } + llvm::LLVMDisposeModule(llmod); if opts.time_llvm_passes { llvm::LLVMRustPrintPassTimings(); } } diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index 74d13c9a4ca0..3787baffc825 100644 --- a/src/comp/driver/rustc.rs +++ b/src/comp/driver/rustc.rs @@ -344,6 +344,8 @@ fn build_session_options(match: getopts::match) let output_type = if parse_only || no_trans { link::output_type_none + } else if opt_present(match, "S") && opt_present(match, "emit-llvm") { + link::output_type_llvm_assembly } else if opt_present(match, "S") { link::output_type_assembly } else if opt_present(match, "c") { @@ -475,6 +477,7 @@ fn build_output_filenames(ifile: str, ofile: option::t, link::output_type_none. { "none" } link::output_type_bitcode. { "bc" } link::output_type_assembly. { "s" } + link::output_type_llvm_assembly. { "s" } // Object and exe output both use the '.o' extension here link::output_type_object. | link::output_type_exe. { "o" diff --git a/src/comp/lib/llvm.rs b/src/comp/lib/llvm.rs index b189f2177c05..ed38682ff7af 100644 --- a/src/comp/lib/llvm.rs +++ b/src/comp/lib/llvm.rs @@ -866,6 +866,9 @@ native "c-stack-cdecl" mod llvm = "rustllvm" { fn LLVMRustConstSmallInt(IntTy: TypeRef, N: uint, SignExtend: Bool) -> ValueRef; + fn LLVMRustAddPrintModulePass(PM: PassManagerRef, M: ModuleRef, + Output: sbuf); + /** Turn on LLVM pass-timing. */ fn LLVMRustEnableTimePasses(); /** Turn on LLVM segmented stacks. */ diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index a9373b6c7e5b..26d0764934e0 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -15,6 +15,7 @@ #include "llvm/Linker.h" #include "llvm/PassManager.h" #include "llvm/ADT/Triple.h" +#include "llvm/Assembly/PrintModulePass.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" @@ -46,6 +47,17 @@ extern "C" const char *LLVMRustGetLastError(void) { extern "C" void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM); +extern "C" void LLVMRustAddPrintModulePass(LLVMPassManagerRef PMR, + LLVMModuleRef M, + const char* path) { + PassManager *PM = unwrap(PMR); + std::string ErrorInfo; + raw_fd_ostream OS(path, ErrorInfo, raw_fd_ostream::F_Binary); + formatted_raw_ostream FOS(OS); + PM->add(createPrintModulePass(&FOS)); + PM->run(*unwrap(M)); +} + extern "C" bool LLVMLinkModules(LLVMModuleRef Dest, LLVMModuleRef Src) { static std::string err; diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in index beaa3980d8ee..b418ba168c88 100644 --- a/src/rustllvm/rustllvm.def.in +++ b/src/rustllvm/rustllvm.def.in @@ -24,6 +24,7 @@ LLVMAddAlias LLVMAddArgumentPromotionPass LLVMAddAttribute LLVMAddBasicAliasAnalysisPass +LLVMRustAddPrintModulePass LLVMAddCFGSimplificationPass LLVMAddCase LLVMAddClause