Skip to content

Commit d7aa991

Browse files
z0w0brson
authored andcommitted
Add experimental JIT compiler
1 parent 97bb812 commit d7aa991

File tree

9 files changed

+105
-14
lines changed

9 files changed

+105
-14
lines changed

Makefile.in

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,8 @@ RUSTC_INPUTS := $(S)src/rustc/driver/rustc.rs
216216
######################################################################
217217

218218
# FIXME: x86-ism
219-
LLVM_COMPONENTS=x86 ipo bitreader bitwriter linker asmparser
219+
LLVM_COMPONENTS=x86 ipo bitreader bitwriter linker asmparser jit mcjit \
220+
interpreter
220221

221222
define DEF_LLVM_VARS
222223
# The configure script defines these variables with the target triples

configure

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ do
595595
LLVM_TARGET="--target=$t"
596596

597597
# Disable unused LLVM features
598-
LLVM_OPTS="$LLVM_DBG_OPTS --disable-docs --disable-jit \
598+
LLVM_OPTS="$LLVM_DBG_OPTS --disable-docs \
599599
--enable-bindings=none --disable-threads \
600600
--disable-pthreads"
601601

src/rustc/back/link.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ mod write {
7676
// Generate a pre-optimization intermediate file if -save-temps was
7777
// specified.
7878

79+
7980
if opts.save_temps {
8081
match opts.output_type {
8182
output_type_bitcode => {
@@ -135,7 +136,7 @@ mod write {
135136
llvm::LLVMPassManagerBuilderDispose(MPMB);
136137
}
137138
if !sess.no_verify() { llvm::LLVMAddVerifierPass(pm.llpm); }
138-
if is_object_or_assembly_or_exe(opts.output_type) {
139+
if is_object_or_assembly_or_exe(opts.output_type) || opts.jit {
139140
let LLVMOptNone = 0 as c_int; // -O0
140141
let LLVMOptLess = 1 as c_int; // -O1
141142
let LLVMOptDefault = 2 as c_int; // -O2, -Os
@@ -148,6 +149,29 @@ mod write {
148149
session::Aggressive => LLVMOptAggressive
149150
};
150151

152+
if opts.jit {
153+
// If we are using JIT, go ahead and create and
154+
// execute the engine now.
155+
156+
/*llvm::LLVMAddBasicAliasAnalysisPass(pm.llpm);
157+
llvm::LLVMAddInstructionCombiningPass(pm.llpm);
158+
llvm::LLVMAddReassociatePass(pm.llpm);
159+
llvm::LLVMAddGVNPass(pm.llpm);
160+
llvm::LLVMAddCFGSimplificationPass(pm.llpm);*/
161+
162+
// JIT execution takes ownership of the module,
163+
// so don't dispose and return.
164+
165+
if !llvm::LLVMRustJIT(pm.llpm,
166+
llmod,
167+
CodeGenOptLevel,
168+
true) {
169+
llvm_err(sess, ~"Could not JIT");
170+
}
171+
if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); }
172+
return;
173+
}
174+
151175
let mut FileType;
152176
if opts.output_type == output_type_object ||
153177
opts.output_type == output_type_exe {

src/rustc/driver/driver.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,8 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
259259

260260
let stop_after_codegen =
261261
sess.opts.output_type != link::output_type_exe ||
262-
sess.opts.static && sess.building_library;
262+
(sess.opts.static && sess.building_library) ||
263+
sess.opts.jit;
263264

264265
if stop_after_codegen { return {crate: crate, tcx: Some(ty_cx)}; }
265266

@@ -483,6 +484,7 @@ fn build_session_options(matches: getopts::Matches,
483484
llvm::LLVMSetDebug(1);
484485
}
485486

487+
let jit = opt_present(matches, ~"jit");
486488
let output_type =
487489
if parse_only || no_trans {
488490
link::output_type_none
@@ -545,6 +547,7 @@ fn build_session_options(matches: getopts::Matches,
545547
extra_debuginfo: extra_debuginfo,
546548
lint_opts: lint_opts,
547549
save_temps: save_temps,
550+
jit: jit,
548551
output_type: output_type,
549552
addl_lib_search_paths: addl_lib_search_paths,
550553
maybe_sysroot: sysroot_opt,
@@ -620,6 +623,7 @@ fn opts() -> ~[getopts::Opt] {
620623
optopt(~"o"), optopt(~"out-dir"), optflag(~"xg"),
621624
optflag(~"c"), optflag(~"g"), optflag(~"save-temps"),
622625
optopt(~"sysroot"), optopt(~"target"),
626+
optflag(~"jit"),
623627

624628
optmulti(~"W"), optmulti(~"warn"),
625629
optmulti(~"A"), optmulti(~"allow"),

src/rustc/driver/rustc.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ Options:
4242
-L <path> Add a directory to the library search path
4343
--lib Compile a library crate
4444
--ls List the symbols defined by a compiled library crate
45+
--jit Execute using JIT (experimental)
4546
--no-trans Run all passes except translation; no output
4647
-O Equivalent to --opt-level=2
4748
-o <filename> Write output to <filename>

src/rustc/driver/session.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ type options =
108108
extra_debuginfo: bool,
109109
lint_opts: ~[(lint::lint, lint::level)],
110110
save_temps: bool,
111+
jit: bool,
111112
output_type: back::link::output_type,
112113
addl_lib_search_paths: ~[Path],
113114
maybe_sysroot: Option<Path>,
@@ -249,6 +250,7 @@ fn basic_options() -> @options {
249250
extra_debuginfo: false,
250251
lint_opts: ~[],
251252
save_temps: false,
253+
jit: false,
252254
output_type: link::output_type_exe,
253255
addl_lib_search_paths: ~[],
254256
maybe_sysroot: None,

src/rustc/lib/llvm.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,12 @@ extern mod llvm {
986986
call. */
987987
fn LLVMRustGetLastError() -> *c_char;
988988

989+
/** JIT the module. **/
990+
fn LLVMRustJIT(PM: PassManagerRef,
991+
M: ModuleRef,
992+
OptLevel: c_int,
993+
EnableSegmentedStacks: bool) -> bool;
994+
989995
/** Parses the bitcode in the given memory buffer. */
990996
fn LLVMRustParseBitcode(MemBuf: MemoryBufferRef) -> ModuleRef;
991997

src/rustllvm/RustWrapper.cpp

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@
2828
#include "llvm/Target/TargetOptions.h"
2929
#include "llvm/Support/Host.h"
3030
#include "llvm/Support/Debug.h"
31+
#include "llvm/Support/DynamicLibrary.h"
32+
#include "llvm/ExecutionEngine/ExecutionEngine.h"
33+
#include "llvm/ExecutionEngine/JIT.h"
34+
#include "llvm/ExecutionEngine/Interpreter.h"
35+
#include "llvm/ExecutionEngine/GenericValue.h"
3136
#include "llvm-c/Core.h"
3237
#include "llvm-c/BitReader.h"
3338
#include "llvm-c/Object.h"
@@ -68,6 +73,61 @@ void LLVMInitializeX86TargetMC();
6873
void LLVMInitializeX86AsmPrinter();
6974
void LLVMInitializeX86AsmParser();
7075

76+
// Only initialize the platforms supported by Rust here,
77+
// because using --llvm-root will have multiple platforms
78+
// that rustllvm doesn't actually link to and it's pointless to put target info
79+
// into the registry that Rust can not generate machine code for.
80+
81+
#define INITIALIZE_TARGETS() LLVMInitializeX86TargetInfo(); \
82+
LLVMInitializeX86Target(); \
83+
LLVMInitializeX86TargetMC(); \
84+
LLVMInitializeX86AsmPrinter(); \
85+
LLVMInitializeX86AsmParser();
86+
87+
extern "C" bool
88+
LLVMRustJIT(LLVMPassManagerRef PMR,
89+
LLVMModuleRef M,
90+
CodeGenOpt::Level OptLevel,
91+
bool EnableSegmentedStacks) {
92+
93+
INITIALIZE_TARGETS();
94+
InitializeNativeTarget();
95+
InitializeNativeTargetAsmPrinter();
96+
97+
std::string Err;
98+
TargetOptions Options;
99+
Options.NoFramePointerElim = true;
100+
Options.EnableSegmentedStacks = EnableSegmentedStacks;
101+
102+
PassManager *PM = unwrap<PassManager>(PMR);
103+
104+
PM->run(*unwrap(M));
105+
106+
ExecutionEngine* EE = EngineBuilder(unwrap(M))
107+
.setTargetOptions(Options)
108+
.setOptLevel(OptLevel)
109+
.setUseMCJIT(true)
110+
.create();
111+
112+
if(!EE || Err != "") {
113+
LLVMRustError = Err.c_str();
114+
return false;
115+
}
116+
117+
Function* func = EE->FindFunctionNamed("main");
118+
119+
if(!func || Err != "") {
120+
LLVMRustError = Err.c_str();
121+
return false;
122+
}
123+
124+
std::vector<GenericValue> args;
125+
126+
EE->runFunction(func, args);
127+
128+
return true;
129+
}
130+
71131
extern "C" bool
72132
LLVMRustWriteOutputFile(LLVMPassManagerRef PMR,
73133
LLVMModuleRef M,
@@ -77,16 +137,7 @@ LLVMRustWriteOutputFile(LLVMPassManagerRef PMR,
77137
CodeGenOpt::Level OptLevel,
78138
bool EnableSegmentedStacks) {
79139

80-
// Only initialize the platforms supported by Rust here,
81-
// because using --llvm-root will have multiple platforms
82-
// that rustllvm doesn't actually link to and it's pointless to put target info
83-
// into the registry that Rust can not generate machine code for.
84-
85-
LLVMInitializeX86TargetInfo();
86-
LLVMInitializeX86Target();
87-
LLVMInitializeX86TargetMC();
88-
LLVMInitializeX86AsmPrinter();
89-
LLVMInitializeX86AsmParser();
140+
INITIALIZE_TARGETS();
90141

91142
TargetOptions Options;
92143
Options.NoFramePointerElim = true;

src/rustllvm/rustllvm.def.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ LLVMRustWriteOutputFile
44
LLVMRustGetLastError
55
LLVMRustConstSmallInt
66
LLVMRustConstInt
7+
LLVMRustJIT
78
LLVMRustParseBitcode
89
LLVMRustParseAssemblyFile
910
LLVMRustPrintPassTimings
@@ -485,6 +486,7 @@ LLVMIsThreadLocal
485486
LLVMIsUndef
486487
LLVMLabelType
487488
LLVMLabelTypeInContext
489+
LLVMLinkInInterpreter
488490
LLVMMDNode
489491
LLVMMDNodeInContext
490492
LLVMMDString

0 commit comments

Comments
 (0)