From 921d52bfcdcdda4e0d1229ff21eba171efb3fc62 Mon Sep 17 00:00:00 2001 From: Mathias Baumann Date: Tue, 5 Mar 2019 17:26:28 +0100 Subject: [PATCH 1/3] Move Literal to u256 conversions to extra functions That way we can reuse them at different places --- libyul/Utilities.cpp | 37 +++++++++++++++++++++++ libyul/Utilities.h | 3 ++ libyul/backends/evm/EVMCodeTransform.cpp | 17 ++--------- test/tools/yulInterpreter/Interpreter.cpp | 15 +-------- 4 files changed, 44 insertions(+), 28 deletions(-) diff --git a/libyul/Utilities.cpp b/libyul/Utilities.cpp index e5f4e517c..4f362e33a 100644 --- a/libyul/Utilities.cpp +++ b/libyul/Utilities.cpp @@ -24,6 +24,7 @@ #include #include +#include using namespace std; using namespace dev; @@ -32,11 +33,47 @@ using namespace yul; u256 yul::valueOfNumberLiteral(Literal const& _literal) { assertThrow(_literal.kind == LiteralKind::Number, OptimizerException, ""); + std::string const& literalString = _literal.value.str(); assertThrow(isValidDecimal(literalString) || isValidHex(literalString), OptimizerException, ""); 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<> bool Less::operator()(Literal const& _lhs, Literal const& _rhs) const { diff --git a/libyul/Utilities.h b/libyul/Utilities.h index 288bc6ee2..827b43aae 100644 --- a/libyul/Utilities.h +++ b/libyul/Utilities.h @@ -27,6 +27,9 @@ namespace yul { 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. diff --git a/libyul/backends/evm/EVMCodeTransform.cpp b/libyul/backends/evm/EVMCodeTransform.cpp index 354627d2b..11c6ed3fc 100644 --- a/libyul/backends/evm/EVMCodeTransform.cpp +++ b/libyul/backends/evm/EVMCodeTransform.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -396,20 +397,8 @@ void CodeTransform::operator()(Identifier const& _identifier) void CodeTransform::operator()(Literal const& _literal) { m_assembly.setSourceLocation(_literal.location); - if (_literal.kind == LiteralKind::Number) - 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))); - } + m_assembly.appendConstant(valueOfLiteral(_literal)); + checkStackHeight(&_literal); } diff --git a/test/tools/yulInterpreter/Interpreter.cpp b/test/tools/yulInterpreter/Interpreter.cpp index c092da446..0731d38a2 100644 --- a/test/tools/yulInterpreter/Interpreter.cpp +++ b/test/tools/yulInterpreter/Interpreter.cpp @@ -155,20 +155,7 @@ void ExpressionEvaluator::operator()(Literal const& _literal) static YulString const trueString("true"); static YulString const falseString("false"); - switch (_literal.kind) - { - 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; - } + setValue(valueOfLiteral(_literal)); } void ExpressionEvaluator::operator()(Identifier const& _identifier) From a52b50d77060cf47c91c3ea04efe889a3a05ce7d Mon Sep 17 00:00:00 2001 From: Mathias Baumann Date: Tue, 5 Mar 2019 18:39:16 +0100 Subject: [PATCH 2/3] libyul: Change assertThrow() to yulAssert() --- libyul/Utilities.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libyul/Utilities.cpp b/libyul/Utilities.cpp index 4f362e33a..2cf72f499 100644 --- a/libyul/Utilities.cpp +++ b/libyul/Utilities.cpp @@ -32,10 +32,10 @@ using namespace yul; 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(); - assertThrow(isValidDecimal(literalString) || isValidHex(literalString), OptimizerException, ""); + yulAssert(isValidDecimal(literalString) || isValidHex(literalString), "Invalid number literal!"); return u256(literalString); } From f6e09d63689e396dab4273a70d02bf36b00d554b Mon Sep 17 00:00:00 2001 From: Mathias Baumann Date: Tue, 5 Mar 2019 17:32:13 +0100 Subject: [PATCH 3/3] YulOpt: Extend StructuralSimplifier to work with all types --- libyul/optimiser/StructuralSimplifier.cpp | 4 ++-- .../switch_inline_no_match_mixed.yul | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 test/libyul/yulOptimizerTests/structuralSimplifier/switch_inline_no_match_mixed.yul diff --git a/libyul/optimiser/StructuralSimplifier.cpp b/libyul/optimiser/StructuralSimplifier.cpp index 34ee26a16..8010b7b22 100644 --- a/libyul/optimiser/StructuralSimplifier.cpp +++ b/libyul/optimiser/StructuralSimplifier.cpp @@ -59,7 +59,7 @@ boost::optional StructuralSimplifier::hasLiteralValue(Expression cons if (expr && expr->type() == typeid(Literal)) { Literal const& literal = boost::get(*expr); - return valueOfNumberLiteral(literal); + return valueOfLiteral(literal); } return boost::optional(); @@ -114,7 +114,7 @@ void StructuralSimplifier::simplify(std::vector& _statements) for (auto& _case: _switchStmt.cases) { - if (_case.value && valueOfNumberLiteral(*_case.value) == constExprVal) + if (_case.value && valueOfLiteral(*_case.value) == constExprVal) { matchingCaseBlock = &_case.body; break; diff --git a/test/libyul/yulOptimizerTests/structuralSimplifier/switch_inline_no_match_mixed.yul b/test/libyul/yulOptimizerTests/structuralSimplifier/switch_inline_no_match_mixed.yul new file mode 100644 index 000000000..8d90ca1f0 --- /dev/null +++ b/test/libyul/yulOptimizerTests/structuralSimplifier/switch_inline_no_match_mixed.yul @@ -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 +// }