mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Use ForLoopConditionIntoBody and Expression splitter as preprocessing in StackToMemoryMover, reversing them afterwards.
This commit is contained in:
parent
b0fa2fb296
commit
a59bf01ebd
@ -16,6 +16,10 @@
|
||||
*/
|
||||
#include <libyul/optimiser/StackToMemoryMover.h>
|
||||
#include <libyul/optimiser/NameDispenser.h>
|
||||
#include <libyul/optimiser/ExpressionSplitter.h>
|
||||
#include <libyul/optimiser/ExpressionJoiner.h>
|
||||
#include <libyul/optimiser/ForLoopConditionIntoBody.h>
|
||||
#include <libyul/optimiser/ForLoopConditionOutOfBody.h>
|
||||
#include <libyul/backends/evm/EVMDialect.h>
|
||||
|
||||
#include <libyul/AsmData.h>
|
||||
@ -66,9 +70,15 @@ void StackToMemoryMover::run(
|
||||
);
|
||||
VariableMemoryOffsetTracker memoryOffsetTracker(_reservedMemory, _memorySlots, _numRequiredSlots);
|
||||
|
||||
ForLoopConditionIntoBody::run(_context, _block);
|
||||
ExpressionSplitter::run(_context, _block);
|
||||
|
||||
VariableDeclarationAndAssignmentMover declarationAndAssignmentMover(_context, memoryOffsetTracker);
|
||||
declarationAndAssignmentMover(_block);
|
||||
|
||||
ExpressionJoiner::runUntilStabilized(_context, _block);
|
||||
ForLoopConditionOutOfBody::run(_context, _block);
|
||||
|
||||
IdentifierMover identifierMover(_context, memoryOffsetTracker);
|
||||
identifierMover(_block);
|
||||
}
|
||||
@ -108,18 +118,6 @@ void StackToMemoryMover::VariableDeclarationAndAssignmentMover::operator()(Block
|
||||
auto const& _variables,
|
||||
std::unique_ptr<Expression> _value
|
||||
) -> std::vector<Statement> {
|
||||
if (_variables.size() == 1)
|
||||
{
|
||||
optional<YulString> offset = m_memoryOffsetTracker(_variables.front().name);
|
||||
yulAssert(offset, "");
|
||||
return generateMemoryStore(
|
||||
m_context.dialect,
|
||||
_loc,
|
||||
*offset,
|
||||
_value ? *std::move(_value) : Literal{_loc, LiteralKind::Number, "0"_yulstring, {}}
|
||||
);
|
||||
}
|
||||
|
||||
VariableDeclaration tempDecl{_loc, {}, std::move(_value)};
|
||||
vector<Statement> memoryAssignments;
|
||||
vector<Statement> variableAssignments;
|
||||
|
@ -30,19 +30,9 @@ namespace solidity::yul
|
||||
/**
|
||||
* Optimisation stage that moves Yul variables from stack to memory.
|
||||
* It takes a map from functions names and variable names to memory offsets.
|
||||
* It then transforms the AST as follows:
|
||||
* It then transforms the AST as follows (after running ForLoopConditionIntoBody and ExpressionSplitter):
|
||||
*
|
||||
* Single variable declarations are replaced by mstore's as follows:
|
||||
* If a is in the map, replace
|
||||
* let a
|
||||
* by
|
||||
* mstore(<memory offset for a>, 0)
|
||||
* respectively, replace
|
||||
* let a := expr
|
||||
* by
|
||||
* mstore(<memory offset for a>, expr)
|
||||
*
|
||||
* In a multi-variable declaration, variables to be moved are replaced by fresh variables and then moved to memory:
|
||||
* In variable declarations, variables to be moved are replaced by fresh variables and then moved to memory:
|
||||
* If b and d are in the map, replace
|
||||
* let a, b, c, d := f()
|
||||
* by
|
||||
@ -52,13 +42,7 @@ namespace solidity::yul
|
||||
* let c := _3
|
||||
* let a := _1
|
||||
*
|
||||
* Assignments to single variables are replaced by mstore's:
|
||||
* If a is in the map, replace
|
||||
* a := expr
|
||||
* by
|
||||
* mstore(<memory offset for a>, expr)
|
||||
*
|
||||
* Assignments to multiple variables are split up similarly to multi-variable declarations:
|
||||
* Assignments are split up similarly to multi-variable declarations:
|
||||
* If b and d are in the map, replace
|
||||
* a, b, c, d := f()
|
||||
* by
|
||||
@ -68,7 +52,8 @@ namespace solidity::yul
|
||||
* c := _3
|
||||
* a := _1
|
||||
*
|
||||
* Replace all references to a variable ``a`` in the map by ``mload(<memory offset for a>)``.
|
||||
* After that, the ExpressionJoiner and ForLoopConditionOutOfBody transformations are run to reverse the preprocessing
|
||||
* and then all references to a variable ``a`` in the map are replaced by ``mload(<memory offset for a>)``.
|
||||
*
|
||||
* If a visited function has arguments or return parameters that are contained in the map,
|
||||
* the entire function is skipped (no local variables in the function will be moved at all).
|
||||
|
@ -29,31 +29,32 @@
|
||||
// {
|
||||
// a := 21
|
||||
// mstore(0x60, 1)
|
||||
// let b_1, a_2, $c_3 := z()
|
||||
// mstore(0x60, $c_3)
|
||||
// a := a_2
|
||||
// b := b_1
|
||||
// let b_8, a_9, $c_10 := z()
|
||||
// mstore(0x60, $c_10)
|
||||
// a := a_9
|
||||
// b := b_8
|
||||
// }
|
||||
// function f() -> x
|
||||
// {
|
||||
// mstore(0x20, 0)
|
||||
// let $x2_11
|
||||
// mstore(0x20, $x2_11)
|
||||
// mstore(0x20, 42)
|
||||
// let $x3_4, $x4_5 := g()
|
||||
// mstore(0x00, $x4_5)
|
||||
// mstore(0x40, $x3_4)
|
||||
// let $x3_13, $x4_14 := g()
|
||||
// mstore(0x00, $x4_14)
|
||||
// mstore(0x40, $x3_13)
|
||||
// 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(0x60, $z_7)
|
||||
// let y := y_8
|
||||
// let x_2 := x_2_6
|
||||
// let a_1_9, $z_10, v_11 := z()
|
||||
// mstore(0x60, $z_10)
|
||||
// v := v_11
|
||||
// a_1 := a_1_9
|
||||
// let x_2_15, $z_16, y_17 := z()
|
||||
// mstore(0x60, $z_16)
|
||||
// let y := y_17
|
||||
// let x_2 := x_2_15
|
||||
// let a_1_18, $z_19, v_20 := z()
|
||||
// mstore(0x60, $z_19)
|
||||
// v := v_20
|
||||
// a_1 := a_1_18
|
||||
// }
|
||||
// function z() -> a_3, b_4, c
|
||||
// { mstore(0x80, 0) }
|
||||
|
@ -30,52 +30,53 @@
|
||||
// mstore(0x40, memoryguard(0x80))
|
||||
// function f()
|
||||
// {
|
||||
// mstore(0x40, 0)
|
||||
// let $fx_8
|
||||
// mstore(0x40, $fx_8)
|
||||
// mstore(0x60, 42)
|
||||
// sstore(mload(0x40), mload(0x60))
|
||||
// mstore(0x40, 21)
|
||||
// }
|
||||
// function g(gx)
|
||||
// {
|
||||
// let $gx_1, $gy_2 := tuple2()
|
||||
// mstore(0x40, $gy_2)
|
||||
// mstore(0x60, $gx_1)
|
||||
// let $gx_11, $gy_12 := tuple2()
|
||||
// mstore(0x40, $gy_12)
|
||||
// mstore(0x60, $gx_11)
|
||||
// {
|
||||
// let $gx_3, $gy_4 := tuple2()
|
||||
// mstore(0x40, $gy_4)
|
||||
// mstore(0x60, $gx_3)
|
||||
// let $gx_13, $gy_14 := tuple2()
|
||||
// mstore(0x40, $gy_14)
|
||||
// mstore(0x60, $gx_13)
|
||||
// }
|
||||
// {
|
||||
// let $gx_5, gx_6 := tuple2()
|
||||
// mstore(0x60, $gx_5)
|
||||
// gx := gx_6
|
||||
// let $gx_15, gx_16 := tuple2()
|
||||
// mstore(0x60, $gx_15)
|
||||
// gx := gx_16
|
||||
// }
|
||||
// {
|
||||
// let gx_7, $gy_8 := tuple2()
|
||||
// mstore(0x40, $gy_8)
|
||||
// gx := gx_7
|
||||
// let gx_17, $gy_18 := tuple2()
|
||||
// mstore(0x40, $gy_18)
|
||||
// gx := gx_17
|
||||
// }
|
||||
// }
|
||||
// function h(hx, hy, hz, hw)
|
||||
// {
|
||||
// let $hx_9, $hy_10, $hz_11, $hw_12 := tuple4()
|
||||
// mstore(0x00, $hw_12)
|
||||
// mstore(0x60, $hz_11)
|
||||
// mstore(0x40, $hy_10)
|
||||
// mstore(0x20, $hx_9)
|
||||
// let $hx_19, $hy_20, $hz_21, $hw_22 := tuple4()
|
||||
// mstore(0x00, $hw_22)
|
||||
// mstore(0x60, $hz_21)
|
||||
// mstore(0x40, $hy_20)
|
||||
// mstore(0x20, $hx_19)
|
||||
// {
|
||||
// let hx_13, $hy_14, hz_15, $hw_16 := tuple4()
|
||||
// mstore(0x00, $hw_16)
|
||||
// mstore(0x40, $hy_14)
|
||||
// hz := hz_15
|
||||
// hx := hx_13
|
||||
// let hx_23, $hy_24, hz_25, $hw_26 := tuple4()
|
||||
// mstore(0x00, $hw_26)
|
||||
// mstore(0x40, $hy_24)
|
||||
// hz := hz_25
|
||||
// hx := hx_23
|
||||
// }
|
||||
// {
|
||||
// let $hx_17, $hy_18, hz_19, hw_20 := tuple4()
|
||||
// mstore(0x40, $hy_18)
|
||||
// mstore(0x20, $hx_17)
|
||||
// hw := hw_20
|
||||
// hz := hz_19
|
||||
// let $hx_27, $hy_28, hz_29, hw_30 := tuple4()
|
||||
// mstore(0x40, $hy_28)
|
||||
// mstore(0x20, $hx_27)
|
||||
// hw := hw_30
|
||||
// hz := hz_29
|
||||
// }
|
||||
// }
|
||||
// function tuple2() -> a, b
|
||||
|
Loading…
Reference in New Issue
Block a user