From 944ac6fb6d7a1400a24db4c436119544a93e4e76 Mon Sep 17 00:00:00 2001 From: Mathias Baumann Date: Mon, 15 Apr 2019 18:10:36 +0200 Subject: [PATCH] Sol -> Yul Generation: Implicit conversions --- .../codegen/ir/IRGeneratorForStatements.cpp | 44 ++++++++++++------- .../codegen/ir/IRGeneratorForStatements.h | 4 ++ .../viaYul/implicit_cast_assignment.sol | 14 ++++++ .../viaYul/implicit_cast_function_call.sol | 17 +++++++ .../viaYul/implicit_cast_local_assignment.sol | 13 ++++++ 5 files changed, 76 insertions(+), 16 deletions(-) create mode 100644 test/libsolidity/semanticTests/viaYul/implicit_cast_assignment.sol create mode 100644 test/libsolidity/semanticTests/viaYul/implicit_cast_function_call.sol create mode 100644 test/libsolidity/semanticTests/viaYul/implicit_cast_local_assignment.sol diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 1c2563771..b95430eb7 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -90,15 +90,12 @@ bool IRGeneratorForStatements::visit(VariableDeclarationStatement const& _varDec expression->accept(*this); - solUnimplementedAssert( - *expression->annotation().type == *_varDeclStatement.declarations().front()->type(), - "Type conversion not yet implemented" - ); + VariableDeclaration const& varDecl = *_varDeclStatement.declarations().front(); m_code << "let " << - m_context.variableName(*_varDeclStatement.declarations().front()) << + m_context.variableName(varDecl) << " := " << - m_context.variable(*expression) << + expressionAsType(*expression, *varDecl.type()) << "\n"; } else @@ -115,15 +112,17 @@ bool IRGeneratorForStatements::visit(Assignment const& _assignment) _assignment.rightHandSide().accept(*this); -// solUnimplementedAssert( -// *_assignment.rightHandSide().annotation().type == *_assignment.leftHandSide().annotation().type, -// "Type conversion not yet implemented" -// ); // TODO proper lvalue handling - auto const& identifier = dynamic_cast(_assignment.leftHandSide()); - string varName = m_context.variableName(dynamic_cast(*identifier.annotation().referencedDeclaration)); - m_code << varName << " := " << m_context.variable(_assignment.rightHandSide()) << "\n"; + auto const& lvalue = dynamic_cast(_assignment.leftHandSide()); + string varName = m_context.variableName(dynamic_cast(*lvalue.annotation().referencedDeclaration)); + + m_code << + varName << + " := " << + expressionAsType(_assignment.rightHandSide(), *lvalue.annotation().type) << + "\n"; m_code << "let " << m_context.variable(_assignment) << " := " << varName << "\n"; + return false; } @@ -185,9 +184,11 @@ bool IRGeneratorForStatements::visit(FunctionCall const& _functionCall) for (unsigned i = 0; i < arguments.size(); ++i) { arguments[i]->accept(*this); - // TODO convert - //utils().convertType(*arguments[i]->annotation().type, *function.parameterTypes()[i]); - args.emplace_back(m_context.variable(*arguments[i])); + + if (functionType->takesArbitraryParameters()) + args.emplace_back(m_context.variable(*arguments[i])); + else + args.emplace_back(expressionAsType(*arguments[i], *parameterTypes[i])); } if (auto identifier = dynamic_cast(&_functionCall.expression())) @@ -273,3 +274,14 @@ bool IRGeneratorForStatements::visit(Literal const& _literal) } return false; } + +string IRGeneratorForStatements::expressionAsType(Expression const& _expression, Type const& _to) +{ + Type const& from = *_expression.annotation().type; + string varName = m_context.variable(_expression); + + if (from == _to) + return varName; + else + return m_utils.conversionFunction(from, _to) + "(" + std::move(varName) + ")"; +} diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.h b/libsolidity/codegen/ir/IRGeneratorForStatements.h index c90f2f0bf..75caa4f85 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.h +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.h @@ -53,6 +53,10 @@ public: bool visit(Literal const& _literal) override; private: + /// @returns a Yul expression representing the current value of @a _expression, + /// converted to type @a _to if it does not yet have that type. + std::string expressionAsType(Expression const& _expression, Type const& _to); + std::ostringstream m_code; IRGenerationContext& m_context; YulUtilFunctions& m_utils; diff --git a/test/libsolidity/semanticTests/viaYul/implicit_cast_assignment.sol b/test/libsolidity/semanticTests/viaYul/implicit_cast_assignment.sol new file mode 100644 index 000000000..d6bba1bf5 --- /dev/null +++ b/test/libsolidity/semanticTests/viaYul/implicit_cast_assignment.sol @@ -0,0 +1,14 @@ +// Tests IRGeneratorForStatements::visit(Assignment const& _assignment) +contract C { + function f() public pure returns (uint16 x) { + uint8 y; + assembly { + y := 0x12345678 + } + x = y; + } +} +// ==== +// compileViaYul: true +// ---- +// f() -> 0x78 diff --git a/test/libsolidity/semanticTests/viaYul/implicit_cast_function_call.sol b/test/libsolidity/semanticTests/viaYul/implicit_cast_function_call.sol new file mode 100644 index 000000000..47a9b1cea --- /dev/null +++ b/test/libsolidity/semanticTests/viaYul/implicit_cast_function_call.sol @@ -0,0 +1,17 @@ +// IRGeneratorForStatements::visit(FunctionCall const& _functionCall) +contract C { + function f(uint b) public pure returns (uint x) { + x = b; + } + function g() public pure returns (uint x) { + uint8 a; + assembly { + a := 0x12345678 + } + x = f(a); + } +} +// ==== +// compileViaYul: true +// ---- +// g() -> 0x78 diff --git a/test/libsolidity/semanticTests/viaYul/implicit_cast_local_assignment.sol b/test/libsolidity/semanticTests/viaYul/implicit_cast_local_assignment.sol new file mode 100644 index 000000000..c99b50969 --- /dev/null +++ b/test/libsolidity/semanticTests/viaYul/implicit_cast_local_assignment.sol @@ -0,0 +1,13 @@ +// IRGeneratorForStatements::visit(VariableDeclarationStatement const& _varDeclStatement) +contract C { + function f() public pure returns (uint y) { + uint8 a; + assembly { a := 0x12345678 } + uint z = a; + y = z; + } +} +// ==== +// compileViaYul: true +// ---- +// f() -> 0x78