]> git.lizzy.rs Git - rust.git/commitdiff
Add experimental JIT compiler
authorZack Corr <zack@z0w0.me>
Sat, 25 Aug 2012 04:54:30 +0000 (14:54 +1000)
committerBrian Anderson <banderson@mozilla.com>
Fri, 31 Aug 2012 23:20:35 +0000 (16:20 -0700)
Makefile.in
configure
src/rustc/back/link.rs
src/rustc/driver/driver.rs
src/rustc/driver/rustc.rs
src/rustc/driver/session.rs
src/rustc/lib/llvm.rs
src/rustllvm/RustWrapper.cpp
src/rustllvm/rustllvm.def.in

index 79c6e7e345ac317be96891ed9b9a18722c4fd20c..608f4a3d3ceb3d7ff8bf1c073c678e592e00c7d3 100644 (file)
@@ -216,7 +216,8 @@ RUSTC_INPUTS := $(S)src/rustc/driver/rustc.rs
 ######################################################################
 
 # FIXME: x86-ism
-LLVM_COMPONENTS=x86 ipo bitreader bitwriter linker asmparser
+LLVM_COMPONENTS=x86 ipo bitreader bitwriter linker asmparser jit mcjit \
+                interpreter
 
 define DEF_LLVM_VARS
 # The configure script defines these variables with the target triples
index 040bae9fe60a3a236c4cb797f76822a5a573f220..8cc6f02c7dbb1b56d594f0b20dce663444e9314b 100755 (executable)
--- a/configure
+++ b/configure
@@ -595,7 +595,7 @@ do
         LLVM_TARGET="--target=$t"
 
         # Disable unused LLVM features
-        LLVM_OPTS="$LLVM_DBG_OPTS --disable-docs --disable-jit \
+        LLVM_OPTS="$LLVM_DBG_OPTS --disable-docs \
                    --enable-bindings=none --disable-threads \
                    --disable-pthreads"
 
index a81755be9333d971b247104ebb7b874c0492337a..04c38c11d62aa41b295c5e359d35d236876d938c 100644 (file)
@@ -76,6 +76,7 @@ fn run_passes(sess: session, llmod: ModuleRef, output: &Path) {
         // Generate a pre-optimization intermediate file if -save-temps was
         // specified.
 
+
         if opts.save_temps {
             match opts.output_type {
               output_type_bitcode => {
@@ -135,7 +136,7 @@ fn run_passes(sess: session, llmod: ModuleRef, output: &Path) {
             llvm::LLVMPassManagerBuilderDispose(MPMB);
         }
         if !sess.no_verify() { llvm::LLVMAddVerifierPass(pm.llpm); }
-        if is_object_or_assembly_or_exe(opts.output_type) {
+        if is_object_or_assembly_or_exe(opts.output_type) || opts.jit {
             let LLVMOptNone       = 0 as c_int; // -O0
             let LLVMOptLess       = 1 as c_int; // -O1
             let LLVMOptDefault    = 2 as c_int; // -O2, -Os
@@ -148,6 +149,29 @@ fn run_passes(sess: session, llmod: ModuleRef, output: &Path) {
               session::Aggressive => LLVMOptAggressive
             };
 
+            if opts.jit {
+                // If we are using JIT, go ahead and create and
+                // execute the engine now.
+
+                /*llvm::LLVMAddBasicAliasAnalysisPass(pm.llpm);
+                llvm::LLVMAddInstructionCombiningPass(pm.llpm);
+                llvm::LLVMAddReassociatePass(pm.llpm);
+                llvm::LLVMAddGVNPass(pm.llpm);
+                llvm::LLVMAddCFGSimplificationPass(pm.llpm);*/
+
+                // JIT execution takes ownership of the module,
+                // so don't dispose and return.
+
+                if !llvm::LLVMRustJIT(pm.llpm,
+                                      llmod,
+                                      CodeGenOptLevel,
+                                      true) {
+                    llvm_err(sess, ~"Could not JIT");
+                }
+                if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); }
+                return;
+            }
+
             let mut FileType;
             if opts.output_type == output_type_object ||
                    opts.output_type == output_type_exe {
index c9be01f4d5647fe874f6a9511650e2f512af7b35..2d5b36debaa7aab0e500450e48d49e1b69e9c88f 100644 (file)
@@ -259,7 +259,8 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
 
     let stop_after_codegen =
         sess.opts.output_type != link::output_type_exe ||
-            sess.opts.static && sess.building_library;
+        (sess.opts.static && sess.building_library)    ||
+        sess.opts.jit;
 
     if stop_after_codegen { return {crate: crate, tcx: Some(ty_cx)}; }
 
@@ -483,6 +484,7 @@ fn build_session_options(matches: getopts::Matches,
         llvm::LLVMSetDebug(1);
     }
 
+    let jit = opt_present(matches, ~"jit");
     let output_type =
         if parse_only || no_trans {
             link::output_type_none
@@ -545,6 +547,7 @@ fn build_session_options(matches: getopts::Matches,
           extra_debuginfo: extra_debuginfo,
           lint_opts: lint_opts,
           save_temps: save_temps,
+          jit: jit,
           output_type: output_type,
           addl_lib_search_paths: addl_lib_search_paths,
           maybe_sysroot: sysroot_opt,
@@ -620,6 +623,7 @@ fn opts() -> ~[getopts::Opt] {
           optopt(~"o"), optopt(~"out-dir"), optflag(~"xg"),
           optflag(~"c"), optflag(~"g"), optflag(~"save-temps"),
           optopt(~"sysroot"), optopt(~"target"),
+          optflag(~"jit"),
 
           optmulti(~"W"), optmulti(~"warn"),
           optmulti(~"A"), optmulti(~"allow"),
index d1929a6862974f42a8691d3ef4d5cd09bd85eec2..42982550325e2cfe95937772c34641a6f55f260d 100644 (file)
@@ -42,6 +42,7 @@ fn usage(argv0: ~str) {
     -L <path>          Add a directory to the library search path
     --lib              Compile a library crate
     --ls               List the symbols defined by a compiled library crate
+    --jit              Execute using JIT (experimental)
     --no-trans         Run all passes except translation; no output
     -O                 Equivalent to --opt-level=2
     -o <filename>      Write output to <filename>
index 59c4e5697adcf276e8952d3a0d6feef758c20646..47aa3019de10e3547f5f8d46e8b2124ea4b2bdc0 100644 (file)
@@ -108,6 +108,7 @@ impl OptLevel : cmp::Eq {
      extra_debuginfo: bool,
      lint_opts: ~[(lint::lint, lint::level)],
      save_temps: bool,
+     jit: bool,
      output_type: back::link::output_type,
      addl_lib_search_paths: ~[Path],
      maybe_sysroot: Option<Path>,
@@ -249,6 +250,7 @@ fn basic_options() -> @options {
         extra_debuginfo: false,
         lint_opts: ~[],
         save_temps: false,
+        jit: false,
         output_type: link::output_type_exe,
         addl_lib_search_paths: ~[],
         maybe_sysroot: None,
index 1440a654a8978a4ec956093a2847b758ac29b4d8..5c8bab166ecb20f86078e51f1ee979a98c5ea6d2 100644 (file)
@@ -986,6 +986,12 @@ fn LLVMRustWriteOutputFile(PM: PassManagerRef, M: ModuleRef,
         call. */
     fn LLVMRustGetLastError() -> *c_char;
 
+    /** JIT the module. **/
+    fn LLVMRustJIT(PM: PassManagerRef,
+                   M: ModuleRef,
+                   OptLevel: c_int,
+                   EnableSegmentedStacks: bool) -> bool;
+
     /** Parses the bitcode in the given memory buffer. */
     fn LLVMRustParseBitcode(MemBuf: MemoryBufferRef) -> ModuleRef;
 
index 4a927744f07a0e15014db331f8e6bddebcde2e81..8f8503a74d497578b507861be8e4c8a307505405 100644 (file)
 #include "llvm/Target/TargetOptions.h"
 #include "llvm/Support/Host.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/JIT.h"
+#include "llvm/ExecutionEngine/Interpreter.h"
+#include "llvm/ExecutionEngine/GenericValue.h"
 #include "llvm-c/Core.h"
 #include "llvm-c/BitReader.h"
 #include "llvm-c/Object.h"
@@ -68,6 +73,61 @@ void LLVMInitializeX86TargetMC();
 void LLVMInitializeX86AsmPrinter();
 void LLVMInitializeX86AsmParser();
 
+// Only initialize the platforms supported by Rust here,
+// because using --llvm-root will have multiple platforms
+// that rustllvm doesn't actually link to and it's pointless to put target info
+// into the registry that Rust can not generate machine code for.
+
+#define INITIALIZE_TARGETS() LLVMInitializeX86TargetInfo(); \
+                             LLVMInitializeX86Target(); \
+                             LLVMInitializeX86TargetMC(); \
+                             LLVMInitializeX86AsmPrinter(); \
+                             LLVMInitializeX86AsmParser();
+
+extern "C" bool
+LLVMRustJIT(LLVMPassManagerRef PMR,
+            LLVMModuleRef M,
+            CodeGenOpt::Level OptLevel,
+            bool EnableSegmentedStacks) {
+
+  INITIALIZE_TARGETS();
+  InitializeNativeTarget();
+  InitializeNativeTargetAsmPrinter();
+
+  std::string Err;
+  TargetOptions Options;
+  Options.NoFramePointerElim = true;
+  Options.EnableSegmentedStacks = EnableSegmentedStacks;
+
+  PassManager *PM = unwrap<PassManager>(PMR);
+
+  PM->run(*unwrap(M));
+
+  ExecutionEngine* EE = EngineBuilder(unwrap(M))
+    .setTargetOptions(Options)
+    .setOptLevel(OptLevel)
+    .setUseMCJIT(true)
+    .create();
+
+  if(!EE || Err != "") {
+    LLVMRustError = Err.c_str();
+    return false;
+  }
+
+  Function* func = EE->FindFunctionNamed("main");
+
+  if(!func || Err != "") {
+    LLVMRustError = Err.c_str();
+    return false;
+  }
+
+  std::vector<GenericValue> args;
+
+  EE->runFunction(func, args);
+
+  return true;
+}
+
 extern "C" bool
 LLVMRustWriteOutputFile(LLVMPassManagerRef PMR,
                         LLVMModuleRef M,
@@ -77,16 +137,7 @@ LLVMRustWriteOutputFile(LLVMPassManagerRef PMR,
                         CodeGenOpt::Level OptLevel,
                        bool EnableSegmentedStacks) {
 
-  // Only initialize the platforms supported by Rust here,
-  // because using --llvm-root will have multiple platforms
-  // that rustllvm doesn't actually link to and it's pointless to put target info
-  // into the registry that Rust can not generate machine code for.
-
-  LLVMInitializeX86TargetInfo();
-  LLVMInitializeX86Target();
-  LLVMInitializeX86TargetMC();
-  LLVMInitializeX86AsmPrinter();
-  LLVMInitializeX86AsmParser();
+  INITIALIZE_TARGETS();
 
   TargetOptions Options;
   Options.NoFramePointerElim = true;
index 64b560999bec5e40e34f43b51d745aa28d297b07..2fd4b3fa6f3594a1b2298bf4f6a0b15c85495189 100644 (file)
@@ -4,6 +4,7 @@ LLVMRustWriteOutputFile
 LLVMRustGetLastError
 LLVMRustConstSmallInt
 LLVMRustConstInt
+LLVMRustJIT
 LLVMRustParseBitcode
 LLVMRustParseAssemblyFile
 LLVMRustPrintPassTimings
@@ -485,6 +486,7 @@ LLVMIsThreadLocal
 LLVMIsUndef
 LLVMLabelType
 LLVMLabelTypeInContext
+LLVMLinkInInterpreter
 LLVMMDNode
 LLVMMDNodeInContext
 LLVMMDString