33use crate :: { compiler:: Compiler , TRAP_ALWAYS , TRAP_CANNOT_ENTER , TRAP_INTERNAL_ASSERT } ;
44use anyhow:: Result ;
55use cranelift_codegen:: ir:: condcodes:: IntCC ;
6- use cranelift_codegen:: ir:: { self , InstBuilder , MemFlags } ;
6+ use cranelift_codegen:: ir:: { self , InstBuilder , MemFlags , Value } ;
77use cranelift_codegen:: isa:: { CallConv , TargetIsa } ;
88use cranelift_frontend:: FunctionBuilder ;
99use std:: any:: Any ;
@@ -98,7 +98,7 @@ impl<'a> TrampolineCompiler<'a> {
9898 _ = instance;
9999 todo ! ( )
100100 }
101- Trampoline :: TaskReturn => todo ! ( ) ,
101+ Trampoline :: TaskReturn => self . translate_task_return_call ( ) ,
102102 Trampoline :: TaskWait {
103103 instance,
104104 async_,
@@ -196,12 +196,12 @@ impl<'a> TrampolineCompiler<'a> {
196196 Trampoline :: ResourceDrop ( ty) => self . translate_resource_drop ( * ty) ,
197197 Trampoline :: ResourceTransferOwn => {
198198 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 ] ) ;
200200 } )
201201 }
202202 Trampoline :: ResourceTransferBorrow => {
203203 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 ] ) ;
205205 } )
206206 }
207207 Trampoline :: ResourceEnterCall => {
@@ -212,14 +212,17 @@ impl<'a> TrampolineCompiler<'a> {
212212 me. raise_if_host_trapped ( rets. pop ( ) . unwrap ( ) ) ;
213213 } )
214214 }
215- Trampoline :: AsyncEnterCall => todo ! ( ) ,
215+ Trampoline :: AsyncEnterCall => {
216+ self . translate_async_enter_or_exit ( host:: async_enter, None , ir:: types:: I8 )
217+ }
216218 Trampoline :: AsyncExitCall {
217219 callback,
218220 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+ ) ,
223226 Trampoline :: FutureTransfer => {
224227 _ = host:: future_transfer;
225228 todo ! ( )
@@ -235,25 +238,18 @@ impl<'a> TrampolineCompiler<'a> {
235238 }
236239 }
237240
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 ) {
244242 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 ( ) ;
248244
249245 // Start off by spilling all the wasm arguments into a stack slot to be
250246 // passed to the host function.
251- let ( values_vec_ptr , values_vec_len ) = match self . abi {
247+ match self . abi {
252248 Abi :: Wasm => {
253249 let ( ptr, len) = self . compiler . allocate_stack_array_and_spill_args (
254250 wasm_func_ty,
255251 & mut self . builder ,
256- & args[ 2 .. ] ,
252+ args,
257253 ) ;
258254 let len = self . builder . ins ( ) . iconst ( pointer_type, i64:: from ( len) ) ;
259255 ( ptr, len)
@@ -262,7 +258,163 @@ impl<'a> TrampolineCompiler<'a> {
262258 let params = self . builder . func . dfg . block_params ( self . block0 ) ;
263259 ( params[ 2 ] , params[ 3 ] )
264260 }
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 ..] ) ;
266418
267419 // Below this will incrementally build both the signature of the host
268420 // function we're calling as well as the list of arguments since the
@@ -457,7 +609,7 @@ impl<'a> TrampolineCompiler<'a> {
457609 ) ;
458610 let call = self . call_libcall ( vmctx, host:: resource_new32, & host_args) ;
459611 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) ;
461613 self . abi_store_results ( & [ result] ) ;
462614 }
463615
@@ -486,7 +638,7 @@ impl<'a> TrampolineCompiler<'a> {
486638 ) ;
487639 let call = self . call_libcall ( vmctx, host:: resource_rep32, & host_args) ;
488640 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) ;
490642 self . abi_store_results ( & [ result] ) ;
491643 }
492644
@@ -799,7 +951,7 @@ impl<'a> TrampolineCompiler<'a> {
799951 self . raise_if_host_trapped ( succeeded) ;
800952 }
801953
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 {
803955 let minus_one = self . builder . ins ( ) . iconst ( ir:: types:: I64 , -1 ) ;
804956 let succeeded = self . builder . ins ( ) . icmp ( IntCC :: NotEqual , ret, minus_one) ;
805957 self . raise_if_host_trapped ( succeeded) ;
0 commit comments