11mod gc;
22pub ( crate ) mod stack_switching;
33
4+ use crate :: BuiltinFunctionSignatures ;
45use crate :: compiler:: Compiler ;
56use crate :: translate:: {
67 FuncTranslationStacks , GlobalVariable , Heap , HeapData , StructFieldsVec , TableData , TableSize ,
78 TargetEnvironment ,
89} ;
9- use crate :: { BuiltinFunctionSignatures , TRAP_INTERNAL_ASSERT } ;
10+ use crate :: trap :: TranslateTrap ;
1011use cranelift_codegen:: cursor:: FuncCursor ;
1112use cranelift_codegen:: ir:: condcodes:: { FloatCC , IntCC } ;
1213use cranelift_codegen:: ir:: immediates:: { Imm64 , Offset32 , V128Imm } ;
@@ -29,9 +30,9 @@ use wasmtime_environ::{
2930 BuiltinFunctionIndex , DataIndex , DefinedFuncIndex , ElemIndex , EngineOrModuleTypeIndex ,
3031 FrameStateSlotBuilder , FrameValType , FuncIndex , FuncKey , GlobalConstValue , GlobalIndex ,
3132 IndexType , Memory , MemoryIndex , Module , ModuleInternedTypeIndex , ModuleTranslation ,
32- ModuleTypesBuilder , PtrSize , Table , TableIndex , TagIndex , TripleExt , Tunables , TypeConvert ,
33- TypeIndex , VMOffsets , WasmCompositeInnerType , WasmFuncType , WasmHeapTopType , WasmHeapType ,
34- WasmRefType , WasmResult , WasmValType ,
33+ ModuleTypesBuilder , PtrSize , Table , TableIndex , TagIndex , Tunables , TypeConvert , TypeIndex ,
34+ VMOffsets , WasmCompositeInnerType , WasmFuncType , WasmHeapTopType , WasmHeapType , WasmRefType ,
35+ WasmResult , WasmValType ,
3536} ;
3637use wasmtime_environ:: { FUNCREF_INIT_BIT , FUNCREF_MASK } ;
3738
@@ -51,15 +52,19 @@ pub(crate) struct BuiltinFunctions {
5152}
5253
5354impl BuiltinFunctions {
54- fn new ( compiler : & Compiler ) -> Self {
55+ pub ( crate ) fn new ( compiler : & Compiler ) -> Self {
5556 Self {
5657 types : BuiltinFunctionSignatures :: new ( compiler) ,
5758 builtins : [ None ; BuiltinFunctionIndex :: len ( ) as usize ] ,
5859 breakpoint_trampoline : None ,
5960 }
6061 }
6162
62- fn load_builtin ( & mut self , func : & mut Function , builtin : BuiltinFunctionIndex ) -> ir:: FuncRef {
63+ pub ( crate ) fn load_builtin (
64+ & mut self ,
65+ func : & mut Function ,
66+ builtin : BuiltinFunctionIndex ,
67+ ) -> ir:: FuncRef {
6368 let cache = & mut self . builtins [ builtin. index ( ) as usize ] ;
6469 if let Some ( f) = cache {
6570 return * f;
@@ -312,12 +317,6 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
312317 } )
313318 }
314319
315- pub ( crate ) fn vmctx_val ( & mut self , pos : & mut FuncCursor < ' _ > ) -> ir:: Value {
316- let pointer_type = self . pointer_type ( ) ;
317- let vmctx = self . vmctx ( & mut pos. func ) ;
318- pos. ins ( ) . global_value ( pointer_type, vmctx)
319- }
320-
321320 fn get_table_copy_func (
322321 & mut self ,
323322 func : & mut Function ,
@@ -1034,34 +1033,6 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
10341033 self . global_load_with_memory_type ( func, vmctx, offset, flags, self . pcc_vmctx_memtype )
10351034 }
10361035
1037- /// Helper to emit a conditional trap based on `trap_cond`.
1038- ///
1039- /// This should only be used if `self.clif_instruction_traps_enabled()` is
1040- /// false, otherwise native CLIF instructions should be used instead.
1041- pub fn conditionally_trap (
1042- & mut self ,
1043- builder : & mut FunctionBuilder ,
1044- trap_cond : ir:: Value ,
1045- trap : ir:: TrapCode ,
1046- ) {
1047- assert ! ( !self . clif_instruction_traps_enabled( ) ) ;
1048-
1049- let trap_block = builder. create_block ( ) ;
1050- builder. set_cold_block ( trap_block) ;
1051- let continuation_block = builder. create_block ( ) ;
1052-
1053- builder
1054- . ins ( )
1055- . brif ( trap_cond, trap_block, & [ ] , continuation_block, & [ ] ) ;
1056-
1057- builder. seal_block ( trap_block) ;
1058- builder. seal_block ( continuation_block) ;
1059-
1060- builder. switch_to_block ( trap_block) ;
1061- self . trap ( builder, trap) ;
1062- builder. switch_to_block ( continuation_block) ;
1063- }
1064-
10651036 /// Helper used when `!self.clif_instruction_traps_enabled()` is enabled to
10661037 /// test whether the divisor is zero.
10671038 fn guard_zero_divisor ( & mut self , builder : & mut FunctionBuilder , rhs : ir:: Value ) {
@@ -1395,6 +1366,26 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
13951366 }
13961367}
13971368
1369+ impl TranslateTrap for FuncEnvironment < ' _ > {
1370+ fn compiler ( & self ) -> & Compiler {
1371+ & self . compiler
1372+ }
1373+
1374+ fn vmctx_val ( & mut self , pos : & mut FuncCursor < ' _ > ) -> ir:: Value {
1375+ let pointer_type = self . pointer_type ( ) ;
1376+ let vmctx = self . vmctx ( & mut pos. func ) ;
1377+ pos. ins ( ) . global_value ( pointer_type, vmctx)
1378+ }
1379+
1380+ fn builtin_funcref (
1381+ & mut self ,
1382+ builder : & mut FunctionBuilder < ' _ > ,
1383+ index : BuiltinFunctionIndex ,
1384+ ) -> ir:: FuncRef {
1385+ self . builtin_functions . load_builtin ( builder. func , index)
1386+ }
1387+ }
1388+
13981389#[ derive( Default ) ]
13991390pub ( crate ) struct WasmEntities {
14001391 /// Map from a Wasm global index from this module to its implementation in
@@ -4431,70 +4422,6 @@ impl FuncEnvironment<'_> {
44314422 & * self . isa
44324423 }
44334424
4434- pub fn trap ( & mut self , builder : & mut FunctionBuilder , trap : ir:: TrapCode ) {
4435- match (
4436- self . clif_instruction_traps_enabled ( ) ,
4437- crate :: clif_trap_to_env_trap ( trap) ,
4438- ) {
4439- // If libcall traps are disabled or there's no wasmtime-defined trap
4440- // code for this, then emit a native trap instruction.
4441- ( true , _) | ( _, None ) => {
4442- builder. ins ( ) . trap ( trap) ;
4443- }
4444- // ... otherwise with libcall traps explicitly enabled and a
4445- // wasmtime-based trap code invoke the libcall to raise a trap and
4446- // pass in our trap code. Leave a debug `unreachable` in place
4447- // afterwards as a defense-in-depth measure.
4448- ( false , Some ( trap) ) => {
4449- let libcall = self . builtin_functions . trap ( & mut builder. func ) ;
4450- let vmctx = self . vmctx_val ( & mut builder. cursor ( ) ) ;
4451- let trap_code = builder. ins ( ) . iconst ( I8 , i64:: from ( trap as u8 ) ) ;
4452- builder. ins ( ) . call ( libcall, & [ vmctx, trap_code] ) ;
4453- let raise = self . builtin_functions . raise ( & mut builder. func ) ;
4454- builder. ins ( ) . call ( raise, & [ vmctx] ) ;
4455- builder. ins ( ) . trap ( TRAP_INTERNAL_ASSERT ) ;
4456- }
4457- }
4458- }
4459-
4460- pub fn trapz ( & mut self , builder : & mut FunctionBuilder , value : ir:: Value , trap : ir:: TrapCode ) {
4461- if self . clif_instruction_traps_enabled ( ) {
4462- builder. ins ( ) . trapz ( value, trap) ;
4463- } else {
4464- let ty = builder. func . dfg . value_type ( value) ;
4465- let zero = builder. ins ( ) . iconst ( ty, 0 ) ;
4466- let cmp = builder. ins ( ) . icmp ( IntCC :: Equal , value, zero) ;
4467- self . conditionally_trap ( builder, cmp, trap) ;
4468- }
4469- }
4470-
4471- pub fn trapnz ( & mut self , builder : & mut FunctionBuilder , value : ir:: Value , trap : ir:: TrapCode ) {
4472- if self . clif_instruction_traps_enabled ( ) {
4473- builder. ins ( ) . trapnz ( value, trap) ;
4474- } else {
4475- let ty = builder. func . dfg . value_type ( value) ;
4476- let zero = builder. ins ( ) . iconst ( ty, 0 ) ;
4477- let cmp = builder. ins ( ) . icmp ( IntCC :: NotEqual , value, zero) ;
4478- self . conditionally_trap ( builder, cmp, trap) ;
4479- }
4480- }
4481-
4482- pub fn uadd_overflow_trap (
4483- & mut self ,
4484- builder : & mut FunctionBuilder ,
4485- lhs : ir:: Value ,
4486- rhs : ir:: Value ,
4487- trap : ir:: TrapCode ,
4488- ) -> ir:: Value {
4489- if self . clif_instruction_traps_enabled ( ) {
4490- builder. ins ( ) . uadd_overflow_trap ( lhs, rhs, trap)
4491- } else {
4492- let ( ret, overflow) = builder. ins ( ) . uadd_overflow ( lhs, rhs) ;
4493- self . conditionally_trap ( builder, overflow, trap) ;
4494- ret
4495- }
4496- }
4497-
44984425 pub fn translate_sdiv (
44994426 & mut self ,
45004427 builder : & mut FunctionBuilder ,
@@ -4572,19 +4499,6 @@ impl FuncEnvironment<'_> {
45724499 self . tunables . signals_based_traps && !self . is_pulley ( )
45734500 }
45744501
4575- /// Returns whether it's acceptable to have CLIF instructions natively trap,
4576- /// such as division-by-zero.
4577- ///
4578- /// This is enabled if `signals_based_traps` is `true` or on
4579- /// Pulley unconditionally since Pulley doesn't use hardware-based
4580- /// traps in its runtime. However, if guest debugging is enabled,
4581- /// then we cannot rely on Pulley traps and still need a libcall
4582- /// to gain proper ownership of the store in the runtime's
4583- /// debugger hooks.
4584- pub fn clif_instruction_traps_enabled ( & self ) -> bool {
4585- self . tunables . signals_based_traps || ( self . is_pulley ( ) && !self . tunables . debug_guest )
4586- }
4587-
45884502 /// Returns whether loads from the null address are allowed as signals of
45894503 /// whether to trap or not.
45904504 pub fn load_from_zero_allowed ( & self ) -> bool {
@@ -4594,11 +4508,6 @@ impl FuncEnvironment<'_> {
45944508 || ( self . clif_memory_traps_enabled ( ) && self . heap_access_spectre_mitigation ( ) )
45954509 }
45964510
4597- /// Returns whether translation is happening for Pulley bytecode.
4598- pub fn is_pulley ( & self ) -> bool {
4599- self . isa . triple ( ) . is_pulley ( )
4600- }
4601-
46024511 /// Returns whether the current location is reachable.
46034512 pub fn is_reachable ( & self ) -> bool {
46044513 self . stacks . reachable ( )
0 commit comments