diff --git a/sway-core/src/asm_generation/from_ir.rs b/sway-core/src/asm_generation/from_ir.rs index d347b7f2e11..35c3a258869 100644 --- a/sway-core/src/asm_generation/from_ir.rs +++ b/sway-core/src/asm_generation/from_ir.rs @@ -1403,19 +1403,24 @@ impl<'ir> AsmBuilder<'ir> { // Value can fit in a register, so we load the value. if word_offs > compiler_constants::TWELVE_BITS { let offs_reg = self.reg_seqr.next(); + self.number_to_reg( + word_offs * 8, // Base reg for LW is in bytes + &offs_reg, + instr_val.get_span(self.context), + ); self.bytecode.push(Op { opcode: Either::Left(VirtualOp::ADD( - base_reg.clone(), + offs_reg.clone(), base_reg, offs_reg.clone(), )), - comment: "insert_value absolute offset".into(), + comment: "absolute offset for load".into(), owning_span: instr_val.get_span(self.context), }); self.bytecode.push(Op { opcode: Either::Left(VirtualOp::LW( instr_reg.clone(), - offs_reg, + offs_reg.clone(), VirtualImmediate12 { value: 0 }, )), comment: "load value".into(), @@ -1784,13 +1789,13 @@ impl<'ir> AsmBuilder<'ir> { if word_offs > compiler_constants::TWELVE_BITS { let offs_reg = self.reg_seqr.next(); self.number_to_reg( - word_offs, + word_offs * 8, // Base reg for SW is in bytes &offs_reg, instr_val.get_span(self.context), ); self.bytecode.push(Op { opcode: Either::Left(VirtualOp::ADD( - base_reg.clone(), + offs_reg.clone(), base_reg, offs_reg.clone(), )), diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/many_stack_variables/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/many_stack_variables/src/main.sw index f72d8f58d28..f38177b233c 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/many_stack_variables/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/many_stack_variables/src/main.sw @@ -10,7 +10,10 @@ struct Z { } fn main() -> u64 { - // Chosen name forces this variable to show up last in the list of locals in IR + // Chosen names force these variables to show up last in the list of locals in IR so they will + // be allocated last and require the highest offset to be computed + + // Test get_ptr large offset let zzz = Z { a: 1, b: 2, @@ -18,134 +21,171 @@ fn main() -> u64 { d: 4, }; - // Add enough stack variables to reach > 4096 bytes - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; - let b = ZERO_B256; + // Test LW/SW with large offsets + let z1 = 5; + let z2 = 6; + + // Add enough stack variables to reach > 4096 words + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + foo(); + + return zzz.a + zzz.b + zzz.c + zzz.d + z1 + z2 // get 16 +} - return zzz.a + zzz.b + zzz.c + zzz.d +fn foo() { + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; + let c = 0; } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/many_stack_variables/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/many_stack_variables/test.toml index 1a37cf3ee4d..6238f8fd3f6 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/many_stack_variables/test.toml +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/many_stack_variables/test.toml @@ -1,3 +1,3 @@ category = "run" -expected_result = { action = "return", value = 10 } +expected_result = { action = "return", value = 21 } validate_abi = true