Split structural simplifier.

This commit is contained in:
chriseth
2019-05-13 10:26:57 +02:00
parent a28b6224a4
commit d9831c8b96
7 changed files with 224 additions and 99 deletions
+1 -92
View File
@@ -32,39 +32,6 @@ using OptionalStatements = boost::optional<vector<Statement>>;
namespace {
ExpressionStatement makePopExpressionStatement(langutil::SourceLocation const& _location, Expression&& _expression)
{
return {_location, FunctionalInstruction{
_location,
dev::eth::Instruction::POP,
{std::move(_expression)}
}};
}
void removeEmptyDefaultFromSwitch(Switch& _switchStmt)
{
boost::remove_erase_if(
_switchStmt.cases,
[](Case const& _case) { return !_case.value && _case.body.statements.empty(); }
);
}
void removeEmptyCasesFromSwitch(Switch& _switchStmt)
{
bool hasDefault = boost::algorithm::any_of(
_switchStmt.cases,
[](Case const& _case) { return !_case.value; }
);
if (hasDefault)
return;
boost::remove_erase_if(
_switchStmt.cases,
[](Case const& _case) { return _case.body.statements.empty(); }
);
}
OptionalStatements replaceConstArgSwitch(Switch& _switchStmt, u256 const& _constExprVal)
{
Block* matchingCaseBlock = nullptr;
@@ -92,35 +59,6 @@ OptionalStatements replaceConstArgSwitch(Switch& _switchStmt, u256 const& _const
return s;
}
OptionalStatements reduceSingleCaseSwitch(Switch& _switchStmt)
{
yulAssert(_switchStmt.cases.size() == 1, "Expected only one case!");
auto& switchCase = _switchStmt.cases.front();
auto loc = locationOf(*_switchStmt.expression);
if (switchCase.value)
{
OptionalStatements s = vector<Statement>{};
s->emplace_back(If{
std::move(_switchStmt.location),
make_unique<Expression>(FunctionalInstruction{
std::move(loc),
dev::eth::Instruction::EQ,
{std::move(*switchCase.value), std::move(*_switchStmt.expression)}
}),
std::move(switchCase.body)
});
return s;
}
else
{
OptionalStatements s = vector<Statement>{};
s->emplace_back(makePopExpressionStatement(loc, std::move(*_switchStmt.expression)));
s->emplace_back(std::move(switchCase.body));
return s;
}
}
}
void StructuralSimplifier::operator()(Block& _block)
@@ -130,19 +68,6 @@ void StructuralSimplifier::operator()(Block& _block)
popScope();
}
OptionalStatements StructuralSimplifier::reduceNoCaseSwitch(Switch& _switchStmt) const
{
yulAssert(_switchStmt.cases.empty(), "Expected no case!");
auto loc = locationOf(*_switchStmt.expression);
OptionalStatements s = vector<Statement>{};
s->emplace_back(makePopExpressionStatement(loc, std::move(*_switchStmt.expression)));
return s;
}
boost::optional<dev::u256> StructuralSimplifier::hasLiteralValue(Expression const& _expression) const
{
Expression const* expr = &_expression;
@@ -167,12 +92,6 @@ void StructuralSimplifier::simplify(std::vector<yul::Statement>& _statements)
{
GenericFallbackReturnsVisitor<OptionalStatements, If, Switch, ForLoop> const visitor(
[&](If& _ifStmt) -> OptionalStatements {
if (_ifStmt.body.statements.empty())
{
OptionalStatements s = vector<Statement>{};
s->emplace_back(makePopExpressionStatement(_ifStmt.location, std::move(*_ifStmt.condition)));
return s;
}
if (expressionAlwaysTrue(*_ifStmt.condition))
return {std::move(_ifStmt.body.statements)};
else if (expressionAlwaysFalse(*_ifStmt.condition))
@@ -182,22 +101,12 @@ void StructuralSimplifier::simplify(std::vector<yul::Statement>& _statements)
[&](Switch& _switchStmt) -> OptionalStatements {
if (boost::optional<u256> const constExprVal = hasLiteralValue(*_switchStmt.expression))
return replaceConstArgSwitch(_switchStmt, constExprVal.get());
removeEmptyDefaultFromSwitch(_switchStmt);
removeEmptyCasesFromSwitch(_switchStmt);
if (_switchStmt.cases.empty())
return reduceNoCaseSwitch(_switchStmt);
else if (_switchStmt.cases.size() == 1)
return reduceSingleCaseSwitch(_switchStmt);
return {};
},
[&](ForLoop& _forLoop) -> OptionalStatements {
if (expressionAlwaysFalse(*_forLoop.condition))
return {std::move(_forLoop.pre.statements)};
else
return {};
return {};
}
);