@@ -101,34 +101,21 @@ pub mod jit {
101101 use back:: link:: llvm_err;
102102 use driver:: session:: Session ;
103103 use lib:: llvm:: llvm;
104- use lib:: llvm:: { ModuleRef , PassManagerRef } ;
104+ use lib:: llvm:: { ModuleRef , ContextRef } ;
105105 use metadata:: cstore;
106106
107107 use core:: cast;
108- use core:: libc:: c_int;
109108 use core:: ptr;
110109 use core:: str;
111-
112- pub mod rusti {
113- #[ nolink]
114- #[ abi = "rust-intrinsic" ]
115- pub extern "rust-intrinsic" {
116- pub fn morestack_addr ( ) -> * ( ) ;
117- }
118- }
119-
120- pub struct Closure {
121- code : * ( ) ,
122- env : * ( ) ,
123- }
110+ use core:: sys;
111+ use core:: unstable:: intrinsics;
124112
125113 pub fn exec ( sess : Session ,
126- pm : PassManagerRef ,
114+ c : ContextRef ,
127115 m : ModuleRef ,
128- opt : c_int ,
129116 stacks : bool ) {
130117 unsafe {
131- let manager = llvm:: LLVMRustPrepareJIT ( rusti :: morestack_addr ( ) ) ;
118+ let manager = llvm:: LLVMRustPrepareJIT ( intrinsics :: morestack_addr ( ) ) ;
132119
133120 // We need to tell JIT where to resolve all linked
134121 // symbols from. The equivalent of -lstd, -lcore, etc.
@@ -152,26 +139,43 @@ pub mod jit {
152139 } ) ;
153140 }
154141
155- // The execute function will return a void pointer
156- // to the _rust_main function. We can do closure
157- // magic here to turn it straight into a callable rust
158- // closure. It will also cleanup the memory manager
159- // for us.
160-
161- let entry = llvm:: LLVMRustExecuteJIT ( manager,
162- pm, m, opt, stacks) ;
163-
164- if ptr:: is_null ( entry) {
165- llvm_err ( sess, ~"Could not JIT ") ;
166- } else {
167- let closure = Closure {
168- code : entry,
169- env : ptr:: null ( )
170- } ;
171- let func: & fn ( ) = cast:: transmute ( closure) ;
142+ // We custom-build a JIT execution engine via some rust wrappers
143+ // first. This wrappers takes ownership of the module passed in.
144+ let ee = llvm:: LLVMRustBuildJIT ( manager, m, stacks) ;
145+ if ee. is_null ( ) {
146+ llvm:: LLVMContextDispose ( c) ;
147+ llvm_err ( sess, ~"Could not create the JIT ") ;
148+ }
172149
173- func ( ) ;
150+ // Next, we need to get a handle on the _rust_main function by
151+ // looking up it's corresponding ValueRef and then requesting that
152+ // the execution engine compiles the function.
153+ let fun = do str:: as_c_str ( "_rust_main" ) |entry| {
154+ llvm:: LLVMGetNamedFunction ( m, entry)
155+ } ;
156+ if fun. is_null ( ) {
157+ llvm:: LLVMDisposeExecutionEngine ( ee) ;
158+ llvm:: LLVMContextDispose ( c) ;
159+ llvm_err ( sess, ~"Could not find _rust_main in the JIT ") ;
174160 }
161+
162+ // Finally, once we have the pointer to the code, we can do some
163+ // closure magic here to turn it straight into a callable rust
164+ // closure
165+ let code = llvm:: LLVMGetPointerToGlobal ( ee, fun) ;
166+ assert ! ( !code. is_null( ) ) ;
167+ let closure = sys:: Closure {
168+ code : code,
169+ env : ptr:: null ( )
170+ } ;
171+ let func: & fn ( ) = cast:: transmute ( closure) ;
172+ func ( ) ;
173+
174+ // Sadly, there currently is no interface to re-use this execution
175+ // engine, so it's disposed of here along with the context to
176+ // prevent leaks.
177+ llvm:: LLVMDisposeExecutionEngine ( ee) ;
178+ llvm:: LLVMContextDispose ( c) ;
175179 }
176180 }
177181}
@@ -188,6 +192,7 @@ pub mod write {
188192 use driver:: session;
189193 use lib:: llvm:: llvm;
190194 use lib:: llvm:: { ModuleRef , mk_pass_manager, mk_target_data} ;
195+ use lib:: llvm:: { ContextRef } ;
191196 use lib;
192197
193198 use back:: passes;
@@ -206,6 +211,7 @@ pub mod write {
206211 }
207212
208213 pub fn run_passes ( sess : Session ,
214+ llcx : ContextRef ,
209215 llmod : ModuleRef ,
210216 output_type : output_type ,
211217 output : & Path ) {
@@ -261,7 +267,17 @@ pub mod write {
261267 debug ! ( "Running Module Optimization Pass" ) ;
262268 mpm. run ( llmod) ;
263269
264- if is_object_or_assembly_or_exe ( output_type) || opts. jit {
270+ if opts. jit {
271+ // If we are using JIT, go ahead and create and execute the
272+ // engine now. JIT execution takes ownership of the module and
273+ // context, so don't dispose and return.
274+ jit:: exec ( sess, llcx, llmod, true ) ;
275+
276+ if sess. time_llvm_passes ( ) {
277+ llvm:: LLVMRustPrintPassTimings ( ) ;
278+ }
279+ return ;
280+ } else if is_object_or_assembly_or_exe ( output_type) {
265281 let LLVMOptNone = 0 as c_int ; // -O0
266282 let LLVMOptLess = 1 as c_int ; // -O1
267283 let LLVMOptDefault = 2 as c_int ; // -O2, -Os
@@ -274,20 +290,6 @@ pub mod write {
274290 session:: Aggressive => LLVMOptAggressive
275291 } ;
276292
277- if opts. jit {
278- // If we are using JIT, go ahead and create and
279- // execute the engine now.
280- // JIT execution takes ownership of the module,
281- // so don't dispose and return.
282-
283- jit:: exec ( sess, pm. llpm , llmod, CodeGenOptLevel , true ) ;
284-
285- if sess. time_llvm_passes ( ) {
286- llvm:: LLVMRustPrintPassTimings ( ) ;
287- }
288- return ;
289- }
290-
291293 let FileType ;
292294 if output_type == output_type_object ||
293295 output_type == output_type_exe {
@@ -348,6 +350,7 @@ pub mod write {
348350 // Clean up and return
349351
350352 llvm:: LLVMDisposeModule ( llmod) ;
353+ llvm:: LLVMContextDispose ( llcx) ;
351354 if sess. time_llvm_passes ( ) {
352355 llvm:: LLVMRustPrintPassTimings ( ) ;
353356 }
@@ -366,6 +369,7 @@ pub mod write {
366369 }
367370
368371 llvm:: LLVMDisposeModule ( llmod) ;
372+ llvm:: LLVMContextDispose ( llcx) ;
369373 if sess. time_llvm_passes ( ) { llvm:: LLVMRustPrintPassTimings ( ) ; }
370374 }
371375 }
0 commit comments