@@ -103,7 +103,7 @@ pub mod jit {
103103 use back:: link:: llvm_err;
104104 use driver:: session:: Session ;
105105 use lib:: llvm:: llvm;
106- use lib:: llvm:: { ModuleRef , PassManagerRef } ;
106+ use lib:: llvm:: { ModuleRef , PassManagerRef , ContextRef } ;
107107 use metadata:: cstore;
108108
109109 use core:: cast;
@@ -126,6 +126,7 @@ pub mod jit {
126126
127127 pub fn exec ( sess : Session ,
128128 pm : PassManagerRef ,
129+ c : ContextRef ,
129130 m : ModuleRef ,
130131 opt : c_int ,
131132 stacks : bool ) {
@@ -154,26 +155,43 @@ pub mod jit {
154155 } ) ;
155156 }
156157
157- // The execute function will return a void pointer
158- // to the _rust_main function. We can do closure
159- // magic here to turn it straight into a callable rust
160- // closure. It will also cleanup the memory manager
161- // for us.
162-
163- let entry = llvm:: LLVMRustExecuteJIT ( manager,
164- pm, m, opt, stacks) ;
165-
166- if ptr:: is_null ( entry) {
167- llvm_err ( sess, ~"Could not JIT ") ;
168- } else {
169- let closure = Closure {
170- code : entry,
171- env : ptr:: null ( )
172- } ;
173- let func: & fn ( ) = cast:: transmute ( closure) ;
158+ // We custom-build a JIT execution engine via some rust wrappers
159+ // first. This wrappers takes ownership of the module passed in.
160+ let ee = llvm:: LLVMRustBuildJIT ( manager, pm, m, opt, stacks) ;
161+ if ee. is_null ( ) {
162+ llvm:: LLVMContextDispose ( c) ;
163+ llvm_err ( sess, ~"Could not create the JIT ") ;
164+ }
174165
175- func ( ) ;
166+ // Next, we need to get a handle on the _rust_main function by
167+ // looking up it's corresponding ValueRef and then requesting that
168+ // the execution engine compiles the function.
169+ let fun = do str:: as_c_str ( "_rust_main" ) |entry| {
170+ llvm:: LLVMGetNamedFunction ( m, entry)
171+ } ;
172+ if fun. is_null ( ) {
173+ llvm:: LLVMDisposeExecutionEngine ( ee) ;
174+ llvm:: LLVMContextDispose ( c) ;
175+ llvm_err ( sess, ~"Could not find _rust_main in the JIT ") ;
176176 }
177+
178+ // Finally, once we have the pointer to the code, we can do some
179+ // closure magic here to turn it straight into a callable rust
180+ // closure
181+ let code = llvm:: LLVMGetPointerToGlobal ( ee, fun) ;
182+ assert ! ( !code. is_null( ) ) ;
183+ let closure = Closure {
184+ code : code,
185+ env : ptr:: null ( )
186+ } ;
187+ let func: & fn ( ) = cast:: transmute ( closure) ;
188+ func ( ) ;
189+
190+ // Sadly, there currently is no interface to re-use this execution
191+ // engine, so it's disposed of here along with the context to
192+ // prevent leaks.
193+ llvm:: LLVMDisposeExecutionEngine ( ee) ;
194+ llvm:: LLVMContextDispose ( c) ;
177195 }
178196 }
179197}
@@ -190,6 +208,7 @@ pub mod write {
190208 use driver:: session;
191209 use lib:: llvm:: llvm;
192210 use lib:: llvm:: { ModuleRef , mk_pass_manager, mk_target_data} ;
211+ use lib:: llvm:: { False , ContextRef } ;
193212 use lib;
194213
195214 use back:: passes;
@@ -208,6 +227,7 @@ pub mod write {
208227 }
209228
210229 pub fn run_passes ( sess : Session ,
230+ llcx : ContextRef ,
211231 llmod : ModuleRef ,
212232 output_type : output_type ,
213233 output : & Path ) {
@@ -282,7 +302,7 @@ pub mod write {
282302 // JIT execution takes ownership of the module,
283303 // so don't dispose and return.
284304
285- jit:: exec ( sess, pm. llpm , llmod, CodeGenOptLevel , true ) ;
305+ jit:: exec ( sess, pm. llpm , llcx , llmod, CodeGenOptLevel , true ) ;
286306
287307 if sess. time_llvm_passes ( ) {
288308 llvm:: LLVMRustPrintPassTimings ( ) ;
@@ -350,6 +370,7 @@ pub mod write {
350370 // Clean up and return
351371
352372 llvm:: LLVMDisposeModule ( llmod) ;
373+ llvm:: LLVMContextDispose ( llcx) ;
353374 if sess. time_llvm_passes ( ) {
354375 llvm:: LLVMRustPrintPassTimings ( ) ;
355376 }
@@ -368,6 +389,7 @@ pub mod write {
368389 }
369390
370391 llvm:: LLVMDisposeModule ( llmod) ;
392+ llvm:: LLVMContextDispose ( llcx) ;
371393 if sess. time_llvm_passes ( ) { llvm:: LLVMRustPrintPassTimings ( ) ; }
372394 }
373395 }
0 commit comments