@@ -200,3 +200,86 @@ fn resource_limiter_allows_guest_memory_grow_by_default() -> TestResult {
200200 assert_eq ! ( grow. call( & mut store, ( ) ) ?, 1 ) ;
201201 Ok ( ( ) )
202202}
203+
204+ #[ test]
205+ fn inline_memory_immediates_preserve_multi_memory_behavior ( ) -> TestResult {
206+ use tinywasm:: parser:: { Parser , ParserOptions } ;
207+ use tinywasm:: types:: Instruction ;
208+
209+ let wasm = wat:: parse_str (
210+ r#"
211+ (module
212+ (memory 1)
213+ (memory $other 1)
214+ (data (memory $other) (i32.const 1) "\7f")
215+ (func (export "inline") (result i32)
216+ i32.const 0
217+ i32.const 0x12345678
218+ i32.store offset=4
219+ i32.const 0
220+ i32.load offset=4
221+ drop
222+ i32.const 0
223+ i32.const -2
224+ i32.store16 offset=8
225+ i32.const 0
226+ i32.load16_s offset=8
227+ drop
228+ i32.const 0
229+ i32.load8_u offset=4)
230+ (func (export "other") (result i32)
231+ i32.const 0
232+ i32.load8_u $other offset=1))
233+ "# ,
234+ ) ?;
235+ let optimized = Parser :: default ( ) . parse_module_bytes ( & wasm) ?;
236+ let instructions = & optimized. funcs [ 0 ] . instructions ;
237+ assert ! ( instructions. iter( ) . any( |op| matches!( op, Instruction :: I32LoadInline ( 4 ) ) ) ) ;
238+ assert ! ( instructions. iter( ) . any( |op| matches!( op, Instruction :: I32Load16SInline ( 8 ) ) ) ) ;
239+ assert ! ( instructions. iter( ) . any( |op| matches!( op, Instruction :: I32Load8UInline ( 4 ) ) ) ) ;
240+ assert ! ( optimized. funcs[ 1 ] . instructions. iter( ) . any( |op| matches!( op, Instruction :: I32Load8U ( _) ) ) ) ;
241+
242+ for optimize in [ true , false ] {
243+ let module = Parser :: new ( ParserOptions :: new ( ) . with_optimize ( optimize) ) . parse_module_bytes ( & wasm) ?;
244+ let mut store = Store :: default ( ) ;
245+ let instance = ModuleInstance :: instantiate ( & mut store, & module, None ) ?;
246+ assert_eq ! ( instance. func:: <( ) , i32 >( & store, "inline" ) ?. call( & mut store, ( ) ) ?, 0x78 ) ;
247+ assert_eq ! ( instance. func:: <( ) , i32 >( & store, "other" ) ?. call( & mut store, ( ) ) ?, 0x7f ) ;
248+ }
249+ Ok ( ( ) )
250+ }
251+
252+ #[ test]
253+ fn inline_memory_loads_preserve_memory64_and_wide_offsets ( ) -> TestResult {
254+ use tinywasm:: parser:: { Parser , ParserOptions } ;
255+ use tinywasm:: types:: Instruction ;
256+
257+ let wasm = wat:: parse_str (
258+ r#"
259+ (module
260+ (memory i64 1)
261+ (data (i64.const 0) "\2a")
262+ (func (export "small") (result i32)
263+ i64.const 0
264+ i32.load8_u)
265+ (func (export "wide") (result i32)
266+ i64.const 0
267+ i32.load8_u offset=4294967296))
268+ "# ,
269+ ) ?;
270+ let optimized = Parser :: default ( ) . parse_module_bytes ( & wasm) ?;
271+ assert ! ( optimized. funcs[ 0 ] . instructions. iter( ) . any( |op| matches!( op, Instruction :: I32Load8UInline ( 0 ) ) ) ) ;
272+ assert ! ( optimized. funcs[ 1 ] . instructions. iter( ) . any( |op| matches!( op, Instruction :: I32Load8U ( _) ) ) ) ;
273+
274+ for optimize in [ true , false ] {
275+ let module = Parser :: new ( ParserOptions :: new ( ) . with_optimize ( optimize) ) . parse_module_bytes ( & wasm) ?;
276+ let mut store = Store :: default ( ) ;
277+ let instance = ModuleInstance :: instantiate ( & mut store, & module, None ) ?;
278+ assert_eq ! ( instance. func:: <( ) , i32 >( & store, "small" ) ?. call( & mut store, ( ) ) ?, 42 ) ;
279+ assert ! ( matches!(
280+ instance. func:: <( ) , i32 >( & store, "wide" ) ?. call( & mut store, ( ) ) ,
281+ Err ( tinywasm:: Error :: Trap ( Trap :: MemoryOutOfBounds { .. } ) )
282+ ) ) ;
283+ }
284+ Ok ( ( ) )
285+ }
0 commit comments