@@ -22,11 +22,11 @@ use smallvec::SmallVec;
2222use std:: mem;
2323use wasmparser:: { Operator , WasmFeatures } ;
2424use wasmtime_environ:: {
25- BuiltinFunctionIndex , DataIndex , ElemIndex , EngineOrModuleTypeIndex , FuncIndex , GlobalIndex ,
26- IndexType , Memory , MemoryIndex , Module , ModuleInternedTypeIndex , ModuleTranslation ,
27- ModuleTypesBuilder , PtrSize , Table , TableIndex , TripleExt , Tunables , TypeConvert , TypeIndex ,
28- VMOffsets , WasmCompositeInnerType , WasmFuncType , WasmHeapTopType , WasmHeapType , WasmRefType ,
29- WasmResult , WasmValType ,
25+ BuiltinFunctionIndex , DataIndex , DefinedFuncIndex , ElemIndex , EngineOrModuleTypeIndex ,
26+ FuncIndex , GlobalIndex , IndexType , Memory , MemoryIndex , Module , ModuleInternedTypeIndex ,
27+ ModuleTranslation , ModuleTypesBuilder , PtrSize , Table , TableIndex , TripleExt , Tunables ,
28+ TypeConvert , TypeIndex , VMOffsets , WasmCompositeInnerType , WasmFuncType , WasmHeapTopType ,
29+ WasmHeapType , WasmRefType , WasmResult , WasmValType ,
3030} ;
3131use wasmtime_environ:: { FUNCREF_INIT_BIT , FUNCREF_MASK } ;
3232use wasmtime_math:: f64_cvt_to_int_bounds;
@@ -1176,9 +1176,14 @@ pub(crate) struct WasmEntities {
11761176 /// `ir::SigRef` in the Cranelift function we are building.
11771177 pub ( crate ) sig_refs : SecondaryMap < ModuleInternedTypeIndex , PackedOption < ir:: SigRef > > ,
11781178
1179- /// Map from a Wasm function index to its associated function reference in
1180- /// the Cranelift function we are building.
1181- pub ( crate ) func_refs : SecondaryMap < FuncIndex , PackedOption < ir:: FuncRef > > ,
1179+ /// Map from a defined Wasm function index to its associated function
1180+ /// reference in the Cranelift function we are building.
1181+ pub ( crate ) defined_func_refs : SecondaryMap < DefinedFuncIndex , PackedOption < ir:: FuncRef > > ,
1182+
1183+ /// Map from an imported Wasm function index for which we statically know
1184+ /// which function will always be used to satisfy that import to its
1185+ /// associated function reference in the Cranelift function we are building.
1186+ pub ( crate ) imported_func_refs : SecondaryMap < FuncIndex , PackedOption < ir:: FuncRef > > ,
11821187
11831188 /// Map from a Wasm table index to its associated implementation in the
11841189 /// Cranelift function we are building.
@@ -1207,7 +1212,8 @@ impl FuncEnvironment<'_> {
12071212 get_or_create_global( globals) : make_global : GlobalIndex => GlobalVariable ;
12081213 get_or_create_heap( memories) : make_heap : MemoryIndex => Heap ;
12091214 get_or_create_interned_sig_ref( sig_refs) : make_sig_ref : ModuleInternedTypeIndex => ir:: SigRef ;
1210- get_or_create_func_ref( func_refs) : make_func_ref : FuncIndex => ir:: FuncRef ;
1215+ get_or_create_defined_func_ref( defined_func_refs) : make_defined_func_ref : DefinedFuncIndex => ir:: FuncRef ;
1216+ get_or_create_imported_func_ref( imported_func_refs) : make_imported_func_ref : FuncIndex => ir:: FuncRef ;
12111217 get_or_create_table( tables) : make_table : TableIndex => TableData ;
12121218 }
12131219
@@ -1253,39 +1259,48 @@ impl FuncEnvironment<'_> {
12531259 sig_ref
12541260 }
12551261
1256- fn make_func_ref ( & mut self , func : & mut ir:: Function , index : FuncIndex ) -> ir:: FuncRef {
1257- let sig = self . module . functions [ index]
1262+ fn make_defined_func_ref (
1263+ & mut self ,
1264+ func : & mut ir:: Function ,
1265+ def_func_index : DefinedFuncIndex ,
1266+ ) -> ir:: FuncRef {
1267+ let func_index = self . module . func_index ( def_func_index) ;
1268+ let ty = self . module . functions [ func_index]
12581269 . signature
12591270 . unwrap_module_type_index ( ) ;
1260- let wasm_func_ty = self . types [ sig] . unwrap_func ( ) ;
1261- let sig = crate :: wasm_call_signature ( self . isa , wasm_func_ty, & self . tunables ) ;
1262- let signature = func. import_signature ( sig) ;
1263- self . sig_ref_to_ty [ signature] = Some ( wasm_func_ty) ;
1271+ let signature = self . get_or_create_interned_sig_ref ( func, ty) ;
12641272 let name =
12651273 ir:: ExternalName :: User ( func. declare_imported_user_function ( ir:: UserExternalName {
12661274 namespace : crate :: NS_WASM_FUNC ,
1267- index : index . as_u32 ( ) ,
1275+ index : func_index . as_u32 ( ) ,
12681276 } ) ) ;
12691277 func. import_function ( ir:: ExtFuncData {
12701278 name,
12711279 signature,
1280+ colocated : true ,
1281+ } )
1282+ }
12721283
1273- // the value of this flag determines the codegen for calls to this
1274- // function. if this flag is `false` then absolute relocations will
1275- // be generated for references to the function, which requires
1276- // load-time relocation resolution. if this flag is set to `true`
1277- // then relative relocations are emitted which can be resolved at
1278- // object-link-time, just after all functions are compiled.
1279- //
1280- // this flag is set to `true` for functions defined in the object
1281- // we'll be defining in this compilation unit, or everything local
1282- // to the wasm module. this means that between functions in a wasm
1283- // module there's relative calls encoded. all calls external to a
1284- // wasm module (e.g. imports or libcalls) are either encoded through
1285- // the `vmcontext` as relative jumps (hence no relocations) or
1286- // they're libcalls with absolute relocations.
1287- colocated : self . module . defined_func_index ( index) . is_some ( )
1288- || self . translation . known_imported_functions [ index] . is_some ( ) ,
1284+ fn make_imported_func_ref (
1285+ & mut self ,
1286+ func : & mut ir:: Function ,
1287+ func_index : FuncIndex ,
1288+ ) -> ir:: FuncRef {
1289+ assert ! ( self . module. is_imported_function( func_index) ) ;
1290+ assert ! ( self . translation. known_imported_functions[ func_index] . is_some( ) ) ;
1291+ let ty = self . module . functions [ func_index]
1292+ . signature
1293+ . unwrap_module_type_index ( ) ;
1294+ let signature = self . get_or_create_interned_sig_ref ( func, ty) ;
1295+ let name =
1296+ ir:: ExternalName :: User ( func. declare_imported_user_function ( ir:: UserExternalName {
1297+ namespace : crate :: NS_WASM_FUNC ,
1298+ index : func_index. as_u32 ( ) ,
1299+ } ) ) ;
1300+ func. import_function ( ir:: ExtFuncData {
1301+ name,
1302+ signature,
1303+ colocated : true ,
12891304 } )
12901305 }
12911306
@@ -1628,11 +1643,11 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> {
16281643 }
16291644 }
16301645
1631- /// Do a direct call to the given callee function.
1646+ /// Do a Wasm-level direct call to the given callee function.
16321647 pub fn direct_call (
16331648 mut self ,
16341649 callee_index : FuncIndex ,
1635- callee : ir:: FuncRef ,
1650+ sig_ref : ir:: SigRef ,
16361651 call_args : & [ ir:: Value ] ,
16371652 ) -> WasmResult < ir:: Inst > {
16381653 let mut real_call_args = Vec :: with_capacity ( call_args. len ( ) + 2 ) ;
@@ -1643,7 +1658,7 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> {
16431658 . unwrap ( ) ;
16441659
16451660 // Handle direct calls to locally-defined functions.
1646- if ! self . env . module . is_imported_function ( callee_index) {
1661+ if let Some ( def_func_index ) = self . env . module . defined_func_index ( callee_index) {
16471662 // First append the callee vmctx address, which is the same as the caller vmctx in
16481663 // this case.
16491664 real_call_args. push ( caller_vmctx) ;
@@ -1655,13 +1670,15 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> {
16551670 real_call_args. extend_from_slice ( call_args) ;
16561671
16571672 // Finally, make the direct call!
1673+ let callee = self
1674+ . env
1675+ . get_or_create_defined_func_ref ( self . builder . func , def_func_index) ;
16581676 return Ok ( self . direct_call_inst ( callee, & real_call_args) ) ;
16591677 }
16601678
16611679 // Handle direct calls to imported functions. We use an indirect call
16621680 // so that we don't have to patch the code at runtime.
16631681 let pointer_type = self . env . pointer_type ( ) ;
1664- let sig_ref = self . builder . func . dfg . ext_funcs [ callee] . signature ;
16651682 let vmctx = self . env . vmctx ( self . builder . func ) ;
16661683 let base = self . builder . ins ( ) . global_value ( pointer_type, vmctx) ;
16671684
@@ -1694,6 +1711,9 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> {
16941711 // pass the callee's vmctx that we just loaded, not our own). Otherwise,
16951712 // we really do an indirect call.
16961713 if self . env . translation . known_imported_functions [ callee_index] . is_some ( ) {
1714+ let callee = self
1715+ . env
1716+ . get_or_create_imported_func_ref ( self . builder . func , callee_index) ;
16971717 Ok ( self . direct_call_inst ( callee, & real_call_args) )
16981718 } else {
16991719 let func_addr = self
@@ -1704,7 +1724,7 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> {
17041724 }
17051725 }
17061726
1707- /// Do an indirect call through the given funcref table.
1727+ /// Do a Wasm-level indirect call through the given funcref table.
17081728 pub fn indirect_call (
17091729 mut self ,
17101730 features : & WasmFeatures ,
@@ -2773,10 +2793,10 @@ impl FuncEnvironment<'_> {
27732793 & mut self ,
27742794 builder : & mut FunctionBuilder ,
27752795 callee_index : FuncIndex ,
2776- callee : ir:: FuncRef ,
2796+ sig_ref : ir:: SigRef ,
27772797 call_args : & [ ir:: Value ] ,
27782798 ) -> WasmResult < ir:: Inst > {
2779- Call :: new ( builder, self ) . direct_call ( callee_index, callee , call_args)
2799+ Call :: new ( builder, self ) . direct_call ( callee_index, sig_ref , call_args)
27802800 }
27812801
27822802 pub fn translate_call_ref (
@@ -2793,10 +2813,10 @@ impl FuncEnvironment<'_> {
27932813 & mut self ,
27942814 builder : & mut FunctionBuilder ,
27952815 callee_index : FuncIndex ,
2796- callee : ir:: FuncRef ,
2816+ sig_ref : ir:: SigRef ,
27972817 call_args : & [ ir:: Value ] ,
27982818 ) -> WasmResult < ( ) > {
2799- Call :: new_tail ( builder, self ) . direct_call ( callee_index, callee , call_args) ?;
2819+ Call :: new_tail ( builder, self ) . direct_call ( callee_index, sig_ref , call_args) ?;
28002820 Ok ( ( ) )
28012821 }
28022822
0 commit comments