summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorRafael Ávila de Espíndola <respindola@mozilla.com>2011-04-15 17:35:46 -0400
committerRafael Ávila de Espíndola <respindola@mozilla.com>2011-04-15 17:41:14 -0400
commit2214b6835d8bf5b33a3fb8b6a897abaea55ef368 (patch)
treed6209d2e1dca535f4e0e5225108a6b8cb876c266 /src
parent790084ced18ca391c30d8e1045c04cbf2111499e (diff)
downloadrust-2214b6835d8bf5b33a3fb8b6a897abaea55ef368.tar.gz
rust-2214b6835d8bf5b33a3fb8b6a897abaea55ef368.zip
Add a -S option for producing assembly. I will move more of it to
rust once the necessary APIs are available in C.
Diffstat (limited to 'src')
-rw-r--r--src/comp/driver/rustc.rs21
-rw-r--r--src/comp/lib/llvm.rs3
-rw-r--r--src/comp/middle/trans.rs34
-rw-r--r--src/rustllvm/RustWrapper.cpp29
-rw-r--r--src/rustllvm/rustllvm.def.in1
5 files changed, 68 insertions, 20 deletions
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 <cstdlib>
 
+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<PassManager>(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