@@ -6,14 +6,15 @@ use wasmparser::ExternalKind;
66use wasmparser:: MemArg ;
77use wasmparser:: Operator ;
88use wirm:: ir:: function:: { FunctionBuilder , FunctionModifier } ;
9- use wirm:: ir:: id:: { ExportsID , FunctionID , LocalID } ;
9+ use wirm:: ir:: id:: { ExportsID , FunctionID , GlobalID , LocalID } ;
1010use wirm:: ir:: module:: Module ;
11- use wirm:: ir:: types:: { BlockType , ElementItems , InstrumentationMode } ;
11+ use wirm:: ir:: module:: module_globals:: GlobalKind ;
12+ use wirm:: ir:: types:: { BlockType , ElementItems , InitInstr , InstrumentationMode , Value } ;
1213use wirm:: module_builder:: AddLocal ;
1314use wirm:: opcode:: { Inject , InjectAt } ;
1415use wirm:: { DataType , Opcode } ;
15- use wit_component:: metadata:: { decode, Bindgen } ;
1616use wit_component:: StringEncoding ;
17+ use wit_component:: metadata:: { Bindgen , decode} ;
1718use wit_parser:: Resolve ;
1819
1920use crate :: bindgen:: BindingItem ;
@@ -757,7 +758,27 @@ fn synthesize_import_functions(
757758 . get_fn_modifier ( coreabi_get_import_fid)
758759 . unwrap ( ) ;
759760
760- // Find the I32Const base index and compute the delta to new base
761+ // Save the idx parameter to local at the start of the function,
762+ // so that orignal code does not oeverwrit it.
763+ let idx_local = builder. add_local ( DataType :: I32 ) ;
764+ builder. inject_at (
765+ 0 ,
766+ InstrumentationMode :: Before ,
767+ Operator :: LocalGet {
768+ local_index : * arg_idx,
769+ } ,
770+ ) ;
771+ builder. inject_at (
772+ 0 ,
773+ InstrumentationMode :: Before ,
774+ Operator :: LocalSet {
775+ local_index : * idx_local,
776+ } ,
777+ ) ;
778+
779+ // Find the I32Const base index and compute the delta to new base.
780+ // The codegen may split the base index into:
781+ // `global.get N` + `i32.const X` where the global is a constant.
761782 let mut table_instr_idx = 0usize ;
762783 let mut delta: i32 = 0 ;
763784 {
@@ -769,7 +790,20 @@ fn synthesize_import_functions(
769790 if * value < 1000 || * value > 5000 {
770791 continue ;
771792 }
772- delta = import_fn_table_start_idx - * value;
793+ // Check if instruction just before is a global.get with a
794+ // constant value and if so, include the global's init value
795+ // in the base computation.
796+ let mut base = * value;
797+ if idx > 0
798+ && let Operator :: GlobalGet { global_index } = & ops_ro[ idx - 1 ]
799+ && let GlobalKind :: Local ( local_global) =
800+ module. globals . get_kind ( GlobalID ( * global_index) )
801+ && let [ InitInstr :: Value ( Value :: I32 ( v) ) ] =
802+ local_global. init_expr . instructions ( )
803+ {
804+ base += v;
805+ }
806+ delta = import_fn_table_start_idx - base;
773807 table_instr_idx = idx;
774808 break ;
775809 }
@@ -780,7 +814,7 @@ fn synthesize_import_functions(
780814 table_instr_idx,
781815 InstrumentationMode :: Before ,
782816 Operator :: LocalGet {
783- local_index : * arg_idx ,
817+ local_index : * idx_local ,
784818 } ,
785819 ) ;
786820 builder. inject_at (
0 commit comments