@@ -25,6 +25,7 @@ import lib.llvm.True;
25
25
26
26
type glue_fns = rec ( ValueRef activate_glue ,
27
27
ValueRef yield_glue ,
28
+ ValueRef exit_task_glue ,
28
29
vec[ ValueRef ] upcall_glues ) ;
29
30
30
31
type trans_ctxt = rec ( session . session sess,
@@ -240,32 +241,48 @@ fn new_builder(BasicBlockRef llbb) -> builder {
240
241
ret builder( llbuild) ;
241
242
}
242
243
243
- fn trans_block ( @fn_ctxt cx, & ast . block b , terminator term) {
244
+ fn new_block_ctxt ( @fn_ctxt cx, terminator term) -> @ block_ctxt {
244
245
let BasicBlockRef llbb =
245
246
llvm. LLVMAppendBasicBlock ( cx. llfn, _str. buf( "") ) ;
246
- auto bcx = @rec( llbb=llbb,
247
- build=new_builder( llbb) ,
248
- term=term,
249
- fcx=cx) ;
247
+ ret @rec( llbb=llbb,
248
+ build=new_builder( llbb) ,
249
+ term=term,
250
+ fcx=cx) ;
251
+ }
252
+
253
+ fn trans_block( @fn_ctxt cx, & ast. block b, terminator term) {
254
+ auto bcx = ( new_block_ctxt( cx, term) ) ;
250
255
for ( @ast. stmt s in b) {
251
256
trans_stmt( bcx, * s) ;
252
257
}
253
258
bcx. term( cx, bcx. build) ;
254
259
}
255
260
256
- fn trans_fn( @trans_ctxt cx, & ast. _fn f) {
257
- let vec[ TypeRef ] args = vec( T_ptr ( T_int ( ) ) , // outptr.
258
- T_taskptr ( ) // taskptr
261
+ fn new_fn_ctxt( @trans_ctxt cx,
262
+ str name,
263
+ TypeRef T_out ,
264
+ vec[ TypeRef ] T_explicit_args ) -> @fn_ctxt {
265
+ let vec[ TypeRef ] args = vec( T_ptr ( T_out ) , // outptr.
266
+ T_taskptr ( ) // taskptr
259
267
) ;
260
- let ValueRef llfn = decl_cdecl_fn( cx. llmod, cx. path, args, T_nil ( ) ) ;
268
+ args += T_explicit_args ;
269
+ let ValueRef llfn = decl_cdecl_fn( cx. llmod, name, args, T_nil ( ) ) ;
261
270
cx. fns. insert( cx. path, llfn) ;
262
271
let ValueRef lloutptr = llvm. LLVMGetParam ( llfn, 0 u) ;
263
272
let ValueRef lltaskptr = llvm. LLVMGetParam ( llfn, 1 u) ;
264
- auto fcx = @rec( llfn=llfn,
265
- lloutptr=lloutptr,
266
- lltaskptr=lltaskptr,
267
- tcx=cx) ;
273
+ ret @rec( llfn=llfn,
274
+ lloutptr=lloutptr,
275
+ lltaskptr=lltaskptr,
276
+ tcx=cx) ;
277
+ }
278
+
279
+ fn trans_fn( @trans_ctxt cx, & ast. _fn f) {
280
+ let TypeRef out = T_int ( ) ;
281
+ let vec[ TypeRef ] args = vec( ) ;
282
+
283
+ auto fcx = new_fn_ctxt( cx, cx. path, out, args) ;
268
284
auto term = default_terminate;
285
+
269
286
trans_block( fcx, f. body, term) ;
270
287
}
271
288
@@ -292,6 +309,24 @@ fn p2i(ValueRef v) -> ValueRef {
292
309
ret llvm. LLVMConstPtrToInt ( v, T_int( ) ) ;
293
310
}
294
311
312
+ fn trans_exit_task_glue( @trans_ctxt cx) {
313
+ let vec[ TypeRef ] T_args = vec( ) ;
314
+ let vec[ ValueRef ] V_args = vec( ) ;
315
+ auto term = default_terminate;
316
+
317
+ auto llfn = cx. glues. exit_task_glue;
318
+ let ValueRef lloutptr = C_null ( T_int ( ) ) ;
319
+ let ValueRef lltaskptr = llvm. LLVMGetParam ( llfn, 0 u) ;
320
+ auto fcx = @rec( llfn=llfn,
321
+ lloutptr=lloutptr,
322
+ lltaskptr=lltaskptr,
323
+ tcx=cx) ;
324
+
325
+ auto bcx = new_block_ctxt( fcx, term) ;
326
+ trans_upcall( bcx, "upcall_exit" , V_args ) ;
327
+ bcx. term( fcx, bcx. build) ;
328
+ }
329
+
295
330
fn crate_constant( @trans_ctxt cx) -> ValueRef {
296
331
297
332
let ValueRef crate_ptr =
@@ -306,9 +341,8 @@ fn crate_constant(@trans_ctxt cx) -> ValueRef {
306
341
let ValueRef yield_glue_off =
307
342
llvm. LLVMConstSub ( p2i( cx. glues. yield_glue) , crate_addr) ;
308
343
309
- // FIXME: we aren't generating the exit-task glue yet.
310
- // llvm.LLVMConstSub(p2i(cx.glues.exit_task_glue), crate_addr);
311
- let ValueRef exit_task_glue_off = C_null ( T_int ( ) ) ;
344
+ let ValueRef exit_task_glue_off =
345
+ llvm. LLVMConstSub ( p2i( cx. glues. exit_task_glue) , crate_addr) ;
312
346
313
347
let ValueRef crate_val =
314
348
C_struct ( vec( C_null ( T_int( ) ) , // ptrdiff_t image_base_off
@@ -373,6 +407,22 @@ fn trans_crate(session.session sess, ast.crate crate) {
373
407
auto glues = @rec( activate_glue = decl_glue( llmod,
374
408
abi. activate_glue_name( ) ) ,
375
409
yield_glue = decl_glue( llmod, abi. yield_glue_name( ) ) ,
410
+ /*
411
+ * Note: the signature passed to decl_cdecl_fn here
412
+ * looks unusual because it is. It corresponds neither
413
+ * to an upcall signature nor a normal rust-ABI
414
+ * signature. In fact it is a fake signature, that
415
+ * exists solely to acquire the task pointer as an
416
+ * argument to the upcall. It so happens that the
417
+ * runtime sets up the task pointer as the sole incoming
418
+ * argument to the frame that we return into when
419
+ * returning to the exit task glue. So this is the
420
+ * signature required to retrieve it.
421
+ */
422
+ exit_task_glue =
423
+ decl_cdecl_fn( llmod, abi. exit_task_glue_name( ) ,
424
+ vec( T_taskptr ( ) ) , T_nil ( ) ) ,
425
+
376
426
upcall_glues =
377
427
_vec. init_fn[ ValueRef ] ( bind decl_upcall( llmod, _) ,
378
428
abi. n_upcall_glues as uint) ) ;
@@ -385,7 +435,7 @@ fn trans_crate(session.session sess, ast.crate crate) {
385
435
path = "_rust" ) ;
386
436
387
437
trans_mod( cx, crate . module) ;
388
-
438
+ trans_exit_task_glue ( cx ) ;
389
439
trans_main_fn( cx, crate_constant( cx) ) ;
390
440
391
441
llvm. LLVMWriteBitcodeToFile ( llmod, _str. buf( "rust_out. bc") ) ;
0 commit comments