@@ -325,11 +325,7 @@ impl<R: WasmModuleResources> FunctionBuilder<R> {
325325 } ;
326326
327327 match frame. kind {
328- FrameKind :: Loop => {
329- if let Instruction :: Jump ( target) = & mut self . instructions [ jump_ip] {
330- * target = self . ctx_stack [ ctx_idx] . start_ip as u32 ;
331- }
332- }
328+ FrameKind :: Loop => self . patch_jump ( jump_ip, self . ctx_stack [ ctx_idx] . start_ip ) ,
333329 _ => self . ctx_stack [ ctx_idx] . branch_jumps . push ( jump_ip) ,
334330 }
335331 }
@@ -385,12 +381,12 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
385381 }
386382
387383 define_mem_operands ! {
388- visit_i32_load( I32Load ) , visit_i64_load( I64Load ) , visit_f32_load( F32Load ) , visit_f64_load( F64Load ) , visit_i32_load8_s( I32Load8S ) , visit_i32_load8_u( I32Load8U ) , visit_i32_load16_s( I32Load16S ) , visit_i32_load16_u( I32Load16U ) , visit_i64_load8_s( I64Load8S ) , visit_i64_load8_u( I64Load8U ) , visit_i64_load16_s( I64Load16S ) , visit_i64_load16_u( I64Load16U ) , visit_i64_load32_s( I64Load32S ) , visit_i64_load32_u( I64Load32U ) , visit_i32_store ( I32Store ) , visit_i64_store( I64Store ) , visit_f32_store( F32Store ) , visit_f64_store( F64Store ) , visit_i32_store8( I32Store8 ) , visit_i32_store16( I32Store16 ) , visit_i64_store8( I64Store8 ) , visit_i64_store16( I64Store16 ) , visit_i64_store32( I64Store32 )
384+ visit_i32_load( I32Load ) , visit_i64_load( I64Load ) , visit_f32_load( F32Load ) , visit_f64_load( F64Load ) , visit_i32_load8_s( I32Load8S ) , visit_i32_load8_u( I32Load8U ) , visit_i32_load16_s( I32Load16S ) , visit_i32_load16_u( I32Load16U ) , visit_i64_load8_s( I64Load8S ) , visit_i64_load8_u( I64Load8U ) , visit_i64_load16_s( I64Load16S ) , visit_i64_load16_u( I64Load16U ) , visit_i64_load32_s( I64Load32S ) , visit_i64_load32_u( I64Load32U ) , visit_i64_store( I64Store ) , visit_f32_store( F32Store ) , visit_f64_store( F64Store ) , visit_i32_store8( I32Store8 ) , visit_i32_store16( I32Store16 ) , visit_i64_store8( I64Store8 ) , visit_i64_store16( I64Store16 ) , visit_i64_store32( I64Store32 )
389385 }
390386
391387 define_operands ! {
392388 // basic instructions
393- visit_global_get( GlobalGet , u32 ) , visit_i32_const( I32Const , i32 ) , visit_i64_const( I64Const , i64 ) , visit_call( Call , u32 ) , visit_return_call( ReturnCall , u32 ) , visit_memory_size( MemorySize , u32 ) , visit_memory_grow( MemoryGrow , u32 ) , visit_unreachable( Unreachable ) , visit_nop( Nop ) , visit_i32_eqz( I32Eqz ) , visit_i32_eq( I32Eq ) , visit_i32_ne( I32Ne ) , visit_i32_lt_s( I32LtS ) , visit_i32_lt_u( I32LtU ) , visit_i32_gt_s( I32GtS ) , visit_i32_gt_u( I32GtU ) , visit_i32_le_s( I32LeS ) , visit_i32_le_u( I32LeU ) , visit_i32_ge_s( I32GeS ) , visit_i32_ge_u( I32GeU ) , visit_i64_eqz( I64Eqz ) , visit_i64_eq( I64Eq ) , visit_i64_ne( I64Ne ) , visit_i64_lt_s( I64LtS ) , visit_i64_lt_u( I64LtU ) , visit_i64_gt_s( I64GtS ) , visit_i64_gt_u( I64GtU ) , visit_i64_le_s( I64LeS ) , visit_i64_le_u( I64LeU ) , visit_i64_ge_s( I64GeS ) , visit_i64_ge_u( I64GeU ) , visit_f32_eq( F32Eq ) , visit_f32_ne( F32Ne ) , visit_f32_lt( F32Lt ) , visit_f32_gt( F32Gt ) , visit_f32_le( F32Le ) , visit_f32_ge( F32Ge ) , visit_f64_eq( F64Eq ) , visit_f64_ne( F64Ne ) , visit_f64_lt( F64Lt ) , visit_f64_gt( F64Gt ) , visit_f64_le( F64Le ) , visit_f64_ge( F64Ge ) , visit_i32_clz( I32Clz ) , visit_i32_ctz( I32Ctz ) , visit_i32_popcnt( I32Popcnt ) , visit_i32_add( I32Add ) , visit_i32_sub( I32Sub ) , visit_i32_mul( I32Mul ) , visit_i32_div_s( I32DivS ) , visit_i32_div_u( I32DivU ) , visit_i32_rem_s( I32RemS ) , visit_i32_rem_u( I32RemU ) , visit_i32_and( I32And ) , visit_i32_or( I32Or ) , visit_i32_xor( I32Xor ) , visit_i32_shl( I32Shl ) , visit_i32_shr_s( I32ShrS ) , visit_i32_shr_u( I32ShrU ) , visit_i32_rotl( I32Rotl ) , visit_i32_rotr( I32Rotr ) , visit_i64_clz( I64Clz ) , visit_i64_ctz( I64Ctz ) , visit_i64_popcnt( I64Popcnt ) , visit_i64_add( I64Add ) , visit_i64_sub( I64Sub ) , visit_i64_mul( I64Mul ) , visit_i64_div_s( I64DivS ) , visit_i64_div_u( I64DivU ) , visit_i64_rem_s( I64RemS ) , visit_i64_rem_u( I64RemU ) , visit_i64_and( I64And ) , visit_i64_or( I64Or ) , visit_i64_xor( I64Xor ) , visit_i64_shl( I64Shl ) , visit_i64_shr_s( I64ShrS ) , visit_i64_shr_u( I64ShrU ) , visit_i64_rotl( I64Rotl ) , visit_i64_rotr( I64Rotr ) , visit_f32_abs( F32Abs ) , visit_f32_neg( F32Neg ) , visit_f32_ceil( F32Ceil ) , visit_f32_floor( F32Floor ) , visit_f32_trunc( F32Trunc ) , visit_f32_nearest( F32Nearest ) , visit_f32_sqrt( F32Sqrt ) , visit_f32_add( F32Add ) , visit_f32_sub( F32Sub ) , visit_f32_mul( F32Mul ) , visit_f32_div( F32Div ) , visit_f32_min( F32Min ) , visit_f32_max( F32Max ) , visit_f32_copysign( F32Copysign ) , visit_f64_abs( F64Abs ) , visit_f64_neg( F64Neg ) , visit_f64_ceil( F64Ceil ) , visit_f64_floor( F64Floor ) , visit_f64_trunc( F64Trunc ) , visit_f64_nearest( F64Nearest ) , visit_f64_sqrt( F64Sqrt ) , visit_f64_add( F64Add ) , visit_f64_sub( F64Sub ) , visit_f64_mul( F64Mul ) , visit_f64_div( F64Div ) , visit_f64_min( F64Min ) , visit_f64_max( F64Max ) , visit_f64_copysign( F64Copysign ) , visit_i32_wrap_i64( I32WrapI64 ) , visit_i32_trunc_f32_s( I32TruncF32S ) , visit_i32_trunc_f32_u( I32TruncF32U ) , visit_i32_trunc_f64_s( I32TruncF64S ) , visit_i32_trunc_f64_u( I32TruncF64U ) , visit_i64_extend_i32_s( I64ExtendI32S ) , visit_i64_extend_i32_u( I64ExtendI32U ) , visit_i64_trunc_f32_s( I64TruncF32S ) , visit_i64_trunc_f32_u( I64TruncF32U ) , visit_i64_trunc_f64_s( I64TruncF64S ) , visit_i64_trunc_f64_u( I64TruncF64U ) , visit_f32_convert_i32_s( F32ConvertI32S ) , visit_f32_convert_i32_u( F32ConvertI32U ) , visit_f32_convert_i64_s( F32ConvertI64S ) , visit_f32_convert_i64_u( F32ConvertI64U ) , visit_f32_demote_f64( F32DemoteF64 ) , visit_f64_convert_i32_s( F64ConvertI32S ) , visit_f64_convert_i32_u( F64ConvertI32U ) , visit_f64_convert_i64_s( F64ConvertI64S ) , visit_f64_convert_i64_u( F64ConvertI64U ) , visit_f64_promote_f32( F64PromoteF32 ) , visit_i32_reinterpret_f32( I32ReinterpretF32 ) , visit_i64_reinterpret_f64( I64ReinterpretF64 ) , visit_f32_reinterpret_i32( F32ReinterpretI32 ) , visit_f64_reinterpret_i64( F64ReinterpretI64 ) ,
389+ visit_global_get( GlobalGet , u32 ) , visit_i32_const( I32Const , i32 ) , visit_i64_const( I64Const , i64 ) , visit_call( Call , u32 ) , visit_return_call( ReturnCall , u32 ) , visit_memory_size( MemorySize , u32 ) , visit_memory_grow( MemoryGrow , u32 ) , visit_unreachable( Unreachable ) , visit_nop( Nop ) , visit_i32_eqz( I32Eqz ) , visit_i32_eq( I32Eq ) , visit_i32_ne( I32Ne ) , visit_i32_lt_s( I32LtS ) , visit_i32_lt_u( I32LtU ) , visit_i32_gt_s( I32GtS ) , visit_i32_gt_u( I32GtU ) , visit_i32_le_s( I32LeS ) , visit_i32_le_u( I32LeU ) , visit_i32_ge_s( I32GeS ) , visit_i32_ge_u( I32GeU ) , visit_i64_eqz( I64Eqz ) , visit_i64_eq( I64Eq ) , visit_i64_ne( I64Ne ) , visit_i64_lt_s( I64LtS ) , visit_i64_lt_u( I64LtU ) , visit_i64_gt_s( I64GtS ) , visit_i64_gt_u( I64GtU ) , visit_i64_le_s( I64LeS ) , visit_i64_le_u( I64LeU ) , visit_i64_ge_s( I64GeS ) , visit_i64_ge_u( I64GeU ) , visit_f32_eq( F32Eq ) , visit_f32_ne( F32Ne ) , visit_f32_lt( F32Lt ) , visit_f32_gt( F32Gt ) , visit_f32_le( F32Le ) , visit_f32_ge( F32Ge ) , visit_f64_eq( F64Eq ) , visit_f64_ne( F64Ne ) , visit_f64_lt( F64Lt ) , visit_f64_gt( F64Gt ) , visit_f64_le( F64Le ) , visit_f64_ge( F64Ge ) , visit_i32_clz( I32Clz ) , visit_i32_ctz( I32Ctz ) , visit_i32_popcnt( I32Popcnt ) , visit_i32_sub( I32Sub ) , visit_i32_mul( I32Mul ) , visit_i32_div_s( I32DivS ) , visit_i32_div_u( I32DivU ) , visit_i32_rem_s( I32RemS ) , visit_i32_rem_u( I32RemU ) , visit_i32_and( I32And ) , visit_i32_or( I32Or ) , visit_i32_xor( I32Xor ) , visit_i32_shl( I32Shl ) , visit_i32_shr_s( I32ShrS ) , visit_i32_shr_u( I32ShrU ) , visit_i32_rotl( I32Rotl ) , visit_i32_rotr( I32Rotr ) , visit_i64_clz( I64Clz ) , visit_i64_ctz( I64Ctz ) , visit_i64_popcnt( I64Popcnt ) , visit_i64_sub( I64Sub ) , visit_i64_mul( I64Mul ) , visit_i64_div_s( I64DivS ) , visit_i64_div_u( I64DivU ) , visit_i64_rem_s( I64RemS ) , visit_i64_rem_u( I64RemU ) , visit_i64_and( I64And ) , visit_i64_or( I64Or ) , visit_i64_xor( I64Xor ) , visit_i64_shl( I64Shl ) , visit_i64_shr_s( I64ShrS ) , visit_i64_shr_u( I64ShrU ) , visit_i64_rotr( I64Rotr ) , visit_f32_abs( F32Abs ) , visit_f32_neg( F32Neg ) , visit_f32_ceil( F32Ceil ) , visit_f32_floor( F32Floor ) , visit_f32_trunc( F32Trunc ) , visit_f32_nearest( F32Nearest ) , visit_f32_sqrt( F32Sqrt ) , visit_f32_add( F32Add ) , visit_f32_sub( F32Sub ) , visit_f32_mul( F32Mul ) , visit_f32_div( F32Div ) , visit_f32_min( F32Min ) , visit_f32_max( F32Max ) , visit_f32_copysign( F32Copysign ) , visit_f64_abs( F64Abs ) , visit_f64_neg( F64Neg ) , visit_f64_ceil( F64Ceil ) , visit_f64_floor( F64Floor ) , visit_f64_trunc( F64Trunc ) , visit_f64_nearest( F64Nearest ) , visit_f64_sqrt( F64Sqrt ) , visit_f64_add( F64Add ) , visit_f64_sub( F64Sub ) , visit_f64_mul( F64Mul ) , visit_f64_div( F64Div ) , visit_f64_min( F64Min ) , visit_f64_max( F64Max ) , visit_f64_copysign( F64Copysign ) , visit_i32_wrap_i64( I32WrapI64 ) , visit_i32_trunc_f32_s( I32TruncF32S ) , visit_i32_trunc_f32_u( I32TruncF32U ) , visit_i32_trunc_f64_s( I32TruncF64S ) , visit_i32_trunc_f64_u( I32TruncF64U ) , visit_i64_extend_i32_s( I64ExtendI32S ) , visit_i64_extend_i32_u( I64ExtendI32U ) , visit_i64_trunc_f32_s( I64TruncF32S ) , visit_i64_trunc_f32_u( I64TruncF32U ) , visit_i64_trunc_f64_s( I64TruncF64S ) , visit_i64_trunc_f64_u( I64TruncF64U ) , visit_f32_convert_i32_s( F32ConvertI32S ) , visit_f32_convert_i32_u( F32ConvertI32U ) , visit_f32_convert_i64_s( F32ConvertI64S ) , visit_f32_convert_i64_u( F32ConvertI64U ) , visit_f32_demote_f64( F32DemoteF64 ) , visit_f64_convert_i32_s( F64ConvertI32S ) , visit_f64_convert_i32_u( F64ConvertI32U ) , visit_f64_convert_i64_s( F64ConvertI64S ) , visit_f64_convert_i64_u( F64ConvertI64U ) , visit_f64_promote_f32( F64PromoteF32 ) , visit_i32_reinterpret_f32( I32ReinterpretF32 ) , visit_i64_reinterpret_f64( I64ReinterpretF64 ) , visit_f32_reinterpret_i32( F32ReinterpretI32 ) , visit_f64_reinterpret_i64( F64ReinterpretI64 ) ,
394390
395391 // sign_extension
396392 visit_i32_extend8_s( I32Extend8S ) , visit_i32_extend16_s( I32Extend16S ) , visit_i64_extend8_s( I64Extend8S ) , visit_i64_extend16_s( I64Extend16S ) , visit_i64_extend32_s( I64Extend32S ) ,
@@ -423,6 +419,23 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
423419 }
424420 }
425421
422+ fn visit_i32_store ( & mut self , memarg : wasmparser:: MemArg ) -> Self :: Output {
423+ let memarg = MemoryArg :: new ( memarg. offset , memarg. memory ) ;
424+ let len = self . instructions . len ( ) ;
425+ if len >= 2 {
426+ let addr = self . instructions [ len - 2 ] ;
427+ let value = self . instructions [ len - 1 ] ;
428+ if let ( Instruction :: LocalGet32 ( addr_local) , Instruction :: LocalGet32 ( value_local) ) = ( addr, value) {
429+ self . instructions . pop ( ) ;
430+ self . instructions . pop ( ) ;
431+ self . instructions . push ( Instruction :: I32StoreLocalLocal ( memarg, addr_local, value_local) ) ;
432+ return ;
433+ }
434+ }
435+
436+ self . instructions . push ( Instruction :: I32Store ( memarg) ) ;
437+ }
438+
426439 fn visit_drop ( & mut self ) -> Self :: Output {
427440 match self . validator . get_operand_type ( 0 ) {
428441 Some ( Some ( t) ) => self . instructions . push ( match t {
@@ -447,21 +460,67 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
447460 }
448461
449462 fn visit_return ( & mut self ) -> Self :: Output {
450- if let Some ( instr) = self . instructions . last_mut ( ) {
451- match instr {
452- Instruction :: Call ( addr) => {
453- * instr = Instruction :: ReturnCall ( * addr) ;
454- return ;
455- }
456- Instruction :: CallIndirect ( ty, table) => {
457- * instr = Instruction :: ReturnCallIndirect ( * ty, * table) ;
458- return ;
459- }
460- _ => { }
463+ self . instructions . push ( Instruction :: Return ) ;
464+ }
465+
466+ fn visit_i32_add ( & mut self ) -> Self :: Output {
467+ let len = self . instructions . len ( ) ;
468+ if len >= 2 {
469+ let lhs = self . instructions [ len - 2 ] ;
470+ let rhs = self . instructions [ len - 1 ] ;
471+ if let ( Instruction :: LocalGet32 ( a) , Instruction :: LocalGet32 ( b) ) = ( lhs, rhs) {
472+ self . instructions . pop ( ) ;
473+ self . instructions . pop ( ) ;
474+ self . instructions . push ( Instruction :: I32AddLocals ( a, b) ) ;
475+ return ;
461476 }
462477 }
463478
464- self . instructions . push ( Instruction :: Return ) ;
479+ if let Some ( Instruction :: I32Const ( c) ) = self . instructions . last ( ) . copied ( ) {
480+ self . instructions . pop ( ) ;
481+ self . instructions . push ( Instruction :: I32AddConst ( c) ) ;
482+ return ;
483+ }
484+
485+ self . instructions . push ( Instruction :: I32Add ) ;
486+ }
487+
488+ fn visit_i64_add ( & mut self ) -> Self :: Output {
489+ let len = self . instructions . len ( ) ;
490+ if len >= 2 {
491+ let lhs = self . instructions [ len - 2 ] ;
492+ let rhs = self . instructions [ len - 1 ] ;
493+ if let ( Instruction :: LocalGet64 ( a) , Instruction :: LocalGet64 ( b) ) = ( lhs, rhs) {
494+ self . instructions . pop ( ) ;
495+ self . instructions . pop ( ) ;
496+ self . instructions . push ( Instruction :: I64AddLocals ( a, b) ) ;
497+ return ;
498+ }
499+ }
500+
501+ if let Some ( Instruction :: I64Const ( c) ) = self . instructions . last ( ) . copied ( ) {
502+ self . instructions . pop ( ) ;
503+ self . instructions . push ( Instruction :: I64AddConst ( c) ) ;
504+ return ;
505+ }
506+
507+ self . instructions . push ( Instruction :: I64Add ) ;
508+ }
509+
510+ fn visit_i64_rotl ( & mut self ) -> Self :: Output {
511+ let len = self . instructions . len ( ) ;
512+ if len >= 2 {
513+ let lhs = self . instructions [ len - 2 ] ;
514+ let rhs = self . instructions [ len - 1 ] ;
515+ if let ( Instruction :: I64Xor , Instruction :: I64Const ( c) ) = ( lhs, rhs) {
516+ self . instructions . pop ( ) ;
517+ self . instructions . pop ( ) ;
518+ self . instructions . push ( Instruction :: I64XorRotlConst ( c) ) ;
519+ return ;
520+ }
521+ }
522+
523+ self . instructions . push ( Instruction :: I64Rotl ) ;
465524 }
466525
467526 fn visit_local_get ( & mut self , idx : u32 ) -> Self :: Output {
@@ -544,6 +603,34 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
544603 return ;
545604 } ;
546605
606+ if let Some ( Instruction :: I64XorRotlConst ( c) ) = self . instructions . last ( ) . copied ( ) {
607+ match self . validator . get_operand_type ( 0 ) {
608+ Some ( Some ( wasmparser:: ValType :: I64 ) ) | Some ( Some ( wasmparser:: ValType :: F64 ) ) => {
609+ self . instructions . pop ( ) ;
610+ self . instructions . push ( Instruction :: I64XorRotlConstTee ( c, resolved_idx) ) ;
611+ return ;
612+ }
613+ _ => { }
614+ }
615+ }
616+
617+ let len = self . instructions . len ( ) ;
618+ if len >= 2 {
619+ let addr = self . instructions [ len - 2 ] ;
620+ let load = self . instructions [ len - 1 ] ;
621+ if let ( Instruction :: LocalGet32 ( addr_local) , Instruction :: I32Load ( memarg) ) = ( addr, load) {
622+ match self . validator . get_operand_type ( 0 ) {
623+ Some ( Some ( wasmparser:: ValType :: I32 ) ) | Some ( Some ( wasmparser:: ValType :: F32 ) ) => {
624+ self . instructions . pop ( ) ;
625+ self . instructions . pop ( ) ;
626+ self . instructions . push ( Instruction :: I32LoadLocalTee ( memarg, addr_local, resolved_idx) ) ;
627+ return ;
628+ }
629+ _ => { }
630+ }
631+ }
632+ }
633+
547634 match self . validator . get_operand_type ( 0 ) {
548635 Some ( Some ( t) ) => self . instructions . push ( match t {
549636 wasmparser:: ValType :: I32 => Instruction :: LocalTee32 ( resolved_idx) ,
@@ -595,13 +682,19 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
595682 ctx. has_else = true ;
596683 ctx. branch_jumps . push ( jump_ip) ;
597684 self . patch_jump_if_zero ( cond_jump_ip, self . instructions . len ( ) ) ;
685+ if !matches ! ( self . instructions. last( ) , Some ( Instruction :: Nop ) ) {
686+ self . instructions . push ( Instruction :: Nop ) ;
687+ }
598688 } ;
599689 } ;
600690 }
601691
602692 fn visit_end ( & mut self ) -> Self :: Output {
603693 if let Some ( ctx) = self . ctx_stack . pop ( ) {
604694 self . patch_end_jumps ( ctx, self . instructions . len ( ) ) ;
695+ if !matches ! ( self . instructions. last( ) , Some ( Instruction :: Nop ) ) {
696+ self . instructions . push ( Instruction :: Nop ) ;
697+ }
605698 } else {
606699 self . instructions . push ( Instruction :: Return ) ;
607700 }
0 commit comments