diff --git a/libyul/Utilities.cpp b/libyul/Utilities.cpp index e5f4e517c..2cf72f499 100644 --- a/libyul/Utilities.cpp +++ b/libyul/Utilities.cpp @@ -24,6 +24,7 @@ #include #include +#include using namespace std; using namespace dev; @@ -31,12 +32,48 @@ 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); } +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/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 +// } 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)