diff --git a/libyul/optimiser/StackLimitEvader.cpp b/libyul/optimiser/StackLimitEvader.cpp index 85adbd98b..98be932cb 100644 --- a/libyul/optimiser/StackLimitEvader.cpp +++ b/libyul/optimiser/StackLimitEvader.cpp @@ -132,7 +132,7 @@ void StackLimitEvader::run( MemoryOffsetAllocator memoryOffsetAllocator{_unreachableVariables, callGraph.functionCalls}; uint64_t requiredSlots = memoryOffsetAllocator.run(); - StackToMemoryMover::run(_context, reservedMemory, memoryOffsetAllocator.slotAllocations, *_object.code); + StackToMemoryMover::run(_context, reservedMemory, memoryOffsetAllocator.slotAllocations, requiredSlots, *_object.code); yulAssert(requiredSlots < std::numeric_limits::max() / 32, ""); reservedMemory += 32 * requiredSlots; diff --git a/libyul/optimiser/StackToMemoryMover.cpp b/libyul/optimiser/StackToMemoryMover.cpp index 19a83c323..136a6043d 100644 --- a/libyul/optimiser/StackToMemoryMover.cpp +++ b/libyul/optimiser/StackToMemoryMover.cpp @@ -52,18 +52,24 @@ void StackToMemoryMover::run( OptimiserStepContext& _context, u256 _reservedMemory, map> const& _memorySlots, + uint64_t _numRequiredSlots, Block& _block ) { - StackToMemoryMover stackToMemoryMover(_context, _reservedMemory, _memorySlots); + StackToMemoryMover stackToMemoryMover(_context, _reservedMemory, _memorySlots, _numRequiredSlots); stackToMemoryMover(_block); } StackToMemoryMover::StackToMemoryMover( OptimiserStepContext& _context, u256 _reservedMemory, - map> const& _memorySlots -): m_reservedMemory(std::move(_reservedMemory)), m_memorySlots(_memorySlots), m_nameDispenser(_context.dispenser) + map> const& _memorySlots, + uint64_t _numRequiredSlots +): +m_reservedMemory(std::move(_reservedMemory)), +m_memorySlots(_memorySlots), +m_numRequiredSlots(_numRequiredSlots), +m_nameDispenser(_context.dispenser) { auto const* evmDialect = dynamic_cast(&_context.dialect); yulAssert( @@ -210,6 +216,8 @@ void StackToMemoryMover::visit(Expression& _expression) YulString StackToMemoryMover::memoryOffset(YulString _variable) { yulAssert(m_currentFunctionMemorySlots, ""); - return YulString{util::toCompactHexWithPrefix(m_reservedMemory + 32 * m_currentFunctionMemorySlots->at(_variable))}; + uint64_t slot = m_currentFunctionMemorySlots->at(_variable); + yulAssert(slot < m_numRequiredSlots, ""); + return YulString{util::toCompactHexWithPrefix(m_reservedMemory + 32 * (m_numRequiredSlots - slot - 1))}; } diff --git a/libyul/optimiser/StackToMemoryMover.h b/libyul/optimiser/StackToMemoryMover.h index fa8701aaa..cf582aba6 100644 --- a/libyul/optimiser/StackToMemoryMover.h +++ b/libyul/optimiser/StackToMemoryMover.h @@ -82,13 +82,16 @@ public: * Runs the stack to memory mover. * @param _reservedMemory Is the amount of previously reserved memory, * i.e. the lowest memory offset to which variables can be moved. - * @param _memorySlots A map from variables to a slot in memory. The offset to which a variables will be moved - * is given by _reservedMemory plus 32 times its entry in @a _memorySlots. + * @param _memorySlots A map from variables to a slot in memory. Based on the slot a unique offset in the memory range + * between _reservedMemory and _reservedMemory + 32 * _numRequiredSlots is calculated for each + * variable. + * @param _numRequiredSlots The number of slots required in total. The maximum value that may occur in @a _memorySlots. */ static void run( OptimiserStepContext& _context, u256 _reservedMemory, std::map> const& _memorySlots, + uint64_t _numRequiredSlots, Block& _block ); using ASTModifier::operator(); @@ -100,13 +103,15 @@ private: StackToMemoryMover( OptimiserStepContext& _context, u256 _reservedMemory, - std::map> const& _memorySlots + std::map> const& _memorySlots, + uint64_t _numRequiredSlots ); /// @returns a YulString containing the memory offset to be assigned to @a _variable as number literal. YulString memoryOffset(YulString _variable); u256 m_reservedMemory; std::map> const& m_memorySlots; + uint64_t m_numRequiredSlots = 0; NameDispenser& m_nameDispenser; std::map const* m_currentFunctionMemorySlots = nullptr; }; diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/connected.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/connected.yul index 075da88cd..82ab48a51 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/connected.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/connected.yul @@ -28,35 +28,35 @@ // function g() -> a, b // { // a := 21 -// mstore(0x20, 1) +// mstore(0x60, 1) // let b_1, a_2, $c_3 := z() -// mstore(0x20, $c_3) +// mstore(0x60, $c_3) // a := a_2 // b := b_1 // } // function f() -> x // { -// mstore(0x60, 0) -// mstore(0x60, 42) +// mstore(0x20, 0) +// mstore(0x20, 42) // let $x3_4, $x4_5 := g() -// mstore(0x80, $x4_5) +// mstore(0x00, $x4_5) // mstore(0x40, $x3_4) -// x := mul(add(mload(0x60), mload(0x40)), h(mload(0x80))) -// sstore(mload(0x40), mload(0x80)) +// x := mul(add(mload(0x20), mload(0x40)), h(mload(0x00))) +// sstore(mload(0x40), mload(0x00)) // } // function h(v) -> a_1 // { // let x_2_6, $z_7, y_8 := z() -// mstore(0x20, $z_7) +// mstore(0x60, $z_7) // let y := y_8 // let x_2 := x_2_6 // let a_1_9, $z_10, v_11 := z() -// mstore(0x20, $z_10) +// mstore(0x60, $z_10) // v := v_11 // a_1 := a_1_9 // } // function z() -> a_3, b_4, c -// { mstore(0x00, 0) } +// { mstore(0x80, 0) } // sstore(0, f()) // let x_5, y_6 := g() // } diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/function_arg.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/function_arg.yul index 033e0b3c0..6ce2e34b4 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/function_arg.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/function_arg.yul @@ -12,8 +12,8 @@ // // { // mstore(0x40, memoryguard(0x40)) -// mstore(0x20, 0) -// sstore(0, mload(0x20)) +// mstore(0x00, 0) +// sstore(0, mload(0x00)) // function h($hx) -> y // { y := $hx } // sstore(1, h(32)) diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/stub.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/stub.yul index 9c792e63f..d2fcb116e 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/stub.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/stub.yul @@ -30,50 +30,50 @@ // mstore(0x40, memoryguard(0x80)) // function f() // { -// mstore(0x20, 0) -// mstore(0x00, 42) -// sstore(mload(0x20), mload(0x00)) -// mstore(0x20, 21) +// mstore(0x40, 0) +// mstore(0x60, 42) +// sstore(mload(0x40), mload(0x60)) +// mstore(0x40, 21) // } // function g(gx) // { // let $gx_1, $gy_2 := tuple2() -// mstore(0x20, $gy_2) -// mstore(0x00, $gx_1) +// mstore(0x40, $gy_2) +// mstore(0x60, $gx_1) // { // let $gx_3, $gy_4 := tuple2() -// mstore(0x20, $gy_4) -// mstore(0x00, $gx_3) +// mstore(0x40, $gy_4) +// mstore(0x60, $gx_3) // } // { // let $gx_5, gx_6 := tuple2() -// mstore(0x00, $gx_5) +// mstore(0x60, $gx_5) // gx := gx_6 // } // { // let gx_7, $gy_8 := tuple2() -// mstore(0x20, $gy_8) +// mstore(0x40, $gy_8) // gx := gx_7 // } // } // function h(hx, hy, hz, hw) // { // let $hx_9, $hy_10, $hz_11, $hw_12 := tuple4() -// mstore(0x60, $hw_12) -// mstore(0x00, $hz_11) -// mstore(0x20, $hy_10) -// mstore(0x40, $hx_9) +// mstore(0x00, $hw_12) +// mstore(0x60, $hz_11) +// mstore(0x40, $hy_10) +// mstore(0x20, $hx_9) // { // let hx_13, $hy_14, hz_15, $hw_16 := tuple4() -// mstore(0x60, $hw_16) -// mstore(0x20, $hy_14) +// mstore(0x00, $hw_16) +// mstore(0x40, $hy_14) // hz := hz_15 // hx := hx_13 // } // { // let $hx_17, $hy_18, hz_19, hw_20 := tuple4() -// mstore(0x20, $hy_18) -// mstore(0x40, $hx_17) +// mstore(0x40, $hy_18) +// mstore(0x20, $hx_17) // hw := hw_20 // hz := hz_19 // } diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/tree.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/tree.yul index 357f6bb68..8407df5d0 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/tree.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/tree.yul @@ -174,7 +174,7 @@ // } // function f() -> v // { -// mstore(0xe0, calldataload(mul(1, 4))) +// mstore(0x80, calldataload(mul(1, 4))) // let a2 := calldataload(mul(2, 4)) // let a3 := calldataload(mul(3, 4)) // let a4 := calldataload(g()) @@ -183,7 +183,7 @@ // let a7 := calldataload(mul(7, 4)) // let a8 := calldataload(mul(8, 4)) // let a9 := calldataload(mul(9, 4)) -// mstore(0xe0, calldataload(mul(0, 4))) +// mstore(0x80, calldataload(mul(0, 4))) // let a10 := calldataload(mul(10, 4)) // let a11 := calldataload(mul(11, 4)) // let a12 := calldataload(mul(12, 4)) @@ -192,7 +192,7 @@ // let a15 := calldataload(mul(15, 4)) // let a16 := calldataload(mul(16, 4)) // let a17 := calldataload(mul(17, 4)) -// sstore(0, mload(0xe0)) +// sstore(0, mload(0x80)) // sstore(mul(17, 4), a17) // sstore(mul(16, 4), a16) // sstore(mul(15, 4), a15) @@ -209,11 +209,11 @@ // sstore(mul(4, 4), a4) // sstore(mul(3, 4), a3) // sstore(mul(2, 4), a2) -// sstore(mul(1, 4), mload(0xe0)) +// sstore(mul(1, 4), mload(0x80)) // } // function g() -> v_1 // { -// mstore(0xa0, calldataload(mul(1, 4))) +// mstore(0xc0, calldataload(mul(1, 4))) // let a2_3 := calldataload(mul(2, 4)) // let a3_4 := calldataload(mul(3, 4)) // let a4_5 := calldataload(mul(4, 4)) @@ -222,7 +222,7 @@ // let a7_8 := calldataload(mul(7, 4)) // let a8_9 := calldataload(mul(8, 4)) // let a9_10 := calldataload(mul(9, 4)) -// mstore(0xa0, calldataload(mul(0, 4))) +// mstore(0xc0, calldataload(mul(0, 4))) // let a10_11 := calldataload(mul(10, 4)) // let a11_12 := calldataload(mul(11, 4)) // let a12_13 := calldataload(mul(12, 4)) @@ -231,7 +231,7 @@ // let a15_16 := calldataload(mul(15, 4)) // let a16_17 := calldataload(mul(16, 4)) // let a17_18 := calldataload(mul(17, 4)) -// sstore(0, mload(0xa0)) +// sstore(0, mload(0xc0)) // sstore(mul(17, 4), a17_18) // sstore(mul(16, 4), a16_17) // sstore(mul(15, 4), a15_16) @@ -248,13 +248,13 @@ // sstore(mul(4, 4), a4_5) // sstore(mul(3, 4), a3_4) // sstore(mul(2, 4), a2_3) -// sstore(mul(1, 4), mload(0xa0)) +// sstore(mul(1, 4), mload(0xc0)) // v_1 := i() // } // function h() -> v_19 // { -// mstore(0xc0, calldataload(mul(1, 4))) -// mstore(0xa0, calldataload(mul(2, 4))) +// mstore(0xa0, calldataload(mul(1, 4))) +// mstore(0xc0, calldataload(mul(2, 4))) // let a3_22 := calldataload(mul(3, 4)) // let a4_23 := calldataload(mul(4, 4)) // let a5_24 := calldataload(mul(5, 4)) @@ -264,8 +264,8 @@ // let a9_28 := calldataload(mul(9, 4)) // let a10_29 := calldataload(mul(10, 4)) // let a11_30 := calldataload(mul(10, 4)) -// mstore(0xc0, calldataload(mul(0, 4))) -// mstore(0xa0, calldataload(mul(1, 4))) +// mstore(0xa0, calldataload(mul(0, 4))) +// mstore(0xc0, calldataload(mul(1, 4))) // let a12_31 := calldataload(mul(12, 4)) // let a13_32 := calldataload(mul(13, 4)) // let a14_33 := calldataload(mul(14, 4)) @@ -274,7 +274,7 @@ // let a17_36 := calldataload(mul(17, 4)) // let a18 := calldataload(mul(18, 4)) // let a19 := calldataload(mul(19, 4)) -// sstore(0, add(mload(0xc0), mload(0xa0))) +// sstore(0, add(mload(0xa0), mload(0xc0))) // sstore(mul(17, 4), a19) // sstore(mul(17, 4), a18) // sstore(mul(17, 4), a17_36) @@ -292,13 +292,13 @@ // sstore(mul(5, 4), a5_24) // sstore(mul(4, 4), a4_23) // sstore(mul(3, 4), a3_22) -// sstore(mul(2, 4), mload(0xa0)) -// sstore(mul(1, 4), mload(0xc0)) +// sstore(mul(2, 4), mload(0xc0)) +// sstore(mul(1, 4), mload(0xa0)) // v_19 := i() // } // function i() -> v_37 // { -// mstore(0x80, calldataload(mul(1, 4))) +// mstore(0xe0, calldataload(mul(1, 4))) // let a2_39 := calldataload(mul(2, 4)) // let a3_40 := calldataload(mul(3, 4)) // let a4_41 := calldataload(mul(4, 4)) @@ -307,7 +307,7 @@ // let a7_44 := calldataload(mul(7, 4)) // let a8_45 := calldataload(mul(8, 4)) // let a9_46 := calldataload(mul(9, 4)) -// mstore(0x80, calldataload(mul(0, 4))) +// mstore(0xe0, calldataload(mul(0, 4))) // let a10_47 := calldataload(mul(10, 4)) // let a11_48 := calldataload(mul(11, 4)) // let a12_49 := calldataload(mul(12, 4)) @@ -316,7 +316,7 @@ // let a15_52 := calldataload(mul(15, 4)) // let a16_53 := calldataload(mul(16, 4)) // let a17_54 := calldataload(mul(17, 4)) -// sstore(0, mload(0x80)) +// sstore(0, mload(0xe0)) // sstore(mul(17, 4), a17_54) // sstore(mul(16, 4), a16_53) // sstore(mul(15, 4), a15_52) @@ -333,7 +333,7 @@ // sstore(mul(4, 4), a4_41) // sstore(mul(3, 4), a3_40) // sstore(mul(2, 4), a2_39) -// sstore(mul(1, 4), mload(0x80)) +// sstore(mul(1, 4), mload(0xe0)) // v_37 := sload(mul(42, 8)) // } // }