Skip to content

Commit 099ab29

Browse files
christianparpartChristian Parpart
authored andcommitted
[yul] Implements DataFlowAnalyzer for break & continue statements.
1 parent cfefa2c commit 099ab29

File tree

4 files changed

+53
-13
lines changed

4 files changed

+53
-13
lines changed

libyul/optimiser/DataFlowAnalyzer.cpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -122,22 +122,19 @@ void DataFlowAnalyzer::operator()(ForLoop& _for)
122122
assignments(_for.post);
123123
clearValues(assignments.names());
124124

125+
AssignmentsSinceContinue assignmentsSinceCont;
126+
assignmentsSinceCont(_for.body);
127+
125128
visit(*_for.condition);
126129
(*this)(_for.body);
127130
(*this)(_for.post);
128131

129-
clearValues(assignments.names());
130-
popScope();
131-
}
132-
133-
void DataFlowAnalyzer::operator()(Break&)
134-
{
135-
yulAssert(false, "Not implemented yet.");
136-
}
132+
if (!assignmentsSinceCont.empty())
133+
clearValues(assignmentsSinceCont.names());
134+
else
135+
clearValues(assignments.names());
137136

138-
void DataFlowAnalyzer::operator()(Continue&)
139-
{
140-
yulAssert(false, "Not implemented yet.");
137+
popScope();
141138
}
142139

143140
void DataFlowAnalyzer::operator()(Block& _block)

libyul/optimiser/DataFlowAnalyzer.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#pragma once
2424

2525
#include <libyul/optimiser/ASTWalker.h>
26+
#include <libyul/optimiser/NameCollector.h>
2627
#include <libyul/YulString.h>
2728

2829
#include <map>
@@ -53,8 +54,6 @@ class DataFlowAnalyzer: public ASTModifier
5354
void operator()(Switch& _switch) override;
5455
void operator()(FunctionDefinition&) override;
5556
void operator()(ForLoop&) override;
56-
void operator()(Break& _continue) override;
57-
void operator()(Continue& _continue) override;
5857
void operator()(Block& _block) override;
5958

6059
protected:

libyul/optimiser/NameCollector.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,23 @@ void Assignments::operator()(Assignment const& _assignment)
7979
for (auto const& var: _assignment.variableNames)
8080
m_names.emplace(var.name);
8181
}
82+
83+
void AssignmentsSinceContinue::operator()(ForLoop const& _forLoop)
84+
{
85+
m_forLoopDepth++;
86+
ASTWalker::operator()(_forLoop);
87+
m_forLoopDepth--;
88+
}
89+
90+
void AssignmentsSinceContinue::operator()(Continue const&)
91+
{
92+
if (m_forLoopDepth == 0)
93+
m_continueFound = true;
94+
}
95+
96+
void AssignmentsSinceContinue::operator()(Assignment const& _assignment)
97+
{
98+
if (m_continueFound)
99+
for (auto const& var: _assignment.variableNames)
100+
m_names.emplace(var.name);
101+
}

libyul/optimiser/NameCollector.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,28 @@ class Assignments: public ASTWalker
8181
std::set<YulString> m_names;
8282
};
8383

84+
/**
85+
* Collects all names from a given continue statement on onwards.
86+
*
87+
* It makes only sense to be invoked from within a body of an outer for loop, that is,
88+
* it will only collect all names from the beginning of the first continue statement
89+
* of the outer-most ForLoop.
90+
*/
91+
class AssignmentsSinceContinue: public ASTWalker
92+
{
93+
public:
94+
using ASTWalker::operator();
95+
void operator()(ForLoop const& _forLoop) override;
96+
void operator()(Continue const&) override;
97+
void operator()(Assignment const& _assignment) override;
98+
99+
std::set<YulString> const& names() const { return m_names; }
100+
bool empty() const noexcept { return m_names.empty(); }
101+
102+
private:
103+
int m_forLoopDepth = 0;
104+
bool m_continueFound = false;
105+
std::set<YulString> m_names;
106+
};
107+
84108
}

0 commit comments

Comments
 (0)