Merge pull request #6193 from ethereum/yul-opt-different-types-6181

YulOpt: Extend StructuralSimplifier to work with all types
This commit is contained in:
chriseth 2019-03-05 19:11:13 +01:00 committed by GitHub
commit 4740dc62df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 60 additions and 32 deletions

View File

@ -24,6 +24,7 @@
#include <libyul/Exceptions.h> #include <libyul/Exceptions.h>
#include <libdevcore/CommonData.h> #include <libdevcore/CommonData.h>
#include <libdevcore/FixedHash.h>
using namespace std; using namespace std;
using namespace dev; using namespace dev;
@ -31,12 +32,48 @@ using namespace yul;
u256 yul::valueOfNumberLiteral(Literal const& _literal) u256 yul::valueOfNumberLiteral(Literal const& _literal)
{ {
assertThrow(_literal.kind == LiteralKind::Number, OptimizerException, ""); yulAssert(_literal.kind == LiteralKind::Number, "Expected number literal!");
std::string const& literalString = _literal.value.str(); std::string const& literalString = _literal.value.str();
assertThrow(isValidDecimal(literalString) || isValidHex(literalString), OptimizerException, ""); yulAssert(isValidDecimal(literalString) || isValidHex(literalString), "Invalid number literal!");
return u256(literalString); return u256(literalString);
} }
u256 yul::valueOfStringLiteral(Literal const& _literal)
{
yulAssert(_literal.kind == LiteralKind::String, "Expected string literal!");
yulAssert(_literal.value.str().size() <= 32, "Literal string too long!");
return u256(h256(_literal.value.str(), h256::FromBinary, h256::AlignLeft));
}
u256 yul::valueOfBoolLiteral(Literal const& _literal)
{
yulAssert(_literal.kind == LiteralKind::Boolean, "Expected bool literal!");
if (_literal.value == "true"_yulstring)
return u256(1);
else if (_literal.value == "false"_yulstring)
return u256(0);
yulAssert(false, "Unexpected bool literal value!");
}
u256 yul::valueOfLiteral(Literal const& _literal)
{
switch(_literal.kind)
{
case LiteralKind::Number:
return valueOfNumberLiteral(_literal);
case LiteralKind::Boolean:
return valueOfBoolLiteral(_literal);
case LiteralKind::String:
return valueOfStringLiteral(_literal);
default:
yulAssert(false, "Unexpected literal kind!");
}
}
template<> template<>
bool Less<Literal>::operator()(Literal const& _lhs, Literal const& _rhs) const bool Less<Literal>::operator()(Literal const& _lhs, Literal const& _rhs) const
{ {

View File

@ -27,6 +27,9 @@ namespace yul
{ {
dev::u256 valueOfNumberLiteral(Literal const& _literal); dev::u256 valueOfNumberLiteral(Literal const& _literal);
dev::u256 valueOfStringLiteral(Literal const& _literal);
dev::u256 valueOfBoolLiteral(Literal const& _literal);
dev::u256 valueOfLiteral(Literal const& _literal);
/** /**
* Linear order on Yul AST nodes. * Linear order on Yul AST nodes.

View File

@ -23,6 +23,7 @@
#include <libyul/optimiser/NameCollector.h> #include <libyul/optimiser/NameCollector.h>
#include <libyul/AsmAnalysisInfo.h> #include <libyul/AsmAnalysisInfo.h>
#include <libyul/AsmData.h> #include <libyul/AsmData.h>
#include <libyul/Utilities.h>
#include <liblangutil/Exceptions.h> #include <liblangutil/Exceptions.h>
@ -396,20 +397,8 @@ void CodeTransform::operator()(Identifier const& _identifier)
void CodeTransform::operator()(Literal const& _literal) void CodeTransform::operator()(Literal const& _literal)
{ {
m_assembly.setSourceLocation(_literal.location); m_assembly.setSourceLocation(_literal.location);
if (_literal.kind == LiteralKind::Number) m_assembly.appendConstant(valueOfLiteral(_literal));
m_assembly.appendConstant(u256(_literal.value.str()));
else if (_literal.kind == LiteralKind::Boolean)
{
if (_literal.value == "true"_yulstring)
m_assembly.appendConstant(u256(1));
else
m_assembly.appendConstant(u256(0));
}
else
{
solAssert(_literal.value.str().size() <= 32, "");
m_assembly.appendConstant(u256(h256(_literal.value.str(), h256::FromBinary, h256::AlignLeft)));
}
checkStackHeight(&_literal); checkStackHeight(&_literal);
} }

View File

@ -59,7 +59,7 @@ boost::optional<dev::u256> StructuralSimplifier::hasLiteralValue(Expression cons
if (expr && expr->type() == typeid(Literal)) if (expr && expr->type() == typeid(Literal))
{ {
Literal const& literal = boost::get<Literal>(*expr); Literal const& literal = boost::get<Literal>(*expr);
return valueOfNumberLiteral(literal); return valueOfLiteral(literal);
} }
return boost::optional<u256>(); return boost::optional<u256>();
@ -114,7 +114,7 @@ void StructuralSimplifier::simplify(std::vector<yul::Statement>& _statements)
for (auto& _case: _switchStmt.cases) for (auto& _case: _switchStmt.cases)
{ {
if (_case.value && valueOfNumberLiteral(*_case.value) == constExprVal) if (_case.value && valueOfLiteral(*_case.value) == constExprVal)
{ {
matchingCaseBlock = &_case.body; matchingCaseBlock = &_case.body;
break; break;

View File

@ -0,0 +1,12 @@
{
// Used to cause assert error
let y := 200
switch 3
case "" { y := 8 }
case 1 { y := 9 }
}
// ----
// structuralSimplifier
// {
// let y := 200
// }

View File

@ -155,20 +155,7 @@ void ExpressionEvaluator::operator()(Literal const& _literal)
static YulString const trueString("true"); static YulString const trueString("true");
static YulString const falseString("false"); static YulString const falseString("false");
switch (_literal.kind) setValue(valueOfLiteral(_literal));
{
case LiteralKind::Boolean:
solAssert(_literal.value == trueString || _literal.value == falseString, "");
setValue(_literal.value == trueString ? 1 : 0);
break;
case LiteralKind::Number:
setValue(valueOfNumberLiteral(_literal));
break;
case LiteralKind::String:
solAssert(_literal.value.str().size() <= 32, "");
setValue(u256(h256(_literal.value.str(), h256::FromBinary, h256::AlignLeft)));
break;
}
} }
void ExpressionEvaluator::operator()(Identifier const& _identifier) void ExpressionEvaluator::operator()(Identifier const& _identifier)