@@ -32,8 +32,8 @@ use wasmtime_environ::obj::ELF_WASMTIME_EXCEPTIONS;
3232use wasmtime_environ:: {
3333 Abi , AddressMapSection , BuiltinFunctionIndex , CacheStore , CompileError , CompiledFunctionBody ,
3434 DefinedFuncIndex , FlagValue , FuncKey , FunctionBodyData , FunctionLoc , HostCall ,
35- InliningCompiler , ModuleTranslation , ModuleTypesBuilder , PtrSize , StackMapSection ,
36- StaticModuleIndex , TrapEncodingBuilder , TrapSentinel , TripleExt , Tunables , VMOffsets ,
35+ InliningCompiler , ModuleInternedTypeIndex , ModuleTranslation , ModuleTypesBuilder , PtrSize ,
36+ StackMapSection , StaticModuleIndex , TrapEncodingBuilder , TrapSentinel , TripleExt , Tunables ,
3737 WasmFuncType , WasmValType ,
3838} ;
3939use wasmtime_unwinder:: ExceptionTableBuilder ;
@@ -343,140 +343,20 @@ impl wasmtime_environ::Compiler for Compiler {
343343 key : FuncKey ,
344344 symbol : & str ,
345345 ) -> Result < CompiledFunctionBody , CompileError > {
346- log:: trace!( "compiling array-to-wasm trampoline: {key:?} = {symbol:?}" ) ;
347-
348346 let ( module_index, def_func_index) = key. unwrap_array_to_wasm_trampoline ( ) ;
349- debug_assert_eq ! ( translation. module_index( ) , module_index) ;
350-
351347 let func_index = translation. module . func_index ( def_func_index) ;
352348 let sig = translation. module . functions [ func_index]
353349 . signature
354350 . unwrap_module_type_index ( ) ;
355- let wasm_func_ty = types[ sig] . unwrap_func ( ) ;
356-
357- let isa = & * self . isa ;
358- let pointer_type = isa. pointer_type ( ) ;
359- let wasm_call_sig = wasm_call_signature ( isa, wasm_func_ty, & self . tunables ) ;
360- let array_call_sig = array_call_signature ( isa) ;
361-
362- let mut compiler = self . function_compiler ( ) ;
363- let func = ir:: Function :: with_name_signature ( key_to_name ( key) , array_call_sig) ;
364- let ( mut builder, block0) = compiler. builder ( func) ;
365-
366- let try_call_block = builder. create_block ( ) ;
367- builder. ins ( ) . jump ( try_call_block, [ ] ) ;
368- builder. switch_to_block ( try_call_block) ;
369-
370- let ( vmctx, caller_vmctx, values_vec_ptr, values_vec_len) = {
371- let params = builder. func . dfg . block_params ( block0) ;
372- ( params[ 0 ] , params[ 1 ] , params[ 2 ] , params[ 3 ] )
373- } ;
374-
375- // First load the actual arguments out of the array.
376- let mut args = self . load_values_from_array (
377- wasm_func_ty. params ( ) ,
378- & mut builder,
379- values_vec_ptr,
380- values_vec_len,
381- ) ;
382- args. insert ( 0 , caller_vmctx) ;
383- args. insert ( 0 , vmctx) ;
384-
385- // Just before we enter Wasm, save our context information.
386- //
387- // Assert that we were really given a core Wasm vmctx, since that's
388- // what we are assuming with our offsets below.
389- self . debug_assert_vmctx_kind ( & mut builder, vmctx, wasmtime_environ:: VMCONTEXT_MAGIC ) ;
390- let offsets = VMOffsets :: new ( isa. pointer_bytes ( ) , & translation. module ) ;
391- let vm_store_context_offset = offsets. ptr . vmctx_store_context ( ) ;
392- save_last_wasm_entry_context (
393- & mut builder,
394- pointer_type,
395- & offsets. ptr ,
396- vm_store_context_offset. into ( ) ,
397- vmctx,
398- try_call_block,
399- ) ;
400-
401- // Create the invocation of wasm, which is notably done with a
402- // `try_call` with an exception handler that's used to handle traps.
403- let normal_return = builder. create_block ( ) ;
404- let exceptional_return = builder. create_block ( ) ;
405- let normal_return_values = wasm_call_sig
406- . returns
407- . iter ( )
408- . map ( |ty| {
409- builder
410- . func
411- . dfg
412- . append_block_param ( normal_return, ty. value_type )
413- } )
414- . collect :: < Vec < _ > > ( ) ;
415-
416- // Then call the Wasm function with those arguments.
417- let callee_key = FuncKey :: DefinedWasmFunction ( module_index, def_func_index) ;
418- let signature = builder. func . import_signature ( wasm_call_sig. clone ( ) ) ;
419- let callee = {
420- let ( namespace, index) = callee_key. into_raw_parts ( ) ;
421- let name = ir:: ExternalName :: User (
422- builder
423- . func
424- . declare_imported_user_function ( ir:: UserExternalName { namespace, index } ) ,
425- ) ;
426- builder. func . dfg . ext_funcs . push ( ir:: ExtFuncData {
427- name,
428- signature,
429- colocated : true ,
430- } )
431- } ;
432-
433- let dfg = & mut builder. func . dfg ;
434- let exception_table = dfg. exception_tables . push ( ir:: ExceptionTableData :: new (
435- signature,
436- ir:: BlockCall :: new (
437- normal_return,
438- ( 0 ..wasm_call_sig. returns . len ( ) )
439- . map ( |i| ir:: BlockArg :: TryCallRet ( i. try_into ( ) . unwrap ( ) ) ) ,
440- & mut dfg. value_lists ,
441- ) ,
442- [ ir:: ExceptionTableItem :: Default ( ir:: BlockCall :: new (
443- exceptional_return,
444- None ,
445- & mut dfg. value_lists ,
446- ) ) ] ,
447- ) ) ;
448- builder. ins ( ) . try_call ( callee, & args, exception_table) ;
449-
450- builder. seal_block ( try_call_block) ;
451- builder. seal_block ( normal_return) ;
452- builder. seal_block ( exceptional_return) ;
453-
454- // On the normal return path store all the results in the array we were
455- // provided and return "true" for "returned successfully".
456- builder. switch_to_block ( normal_return) ;
457- self . store_values_to_array (
458- & mut builder,
459- wasm_func_ty. returns ( ) ,
460- & normal_return_values,
461- values_vec_ptr,
462- values_vec_len,
463- ) ;
464- let true_return = builder. ins ( ) . iconst ( ir:: types:: I8 , 1 ) ;
465- builder. ins ( ) . return_ ( & [ true_return] ) ;
466-
467- // On the exceptional return path just return "false" for "did not
468- // succeed". Note that register restoration is part of the `try_call`
469- // and handler implementation.
470- builder. switch_to_block ( exceptional_return) ;
471- let false_return = builder. ins ( ) . iconst ( ir:: types:: I8 , 0 ) ;
472- builder. ins ( ) . return_ ( & [ false_return] ) ;
473-
474- builder. finalize ( ) ;
475-
476- Ok ( CompiledFunctionBody {
477- code : box_dyn_any_compiler_context ( Some ( compiler. cx ) ) ,
478- needs_gc_heap : false ,
479- } )
351+ self . array_to_wasm_trampoline (
352+ key,
353+ FuncKey :: DefinedWasmFunction ( module_index, def_func_index) ,
354+ types,
355+ sig,
356+ symbol,
357+ self . isa . pointer_bytes ( ) . vmctx_store_context ( ) . into ( ) ,
358+ wasmtime_environ:: VMCONTEXT_MAGIC ,
359+ )
480360 }
481361
482362 fn compile_wasm_to_array_trampoline (
@@ -1284,6 +1164,142 @@ impl Compiler {
12841164 ) ;
12851165 builder. ins ( ) . trapz ( is_expected_vmctx, TRAP_INTERNAL_ASSERT ) ;
12861166 }
1167+
1168+ fn array_to_wasm_trampoline (
1169+ & self ,
1170+ trampoline_key : FuncKey ,
1171+ callee_key : FuncKey ,
1172+ types : & ModuleTypesBuilder ,
1173+ callee_sig : ModuleInternedTypeIndex ,
1174+ symbol : & str ,
1175+ vm_store_context_offset : u32 ,
1176+ expected_vmctx_magic : u32 ,
1177+ ) -> Result < CompiledFunctionBody , CompileError > {
1178+ log:: trace!( "compiling array-to-wasm trampoline: {trampoline_key:?} = {symbol:?}" ) ;
1179+
1180+ let wasm_func_ty = types[ callee_sig] . unwrap_func ( ) ;
1181+
1182+ let isa = & * self . isa ;
1183+ let pointer_type = isa. pointer_type ( ) ;
1184+ let wasm_call_sig = wasm_call_signature ( isa, wasm_func_ty, & self . tunables ) ;
1185+ let array_call_sig = array_call_signature ( isa) ;
1186+
1187+ let mut compiler = self . function_compiler ( ) ;
1188+ let func = ir:: Function :: with_name_signature ( key_to_name ( trampoline_key) , array_call_sig) ;
1189+ let ( mut builder, block0) = compiler. builder ( func) ;
1190+
1191+ let try_call_block = builder. create_block ( ) ;
1192+ builder. ins ( ) . jump ( try_call_block, [ ] ) ;
1193+ builder. switch_to_block ( try_call_block) ;
1194+
1195+ let ( vmctx, caller_vmctx, values_vec_ptr, values_vec_len) = {
1196+ let params = builder. func . dfg . block_params ( block0) ;
1197+ ( params[ 0 ] , params[ 1 ] , params[ 2 ] , params[ 3 ] )
1198+ } ;
1199+
1200+ // First load the actual arguments out of the array.
1201+ let mut args = self . load_values_from_array (
1202+ wasm_func_ty. params ( ) ,
1203+ & mut builder,
1204+ values_vec_ptr,
1205+ values_vec_len,
1206+ ) ;
1207+ args. insert ( 0 , caller_vmctx) ;
1208+ args. insert ( 0 , vmctx) ;
1209+
1210+ // Just before we enter Wasm, save our context information.
1211+ //
1212+ // Assert that we were really given a core Wasm vmctx, since that's
1213+ // what we are assuming with our offsets below.
1214+ self . debug_assert_vmctx_kind ( & mut builder, vmctx, expected_vmctx_magic) ;
1215+ save_last_wasm_entry_context (
1216+ & mut builder,
1217+ pointer_type,
1218+ & self . isa . pointer_bytes ( ) ,
1219+ vm_store_context_offset,
1220+ vmctx,
1221+ try_call_block,
1222+ ) ;
1223+
1224+ // Create the invocation of wasm, which is notably done with a
1225+ // `try_call` with an exception handler that's used to handle traps.
1226+ let normal_return = builder. create_block ( ) ;
1227+ let exceptional_return = builder. create_block ( ) ;
1228+ let normal_return_values = wasm_call_sig
1229+ . returns
1230+ . iter ( )
1231+ . map ( |ty| {
1232+ builder
1233+ . func
1234+ . dfg
1235+ . append_block_param ( normal_return, ty. value_type )
1236+ } )
1237+ . collect :: < Vec < _ > > ( ) ;
1238+
1239+ // Then call the Wasm function with those arguments.
1240+ let signature = builder. func . import_signature ( wasm_call_sig. clone ( ) ) ;
1241+ let callee = {
1242+ let ( namespace, index) = callee_key. into_raw_parts ( ) ;
1243+ let name = ir:: ExternalName :: User (
1244+ builder
1245+ . func
1246+ . declare_imported_user_function ( ir:: UserExternalName { namespace, index } ) ,
1247+ ) ;
1248+ builder. func . dfg . ext_funcs . push ( ir:: ExtFuncData {
1249+ name,
1250+ signature,
1251+ colocated : true ,
1252+ } )
1253+ } ;
1254+
1255+ let dfg = & mut builder. func . dfg ;
1256+ let exception_table = dfg. exception_tables . push ( ir:: ExceptionTableData :: new (
1257+ signature,
1258+ ir:: BlockCall :: new (
1259+ normal_return,
1260+ ( 0 ..wasm_call_sig. returns . len ( ) )
1261+ . map ( |i| ir:: BlockArg :: TryCallRet ( i. try_into ( ) . unwrap ( ) ) ) ,
1262+ & mut dfg. value_lists ,
1263+ ) ,
1264+ [ ir:: ExceptionTableItem :: Default ( ir:: BlockCall :: new (
1265+ exceptional_return,
1266+ None ,
1267+ & mut dfg. value_lists ,
1268+ ) ) ] ,
1269+ ) ) ;
1270+ builder. ins ( ) . try_call ( callee, & args, exception_table) ;
1271+
1272+ builder. seal_block ( try_call_block) ;
1273+ builder. seal_block ( normal_return) ;
1274+ builder. seal_block ( exceptional_return) ;
1275+
1276+ // On the normal return path store all the results in the array we were
1277+ // provided and return "true" for "returned successfully".
1278+ builder. switch_to_block ( normal_return) ;
1279+ self . store_values_to_array (
1280+ & mut builder,
1281+ wasm_func_ty. returns ( ) ,
1282+ & normal_return_values,
1283+ values_vec_ptr,
1284+ values_vec_len,
1285+ ) ;
1286+ let true_return = builder. ins ( ) . iconst ( ir:: types:: I8 , 1 ) ;
1287+ builder. ins ( ) . return_ ( & [ true_return] ) ;
1288+
1289+ // On the exceptional return path just return "false" for "did not
1290+ // succeed". Note that register restoration is part of the `try_call`
1291+ // and handler implementation.
1292+ builder. switch_to_block ( exceptional_return) ;
1293+ let false_return = builder. ins ( ) . iconst ( ir:: types:: I8 , 0 ) ;
1294+ builder. ins ( ) . return_ ( & [ false_return] ) ;
1295+
1296+ builder. finalize ( ) ;
1297+
1298+ Ok ( CompiledFunctionBody {
1299+ code : box_dyn_any_compiler_context ( Some ( compiler. cx ) ) ,
1300+ needs_gc_heap : false ,
1301+ } )
1302+ }
12871303}
12881304
12891305struct FunctionCompiler < ' a > {
@@ -1450,7 +1466,7 @@ fn clif_to_env_exception_tables<'a>(
14501466fn save_last_wasm_entry_context (
14511467 builder : & mut FunctionBuilder ,
14521468 pointer_type : ir:: Type ,
1453- ptr_size : & impl PtrSize ,
1469+ ptr_size : & dyn PtrSize ,
14541470 vm_store_context_offset : u32 ,
14551471 vmctx : Value ,
14561472 block : ir:: Block ,
0 commit comments