Reverse the order of the memory offsets assigned to variables.

This commit is contained in:
Daniel Kirchner 2020-09-17 17:36:18 +02:00
parent 976abf4715
commit 48f620fb50
7 changed files with 70 additions and 57 deletions

View File

@ -132,7 +132,7 @@ void StackLimitEvader::run(
MemoryOffsetAllocator memoryOffsetAllocator{_unreachableVariables, callGraph.functionCalls}; MemoryOffsetAllocator memoryOffsetAllocator{_unreachableVariables, callGraph.functionCalls};
uint64_t requiredSlots = memoryOffsetAllocator.run(); 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<uint64_t>::max() / 32, ""); yulAssert(requiredSlots < std::numeric_limits<uint64_t>::max() / 32, "");
reservedMemory += 32 * requiredSlots; reservedMemory += 32 * requiredSlots;

View File

@ -52,18 +52,24 @@ void StackToMemoryMover::run(
OptimiserStepContext& _context, OptimiserStepContext& _context,
u256 _reservedMemory, u256 _reservedMemory,
map<YulString, map<YulString, uint64_t>> const& _memorySlots, map<YulString, map<YulString, uint64_t>> const& _memorySlots,
uint64_t _numRequiredSlots,
Block& _block Block& _block
) )
{ {
StackToMemoryMover stackToMemoryMover(_context, _reservedMemory, _memorySlots); StackToMemoryMover stackToMemoryMover(_context, _reservedMemory, _memorySlots, _numRequiredSlots);
stackToMemoryMover(_block); stackToMemoryMover(_block);
} }
StackToMemoryMover::StackToMemoryMover( StackToMemoryMover::StackToMemoryMover(
OptimiserStepContext& _context, OptimiserStepContext& _context,
u256 _reservedMemory, u256 _reservedMemory,
map<YulString, map<YulString, uint64_t>> const& _memorySlots map<YulString, map<YulString, uint64_t>> const& _memorySlots,
): m_reservedMemory(std::move(_reservedMemory)), m_memorySlots(_memorySlots), m_nameDispenser(_context.dispenser) uint64_t _numRequiredSlots
):
m_reservedMemory(std::move(_reservedMemory)),
m_memorySlots(_memorySlots),
m_numRequiredSlots(_numRequiredSlots),
m_nameDispenser(_context.dispenser)
{ {
auto const* evmDialect = dynamic_cast<EVMDialect const*>(&_context.dialect); auto const* evmDialect = dynamic_cast<EVMDialect const*>(&_context.dialect);
yulAssert( yulAssert(
@ -210,6 +216,8 @@ void StackToMemoryMover::visit(Expression& _expression)
YulString StackToMemoryMover::memoryOffset(YulString _variable) YulString StackToMemoryMover::memoryOffset(YulString _variable)
{ {
yulAssert(m_currentFunctionMemorySlots, ""); 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))};
} }

View File

@ -82,13 +82,16 @@ public:
* Runs the stack to memory mover. * Runs the stack to memory mover.
* @param _reservedMemory Is the amount of previously reserved memory, * @param _reservedMemory Is the amount of previously reserved memory,
* i.e. the lowest memory offset to which variables can be moved. * 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 * @param _memorySlots A map from variables to a slot in memory. Based on the slot a unique offset in the memory range
* is given by _reservedMemory plus 32 times its entry in @a _memorySlots. * 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( static void run(
OptimiserStepContext& _context, OptimiserStepContext& _context,
u256 _reservedMemory, u256 _reservedMemory,
std::map<YulString, std::map<YulString, uint64_t>> const& _memorySlots, std::map<YulString, std::map<YulString, uint64_t>> const& _memorySlots,
uint64_t _numRequiredSlots,
Block& _block Block& _block
); );
using ASTModifier::operator(); using ASTModifier::operator();
@ -100,13 +103,15 @@ private:
StackToMemoryMover( StackToMemoryMover(
OptimiserStepContext& _context, OptimiserStepContext& _context,
u256 _reservedMemory, u256 _reservedMemory,
std::map<YulString, std::map<YulString, uint64_t>> const& _memorySlots std::map<YulString, std::map<YulString, uint64_t>> const& _memorySlots,
uint64_t _numRequiredSlots
); );
/// @returns a YulString containing the memory offset to be assigned to @a _variable as number literal. /// @returns a YulString containing the memory offset to be assigned to @a _variable as number literal.
YulString memoryOffset(YulString _variable); YulString memoryOffset(YulString _variable);
u256 m_reservedMemory; u256 m_reservedMemory;
std::map<YulString, std::map<YulString, uint64_t>> const& m_memorySlots; std::map<YulString, std::map<YulString, uint64_t>> const& m_memorySlots;
uint64_t m_numRequiredSlots = 0;
NameDispenser& m_nameDispenser; NameDispenser& m_nameDispenser;
std::map<YulString, uint64_t> const* m_currentFunctionMemorySlots = nullptr; std::map<YulString, uint64_t> const* m_currentFunctionMemorySlots = nullptr;
}; };

View File

@ -28,35 +28,35 @@
// function g() -> a, b // function g() -> a, b
// { // {
// a := 21 // a := 21
// mstore(0x20, 1) // mstore(0x60, 1)
// let b_1, a_2, $c_3 := z() // let b_1, a_2, $c_3 := z()
// mstore(0x20, $c_3) // mstore(0x60, $c_3)
// a := a_2 // a := a_2
// b := b_1 // b := b_1
// } // }
// function f() -> x // function f() -> x
// { // {
// mstore(0x60, 0) // mstore(0x20, 0)
// mstore(0x60, 42) // mstore(0x20, 42)
// let $x3_4, $x4_5 := g() // let $x3_4, $x4_5 := g()
// mstore(0x80, $x4_5) // mstore(0x00, $x4_5)
// mstore(0x40, $x3_4) // mstore(0x40, $x3_4)
// x := mul(add(mload(0x60), mload(0x40)), h(mload(0x80))) // x := mul(add(mload(0x20), mload(0x40)), h(mload(0x00)))
// sstore(mload(0x40), mload(0x80)) // sstore(mload(0x40), mload(0x00))
// } // }
// function h(v) -> a_1 // function h(v) -> a_1
// { // {
// let x_2_6, $z_7, y_8 := z() // let x_2_6, $z_7, y_8 := z()
// mstore(0x20, $z_7) // mstore(0x60, $z_7)
// let y := y_8 // let y := y_8
// let x_2 := x_2_6 // let x_2 := x_2_6
// let a_1_9, $z_10, v_11 := z() // let a_1_9, $z_10, v_11 := z()
// mstore(0x20, $z_10) // mstore(0x60, $z_10)
// v := v_11 // v := v_11
// a_1 := a_1_9 // a_1 := a_1_9
// } // }
// function z() -> a_3, b_4, c // function z() -> a_3, b_4, c
// { mstore(0x00, 0) } // { mstore(0x80, 0) }
// sstore(0, f()) // sstore(0, f())
// let x_5, y_6 := g() // let x_5, y_6 := g()
// } // }

View File

@ -12,8 +12,8 @@
// //
// { // {
// mstore(0x40, memoryguard(0x40)) // mstore(0x40, memoryguard(0x40))
// mstore(0x20, 0) // mstore(0x00, 0)
// sstore(0, mload(0x20)) // sstore(0, mload(0x00))
// function h($hx) -> y // function h($hx) -> y
// { y := $hx } // { y := $hx }
// sstore(1, h(32)) // sstore(1, h(32))

View File

@ -30,50 +30,50 @@
// mstore(0x40, memoryguard(0x80)) // mstore(0x40, memoryguard(0x80))
// function f() // function f()
// { // {
// mstore(0x20, 0) // mstore(0x40, 0)
// mstore(0x00, 42) // mstore(0x60, 42)
// sstore(mload(0x20), mload(0x00)) // sstore(mload(0x40), mload(0x60))
// mstore(0x20, 21) // mstore(0x40, 21)
// } // }
// function g(gx) // function g(gx)
// { // {
// let $gx_1, $gy_2 := tuple2() // let $gx_1, $gy_2 := tuple2()
// mstore(0x20, $gy_2) // mstore(0x40, $gy_2)
// mstore(0x00, $gx_1) // mstore(0x60, $gx_1)
// { // {
// let $gx_3, $gy_4 := tuple2() // let $gx_3, $gy_4 := tuple2()
// mstore(0x20, $gy_4) // mstore(0x40, $gy_4)
// mstore(0x00, $gx_3) // mstore(0x60, $gx_3)
// } // }
// { // {
// let $gx_5, gx_6 := tuple2() // let $gx_5, gx_6 := tuple2()
// mstore(0x00, $gx_5) // mstore(0x60, $gx_5)
// gx := gx_6 // gx := gx_6
// } // }
// { // {
// let gx_7, $gy_8 := tuple2() // let gx_7, $gy_8 := tuple2()
// mstore(0x20, $gy_8) // mstore(0x40, $gy_8)
// gx := gx_7 // gx := gx_7
// } // }
// } // }
// function h(hx, hy, hz, hw) // function h(hx, hy, hz, hw)
// { // {
// let $hx_9, $hy_10, $hz_11, $hw_12 := tuple4() // let $hx_9, $hy_10, $hz_11, $hw_12 := tuple4()
// mstore(0x60, $hw_12) // mstore(0x00, $hw_12)
// mstore(0x00, $hz_11) // mstore(0x60, $hz_11)
// mstore(0x20, $hy_10) // mstore(0x40, $hy_10)
// mstore(0x40, $hx_9) // mstore(0x20, $hx_9)
// { // {
// let hx_13, $hy_14, hz_15, $hw_16 := tuple4() // let hx_13, $hy_14, hz_15, $hw_16 := tuple4()
// mstore(0x60, $hw_16) // mstore(0x00, $hw_16)
// mstore(0x20, $hy_14) // mstore(0x40, $hy_14)
// hz := hz_15 // hz := hz_15
// hx := hx_13 // hx := hx_13
// } // }
// { // {
// let $hx_17, $hy_18, hz_19, hw_20 := tuple4() // let $hx_17, $hy_18, hz_19, hw_20 := tuple4()
// mstore(0x20, $hy_18) // mstore(0x40, $hy_18)
// mstore(0x40, $hx_17) // mstore(0x20, $hx_17)
// hw := hw_20 // hw := hw_20
// hz := hz_19 // hz := hz_19
// } // }

View File

@ -174,7 +174,7 @@
// } // }
// function f() -> v // function f() -> v
// { // {
// mstore(0xe0, calldataload(mul(1, 4))) // mstore(0x80, calldataload(mul(1, 4)))
// let a2 := calldataload(mul(2, 4)) // let a2 := calldataload(mul(2, 4))
// let a3 := calldataload(mul(3, 4)) // let a3 := calldataload(mul(3, 4))
// let a4 := calldataload(g()) // let a4 := calldataload(g())
@ -183,7 +183,7 @@
// let a7 := calldataload(mul(7, 4)) // let a7 := calldataload(mul(7, 4))
// let a8 := calldataload(mul(8, 4)) // let a8 := calldataload(mul(8, 4))
// let a9 := calldataload(mul(9, 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 a10 := calldataload(mul(10, 4))
// let a11 := calldataload(mul(11, 4)) // let a11 := calldataload(mul(11, 4))
// let a12 := calldataload(mul(12, 4)) // let a12 := calldataload(mul(12, 4))
@ -192,7 +192,7 @@
// let a15 := calldataload(mul(15, 4)) // let a15 := calldataload(mul(15, 4))
// let a16 := calldataload(mul(16, 4)) // let a16 := calldataload(mul(16, 4))
// let a17 := calldataload(mul(17, 4)) // let a17 := calldataload(mul(17, 4))
// sstore(0, mload(0xe0)) // sstore(0, mload(0x80))
// sstore(mul(17, 4), a17) // sstore(mul(17, 4), a17)
// sstore(mul(16, 4), a16) // sstore(mul(16, 4), a16)
// sstore(mul(15, 4), a15) // sstore(mul(15, 4), a15)
@ -209,11 +209,11 @@
// sstore(mul(4, 4), a4) // sstore(mul(4, 4), a4)
// sstore(mul(3, 4), a3) // sstore(mul(3, 4), a3)
// sstore(mul(2, 4), a2) // sstore(mul(2, 4), a2)
// sstore(mul(1, 4), mload(0xe0)) // sstore(mul(1, 4), mload(0x80))
// } // }
// function g() -> v_1 // function g() -> v_1
// { // {
// mstore(0xa0, calldataload(mul(1, 4))) // mstore(0xc0, calldataload(mul(1, 4)))
// let a2_3 := calldataload(mul(2, 4)) // let a2_3 := calldataload(mul(2, 4))
// let a3_4 := calldataload(mul(3, 4)) // let a3_4 := calldataload(mul(3, 4))
// let a4_5 := calldataload(mul(4, 4)) // let a4_5 := calldataload(mul(4, 4))
@ -222,7 +222,7 @@
// let a7_8 := calldataload(mul(7, 4)) // let a7_8 := calldataload(mul(7, 4))
// let a8_9 := calldataload(mul(8, 4)) // let a8_9 := calldataload(mul(8, 4))
// let a9_10 := calldataload(mul(9, 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 a10_11 := calldataload(mul(10, 4))
// let a11_12 := calldataload(mul(11, 4)) // let a11_12 := calldataload(mul(11, 4))
// let a12_13 := calldataload(mul(12, 4)) // let a12_13 := calldataload(mul(12, 4))
@ -231,7 +231,7 @@
// let a15_16 := calldataload(mul(15, 4)) // let a15_16 := calldataload(mul(15, 4))
// let a16_17 := calldataload(mul(16, 4)) // let a16_17 := calldataload(mul(16, 4))
// let a17_18 := calldataload(mul(17, 4)) // let a17_18 := calldataload(mul(17, 4))
// sstore(0, mload(0xa0)) // sstore(0, mload(0xc0))
// sstore(mul(17, 4), a17_18) // sstore(mul(17, 4), a17_18)
// sstore(mul(16, 4), a16_17) // sstore(mul(16, 4), a16_17)
// sstore(mul(15, 4), a15_16) // sstore(mul(15, 4), a15_16)
@ -248,13 +248,13 @@
// sstore(mul(4, 4), a4_5) // sstore(mul(4, 4), a4_5)
// sstore(mul(3, 4), a3_4) // sstore(mul(3, 4), a3_4)
// sstore(mul(2, 4), a2_3) // sstore(mul(2, 4), a2_3)
// sstore(mul(1, 4), mload(0xa0)) // sstore(mul(1, 4), mload(0xc0))
// v_1 := i() // v_1 := i()
// } // }
// function h() -> v_19 // function h() -> v_19
// { // {
// mstore(0xc0, calldataload(mul(1, 4))) // mstore(0xa0, calldataload(mul(1, 4)))
// mstore(0xa0, calldataload(mul(2, 4))) // mstore(0xc0, calldataload(mul(2, 4)))
// let a3_22 := calldataload(mul(3, 4)) // let a3_22 := calldataload(mul(3, 4))
// let a4_23 := calldataload(mul(4, 4)) // let a4_23 := calldataload(mul(4, 4))
// let a5_24 := calldataload(mul(5, 4)) // let a5_24 := calldataload(mul(5, 4))
@ -264,8 +264,8 @@
// let a9_28 := calldataload(mul(9, 4)) // let a9_28 := calldataload(mul(9, 4))
// let a10_29 := calldataload(mul(10, 4)) // let a10_29 := calldataload(mul(10, 4))
// let a11_30 := calldataload(mul(10, 4)) // let a11_30 := calldataload(mul(10, 4))
// mstore(0xc0, calldataload(mul(0, 4))) // mstore(0xa0, calldataload(mul(0, 4)))
// mstore(0xa0, calldataload(mul(1, 4))) // mstore(0xc0, calldataload(mul(1, 4)))
// let a12_31 := calldataload(mul(12, 4)) // let a12_31 := calldataload(mul(12, 4))
// let a13_32 := calldataload(mul(13, 4)) // let a13_32 := calldataload(mul(13, 4))
// let a14_33 := calldataload(mul(14, 4)) // let a14_33 := calldataload(mul(14, 4))
@ -274,7 +274,7 @@
// let a17_36 := calldataload(mul(17, 4)) // let a17_36 := calldataload(mul(17, 4))
// let a18 := calldataload(mul(18, 4)) // let a18 := calldataload(mul(18, 4))
// let a19 := calldataload(mul(19, 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), a19)
// sstore(mul(17, 4), a18) // sstore(mul(17, 4), a18)
// sstore(mul(17, 4), a17_36) // sstore(mul(17, 4), a17_36)
@ -292,13 +292,13 @@
// sstore(mul(5, 4), a5_24) // sstore(mul(5, 4), a5_24)
// sstore(mul(4, 4), a4_23) // sstore(mul(4, 4), a4_23)
// sstore(mul(3, 4), a3_22) // sstore(mul(3, 4), a3_22)
// sstore(mul(2, 4), mload(0xa0)) // sstore(mul(2, 4), mload(0xc0))
// sstore(mul(1, 4), mload(0xc0)) // sstore(mul(1, 4), mload(0xa0))
// v_19 := i() // v_19 := i()
// } // }
// function i() -> v_37 // function i() -> v_37
// { // {
// mstore(0x80, calldataload(mul(1, 4))) // mstore(0xe0, calldataload(mul(1, 4)))
// let a2_39 := calldataload(mul(2, 4)) // let a2_39 := calldataload(mul(2, 4))
// let a3_40 := calldataload(mul(3, 4)) // let a3_40 := calldataload(mul(3, 4))
// let a4_41 := calldataload(mul(4, 4)) // let a4_41 := calldataload(mul(4, 4))
@ -307,7 +307,7 @@
// let a7_44 := calldataload(mul(7, 4)) // let a7_44 := calldataload(mul(7, 4))
// let a8_45 := calldataload(mul(8, 4)) // let a8_45 := calldataload(mul(8, 4))
// let a9_46 := calldataload(mul(9, 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 a10_47 := calldataload(mul(10, 4))
// let a11_48 := calldataload(mul(11, 4)) // let a11_48 := calldataload(mul(11, 4))
// let a12_49 := calldataload(mul(12, 4)) // let a12_49 := calldataload(mul(12, 4))
@ -316,7 +316,7 @@
// let a15_52 := calldataload(mul(15, 4)) // let a15_52 := calldataload(mul(15, 4))
// let a16_53 := calldataload(mul(16, 4)) // let a16_53 := calldataload(mul(16, 4))
// let a17_54 := calldataload(mul(17, 4)) // let a17_54 := calldataload(mul(17, 4))
// sstore(0, mload(0x80)) // sstore(0, mload(0xe0))
// sstore(mul(17, 4), a17_54) // sstore(mul(17, 4), a17_54)
// sstore(mul(16, 4), a16_53) // sstore(mul(16, 4), a16_53)
// sstore(mul(15, 4), a15_52) // sstore(mul(15, 4), a15_52)
@ -333,7 +333,7 @@
// sstore(mul(4, 4), a4_41) // sstore(mul(4, 4), a4_41)
// sstore(mul(3, 4), a3_40) // sstore(mul(3, 4), a3_40)
// sstore(mul(2, 4), a2_39) // sstore(mul(2, 4), a2_39)
// sstore(mul(1, 4), mload(0x80)) // sstore(mul(1, 4), mload(0xe0))
// v_37 := sload(mul(42, 8)) // v_37 := sload(mul(42, 8))
// } // }
// } // }