3
3
use crate :: { compiler:: Compiler , TRAP_ALWAYS , TRAP_CANNOT_ENTER , TRAP_INTERNAL_ASSERT } ;
4
4
use anyhow:: Result ;
5
5
use cranelift_codegen:: ir:: condcodes:: IntCC ;
6
- use cranelift_codegen:: ir:: { self , InstBuilder , MemFlags } ;
6
+ use cranelift_codegen:: ir:: { self , InstBuilder , MemFlags , Value } ;
7
7
use cranelift_codegen:: isa:: { CallConv , TargetIsa } ;
8
8
use cranelift_frontend:: FunctionBuilder ;
9
9
use std:: any:: Any ;
@@ -98,7 +98,7 @@ impl<'a> TrampolineCompiler<'a> {
98
98
_ = instance;
99
99
todo ! ( )
100
100
}
101
- Trampoline :: TaskReturn => todo ! ( ) ,
101
+ Trampoline :: TaskReturn => self . translate_task_return_call ( ) ,
102
102
Trampoline :: TaskWait {
103
103
instance,
104
104
async_,
@@ -196,12 +196,12 @@ impl<'a> TrampolineCompiler<'a> {
196
196
Trampoline :: ResourceDrop ( ty) => self . translate_resource_drop ( * ty) ,
197
197
Trampoline :: ResourceTransferOwn => {
198
198
self . translate_resource_libcall ( host:: resource_transfer_own, |me, rets| {
199
- rets[ 0 ] = me. raise_if_resource_trapped ( rets[ 0 ] ) ;
199
+ rets[ 0 ] = me. raise_if_i32_trapped ( rets[ 0 ] ) ;
200
200
} )
201
201
}
202
202
Trampoline :: ResourceTransferBorrow => {
203
203
self . translate_resource_libcall ( host:: resource_transfer_borrow, |me, rets| {
204
- rets[ 0 ] = me. raise_if_resource_trapped ( rets[ 0 ] ) ;
204
+ rets[ 0 ] = me. raise_if_i32_trapped ( rets[ 0 ] ) ;
205
205
} )
206
206
}
207
207
Trampoline :: ResourceEnterCall => {
@@ -212,14 +212,17 @@ impl<'a> TrampolineCompiler<'a> {
212
212
me. raise_if_host_trapped ( rets. pop ( ) . unwrap ( ) ) ;
213
213
} )
214
214
}
215
- Trampoline :: AsyncEnterCall => todo ! ( ) ,
215
+ Trampoline :: AsyncEnterCall => {
216
+ self . translate_async_enter_or_exit ( host:: async_enter, None , ir:: types:: I8 )
217
+ }
216
218
Trampoline :: AsyncExitCall {
217
219
callback,
218
220
post_return,
219
- } => {
220
- _ = ( callback, post_return) ;
221
- todo ! ( )
222
- }
221
+ } => self . translate_async_enter_or_exit (
222
+ host:: async_exit,
223
+ Some ( ( * callback, * post_return) ) ,
224
+ ir:: types:: I64 ,
225
+ ) ,
223
226
Trampoline :: FutureTransfer => {
224
227
_ = host:: future_transfer;
225
228
todo ! ( )
@@ -235,25 +238,18 @@ impl<'a> TrampolineCompiler<'a> {
235
238
}
236
239
}
237
240
238
- fn translate_lower_import (
239
- & mut self ,
240
- index : LoweredIndex ,
241
- options : & CanonicalOptions ,
242
- lower_ty : TypeFuncIndex ,
243
- ) {
241
+ fn store_wasm_arguments ( & mut self , args : & [ Value ] ) -> ( Value , Value ) {
244
242
let pointer_type = self . isa . pointer_type ( ) ;
245
- let args = self . builder . func . dfg . block_params ( self . block0 ) . to_vec ( ) ;
246
- let vmctx = args[ 0 ] ;
247
- let wasm_func_ty = self . types [ self . signature ] . unwrap_func ( ) ;
243
+ let wasm_func_ty = & self . types [ self . signature ] . unwrap_func ( ) ;
248
244
249
245
// Start off by spilling all the wasm arguments into a stack slot to be
250
246
// passed to the host function.
251
- let ( values_vec_ptr , values_vec_len ) = match self . abi {
247
+ match self . abi {
252
248
Abi :: Wasm => {
253
249
let ( ptr, len) = self . compiler . allocate_stack_array_and_spill_args (
254
250
wasm_func_ty,
255
251
& mut self . builder ,
256
- & args[ 2 .. ] ,
252
+ args,
257
253
) ;
258
254
let len = self . builder . ins ( ) . iconst ( pointer_type, i64:: from ( len) ) ;
259
255
( ptr, len)
@@ -262,7 +258,163 @@ impl<'a> TrampolineCompiler<'a> {
262
258
let params = self . builder . func . dfg . block_params ( self . block0 ) ;
263
259
( params[ 2 ] , params[ 3 ] )
264
260
}
265
- } ;
261
+ }
262
+ }
263
+
264
+ fn translate_task_return_call ( & mut self ) {
265
+ match self . abi {
266
+ Abi :: Wasm => { }
267
+
268
+ // These trampolines can only actually be called by Wasm, so
269
+ // let's assert that here.
270
+ Abi :: Array => {
271
+ self . builder . ins ( ) . trap ( TRAP_INTERNAL_ASSERT ) ;
272
+ return ;
273
+ }
274
+ }
275
+
276
+ let args = self . builder . func . dfg . block_params ( self . block0 ) . to_vec ( ) ;
277
+ let vmctx = args[ 0 ] ;
278
+
279
+ let ( values_vec_ptr, values_vec_len) = self . store_wasm_arguments ( & args[ 2 ..] ) ;
280
+
281
+ let ( host_sig, index) = host:: task_return ( self . isa , & mut self . builder . func ) ;
282
+ let host_fn = self . load_libcall ( vmctx, index) ;
283
+
284
+ let params = self . types [ self . signature ]
285
+ . unwrap_func ( )
286
+ . params ( )
287
+ . iter ( )
288
+ . map ( |& v| {
289
+ Some ( match v {
290
+ WasmValType :: I32 => FlatType :: I32 ,
291
+ WasmValType :: I64 => FlatType :: I64 ,
292
+ WasmValType :: F32 => FlatType :: F32 ,
293
+ WasmValType :: F64 => FlatType :: F64 ,
294
+ _ => return None ,
295
+ } )
296
+ } )
297
+ . collect :: < Option < _ > > ( ) ;
298
+
299
+ let ty = self . builder . ins ( ) . iconst (
300
+ ir:: types:: I32 ,
301
+ i64:: from (
302
+ params
303
+ . and_then ( |params| {
304
+ self . types
305
+ . get_task_return_type ( & TypeTaskReturn { params } )
306
+ . map ( |v| v. as_u32 ( ) )
307
+ } )
308
+ . unwrap_or ( u32:: MAX ) ,
309
+ ) ,
310
+ ) ;
311
+
312
+ let call = self . compiler . call_indirect_host (
313
+ & mut self . builder ,
314
+ index,
315
+ host_sig,
316
+ host_fn,
317
+ & [ vmctx, ty, values_vec_ptr, values_vec_len] ,
318
+ ) ;
319
+ let succeeded = self . builder . func . dfg . inst_results ( call) [ 0 ] ;
320
+ self . raise_if_host_trapped ( succeeded) ;
321
+ self . builder . ins ( ) . return_ ( & [ ] ) ;
322
+ }
323
+
324
+ fn translate_async_enter_or_exit (
325
+ & mut self ,
326
+ get_libcall : fn (
327
+ & dyn TargetIsa ,
328
+ & mut ir:: Function ,
329
+ ) -> ( ir:: SigRef , ComponentBuiltinFunctionIndex ) ,
330
+ callback_and_post_return : Option < (
331
+ Option < RuntimeCallbackIndex > ,
332
+ Option < RuntimePostReturnIndex > ,
333
+ ) > ,
334
+ result : ir:: types:: Type ,
335
+ ) {
336
+ match self . abi {
337
+ Abi :: Wasm => { }
338
+
339
+ // These trampolines can only actually be called by Wasm, so
340
+ // let's assert that here.
341
+ Abi :: Array => {
342
+ self . builder . ins ( ) . trap ( TRAP_INTERNAL_ASSERT ) ;
343
+ return ;
344
+ }
345
+ }
346
+
347
+ let args = self . builder . func . dfg . block_params ( self . block0 ) . to_vec ( ) ;
348
+ let vmctx = args[ 0 ] ;
349
+
350
+ let ( host_sig, index) = get_libcall ( self . isa , & mut self . builder . func ) ;
351
+ let host_fn = self . load_libcall ( vmctx, index) ;
352
+
353
+ let mut callee_args = vec ! [ vmctx] ;
354
+
355
+ if let Some ( ( callback, post_return) ) = callback_and_post_return {
356
+ let pointer_type = self . isa . pointer_type ( ) ;
357
+
358
+ // callback: *mut VMFuncRef
359
+ if let Some ( callback) = callback {
360
+ callee_args. push ( self . builder . ins ( ) . load (
361
+ pointer_type,
362
+ MemFlags :: trusted ( ) ,
363
+ vmctx,
364
+ i32:: try_from ( self . offsets . runtime_callback ( callback) ) . unwrap ( ) ,
365
+ ) ) ;
366
+ } else {
367
+ callee_args. push ( self . builder . ins ( ) . iconst ( pointer_type, 0 ) ) ;
368
+ }
369
+
370
+ // post_return: *mut VMFuncRef
371
+ if let Some ( post_return) = post_return {
372
+ callee_args. push ( self . builder . ins ( ) . load (
373
+ pointer_type,
374
+ MemFlags :: trusted ( ) ,
375
+ vmctx,
376
+ i32:: try_from ( self . offsets . runtime_post_return ( post_return) ) . unwrap ( ) ,
377
+ ) ) ;
378
+ } else {
379
+ callee_args. push ( self . builder . ins ( ) . iconst ( pointer_type, 0 ) ) ;
380
+ }
381
+ }
382
+
383
+ // remaining parameters
384
+ callee_args. extend ( args[ 2 ..] . iter ( ) . copied ( ) ) ;
385
+
386
+ let call = self . compiler . call_indirect_host (
387
+ & mut self . builder ,
388
+ index,
389
+ host_sig,
390
+ host_fn,
391
+ & callee_args,
392
+ ) ;
393
+
394
+ if result == ir:: types:: I64 {
395
+ let result = self . builder . func . dfg . inst_results ( call) [ 0 ] ;
396
+ let result = self . raise_if_i32_trapped ( result) ;
397
+ self . abi_store_results ( & [ result] ) ;
398
+ } else {
399
+ assert ! ( result == ir:: types:: I8 ) ;
400
+ let succeeded = self . builder . func . dfg . inst_results ( call) [ 0 ] ;
401
+ self . raise_if_host_trapped ( succeeded) ;
402
+ self . builder . ins ( ) . return_ ( & [ ] ) ;
403
+ }
404
+ }
405
+
406
+ fn translate_lower_import (
407
+ & mut self ,
408
+ index : LoweredIndex ,
409
+ options : & CanonicalOptions ,
410
+ lower_ty : TypeFuncIndex ,
411
+ ) {
412
+ let pointer_type = self . isa . pointer_type ( ) ;
413
+ let args = self . builder . func . dfg . block_params ( self . block0 ) . to_vec ( ) ;
414
+ let vmctx = args[ 0 ] ;
415
+ let wasm_func_ty = self . types [ self . signature ] . unwrap_func ( ) ;
416
+
417
+ let ( values_vec_ptr, values_vec_len) = self . store_wasm_arguments ( & args[ 2 ..] ) ;
266
418
267
419
// Below this will incrementally build both the signature of the host
268
420
// function we're calling as well as the list of arguments since the
@@ -457,7 +609,7 @@ impl<'a> TrampolineCompiler<'a> {
457
609
) ;
458
610
let call = self . call_libcall ( vmctx, host:: resource_new32, & host_args) ;
459
611
let result = self . builder . func . dfg . inst_results ( call) [ 0 ] ;
460
- let result = self . raise_if_resource_trapped ( result) ;
612
+ let result = self . raise_if_i32_trapped ( result) ;
461
613
self . abi_store_results ( & [ result] ) ;
462
614
}
463
615
@@ -486,7 +638,7 @@ impl<'a> TrampolineCompiler<'a> {
486
638
) ;
487
639
let call = self . call_libcall ( vmctx, host:: resource_rep32, & host_args) ;
488
640
let result = self . builder . func . dfg . inst_results ( call) [ 0 ] ;
489
- let result = self . raise_if_resource_trapped ( result) ;
641
+ let result = self . raise_if_i32_trapped ( result) ;
490
642
self . abi_store_results ( & [ result] ) ;
491
643
}
492
644
@@ -799,7 +951,7 @@ impl<'a> TrampolineCompiler<'a> {
799
951
self . raise_if_host_trapped ( succeeded) ;
800
952
}
801
953
802
- fn raise_if_resource_trapped ( & mut self , ret : ir:: Value ) -> ir:: Value {
954
+ fn raise_if_i32_trapped ( & mut self , ret : ir:: Value ) -> ir:: Value {
803
955
let minus_one = self . builder . ins ( ) . iconst ( ir:: types:: I64 , -1 ) ;
804
956
let succeeded = self . builder . ins ( ) . icmp ( IntCC :: NotEqual , ret, minus_one) ;
805
957
self . raise_if_host_trapped ( succeeded) ;
0 commit comments