@@ -102,7 +102,7 @@ pub mod jit {
102102 use back:: link:: llvm_err;
103103 use driver:: session:: Session ;
104104 use lib:: llvm:: llvm;
105- use lib:: llvm:: { ModuleRef , PassManagerRef } ;
105+ use lib:: llvm:: { ModuleRef , PassManagerRef , ContextRef } ;
106106 use metadata:: cstore;
107107
108108 use core:: cast;
@@ -125,6 +125,7 @@ pub mod jit {
125125
126126 pub fn exec ( sess : Session ,
127127 pm : PassManagerRef ,
128+ c : ContextRef ,
128129 m : ModuleRef ,
129130 opt : c_int ,
130131 stacks : bool ) {
@@ -153,26 +154,43 @@ pub mod jit {
153154 } ) ;
154155 }
155156
156- // The execute function will return a void pointer
157- // to the _rust_main function. We can do closure
158- // magic here to turn it straight into a callable rust
159- // closure. It will also cleanup the memory manager
160- // for us.
161-
162- let entry = llvm:: LLVMRustExecuteJIT ( manager,
163- pm, m, opt, stacks) ;
164-
165- if ptr:: is_null ( entry) {
166- llvm_err ( sess, ~"Could not JIT ") ;
167- } else {
168- let closure = Closure {
169- code : entry,
170- env : ptr:: null ( )
171- } ;
172- let func: & fn ( ) = cast:: transmute ( closure) ;
157+ // We custom-build a JIT execution engine via some rust wrappers
158+ // first. This wrappers takes ownership of the module passed in.
159+ let ee = llvm:: LLVMRustBuildJIT ( manager, pm, m, opt, stacks) ;
160+ if ee. is_null ( ) {
161+ llvm:: LLVMContextDispose ( c) ;
162+ llvm_err ( sess, ~"Could not create the JIT ") ;
163+ }
173164
174- func ( ) ;
165+ // Next, we need to get a handle on the _rust_main function by
166+ // looking up it's corresponding ValueRef and then requesting that
167+ // the execution engine compiles the function.
168+ let fun = do str:: as_c_str ( "_rust_main" ) |entry| {
169+ llvm:: LLVMGetNamedFunction ( m, entry)
170+ } ;
171+ if fun. is_null ( ) {
172+ llvm:: LLVMDisposeExecutionEngine ( ee) ;
173+ llvm:: LLVMContextDispose ( c) ;
174+ llvm_err ( sess, ~"Could not find _rust_main in the JIT ") ;
175175 }
176+
177+ // Finally, once we have the pointer to the code, we can do some
178+ // closure magic here to turn it straight into a callable rust
179+ // closure
180+ let code = llvm:: LLVMGetPointerToGlobal ( ee, fun) ;
181+ assert ! ( !code. is_null( ) ) ;
182+ let closure = Closure {
183+ code : code,
184+ env : ptr:: null ( )
185+ } ;
186+ let func: & fn ( ) = cast:: transmute ( closure) ;
187+ func ( ) ;
188+
189+ // Sadly, there currently is no interface to re-use this execution
190+ // engine, so it's disposed of here along with the context to
191+ // prevent leaks.
192+ llvm:: LLVMDisposeExecutionEngine ( ee) ;
193+ llvm:: LLVMContextDispose ( c) ;
176194 }
177195 }
178196}
@@ -189,6 +207,7 @@ pub mod write {
189207 use driver:: session;
190208 use lib:: llvm:: llvm;
191209 use lib:: llvm:: { ModuleRef , mk_pass_manager, mk_target_data} ;
210+ use lib:: llvm:: { ContextRef } ;
192211 use lib;
193212
194213 use back:: passes;
@@ -207,6 +226,7 @@ pub mod write {
207226 }
208227
209228 pub fn run_passes ( sess : Session ,
229+ llcx : ContextRef ,
210230 llmod : ModuleRef ,
211231 output_type : output_type ,
212232 output : & Path ) {
@@ -281,7 +301,7 @@ pub mod write {
281301 // JIT execution takes ownership of the module,
282302 // so don't dispose and return.
283303
284- jit:: exec ( sess, pm. llpm , llmod, CodeGenOptLevel , true ) ;
304+ jit:: exec ( sess, pm. llpm , llcx , llmod, CodeGenOptLevel , true ) ;
285305
286306 if sess. time_llvm_passes ( ) {
287307 llvm:: LLVMRustPrintPassTimings ( ) ;
@@ -349,6 +369,7 @@ pub mod write {
349369 // Clean up and return
350370
351371 llvm:: LLVMDisposeModule ( llmod) ;
372+ llvm:: LLVMContextDispose ( llcx) ;
352373 if sess. time_llvm_passes ( ) {
353374 llvm:: LLVMRustPrintPassTimings ( ) ;
354375 }
@@ -367,6 +388,7 @@ pub mod write {
367388 }
368389
369390 llvm:: LLVMDisposeModule ( llmod) ;
391+ llvm:: LLVMContextDispose ( llcx) ;
370392 if sess. time_llvm_passes ( ) { llvm:: LLVMRustPrintPassTimings ( ) ; }
371393 }
372394 }
0 commit comments