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/StackToMemoryMover.h>
|
||||||
#include <libyul/optimiser/NameDispenser.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/backends/evm/EVMDialect.h>
|
||||||
|
|
||||||
#include <libyul/AsmData.h>
|
#include <libyul/AsmData.h>
|
||||||
@ -66,9 +70,15 @@ void StackToMemoryMover::run(
|
|||||||
);
|
);
|
||||||
VariableMemoryOffsetTracker memoryOffsetTracker(_reservedMemory, _memorySlots, _numRequiredSlots);
|
VariableMemoryOffsetTracker memoryOffsetTracker(_reservedMemory, _memorySlots, _numRequiredSlots);
|
||||||
|
|
||||||
|
ForLoopConditionIntoBody::run(_context, _block);
|
||||||
|
ExpressionSplitter::run(_context, _block);
|
||||||
|
|
||||||
VariableDeclarationAndAssignmentMover declarationAndAssignmentMover(_context, memoryOffsetTracker);
|
VariableDeclarationAndAssignmentMover declarationAndAssignmentMover(_context, memoryOffsetTracker);
|
||||||
declarationAndAssignmentMover(_block);
|
declarationAndAssignmentMover(_block);
|
||||||
|
|
||||||
|
ExpressionJoiner::runUntilStabilized(_context, _block);
|
||||||
|
ForLoopConditionOutOfBody::run(_context, _block);
|
||||||
|
|
||||||
IdentifierMover identifierMover(_context, memoryOffsetTracker);
|
IdentifierMover identifierMover(_context, memoryOffsetTracker);
|
||||||
identifierMover(_block);
|
identifierMover(_block);
|
||||||
}
|
}
|
||||||
@ -108,18 +118,6 @@ void StackToMemoryMover::VariableDeclarationAndAssignmentMover::operator()(Block
|
|||||||
auto const& _variables,
|
auto const& _variables,
|
||||||
std::unique_ptr<Expression> _value
|
std::unique_ptr<Expression> _value
|
||||||
) -> std::vector<Statement> {
|
) -> 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)};
|
VariableDeclaration tempDecl{_loc, {}, std::move(_value)};
|
||||||
vector<Statement> memoryAssignments;
|
vector<Statement> memoryAssignments;
|
||||||
vector<Statement> variableAssignments;
|
vector<Statement> variableAssignments;
|
||||||
|
|||||||
@ -30,19 +30,9 @@ namespace solidity::yul
|
|||||||
/**
|
/**
|
||||||
* Optimisation stage that moves Yul variables from stack to memory.
|
* Optimisation stage that moves Yul variables from stack to memory.
|
||||||
* It takes a map from functions names and variable names to memory offsets.
|
* 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:
|
* In variable declarations, variables to be moved are replaced by fresh variables and then moved to memory:
|
||||||
* 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:
|
|
||||||
* If b and d are in the map, replace
|
* If b and d are in the map, replace
|
||||||
* let a, b, c, d := f()
|
* let a, b, c, d := f()
|
||||||
* by
|
* by
|
||||||
@ -52,13 +42,7 @@ namespace solidity::yul
|
|||||||
* let c := _3
|
* let c := _3
|
||||||
* let a := _1
|
* let a := _1
|
||||||
*
|
*
|
||||||
* Assignments to single variables are replaced by mstore's:
|
* Assignments are split up similarly to multi-variable declarations:
|
||||||
* 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:
|
|
||||||
* If b and d are in the map, replace
|
* If b and d are in the map, replace
|
||||||
* a, b, c, d := f()
|
* a, b, c, d := f()
|
||||||
* by
|
* by
|
||||||
@ -68,7 +52,8 @@ namespace solidity::yul
|
|||||||
* c := _3
|
* c := _3
|
||||||
* a := _1
|
* 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,
|
* 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).
|
* the entire function is skipped (no local variables in the function will be moved at all).
|
||||||
|
|||||||
@ -29,31 +29,32 @@
|
|||||||
// {
|
// {
|
||||||
// a := 21
|
// a := 21
|
||||||
// mstore(0x60, 1)
|
// mstore(0x60, 1)
|
||||||
// let b_1, a_2, $c_3 := z()
|
// let b_8, a_9, $c_10 := z()
|
||||||
// mstore(0x60, $c_3)
|
// mstore(0x60, $c_10)
|
||||||
// a := a_2
|
// a := a_9
|
||||||
// b := b_1
|
// b := b_8
|
||||||
// }
|
// }
|
||||||
// function f() -> x
|
// function f() -> x
|
||||||
// {
|
// {
|
||||||
// mstore(0x20, 0)
|
// let $x2_11
|
||||||
|
// mstore(0x20, $x2_11)
|
||||||
// mstore(0x20, 42)
|
// mstore(0x20, 42)
|
||||||
// let $x3_4, $x4_5 := g()
|
// let $x3_13, $x4_14 := g()
|
||||||
// mstore(0x00, $x4_5)
|
// mstore(0x00, $x4_14)
|
||||||
// mstore(0x40, $x3_4)
|
// mstore(0x40, $x3_13)
|
||||||
// x := mul(add(mload(0x20), mload(0x40)), h(mload(0x00)))
|
// x := mul(add(mload(0x20), mload(0x40)), h(mload(0x00)))
|
||||||
// sstore(mload(0x40), mload(0x00))
|
// 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_15, $z_16, y_17 := z()
|
||||||
// mstore(0x60, $z_7)
|
// mstore(0x60, $z_16)
|
||||||
// let y := y_8
|
// let y := y_17
|
||||||
// let x_2 := x_2_6
|
// let x_2 := x_2_15
|
||||||
// let a_1_9, $z_10, v_11 := z()
|
// let a_1_18, $z_19, v_20 := z()
|
||||||
// mstore(0x60, $z_10)
|
// mstore(0x60, $z_19)
|
||||||
// v := v_11
|
// v := v_20
|
||||||
// a_1 := a_1_9
|
// a_1 := a_1_18
|
||||||
// }
|
// }
|
||||||
// function z() -> a_3, b_4, c
|
// function z() -> a_3, b_4, c
|
||||||
// { mstore(0x80, 0) }
|
// { mstore(0x80, 0) }
|
||||||
|
|||||||
@ -30,52 +30,53 @@
|
|||||||
// mstore(0x40, memoryguard(0x80))
|
// mstore(0x40, memoryguard(0x80))
|
||||||
// function f()
|
// function f()
|
||||||
// {
|
// {
|
||||||
// mstore(0x40, 0)
|
// let $fx_8
|
||||||
|
// mstore(0x40, $fx_8)
|
||||||
// mstore(0x60, 42)
|
// mstore(0x60, 42)
|
||||||
// sstore(mload(0x40), mload(0x60))
|
// sstore(mload(0x40), mload(0x60))
|
||||||
// mstore(0x40, 21)
|
// mstore(0x40, 21)
|
||||||
// }
|
// }
|
||||||
// function g(gx)
|
// function g(gx)
|
||||||
// {
|
// {
|
||||||
// let $gx_1, $gy_2 := tuple2()
|
// let $gx_11, $gy_12 := tuple2()
|
||||||
// mstore(0x40, $gy_2)
|
// mstore(0x40, $gy_12)
|
||||||
// mstore(0x60, $gx_1)
|
// mstore(0x60, $gx_11)
|
||||||
// {
|
// {
|
||||||
// let $gx_3, $gy_4 := tuple2()
|
// let $gx_13, $gy_14 := tuple2()
|
||||||
// mstore(0x40, $gy_4)
|
// mstore(0x40, $gy_14)
|
||||||
// mstore(0x60, $gx_3)
|
// mstore(0x60, $gx_13)
|
||||||
// }
|
// }
|
||||||
// {
|
// {
|
||||||
// let $gx_5, gx_6 := tuple2()
|
// let $gx_15, gx_16 := tuple2()
|
||||||
// mstore(0x60, $gx_5)
|
// mstore(0x60, $gx_15)
|
||||||
// gx := gx_6
|
// gx := gx_16
|
||||||
// }
|
// }
|
||||||
// {
|
// {
|
||||||
// let gx_7, $gy_8 := tuple2()
|
// let gx_17, $gy_18 := tuple2()
|
||||||
// mstore(0x40, $gy_8)
|
// mstore(0x40, $gy_18)
|
||||||
// gx := gx_7
|
// gx := gx_17
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// function h(hx, hy, hz, hw)
|
// function h(hx, hy, hz, hw)
|
||||||
// {
|
// {
|
||||||
// let $hx_9, $hy_10, $hz_11, $hw_12 := tuple4()
|
// let $hx_19, $hy_20, $hz_21, $hw_22 := tuple4()
|
||||||
// mstore(0x00, $hw_12)
|
// mstore(0x00, $hw_22)
|
||||||
// mstore(0x60, $hz_11)
|
// mstore(0x60, $hz_21)
|
||||||
// mstore(0x40, $hy_10)
|
// mstore(0x40, $hy_20)
|
||||||
// mstore(0x20, $hx_9)
|
// mstore(0x20, $hx_19)
|
||||||
// {
|
// {
|
||||||
// let hx_13, $hy_14, hz_15, $hw_16 := tuple4()
|
// let hx_23, $hy_24, hz_25, $hw_26 := tuple4()
|
||||||
// mstore(0x00, $hw_16)
|
// mstore(0x00, $hw_26)
|
||||||
// mstore(0x40, $hy_14)
|
// mstore(0x40, $hy_24)
|
||||||
// hz := hz_15
|
// hz := hz_25
|
||||||
// hx := hx_13
|
// hx := hx_23
|
||||||
// }
|
// }
|
||||||
// {
|
// {
|
||||||
// let $hx_17, $hy_18, hz_19, hw_20 := tuple4()
|
// let $hx_27, $hy_28, hz_29, hw_30 := tuple4()
|
||||||
// mstore(0x40, $hy_18)
|
// mstore(0x40, $hy_28)
|
||||||
// mstore(0x20, $hx_17)
|
// mstore(0x20, $hx_27)
|
||||||
// hw := hw_20
|
// hw := hw_30
|
||||||
// hz := hz_19
|
// hz := hz_29
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// function tuple2() -> a, b
|
// function tuple2() -> a, b
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user