@ -1,13 +1,12 @@
use crate ::BuiltinFunctionSignatures ;
use cranelift_codegen ::cursor ::FuncCursor ;
use cranelift_codegen ::ir ;
use cranelift_codegen ::ir ::condcodes ::* ;
use cranelift_codegen ::ir ::immediates ::{ Imm64 , Offset32 } ;
use cranelift_codegen ::ir ::pcc ::Fact ;
use cranelift_codegen ::ir ::types ::* ;
use cranelift_codegen ::ir ::{
AbiParam , ArgumentPurpose , Function , InstBuilder , MemFlags , Signature ,
} ;
use cranelift_codegen ::isa ::{ self , CallConv , TargetFrontendConfig , TargetIsa } ;
use cranelift_codegen ::ir ::{ ArgumentPurpose , Function , InstBuilder , MemFlags } ;
use cranelift_codegen ::isa ::{ TargetFrontendConfig , TargetIsa } ;
use cranelift_entity ::{ EntityRef , PrimaryMap , SecondaryMap } ;
use cranelift_frontend ::FunctionBuilder ;
use cranelift_frontend ::Variable ;
@ -24,103 +23,59 @@ use wasmtime_environ::{
} ;
use wasmtime_environ ::{ FUNCREF_INIT_BIT , FUNCREF_MASK } ;
macro_rules ! declare_function_signatures {
(
$(
$( #[ $attr:meta ] ) *
$name :ident ( $( $pname :ident : $param :ident ) , * ) $( -> $result :ident ) ? ;
) *
) = > {
/// A struct with an `Option<ir::SigRef>` member for every builtin
/// function, to de-duplicate constructing/getting its signature.
#[ allow(unused_doc_comments) ]
struct BuiltinFunctionSignatures {
pointer_type : ir ::Type ,
/// A struct with an `Option<ir::FuncRef>` member for every builtin
/// function, to de-duplicate constructing/getting its function.
struct BuiltinFunctions {
types : BuiltinFunctionSignatures ,
#[ cfg(feature = " gc " ) ]
reference_type : ir ::Type ,
call_conv : isa ::CallConv ,
builtins :
[ Option < ir ::FuncRef > ; BuiltinFunctionIndex ::builtin_functions_total_number ( ) as usize ] ,
}
$(
$( #[ $attr ] ) *
$name : Option < ir ::SigRef > ,
) *
impl BuiltinFunctions {
fn new ( isa : & dyn TargetIsa ) -> Self {
Self {
types : BuiltinFunctionSignatures ::new ( isa ) ,
builtins : [ None ; BuiltinFunctionIndex ::builtin_functions_total_number ( ) as usize ] ,
}
}
#[ allow(unused_doc_comments) ]
impl BuiltinFunctionSignatures {
fn new (
pointer_type : ir ::Type ,
reference_type : ir ::Type ,
call_conv : isa ::CallConv ,
) -> Self {
#[ cfg(not(feature = " gc " )) ]
let _ = reference_type ;
Self {
pointer_type ,
#[ cfg(feature = " gc " ) ]
reference_type ,
call_conv ,
$(
$( #[ $attr ] ) *
$name : None ,
) *
}
}
fn vmctx ( & self ) -> AbiParam {
AbiParam ::special ( self . pointer_type , ArgumentPurpose ::VMContext )
}
#[ cfg(feature = " gc " ) ]
fn reference ( & self ) -> AbiParam {
AbiParam ::new ( self . reference_type )
}
fn pointer ( & self ) -> AbiParam {
AbiParam ::new ( self . pointer_type )
}
fn i32 ( & self ) -> AbiParam {
// Some platform ABIs require i32 values to be zero- or sign-
// extended to the full register width. We need to indicate
// this here by using the appropriate .uext or .sext attribute.
// The attribute can be added unconditionally; platforms whose
// ABI does not require such extensions will simply ignore it.
// Note that currently all i32 arguments or return values used
// by builtin functions are unsigned, so we always use .uext.
// If that ever changes, we will have to add a second type
// marker here.
AbiParam ::new ( I32 ) . uext ( )
}
fn load_builtin ( & mut self , func : & mut Function , index : BuiltinFunctionIndex ) -> ir ::FuncRef {
let cache = & mut self . builtins [ index . index ( ) as usize ] ;
if let Some ( f ) = cache {
return * f ;
}
let signature = func . import_signature ( self . types . signature ( index ) ) ;
let name =
ir ::ExternalName ::User ( func . declare_imported_user_function ( ir ::UserExternalName {
namespace : crate ::NS_WASMTIME_BUILTIN ,
index : index . index ( ) ,
} ) ) ;
let f = func . import_function ( ir ::ExtFuncData {
name ,
signature ,
colocated : true ,
} ) ;
* cache = Some ( f ) ;
f
}
}
fn i64 ( & self ) -> AbiParam {
AbiParam ::new ( I64 )
// Generate helper methods on `BuiltinFunctions` above for each named builtin
// as well.
macro_rules ! declare_function_signatures {
( $(
$( #[ $attr:meta ] ) *
$name :ident ( $( $pname :ident : $param :ident ) , * ) $( -> $result :ident ) ? ;
) * ) = > {
$( impl BuiltinFunctions {
$( #[ $attr ] ) *
fn $name ( & mut self , func : & mut Function ) -> ir ::FuncRef {
self . load_builtin ( func , BuiltinFunctionIndex ::$name ( ) )
}
$(
$( #[ $attr ] ) *
fn $name ( & mut self , func : & mut Function ) -> ir ::SigRef {
let sig = self . $name . unwrap_or_else ( | | {
func . import_signature ( Signature {
params : vec ! [ $( self . $param ( ) ) , * ] ,
returns : vec ! [ $( self . $result ( ) ) ? ] ,
call_conv : self . call_conv ,
} )
} ) ;
self . $name = Some ( sig ) ;
sig
}
) *
}
} ) *
} ;
}
wasmtime_environ ::foreach_builtin_function ! ( declare_function_signatures ) ;
/// The `FuncEnvironment` implementation for use by the `ModuleEnvironment`.
@ -146,7 +101,7 @@ pub struct FuncEnvironment<'module_environment> {
pcc_vmctx_memtype : Option < ir ::MemoryType > ,
/// Caches of signatures for builtin functions.
builtin_function_signature s : BuiltinFunctionSignature s ,
builtin_functions : BuiltinFunctions ,
/// Offsets to struct fields accessed by JIT code.
pub ( crate ) offsets : VMOffsets < u8 > ,
@ -192,15 +147,7 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
tunables : & 'module_environment Tunables ,
wmemcheck : bool ,
) -> Self {
let builtin_function_signatures = BuiltinFunctionSignatures ::new (
isa . pointer_type ( ) ,
match isa . pointer_type ( ) {
ir ::types ::I32 = > ir ::types ::R32 ,
ir ::types ::I64 = > ir ::types ::R64 ,
_ = > panic ! ( ) ,
} ,
CallConv ::triple_default ( isa . triple ( ) ) ,
) ;
let builtin_functions = BuiltinFunctions ::new ( isa ) ;
// Avoid unused warning in default build.
#[ cfg(not(feature = " wmemcheck " )) ]
@ -214,7 +161,7 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
tables : SecondaryMap ::default ( ) ,
vmctx : None ,
pcc_vmctx_memtype : None ,
builtin_function_signature s ,
builtin_functions ,
offsets : VMOffsets ::new ( isa . pointer_bytes ( ) , & translation . module ) ,
tunables ,
fuel_var : Variable ::new ( 0 ) ,
@ -262,98 +209,45 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
} )
}
fn vmctx_val ( & mut self , pos : & mut FuncCursor < '_ > ) -> ir ::Value {
let pointer_type = self . pointer_type ( ) ;
let vmctx = self . vmctx ( & mut pos . func ) ;
pos . ins ( ) . global_value ( pointer_type , vmctx )
}
fn get_table_copy_func (
& mut self ,
func : & mut Function ,
dst_table_index : TableIndex ,
src_table_index : TableIndex ,
) -> ( ir ::SigRef , usize , usize , BuiltinFunctionIndex ) {
let sig = self . builtin_function_signature s . table_copy ( func ) ;
) -> ( ir ::Func Ref, usize , usize ) {
let sig = self . builtin_functions . table_copy ( func ) ;
(
sig ,
dst_table_index . as_u32 ( ) as usize ,
src_table_index . as_u32 ( ) as usize ,
BuiltinFunctionIndex ::table_copy ( ) ,
)
}
fn get_table_init_func (
& mut self ,
func : & mut Function ,
table_index : TableIndex ,
) -> ( ir ::SigRef , usize , BuiltinFunctionIndex ) {
let sig = self . builtin_function_signatures . table_init ( func ) ;
let table_index = table_index . as_u32 ( ) as usize ;
( sig , table_index , BuiltinFunctionIndex ::table_init ( ) )
}
fn get_elem_drop_func ( & mut self , func : & mut Function ) -> ( ir ::SigRef , BuiltinFunctionIndex ) {
let sig = self . builtin_function_signatures . elem_drop ( func ) ;
( sig , BuiltinFunctionIndex ::elem_drop ( ) )
}
fn get_memory_atomic_wait (
& mut self ,
func : & mut Function ,
memory_index : MemoryIndex ,
ty : ir ::Type ,
) -> ( ir ::Sig Ref, usize , BuiltinFunctionIndex ) {
) -> ( ir ::FuncRef , usize ) {
match ty {
I32 = > (
self . builtin_function_signature s . memory_atomic_wait32 ( func ) ,
self . builtin_functions . memory_atomic_wait32 ( func ) ,
memory_index . index ( ) ,
BuiltinFunctionIndex ::memory_atomic_wait32 ( ) ,
) ,
I64 = > (
self . builtin_function_signature s . memory_atomic_wait64 ( func ) ,
self . builtin_functions . memory_atomic_wait64 ( func ) ,
memory_index . index ( ) ,
BuiltinFunctionIndex ::memory_atomic_wait64 ( ) ,
) ,
x = > panic ! ( "get_memory_atomic_wait unsupported type: {:?}" , x ) ,
}
}
fn get_memory_init_func ( & mut self , func : & mut Function ) -> ( ir ::SigRef , BuiltinFunctionIndex ) {
(
self . builtin_function_signatures . memory_init ( func ) ,
BuiltinFunctionIndex ::memory_init ( ) ,
)
}
fn get_data_drop_func ( & mut self , func : & mut Function ) -> ( ir ::SigRef , BuiltinFunctionIndex ) {
(
self . builtin_function_signatures . data_drop ( func ) ,
BuiltinFunctionIndex ::data_drop ( ) ,
)
}
/// Translates load of builtin function and returns a pair of values `vmctx`
/// and address of the loaded function.
fn translate_load_builtin_function_address (
& mut self ,
pos : & mut FuncCursor < '_ > ,
callee_func_idx : BuiltinFunctionIndex ,
) -> ( ir ::Value , ir ::Value ) {
// We use an indirect call so that we don't have to patch the code at runtime.
let pointer_type = self . pointer_type ( ) ;
let vmctx = self . vmctx ( & mut pos . func ) ;
let base = pos . ins ( ) . global_value ( pointer_type , vmctx ) ;
let mem_flags = ir ::MemFlags ::trusted ( ) . with_readonly ( ) ;
// Load the base of the array of builtin functions
let array_offset = i32 ::try_from ( self . offsets . vmctx_builtin_functions ( ) ) . unwrap ( ) ;
let array_addr = pos . ins ( ) . load ( pointer_type , mem_flags , base , array_offset ) ;
// Load the callee address.
let body_offset = i32 ::try_from ( callee_func_idx . index ( ) * pointer_type . bytes ( ) ) . unwrap ( ) ;
let func_addr = pos
. ins ( )
. load ( pointer_type , mem_flags , array_addr , body_offset ) ;
( base , func_addr )
}
/// Generate code to increment or decrement the given `externref`'s
/// reference count.
///
@ -621,14 +515,9 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
// intrinsic may alter how much fuel is in the system.
builder . switch_to_block ( out_of_gas_block ) ;
self . fuel_save_from_var ( builder ) ;
let out_of_gas_sig = self . builtin_function_signatures . out_of_gas ( builder . func ) ;
let ( vmctx , out_of_gas ) = self . translate_load_builtin_function_address (
& mut builder . cursor ( ) ,
BuiltinFunctionIndex ::out_of_gas ( ) ,
) ;
builder
. ins ( )
. call_indirect ( out_of_gas_sig , out_of_gas , & [ vmctx ] ) ;
let out_of_gas = self . builtin_functions . out_of_gas ( builder . func ) ;
let vmctx = self . vmctx_val ( & mut builder . cursor ( ) ) ;
builder . ins ( ) . call ( out_of_gas , & [ vmctx ] ) ;
self . fuel_load_into_var ( builder ) ;
builder . ins ( ) . jump ( continuation_block , & [ ] ) ;
builder . seal_block ( continuation_block ) ;
@ -665,7 +554,7 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
#[ cfg(feature = " wmemcheck " ) ]
fn hook_malloc_exit ( & mut self , builder : & mut FunctionBuilder , retvals : & [ Value ] ) {
let check_malloc_sig = self . builtin_function_signature s . check_malloc ( builder . func ) ;
let check_malloc_sig = self . builtin_functions . check_malloc ( builder . func ) ;
let ( vmctx , check_malloc ) = self . translate_load_builtin_function_address (
& mut builder . cursor ( ) ,
BuiltinFunctionIndex ::check_malloc ( ) ,
@ -693,7 +582,7 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
#[ cfg(feature = " wmemcheck " ) ]
fn hook_free_exit ( & mut self , builder : & mut FunctionBuilder ) {
let check_free_sig = self . builtin_function_signature s . check_free ( builder . func ) ;
let check_free_sig = self . builtin_functions . check_free ( builder . func ) ;
let ( vmctx , check_free ) = self . translate_load_builtin_function_address (
& mut builder . cursor ( ) ,
BuiltinFunctionIndex ::check_free ( ) ,
@ -798,16 +687,11 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
builder . seal_block ( new_epoch_doublecheck_block ) ;
builder . switch_to_block ( new_epoch_doublecheck_block ) ;
let new_epoch_sig = self . builtin_function_signatures . new_epoch ( builder . func ) ;
let ( vmctx , new_epoch ) = self . translate_load_builtin_function_address (
& mut builder . cursor ( ) ,
BuiltinFunctionIndex ::new_epoch ( ) ,
) ;
let new_epoch = self . builtin_functions . new_epoch ( builder . func ) ;
let vmctx = self . vmctx_val ( & mut builder . cursor ( ) ) ;
// new_epoch() returns the new deadline, so we don't have to
// reload it.
let call = builder
. ins ( )
. call_indirect ( new_epoch_sig , new_epoch , & [ vmctx ] ) ;
let call = builder . ins ( ) . call ( new_epoch , & [ vmctx ] ) ;
let new_deadline = * builder . func . dfg . inst_results ( call ) . first ( ) . unwrap ( ) ;
builder . def_var ( self . epoch_deadline_var , new_deadline ) ;
builder . ins ( ) . jump ( continuation_block , & [ ] ) ;
@ -984,16 +868,11 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
builder . switch_to_block ( null_block ) ;
let table_index = builder . ins ( ) . iconst ( I32 , table_index . index ( ) as i64 ) ;
let builtin_idx = BuiltinFunctionIndex ::table_get_lazy_init_func_ref ( ) ;
let builtin_sig = self
. builtin_function_signatures
let lazy_init = self
. builtin_functions
. table_get_lazy_init_func_ref ( builder . func ) ;
let ( vmctx , builtin_addr ) =
self . translate_load_builtin_function_address ( & mut builder . cursor ( ) , builtin_idx ) ;
let call_inst =
builder
. ins ( )
. call_indirect ( builtin_sig , builtin_addr , & [ vmctx , table_index , index ] ) ;
let vmctx = self . vmctx_val ( & mut builder . cursor ( ) ) ;
let call_inst = builder . ins ( ) . call ( lazy_init , & [ vmctx , table_index , index ] ) ;
let returned_entry = builder . func . dfg . inst_results ( call_inst ) [ 0 ] ;
builder . ins ( ) . jump ( continuation_block , & [ returned_entry ] ) ;
builder . seal_block ( continuation_block ) ;
@ -1544,36 +1423,29 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
delta : ir ::Value ,
init_value : ir ::Value ,
) -> WasmResult < ir ::Value > {
let ( func_idx , func_sig ) =
match self . module . table_plans [ table_index ] . table . wasm_ty . heap_type {
WasmHeapType ::Func | WasmHeapType ::Concrete ( _ ) | WasmHeapType ::NoFunc = > (
BuiltinFunctionIndex ::table_grow_func_ref ( ) ,
self . builtin_function_signatures
. table_grow_func_ref ( & mut pos . func ) ,
) ,
#[ cfg(feature = " gc " ) ]
WasmHeapType ::Extern = > (
BuiltinFunctionIndex ::table_grow_externref ( ) ,
self . builtin_function_signatures
. table_grow_externref ( & mut pos . func ) ,
) ,
#[ cfg(not(feature = " gc " )) ]
WasmHeapType ::Extern = > {
return Err ( cranelift_wasm ::wasm_unsupported ! (
" support for ` externref ` disabled at compile time because \
let grow = match self . module . table_plans [ table_index ] . table . wasm_ty . heap_type {
WasmHeapType ::Func | WasmHeapType ::Concrete ( _ ) | WasmHeapType ::NoFunc = > {
self . builtin_functions . table_grow_func_ref ( & mut pos . func )
}
#[ cfg(feature = " gc " ) ]
WasmHeapType ::Extern = > self . builtin_functions . table_grow_externref ( & mut pos . func ) ,
#[ cfg(not(feature = " gc " )) ]
WasmHeapType ::Extern = > {
return Err ( cranelift_wasm ::wasm_unsupported ! (
" support for ` externref ` disabled at compile time because \
the ` gc ` cargo feature was not enabled " ,
) )
}
} ;
) )
}
} ;
let ( vmctx , func_addr ) = self . translate_load_builtin_function_address ( & mut pos , func_idx ) ;
let vmctx = self . vmctx_val ( & mut pos ) ;
let table_index_arg = pos . ins ( ) . iconst ( I32 , table_index . as_u32 ( ) as i64 ) ;
let call_inst = pos . ins ( ) . call_indirect (
func_sig ,
func_addr ,
& [ vmctx , table_index_arg , delta , init_value ] ,
) ;
let call_inst = pos
. ins ( )
. call ( grow , & [ vmctx , table_index_arg , delta , init_value ] ) ;
Ok ( pos . func . dfg . first_result ( call_inst ) )
}
@ -1677,15 +1549,11 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
. ins ( )
. brif ( at_capacity , gc_block , & [ ] , no_gc_block , & [ ] ) ;
builder . switch_to_block ( gc_block ) ;
let builtin_idx = BuiltinFunctionIndex ::activations_table_insert_with_gc ( ) ;
let builtin_sig = self
. builtin_function_signatures
let insert = self
. builtin_functions
. activations_table_insert_with_gc ( builder . func ) ;
let ( vmctx , builtin_addr ) = self
. translate_load_builtin_function_address ( & mut builder . cursor ( ) , builtin_idx ) ;
builder
. ins ( )
. call_indirect ( builtin_sig , builtin_addr , & [ vmctx , elem ] ) ;
let vmctx = self . vmctx_val ( & mut builder . cursor ( ) ) ;
builder . ins ( ) . call ( insert , & [ vmctx , elem ] ) ;
builder . ins ( ) . jump ( continue _block , & [ ] ) ;
// If `next != end`, then:
@ -1876,15 +1744,9 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
// Call the `drop_externref` builtin to (you guessed it) drop
// the `externref`.
builder . switch_to_block ( drop_block ) ;
let builtin_idx = BuiltinFunctionIndex ::drop_externref ( ) ;
let builtin_sig = self
. builtin_function_signatures
. drop_externref ( builder . func ) ;
let ( vmctx , builtin_addr ) = self
. translate_load_builtin_function_address ( & mut builder . cursor ( ) , builtin_idx ) ;
builder
. ins ( )
. call_indirect ( builtin_sig , builtin_addr , & [ vmctx , current_elem ] ) ;
let drop_externref = self . builtin_functions . drop_externref ( builder . func ) ;
let vmctx = self . vmctx_val ( & mut builder . cursor ( ) ) ;
builder . ins ( ) . call ( drop_externref , & [ vmctx , current_elem ] ) ;
builder . ins ( ) . jump ( continue _block , & [ ] ) ;
builder . switch_to_block ( continue _block ) ;
@ -1916,37 +1778,26 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
val : ir ::Value ,
len : ir ::Value ,
) -> WasmResult < ( ) > {
let ( builtin_idx , builtin_sig ) =
match self . module . table_plans [ table_index ] . table . wasm_ty . heap_type {
WasmHeapType ::Func | WasmHeapType ::Concrete ( _ ) | WasmHeapType ::NoFunc = > (
BuiltinFunctionIndex ::table_fill_func_ref ( ) ,
self . builtin_function_signatures
. table_fill_func_ref ( & mut pos . func ) ,
) ,
#[ cfg(feature = " gc " ) ]
WasmHeapType ::Extern = > (
BuiltinFunctionIndex ::table_fill_externref ( ) ,
self . builtin_function_signatures
. table_fill_externref ( & mut pos . func ) ,
) ,
#[ cfg(not(feature = " gc " )) ]
WasmHeapType ::Extern = > {
return Err ( cranelift_wasm ::wasm_unsupported ! (
" support for ` externref ` disabled at compile time because the \
let libcall = match self . module . table_plans [ table_index ] . table . wasm_ty . heap_type {
WasmHeapType ::Func | WasmHeapType ::Concrete ( _ ) | WasmHeapType ::NoFunc = > {
self . builtin_functions . table_fill_func_ref ( & mut pos . func )
}
#[ cfg(feature = " gc " ) ]
WasmHeapType ::Extern = > self . builtin_functions . table_fill_externref ( & mut pos . func ) ,
#[ cfg(not(feature = " gc " )) ]
WasmHeapType ::Extern = > {
return Err ( cranelift_wasm ::wasm_unsupported ! (
" support for ` externref ` disabled at compile time because the \
` gc ` cargo feature was not enabled " ,
) ) ;
}
} ;
) ) ;
}
} ;
let ( vmctx , builtin_addr ) =
self . translate_load_builtin_function_address ( & mut pos , builtin_idx ) ;
let vmctx = self . vmctx_val ( & mut pos ) ;
let table_index_arg = pos . ins ( ) . iconst ( I32 , table_index . as_u32 ( ) as i64 ) ;
pos . ins ( ) . call_indirect (
builtin_sig ,
builtin_addr ,
& [ vmctx , table_index_arg , dst , val , len ] ,
) ;
pos . ins ( )
. call ( libcall , & [ vmctx , table_index_arg , dst , val , len ] ) ;
Ok ( ( ) )
}
@ -1989,14 +1840,10 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
func_index : FuncIndex ,
) -> WasmResult < ir ::Value > {
let func_index = pos . ins ( ) . iconst ( I32 , func_index . as_u32 ( ) as i64 ) ;
let builtin_index = BuiltinFunctionIndex ::ref_func ( ) ;
let builtin_sig = self . builtin_function_signatures . ref_func ( & mut pos . func ) ;
let ( vmctx , builtin_addr ) =
self . translate_load_builtin_function_address ( & mut pos , builtin_index ) ;
let ref_func = self . builtin_functions . ref_func ( & mut pos . func ) ;
let vmctx = self . vmctx_val ( & mut pos ) ;
let call_inst = pos
. ins ( )
. call_indirect ( builtin_sig , builtin_addr , & [ vmctx , func_index ] ) ;
let call_inst = pos . ins ( ) . call ( ref_func , & [ vmctx , func_index ] ) ;
Ok ( pos . func . dfg . first_result ( call_inst ) )
}
@ -2012,18 +1859,14 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
"We only use GlobalVariable::Custom for externref"
) ;
let builtin_index = BuiltinFunctionIndex ::externref_global_get ( ) ;
let builtin_sig = self
. builtin_function_signatures
. externref_global_get ( & mut pos . func ) ;
let externref_global_get = self . builtin_functions . externref_global_get ( & mut pos . func ) ;
let ( vmctx , builtin_addr ) =
self . translate_load_builtin_function_address ( & mut pos , builtin_index ) ;
let vmctx = self . vmctx_val ( & mut pos ) ;
let global_index_arg = pos . ins ( ) . iconst ( I32 , index . as_u32 ( ) as i64 ) ;
let call_inst =
pos . ins ( )
. call_indirect ( builtin_sig , builtin_addr , & [ vmctx , global_index_arg ] ) ;
let call_inst = pos
. ins ( )
. call ( externref_global_get , & [ vmctx , global_index_arg ] ) ;
Ok ( pos . func . dfg . first_result ( call_inst ) )
}
@ -2058,17 +1901,13 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
"We only use GlobalVariable::Custom for externref"
) ;
let builtin_index = BuiltinFunctionIndex ::externref_global_set ( ) ;
let builtin_sig = self
. builtin_function_signatures
. externref_global_set ( & mut pos . func ) ;
let externref_global_set = self . builtin_functions . externref_global_set ( & mut pos . func ) ;
let ( vmctx , builtin_addr ) =
self . translate_load_builtin_function_address ( & mut pos , builtin_index ) ;
let vmctx = self . vmctx_val ( & mut pos ) ;
let global_index_arg = pos . ins ( ) . iconst ( I32 , index . as_u32 ( ) as i64 ) ;
pos . ins ( )
. call_indirect ( builtin_sig , builtin_addr , & [ vmctx , global_index_arg , value ] ) ;
. call ( externref_global_set , & [ vmctx , global_index_arg , value ] ) ;
Ok ( ( ) )
}
@ -2393,7 +2232,7 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
let signature = func . import_signature ( sig ) ;
let name =
ir ::ExternalName ::User ( func . declare_imported_user_function ( ir ::UserExternalName {
namespace : 0 ,
namespace : crate ::NS_WASM_FUNC ,
index : index . as_u32 ( ) ,
} ) ) ;
Ok ( func . import_function ( ir ::ExtFuncData {
@ -2498,21 +2337,14 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
_heap : Heap ,
val : ir ::Value ,
) -> WasmResult < ir ::Value > {
let func_sig = self
. builtin_function_signatures
. memory32_grow ( & mut pos . func ) ;
let memory_grow = self . builtin_functions . memory32_grow ( & mut pos . func ) ;
let index_arg = index . index ( ) ;
let memory_index = pos . ins ( ) . iconst ( I32 , index_arg as i64 ) ;
let ( vmctx , func_addr ) = self . translate_load_builtin_function_address (
& mut pos ,
BuiltinFunctionIndex ::memory32_grow ( ) ,
) ;
let vmctx = self . vmctx_val ( & mut pos ) ;
let val = self . cast_memory_index_to_i64 ( & mut pos , val , index ) ;
let call_inst = pos
. ins ( )
. call_indirect ( func_sig , func_addr , & [ vmctx , val , memory_index ] ) ;
let call_inst = pos . ins ( ) . call ( memory_grow , & [ vmctx , val , memory_index ] ) ;
let result = * pos . func . dfg . inst_results ( call_inst ) . first ( ) . unwrap ( ) ;
Ok ( self . cast_pointer_to_memory_index ( pos , result , index ) )
}
@ -2604,10 +2436,9 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
src : ir ::Value ,
len : ir ::Value ,
) -> WasmResult < ( ) > {
let ( vmctx , func_addr ) = self
. translate_load_builtin_function_address ( & mut pos , BuiltinFunctionIndex ::memory_copy ( ) ) ;
let vmctx = self . vmctx_val ( & mut pos ) ;
let func_sig = self . builtin_function_signature s . memory_copy ( & mut pos . func ) ;
let memory_copy = self . builtin_functions . memory_copy ( & mut pos . func ) ;
let dst = self . cast_memory_index_to_i64 ( & mut pos , dst , dst_index ) ;
let src = self . cast_memory_index_to_i64 ( & mut pos , src , src_index ) ;
// The length is 32-bit if either memory is 32-bit, but if they're both
@ -2624,11 +2455,8 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
} ;
let src_index = pos . ins ( ) . iconst ( I32 , i64 ::from ( src_index . as_u32 ( ) ) ) ;
let dst_index = pos . ins ( ) . iconst ( I32 , i64 ::from ( dst_index . as_u32 ( ) ) ) ;
pos . ins ( ) . call_indirect (
func_sig ,
func_addr ,
& [ vmctx , dst_index , dst , src_index , src , len ] ,
) ;
pos . ins ( )
. call ( memory_copy , & [ vmctx , dst_index , dst , src_index , src , len ] ) ;
Ok ( ( ) )
}
@ -2642,19 +2470,15 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
val : ir ::Value ,
len : ir ::Value ,
) -> WasmResult < ( ) > {
let func_sig = self . builtin_function_signature s . memory_fill ( & mut pos . func ) ;
let memory_fill = self . builtin_functions . memory_fill ( & mut pos . func ) ;
let dst = self . cast_memory_index_to_i64 ( & mut pos , dst , memory_index ) ;
let len = self . cast_memory_index_to_i64 ( & mut pos , len , memory_index ) ;
let memory_index_arg = pos . ins ( ) . iconst ( I32 , i64 ::from ( memory_index . as_u32 ( ) ) ) ;
let ( vmctx , func_addr ) = self
. translate_load_builtin_function_address ( & mut pos , BuiltinFunctionIndex ::memory_fill ( ) ) ;
let vmctx = self . vmctx_val ( & mut pos ) ;
pos . ins ( ) . call_indirect (
func_sig ,
func_addr ,
& [ vmctx , memory_index_arg , dst , val , len ] ,
) ;
pos . ins ( )
. call ( memory_fill , & [ vmctx , memory_index_arg , dst , val , len ] ) ;
Ok ( ( ) )
}
@ -2669,18 +2493,17 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
src : ir ::Value ,
len : ir ::Value ,
) -> WasmResult < ( ) > {
let ( func_sig , func_idx ) = self . get_memory_init_func ( & mut pos . func ) ;
let memory_init = self . builtin_functions . memory_init ( & mut pos . func ) ;
let memory_index_arg = pos . ins ( ) . iconst ( I32 , memory_index . index ( ) as i64 ) ;
let seg_index_arg = pos . ins ( ) . iconst ( I32 , seg_index as i64 ) ;
let ( vmctx , func_addr ) = self . translate_load_builtin_function_address ( & mut pos , func_idx ) ;
let vmctx = self . vmctx_val ( & mut pos ) ;
let dst = self . cast_memory_index_to_i64 ( & mut pos , dst , memory_index ) ;
pos . ins ( ) . call_indirect (
func_sig ,
func_addr ,
pos . ins ( ) . call (
memory_init ,
& [ vmctx , memory_index_arg , seg_index_arg , dst , src , len ] ,
) ;
@ -2688,11 +2511,10 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
}
fn translate_data_drop ( & mut self , mut pos : FuncCursor , seg_index : u32 ) -> WasmResult < ( ) > {
let ( func_sig , func_idx ) = self . get_data_drop_func ( & mut pos . func ) ;
let data_drop = self . builtin_functions . data_drop ( & mut pos . func ) ;
let seg_index_arg = pos . ins ( ) . iconst ( I32 , seg_index as i64 ) ;
let ( vmctx , func_addr ) = self . translate_load_builtin_function_address ( & mut pos , func_idx ) ;
pos . ins ( )
. call_indirect ( func_sig , func_addr , & [ vmctx , seg_index_arg ] ) ;
let vmctx = self . vmctx_val ( & mut pos ) ;
pos . ins ( ) . call ( data_drop , & [ vmctx , seg_index_arg ] ) ;
Ok ( ( ) )
}
@ -2715,17 +2537,14 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
src : ir ::Value ,
len : ir ::Value ,
) -> WasmResult < ( ) > {
let ( func_sig , dst_table_index_arg , src_table_index_arg , func_idx ) =
let ( table_copy , dst_table_index_arg , src_table_index_arg ) =
self . get_table_copy_func ( & mut pos . func , dst_table_index , src_table_index ) ;
let dst_table_index_arg = pos . ins ( ) . iconst ( I32 , dst_table_index_arg as i64 ) ;
let src_table_index_arg = pos . ins ( ) . iconst ( I32 , src_table_index_arg as i64 ) ;
let ( vmctx , func_addr ) = self . translate_load_builtin_function_address ( & mut pos , func_idx ) ;
pos . ins ( ) . call_indirect (
func_sig ,
func_addr ,
let vmctx = self . vmctx_val ( & mut pos ) ;
pos . ins ( ) . call (
table_copy ,
& [
vmctx ,
dst_table_index_arg ,
@ -2748,17 +2567,12 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
src : ir ::Value ,
len : ir ::Value ,
) -> WasmResult < ( ) > {
let ( func_sig , table_index_arg , func_idx ) =
self . get_table_init_func ( & mut pos . func , table_index ) ;
let table_index_arg = pos . ins ( ) . iconst ( I32 , table_index_arg as i64 ) ;
let seg_index_arg = pos . ins ( ) . iconst ( I32 , seg_index as i64 ) ;
let ( vmctx , func_addr ) = self . translate_load_builtin_function_address ( & mut pos , func_idx ) ;
pos . ins ( ) . call_indirect (
func_sig ,
func_addr ,
let table_init = self . builtin_functions . table_init ( & mut pos . func ) ;
let table_index_arg = pos . ins ( ) . iconst ( I32 , i64 ::from ( table_index . as_u32 ( ) ) ) ;
let seg_index_arg = pos . ins ( ) . iconst ( I32 , i64 ::from ( seg_index ) ) ;
let vmctx = self . vmctx_val ( & mut pos ) ;
pos . ins ( ) . call (
table_init ,
& [ vmctx , table_index_arg , seg_index_arg , dst , src , len ] ,
) ;
@ -2766,15 +2580,10 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
}
fn translate_elem_drop ( & mut self , mut pos : FuncCursor , elem_index : u32 ) -> WasmResult < ( ) > {
let ( func_sig , func_idx ) = self . get_elem_drop_func ( & mut pos . func ) ;
let elem_drop = self . builtin_functions . elem_drop ( & mut pos . func ) ;
let elem_index_arg = pos . ins ( ) . iconst ( I32 , elem_index as i64 ) ;
let ( vmctx , func_addr ) = self . translate_load_builtin_function_address ( & mut pos , func_idx ) ;
pos . ins ( )
. call_indirect ( func_sig , func_addr , & [ vmctx , elem_index_arg ] ) ;
let vmctx = self . vmctx_val ( & mut pos ) ;
pos . ins ( ) . call ( elem_drop , & [ vmctx , elem_index_arg ] ) ;
Ok ( ( ) )
}
@ -2789,16 +2598,15 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
) -> WasmResult < ir ::Value > {
let addr = self . cast_memory_index_to_i64 ( & mut pos , addr , memory_index ) ;
let implied_ty = pos . func . dfg . value_type ( expected ) ;
let ( func_sig , memory_index , func_id x ) =
let ( wait_ func, memory_index ) =
self . get_memory_atomic_wait ( & mut pos . func , memory_index , implied_ty ) ;
let memory_index_arg = pos . ins ( ) . iconst ( I32 , memory_index as i64 ) ;
let ( vmctx , func_addr ) = self . translate_load_builtin_function_address ( & mut pos , func_idx ) ;
let vmctx = self . vmctx_val ( & mut pos ) ;
let call_inst = pos . ins ( ) . call_indirect (
func_sig ,
func_addr ,
let call_inst = pos . ins ( ) . call (
wait_func ,
& [ vmctx , memory_index_arg , addr , expected , timeout ] ,
) ;
@ -2814,20 +2622,13 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
count : ir ::Value ,
) -> WasmResult < ir ::Value > {
let addr = self . cast_memory_index_to_i64 ( & mut pos , addr , memory_index ) ;
let func_sig = self
. builtin_function_signatures
. memory_atomic_notify ( & mut pos . func ) ;
let atomic_notify = self . builtin_functions . memory_atomic_notify ( & mut pos . func ) ;
let memory_index_arg = pos . ins ( ) . iconst ( I32 , memory_index . index ( ) as i64 ) ;
let ( vmctx , func_addr ) = self . translate_load_builtin_function_address (
& mut pos ,
BuiltinFunctionIndex ::memory_atomic_notify ( ) ,
) ;
let call_inst =
pos . ins ( )
. call_indirect ( func_sig , func_addr , & [ vmctx , memory_index_arg , addr , count ] ) ;
let vmctx = self . vmctx_val ( & mut pos ) ;
let call_inst = pos
. ins ( )
. call ( atomic_notify , & [ vmctx , memory_index_arg , addr , count ] ) ;
Ok ( * pos . func . dfg . inst_results ( call_inst ) . first ( ) . unwrap ( ) )
}