mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #6241 from ethereum/yul-bc-codegen
Yul codegen for break & continue statements
This commit is contained in:
commit
2b0c653f57
@ -4,6 +4,7 @@ Language Features:
|
|||||||
|
|
||||||
|
|
||||||
Compiler Features:
|
Compiler Features:
|
||||||
|
* Yul: Adds break and continue keywords to for-loop syntax.
|
||||||
|
|
||||||
|
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
|
@ -633,14 +633,34 @@ void CodeTransform::operator()(ForLoop const& _forLoop)
|
|||||||
checkStackHeight(&_forLoop);
|
checkStackHeight(&_forLoop);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeTransform::operator()(Break const&)
|
int CodeTransform::appendPopUntil(int _targetDepth)
|
||||||
{
|
{
|
||||||
yulAssert(false, "Code generation for break statement in Yul is not implemented yet.");
|
int const stackDiffAfter = m_assembly.stackHeight() - _targetDepth;
|
||||||
|
for (int i = 0; i < stackDiffAfter; ++i)
|
||||||
|
m_assembly.appendInstruction(solidity::Instruction::POP);
|
||||||
|
return stackDiffAfter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeTransform::operator()(Continue const&)
|
void CodeTransform::operator()(Break const& _break)
|
||||||
{
|
{
|
||||||
yulAssert(false, "Code generation for continue statement in Yul is not implemented yet.");
|
yulAssert(!m_context->forLoopStack.empty(), "Invalid break-statement. Requires surrounding for-loop in code generation.");
|
||||||
|
m_assembly.setSourceLocation(_break.location);
|
||||||
|
|
||||||
|
Context::JumpInfo const& jump = m_context->forLoopStack.top().done;
|
||||||
|
m_assembly.appendJumpTo(jump.label, appendPopUntil(jump.targetStackHeight));
|
||||||
|
|
||||||
|
checkStackHeight(&_break);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeTransform::operator()(Continue const& _continue)
|
||||||
|
{
|
||||||
|
yulAssert(!m_context->forLoopStack.empty(), "Invalid continue-statement. Requires surrounding for-loop in code generation.");
|
||||||
|
m_assembly.setSourceLocation(_continue.location);
|
||||||
|
|
||||||
|
Context::JumpInfo const& jump = m_context->forLoopStack.top().post;
|
||||||
|
m_assembly.appendJumpTo(jump.label, appendPopUntil(jump.targetStackHeight));
|
||||||
|
|
||||||
|
checkStackHeight(&_continue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeTransform::operator()(Block const& _block)
|
void CodeTransform::operator()(Block const& _block)
|
||||||
|
@ -217,6 +217,10 @@ private:
|
|||||||
/// and corrects the stack height to the target stack height.
|
/// and corrects the stack height to the target stack height.
|
||||||
void stackError(StackTooDeepError _error, int _targetStackSize);
|
void stackError(StackTooDeepError _error, int _targetStackSize);
|
||||||
|
|
||||||
|
/// Ensures stack height is down to @p _targetDepth by appending POP instructions to the output assembly.
|
||||||
|
/// Returns the number of POP statements that have been appended.
|
||||||
|
int appendPopUntil(int _targetDepth);
|
||||||
|
|
||||||
AbstractAssembly& m_assembly;
|
AbstractAssembly& m_assembly;
|
||||||
AsmAnalysisInfo& m_info;
|
AsmAnalysisInfo& m_info;
|
||||||
Scope* m_scope = nullptr;
|
Scope* m_scope = nullptr;
|
||||||
|
13
test/libsolidity/semanticTests/asmForLoop/for_loop_break.sol
Normal file
13
test/libsolidity/semanticTests/asmForLoop/for_loop_break.sol
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public returns (uint i) {
|
||||||
|
assembly {
|
||||||
|
for {} lt(i, 10) { i := add(i, 1) }
|
||||||
|
{
|
||||||
|
if eq(i, 6) { break }
|
||||||
|
i := add(i, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// f() -> 6
|
@ -0,0 +1,13 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public returns (uint k) {
|
||||||
|
assembly {
|
||||||
|
for {let i := 0} lt(i, 10) { i := add(i, 1) }
|
||||||
|
{
|
||||||
|
if eq(mod(i, 2), 0) { continue }
|
||||||
|
k := add(k, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// f() -> 5
|
@ -0,0 +1,20 @@
|
|||||||
|
contract C {
|
||||||
|
function f(uint x) public returns (uint i) {
|
||||||
|
assembly {
|
||||||
|
for {} lt(i, 10) { i := add(i, 1) }
|
||||||
|
{
|
||||||
|
if eq(x, 0) { i := 2 break }
|
||||||
|
for {} lt(x, 3) { i := 17 x := 9 } {
|
||||||
|
if eq(x, 1) { continue }
|
||||||
|
if eq(x, 2) { break }
|
||||||
|
}
|
||||||
|
if eq(x, 4) { i := 90 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// f(uint256): 0 -> 2
|
||||||
|
// f(uint256): 1 -> 18
|
||||||
|
// f(uint256): 2 -> 10
|
||||||
|
// f(uint256): 4 -> 91
|
Loading…
Reference in New Issue
Block a user