@@ -101,34 +101,21 @@ pub mod jit {
101
101
use back:: link:: llvm_err;
102
102
use driver:: session:: Session ;
103
103
use lib:: llvm:: llvm;
104
- use lib:: llvm:: { ModuleRef , PassManagerRef } ;
104
+ use lib:: llvm:: { ModuleRef , ContextRef } ;
105
105
use metadata:: cstore;
106
106
107
107
use core:: cast;
108
- use core:: libc:: c_int;
109
108
use core:: ptr;
110
109
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;
124
112
125
113
pub fn exec ( sess : Session ,
126
- pm : PassManagerRef ,
114
+ c : ContextRef ,
127
115
m : ModuleRef ,
128
- opt : c_int ,
129
116
stacks : bool ) {
130
117
unsafe {
131
- let manager = llvm:: LLVMRustPrepareJIT ( rusti :: morestack_addr ( ) ) ;
118
+ let manager = llvm:: LLVMRustPrepareJIT ( intrinsics :: morestack_addr ( ) ) ;
132
119
133
120
// We need to tell JIT where to resolve all linked
134
121
// symbols from. The equivalent of -lstd, -lcore, etc.
@@ -152,26 +139,43 @@ pub mod jit {
152
139
} ) ;
153
140
}
154
141
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
+ }
172
149
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 ") ;
174
160
}
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) ;
175
179
}
176
180
}
177
181
}
@@ -188,6 +192,7 @@ pub mod write {
188
192
use driver:: session;
189
193
use lib:: llvm:: llvm;
190
194
use lib:: llvm:: { ModuleRef , mk_pass_manager, mk_target_data} ;
195
+ use lib:: llvm:: { ContextRef } ;
191
196
use lib;
192
197
193
198
use back:: passes;
@@ -206,6 +211,7 @@ pub mod write {
206
211
}
207
212
208
213
pub fn run_passes ( sess : Session ,
214
+ llcx : ContextRef ,
209
215
llmod : ModuleRef ,
210
216
output_type : output_type ,
211
217
output : & Path ) {
@@ -261,7 +267,17 @@ pub mod write {
261
267
debug ! ( "Running Module Optimization Pass" ) ;
262
268
mpm. run ( llmod) ;
263
269
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) {
265
281
let LLVMOptNone = 0 as c_int ; // -O0
266
282
let LLVMOptLess = 1 as c_int ; // -O1
267
283
let LLVMOptDefault = 2 as c_int ; // -O2, -Os
@@ -274,20 +290,6 @@ pub mod write {
274
290
session:: Aggressive => LLVMOptAggressive
275
291
} ;
276
292
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
-
291
293
let FileType ;
292
294
if output_type == output_type_object ||
293
295
output_type == output_type_exe {
@@ -348,6 +350,7 @@ pub mod write {
348
350
// Clean up and return
349
351
350
352
llvm:: LLVMDisposeModule ( llmod) ;
353
+ llvm:: LLVMContextDispose ( llcx) ;
351
354
if sess. time_llvm_passes ( ) {
352
355
llvm:: LLVMRustPrintPassTimings ( ) ;
353
356
}
@@ -366,6 +369,7 @@ pub mod write {
366
369
}
367
370
368
371
llvm:: LLVMDisposeModule ( llmod) ;
372
+ llvm:: LLVMContextDispose ( llcx) ;
369
373
if sess. time_llvm_passes ( ) { llvm:: LLVMRustPrintPassTimings ( ) ; }
370
374
}
371
375
}
0 commit comments