Merge pull request #6670 from ethereum/refactorIRGen

[SolYul] Add type helper and move some items to post visit.
This commit is contained in:
chriseth 2019-05-06 14:14:23 +02:00 committed by GitHub
commit 442742e497
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 32 deletions

View File

@ -86,7 +86,7 @@ string IRGeneratorForStatements::code() const
return m_code.str(); return m_code.str();
} }
bool IRGeneratorForStatements::visit(VariableDeclarationStatement const& _varDeclStatement) void IRGeneratorForStatements::endVisit(VariableDeclarationStatement const& _varDeclStatement)
{ {
for (auto const& decl: _varDeclStatement.declarations()) for (auto const& decl: _varDeclStatement.declarations())
if (decl) if (decl)
@ -96,8 +96,6 @@ bool IRGeneratorForStatements::visit(VariableDeclarationStatement const& _varDec
{ {
solUnimplementedAssert(_varDeclStatement.declarations().size() == 1, ""); solUnimplementedAssert(_varDeclStatement.declarations().size() == 1, "");
expression->accept(*this);
VariableDeclaration const& varDecl = *_varDeclStatement.declarations().front(); VariableDeclaration const& varDecl = *_varDeclStatement.declarations().front();
m_code << m_code <<
"let " << "let " <<
@ -110,8 +108,6 @@ bool IRGeneratorForStatements::visit(VariableDeclarationStatement const& _varDec
for (auto const& decl: _varDeclStatement.declarations()) for (auto const& decl: _varDeclStatement.declarations())
if (decl) if (decl)
m_code << "let " << m_context.localVariableName(*decl) << "\n"; m_code << "let " << m_context.localVariableName(*decl) << "\n";
return false;
} }
bool IRGeneratorForStatements::visit(Assignment const& _assignment) bool IRGeneratorForStatements::visit(Assignment const& _assignment)
@ -120,7 +116,7 @@ bool IRGeneratorForStatements::visit(Assignment const& _assignment)
_assignment.rightHandSide().accept(*this); _assignment.rightHandSide().accept(*this);
Type const* intermediateType = _assignment.rightHandSide().annotation().type->closestTemporaryType( Type const* intermediateType = _assignment.rightHandSide().annotation().type->closestTemporaryType(
_assignment.leftHandSide().annotation().type &type(_assignment.leftHandSide())
); );
string intermediateValue = m_context.newYulVariable(); string intermediateValue = m_context.newYulVariable();
m_code << "let " << intermediateValue << " := " << expressionAsType(_assignment.rightHandSide(), *intermediateType) << "\n"; m_code << "let " << intermediateValue << " := " << expressionAsType(_assignment.rightHandSide(), *intermediateType) << "\n";
@ -171,7 +167,7 @@ bool IRGeneratorForStatements::visit(Break const&)
return false; return false;
} }
bool IRGeneratorForStatements::visit(Return const& _return) void IRGeneratorForStatements::endVisit(Return const& _return)
{ {
if (Expression const* value = _return.expression()) if (Expression const* value = _return.expression())
{ {
@ -182,8 +178,6 @@ bool IRGeneratorForStatements::visit(Return const& _return)
for (auto const& retVariable: returnParameters) for (auto const& retVariable: returnParameters)
types.push_back(retVariable->annotation().type); types.push_back(retVariable->annotation().type);
value->accept(*this);
// TODO support tuples // TODO support tuples
solUnimplementedAssert(types.size() == 1, "Multi-returns not implemented."); solUnimplementedAssert(types.size() == 1, "Multi-returns not implemented.");
m_code << m_code <<
@ -193,7 +187,6 @@ bool IRGeneratorForStatements::visit(Return const& _return)
"\n"; "\n";
} }
m_code << "return_flag := 0\n" << "break\n"; m_code << "return_flag := 0\n" << "break\n";
return false;
} }
void IRGeneratorForStatements::endVisit(BinaryOperation const& _binOp) void IRGeneratorForStatements::endVisit(BinaryOperation const& _binOp)
@ -227,7 +220,7 @@ void IRGeneratorForStatements::endVisit(BinaryOperation const& _binOp)
} }
} }
bool IRGeneratorForStatements::visit(FunctionCall const& _functionCall) void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
{ {
solUnimplementedAssert( solUnimplementedAssert(
_functionCall.annotation().kind == FunctionCallKind::FunctionCall || _functionCall.annotation().kind == FunctionCallKind::FunctionCall ||
@ -235,22 +228,21 @@ bool IRGeneratorForStatements::visit(FunctionCall const& _functionCall)
"This type of function call is not yet implemented" "This type of function call is not yet implemented"
); );
TypePointer const funcType = _functionCall.expression().annotation().type; Type const& funcType = type(_functionCall.expression());
if (_functionCall.annotation().kind == FunctionCallKind::TypeConversion) if (_functionCall.annotation().kind == FunctionCallKind::TypeConversion)
{ {
solAssert(funcType->category() == Type::Category::TypeType, "Expected category to be TypeType"); solAssert(funcType.category() == Type::Category::TypeType, "Expected category to be TypeType");
solAssert(_functionCall.arguments().size() == 1, "Expected one argument for type conversion"); solAssert(_functionCall.arguments().size() == 1, "Expected one argument for type conversion");
_functionCall.arguments().front()->accept(*this);
defineExpression(_functionCall) << defineExpression(_functionCall) <<
expressionAsType(*_functionCall.arguments().front(), *_functionCall.annotation().type) << expressionAsType(*_functionCall.arguments().front(), type(_functionCall)) <<
"\n"; "\n";
return false; return;
} }
FunctionTypePointer functionType = dynamic_cast<FunctionType const*>(funcType); FunctionTypePointer functionType = dynamic_cast<FunctionType const*>(&funcType);
TypePointers parameterTypes = functionType->parameterTypes(); TypePointers parameterTypes = functionType->parameterTypes();
vector<ASTPointer<Expression const>> const& callArguments = _functionCall.arguments(); vector<ASTPointer<Expression const>> const& callArguments = _functionCall.arguments();
@ -281,14 +273,10 @@ bool IRGeneratorForStatements::visit(FunctionCall const& _functionCall)
{ {
vector<string> args; vector<string> args;
for (unsigned i = 0; i < arguments.size(); ++i) for (unsigned i = 0; i < arguments.size(); ++i)
{
arguments[i]->accept(*this);
if (functionType->takesArbitraryParameters()) if (functionType->takesArbitraryParameters())
args.emplace_back(m_context.variable(*arguments[i])); args.emplace_back(m_context.variable(*arguments[i]));
else else
args.emplace_back(expressionAsType(*arguments[i], *parameterTypes[i])); args.emplace_back(expressionAsType(*arguments[i], *parameterTypes[i]));
}
if (auto identifier = dynamic_cast<Identifier const*>(&_functionCall.expression())) if (auto identifier = dynamic_cast<Identifier const*>(&_functionCall.expression()))
{ {
@ -301,12 +289,10 @@ bool IRGeneratorForStatements::visit(FunctionCall const& _functionCall)
"(" << "(" <<
joinHumanReadable(args) << joinHumanReadable(args) <<
")\n"; ")\n";
return false; return;
} }
} }
_functionCall.expression().accept(*this);
// @TODO The function can very well return multiple vars. // @TODO The function can very well return multiple vars.
args = vector<string>{m_context.variable(_functionCall.expression())} + args; args = vector<string>{m_context.variable(_functionCall.expression())} + args;
defineExpression(_functionCall) << defineExpression(_functionCall) <<
@ -319,7 +305,6 @@ bool IRGeneratorForStatements::visit(FunctionCall const& _functionCall)
default: default:
solUnimplemented(""); solUnimplemented("");
} }
return false;
} }
bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm) bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm)
@ -362,14 +347,14 @@ bool IRGeneratorForStatements::visit(Identifier const& _identifier)
bool IRGeneratorForStatements::visit(Literal const& _literal) bool IRGeneratorForStatements::visit(Literal const& _literal)
{ {
TypePointer type = _literal.annotation().type; Type const& literalType = type(_literal);
switch (type->category()) switch (literalType.category())
{ {
case Type::Category::RationalNumber: case Type::Category::RationalNumber:
case Type::Category::Bool: case Type::Category::Bool:
case Type::Category::Address: case Type::Category::Address:
defineExpression(_literal) << toCompactHexWithPrefix(type->literalValue(&_literal)) << "\n"; defineExpression(_literal) << toCompactHexWithPrefix(literalType.literalValue(&_literal)) << "\n";
break; break;
case Type::Category::StringLiteral: case Type::Category::StringLiteral:
solUnimplemented(""); solUnimplemented("");
@ -382,7 +367,7 @@ bool IRGeneratorForStatements::visit(Literal const& _literal)
string IRGeneratorForStatements::expressionAsType(Expression const& _expression, Type const& _to) string IRGeneratorForStatements::expressionAsType(Expression const& _expression, Type const& _to)
{ {
Type const& from = *_expression.annotation().type; Type const& from = type(_expression);
string varName = m_context.variable(_expression); string varName = m_context.variable(_expression);
if (from == _to) if (from == _to)
@ -406,3 +391,9 @@ void IRGeneratorForStatements::setLValue(Expression const& _expression, unique_p
else else
defineExpression(_expression) << _lvalue->retrieveValue() << "\n"; defineExpression(_expression) << _lvalue->retrieveValue() << "\n";
} }
Type const& IRGeneratorForStatements::type(Expression const& _expression)
{
solAssert(_expression.annotation().type, "Type of expression not set.");
return *_expression.annotation().type;
}

View File

@ -45,14 +45,14 @@ public:
std::string code() const; std::string code() const;
bool visit(VariableDeclarationStatement const& _variableDeclaration) override; void endVisit(VariableDeclarationStatement const& _variableDeclaration) override;
bool visit(Assignment const& _assignment) override; bool visit(Assignment const& _assignment) override;
bool visit(ForStatement const& _forStatement) override; bool visit(ForStatement const& _forStatement) override;
bool visit(Continue const& _continueStatement) override; bool visit(Continue const& _continueStatement) override;
bool visit(Break const& _breakStatement) override; bool visit(Break const& _breakStatement) override;
bool visit(Return const& _return) override; void endVisit(Return const& _return) override;
void endVisit(BinaryOperation const& _binOp) override; void endVisit(BinaryOperation const& _binOp) override;
bool visit(FunctionCall const& _funCall) override; void endVisit(FunctionCall const& _funCall) override;
bool visit(InlineAssembly const& _inlineAsm) override; bool visit(InlineAssembly const& _inlineAsm) override;
bool visit(Identifier const& _identifier) override; bool visit(Identifier const& _identifier) override;
bool visit(Literal const& _literal) override; bool visit(Literal const& _literal) override;
@ -65,6 +65,8 @@ private:
void setLValue(Expression const& _expression, std::unique_ptr<IRLValue> _lvalue); void setLValue(Expression const& _expression, std::unique_ptr<IRLValue> _lvalue);
static Type const& type(Expression const& _expression);
std::ostringstream m_code; std::ostringstream m_code;
IRGenerationContext& m_context; IRGenerationContext& m_context;
YulUtilFunctions& m_utils; YulUtilFunctions& m_utils;