@@ -343,8 +343,18 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder<'_> {
343343 fixed [ ] => [ ] { visit_data_drop( segment: u32 ) => DataDrop , visit_elem_drop( segment: u32 ) => ElemDrop }
344344 fixed [ ] => [ S32 ] { visit_i32_const( value: i32 ) => Const32 , visit_ref_func( function: u32 ) => RefFunc }
345345 fixed [ ] => [ S64 ] { visit_i64_const( value: i64 ) => Const64 }
346+ heap false [ ] => [ S32 ] { visit_ref_null => RefNull }
347+ heap false [ S32 ] => [ S32 ] {
348+ visit_ref_test_non_null => RefTest , visit_ref_cast_non_null => RefCast ,
349+ }
350+ heap true [ S32 ] => [ S32 ] {
351+ visit_ref_test_nullable => RefTest , visit_ref_cast_nullable => RefCast ,
352+ }
346353 fixed [ S32 ] => [ S32 ] {
347- visit_i32_eqz => I32Eqz , visit_ref_is_null => RefIsNull , visit_i32_clz => I32Clz ,
354+ visit_ref_is_null => RefIsNull , visit_ref_as_non_null => RefAsNonNull , visit_ref_i31 => RefI31 ,
355+ visit_i31_get_s => I31GetS , visit_i31_get_u => I31GetU ,
356+ visit_any_convert_extern => AnyConvertExtern , visit_extern_convert_any => ExternConvertAny ,
357+ visit_i32_eqz => I32Eqz , visit_i32_clz => I32Clz ,
348358 visit_i32_ctz => I32Ctz , visit_i32_popcnt => I32Popcnt , visit_i32_extend8_s => I32Extend8S ,
349359 visit_i32_extend16_s => I32Extend16S , visit_i32_trunc_f32_s => I32TruncF32S ,
350360 visit_i32_trunc_f32_u => I32TruncF32U , visit_f32_convert_i32_s => F32ConvertI32S ,
@@ -377,7 +387,8 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder<'_> {
377387 visit_i64_trunc_sat_f32_u => I64TruncSatF32U ,
378388 }
379389 fixed [ S32 , S32 ] => [ S32 ] {
380- visit_i32_eq => I32Eq , visit_i32_ne => I32Ne , visit_i32_lt_s => I32LtS , visit_i32_lt_u => I32LtU ,
390+ visit_ref_eq => RefEq , visit_i32_eq => I32Eq , visit_i32_ne => I32Ne ,
391+ visit_i32_lt_s => I32LtS , visit_i32_lt_u => I32LtU ,
381392 visit_i32_gt_s => I32GtS , visit_i32_gt_u => I32GtU , visit_i32_le_s => I32LeS ,
382393 visit_i32_le_u => I32LeU , visit_i32_ge_s => I32GeS , visit_i32_ge_u => I32GeU ,
383394 visit_f32_eq => F32Eq , visit_f32_ne => F32Ne , visit_f32_lt => F32Lt , visit_f32_gt => F32Gt ,
@@ -424,6 +435,16 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder<'_> {
424435 table [ S32 , Addr ] => [ Addr ] { visit_table_grow( table: u32 ) => TableGrow }
425436 table [ Addr , S32 , Addr ] => [ ] { visit_table_fill( table: u32 ) => TableFill }
426437 table [ Addr , S32 , S32 ] => [ ] { visit_table_init( elem_index: u32 , table: u32 ) => TableInit }
438+ unsupported [ ] { visit_array_len }
439+ unsupported [ u32 ] {
440+ visit_struct_new, visit_struct_new_default, visit_array_new, visit_array_new_default,
441+ visit_array_get, visit_array_get_s, visit_array_get_u, visit_array_set, visit_array_fill,
442+ }
443+ unsupported [ u32 , u32 ] {
444+ visit_struct_get, visit_struct_get_s, visit_struct_get_u, visit_struct_set,
445+ visit_array_new_fixed, visit_array_new_data, visit_array_new_elem, visit_array_copy,
446+ visit_array_init_data, visit_array_init_elem,
447+ }
427448 }
428449
429450 fn visit_call ( & mut self , function_index : u32 ) -> Self :: Output {
@@ -722,14 +743,22 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder<'_> {
722743 self . emit ( & [ dst, src, len] , & [ ] , Instruction :: MemoryCopy { dst_mem, src_mem } )
723744 }
724745
725- // Reference Types
726- fn visit_ref_null ( & mut self , ty : wasmparser:: HeapType ) -> Self :: Output {
727- let instruction = Instruction :: RefNull ( convert_heap_type ( ty, false ) ?) ;
728- self . emit ( & [ ] , & [ OperandSize :: S32 ] , instruction)
746+ fn visit_br_on_cast (
747+ & mut self ,
748+ relative_depth : u32 ,
749+ _from_ref_type : wasmparser:: RefType ,
750+ to_ref_type : wasmparser:: RefType ,
751+ ) -> Self :: Output {
752+ self . emit_cast_branch ( relative_depth, to_ref_type, false )
729753 }
730754
731- fn visit_ref_as_non_null ( & mut self ) -> Self :: Output {
732- self . emit ( & [ OperandSize :: S32 ] , & [ OperandSize :: S32 ] , Instruction :: RefAsNonNull )
755+ fn visit_br_on_cast_fail (
756+ & mut self ,
757+ relative_depth : u32 ,
758+ _from_ref_type : wasmparser:: RefType ,
759+ to_ref_type : wasmparser:: RefType ,
760+ ) -> Self :: Output {
761+ self . emit_cast_branch ( relative_depth, to_ref_type, true )
733762 }
734763
735764 fn visit_br_on_null ( & mut self , relative_depth : u32 ) -> Self :: Output {
@@ -975,6 +1004,23 @@ impl wasmparser::VisitSimdOperator<'_> for FunctionBuilder<'_> {
9751004}
9761005
9771006impl FunctionBuilder < ' _ > {
1007+ fn emit_cast_branch (
1008+ & mut self ,
1009+ relative_depth : u32 ,
1010+ target : wasmparser:: RefType ,
1011+ branch_on_fail : bool ,
1012+ ) -> Result < ( ) > {
1013+ self . pop_expect ( OperandSize :: S32 ) ?;
1014+ let target = convert_heap_type ( target. heap_type ( ) , target. is_nullable ( ) ) ?;
1015+ let conditional_ip = self . instructions . len ( ) ;
1016+ self . instructions . push ( Instruction :: BrOnCast ( 0 , target, branch_on_fail) ) ;
1017+ self . push_sizes ( & [ OperandSize :: S32 ] ) ?;
1018+ self . emit_dropkeep_to_label ( relative_depth) ?;
1019+ self . emit_branch_jump_or_return ( relative_depth) ?;
1020+ self . patch_jump ( conditional_ip, self . instructions . len ( ) ) ;
1021+ Ok ( ( ) )
1022+ }
1023+
9781024 fn is_unreachable ( & self ) -> bool {
9791025 self . control_stack . last ( ) . is_none_or ( |frame| frame. unreachable )
9801026 }
@@ -1112,7 +1158,8 @@ impl FunctionBuilder<'_> {
11121158 | Instruction :: JumpIfZero32 ( ip)
11131159 | Instruction :: JumpIfNonZero32 ( ip)
11141160 | Instruction :: JumpIfRefNull ( ip)
1115- | Instruction :: JumpIfRefNonNull ( ip) => {
1161+ | Instruction :: JumpIfRefNonNull ( ip)
1162+ | Instruction :: BrOnCast ( ip, _, _) => {
11161163 * ip = target as u32 ;
11171164 }
11181165 _ => { }
0 commit comments