From b1ccf73511f9ff9434b56f7686b467ec51ff887d Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 11 Sep 2020 11:03:22 +0200 Subject: [PATCH] Store current source location in Yul IR generation. --- .../codegen/ir/IRGeneratorForStatements.cpp | 60 ++++++++++++++++++- .../codegen/ir/IRGeneratorForStatements.h | 3 + 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 34b677c9c..9b9675562 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -154,6 +154,8 @@ string IRGeneratorForStatements::code() const void IRGeneratorForStatements::initializeStateVar(VariableDeclaration const& _varDecl) { + setLocation(_varDecl); + solAssert(_varDecl.immutable() || m_context.isStateVariable(_varDecl), "Must be immutable or a state variable."); solAssert(!_varDecl.isConstant(), ""); if (!_varDecl.value()) @@ -173,6 +175,8 @@ void IRGeneratorForStatements::initializeStateVar(VariableDeclaration const& _va void IRGeneratorForStatements::initializeLocalVar(VariableDeclaration const& _varDecl) { + setLocation(_varDecl); + solAssert(m_context.isLocalVariable(_varDecl), "Must be a local variable."); auto const* type = _varDecl.type(); @@ -186,6 +190,8 @@ void IRGeneratorForStatements::initializeLocalVar(VariableDeclaration const& _va IRVariable IRGeneratorForStatements::evaluateExpression(Expression const& _expression, Type const& _targetType) { + setLocation(_expression); + _expression.accept(*this); IRVariable variable{m_context.newYulVariable(), _targetType}; define(variable, _expression); @@ -194,6 +200,8 @@ IRVariable IRGeneratorForStatements::evaluateExpression(Expression const& _expre string IRGeneratorForStatements::constantValueFunction(VariableDeclaration const& _constant) { + setLocation(_constant); + string functionName = IRNames::constantValueFunction(_constant); return m_context.functionCollector().createFunction(functionName, [&] { Whiskers templ(R"( @@ -216,6 +224,8 @@ string IRGeneratorForStatements::constantValueFunction(VariableDeclaration const void IRGeneratorForStatements::endVisit(VariableDeclarationStatement const& _varDeclStatement) { + setLocation(_varDeclStatement); + if (Expression const* expression = _varDeclStatement.initialValue()) { if (_varDeclStatement.declarations().size() > 1) @@ -249,14 +259,22 @@ bool IRGeneratorForStatements::visit(Conditional const& _conditional) { _conditional.condition().accept(*this); + setLocation(_conditional); + string condition = expressionAsType(_conditional.condition(), *TypeProvider::boolean()); declare(_conditional); m_code << "switch " << condition << "\n" "case 0 {\n"; + _conditional.falseExpression().accept(*this); + setLocation(_conditional); + assign(_conditional, _conditional.falseExpression()); m_code << "}\n" "default {\n"; + _conditional.trueExpression().accept(*this); + setLocation(_conditional); + assign(_conditional, _conditional.trueExpression()); m_code << "}\n"; @@ -266,6 +284,7 @@ bool IRGeneratorForStatements::visit(Conditional const& _conditional) bool IRGeneratorForStatements::visit(Assignment const& _assignment) { _assignment.rightHandSide().accept(*this); + setLocation(_assignment); Token assignmentOperator = _assignment.assignmentOperator(); Token binaryOperator = @@ -283,6 +302,7 @@ bool IRGeneratorForStatements::visit(Assignment const& _assignment) IRVariable value = convert(_assignment.rightHandSide(), *rightIntermediateType); _assignment.leftHandSide().accept(*this); solAssert(!!m_currentLValue, "LValue not retrieved."); + setLocation(_assignment); if (assignmentOperator != Token::Assign) { @@ -323,6 +343,8 @@ bool IRGeneratorForStatements::visit(Assignment const& _assignment) bool IRGeneratorForStatements::visit(TupleExpression const& _tuple) { + setLocation(_tuple); + if (_tuple.isInlineArray()) { auto const& arrayType = dynamic_cast(*_tuple.annotation().type); @@ -339,6 +361,7 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tuple) { Expression const& component = *_tuple.components()[i]; component.accept(*this); + setLocation(_tuple); IRVariable converted = convert(component, baseType); m_code << m_utils.writeToMemoryFunction(baseType) << @@ -358,6 +381,7 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tuple) { solAssert(_tuple.components().front(), ""); _tuple.components().front()->accept(*this); + setLocation(_tuple); if (willBeWrittenTo) solAssert(!!m_currentLValue, ""); else @@ -370,6 +394,7 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tuple) if (auto const& component = _tuple.components()[i]) { component->accept(*this); + setLocation(_tuple); if (willBeWrittenTo) { solAssert(!!m_currentLValue, ""); @@ -395,17 +420,20 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tuple) bool IRGeneratorForStatements::visit(IfStatement const& _ifStatement) { _ifStatement.condition().accept(*this); + setLocation(_ifStatement); string condition = expressionAsType(_ifStatement.condition(), *TypeProvider::boolean()); if (_ifStatement.falseStatement()) { m_code << "switch " << condition << "\n" "case 0 {\n"; _ifStatement.falseStatement()->accept(*this); + setLocation(_ifStatement); m_code << "}\n" "default {\n"; } else m_code << "if " << condition << " {\n"; _ifStatement.trueStatement().accept(*this); + setLocation(_ifStatement); m_code << "}\n"; return false; @@ -413,6 +441,7 @@ bool IRGeneratorForStatements::visit(IfStatement const& _ifStatement) bool IRGeneratorForStatements::visit(ForStatement const& _forStatement) { + setLocation(_forStatement); generateLoop( _forStatement.body(), _forStatement.condition(), @@ -425,6 +454,7 @@ bool IRGeneratorForStatements::visit(ForStatement const& _forStatement) bool IRGeneratorForStatements::visit(WhileStatement const& _whileStatement) { + setLocation(_whileStatement); generateLoop( _whileStatement.body(), &_whileStatement.condition(), @@ -436,20 +466,23 @@ bool IRGeneratorForStatements::visit(WhileStatement const& _whileStatement) return false; } -bool IRGeneratorForStatements::visit(Continue const&) +bool IRGeneratorForStatements::visit(Continue const& _continue) { + setLocation(_continue); m_code << "continue\n"; return false; } -bool IRGeneratorForStatements::visit(Break const&) +bool IRGeneratorForStatements::visit(Break const& _break) { + setLocation(_break); m_code << "break\n"; return false; } void IRGeneratorForStatements::endVisit(Return const& _return) { + setLocation(_return); if (Expression const* value = _return.expression()) { solAssert(_return.annotation().functionReturnParameters, "Invalid return parameters pointer."); @@ -466,6 +499,7 @@ void IRGeneratorForStatements::endVisit(Return const& _return) void IRGeneratorForStatements::endVisit(UnaryOperation const& _unaryOperation) { + setLocation(_unaryOperation); Type const& resultType = type(_unaryOperation); Token const op = _unaryOperation.getOperator(); @@ -551,6 +585,8 @@ void IRGeneratorForStatements::endVisit(UnaryOperation const& _unaryOperation) bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp) { + setLocation(_binOp); + solAssert(!!_binOp.annotation().commonType, ""); TypePointer commonType = _binOp.annotation().commonType; langutil::Token op = _binOp.getOperator(); @@ -570,6 +606,7 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp) _binOp.leftExpression().accept(*this); _binOp.rightExpression().accept(*this); + setLocation(_binOp); if (TokenTraits::isCompareOp(op)) { @@ -629,6 +666,7 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp) bool IRGeneratorForStatements::visit(FunctionCall const& _functionCall) { + setLocation(_functionCall); FunctionTypePointer functionType = dynamic_cast(&type(_functionCall.expression())); if ( functionType && @@ -643,6 +681,7 @@ bool IRGeneratorForStatements::visit(FunctionCall const& _functionCall) void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) { + setLocation(_functionCall); auto functionCallKind = *_functionCall.annotation().kind; if (functionCallKind == FunctionCallKind::TypeConversion) @@ -1360,6 +1399,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) void IRGeneratorForStatements::endVisit(FunctionCallOptions const& _options) { + setLocation(_options); FunctionType const& previousType = dynamic_cast(*_options.expression().annotation().type); solUnimplementedAssert(!previousType.bound(), ""); @@ -1379,6 +1419,7 @@ void IRGeneratorForStatements::endVisit(FunctionCallOptions const& _options) void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) { + setLocation(_memberAccess); ASTString const& member = _memberAccess.memberName(); auto memberFunctionType = dynamic_cast(_memberAccess.annotation().type); Type::Category objectCategory = _memberAccess.expression().annotation().type->category(); @@ -1764,6 +1805,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm) { + setLocation(_inlineAsm); CopyTranslate bodyCopier{_inlineAsm.dialect(), m_context, _inlineAsm.annotation().externalReferences}; yul::Statement modified = bodyCopier(_inlineAsm.operations()); @@ -1778,6 +1820,7 @@ bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm) void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess) { + setLocation(_indexAccess); Type const& baseType = *_indexAccess.baseExpression().annotation().type; if (baseType.category() == Type::Category::Mapping) @@ -1913,6 +1956,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess) void IRGeneratorForStatements::endVisit(IndexRangeAccess const& _indexRangeAccess) { + setLocation(_indexRangeAccess); Type const& baseType = *_indexRangeAccess.baseExpression().annotation().type; solAssert( baseType.category() == Type::Category::Array || baseType.category() == Type::Category::ArraySlice, @@ -1959,6 +2003,7 @@ void IRGeneratorForStatements::endVisit(IndexRangeAccess const& _indexRangeAcces void IRGeneratorForStatements::endVisit(Identifier const& _identifier) { + setLocation(_identifier); Declaration const* declaration = _identifier.annotation().referencedDeclaration; if (MagicVariableDeclaration const* magicVar = dynamic_cast(declaration)) { @@ -2017,6 +2062,7 @@ void IRGeneratorForStatements::endVisit(Identifier const& _identifier) bool IRGeneratorForStatements::visit(Literal const& _literal) { + setLocation(_literal); Type const& literalType = type(_literal); switch (literalType.category()) @@ -2039,6 +2085,7 @@ void IRGeneratorForStatements::handleVariableReference( Expression const& _referencingExpression ) { + setLocation(_referencingExpression); if (_variable.isStateVariable() && _variable.isConstant()) define(_referencingExpression) << constantValueFunction(_variable) << "()\n"; else if (_variable.isStateVariable() && _variable.immutable()) @@ -2480,6 +2527,7 @@ void IRGeneratorForStatements::appendAndOrOperatorCode(BinaryOperation const& _b solAssert(op == Token::Or || op == Token::And, ""); _binOp.leftExpression().accept(*this); + setLocation(_binOp); IRVariable value(_binOp); define(value, _binOp.leftExpression()); @@ -2488,6 +2536,7 @@ void IRGeneratorForStatements::appendAndOrOperatorCode(BinaryOperation const& _b else m_code << "if " << value.name() << " {\n"; _binOp.rightExpression().accept(*this); + setLocation(_binOp); assign(value, _binOp.rightExpression()); m_code << "}\n"; } @@ -2687,6 +2736,7 @@ bool IRGeneratorForStatements::visit(TryStatement const& _tryStatement) { Expression const& externalCall = _tryStatement.externalCall(); externalCall.accept(*this); + setLocation(_tryStatement); m_code << "switch iszero(" << IRNames::trySuccessConditionVariable(externalCall) << ")\n"; @@ -2707,6 +2757,7 @@ bool IRGeneratorForStatements::visit(TryStatement const& _tryStatement) } successClause.block().accept(*this); + setLocation(_tryStatement); m_code << "}\n"; m_code << "default { // failure case\n"; @@ -2797,3 +2848,8 @@ bool IRGeneratorForStatements::visit(TryCatchClause const& _clause) _clause.block().accept(*this); return false; } + +void IRGeneratorForStatements::setLocation(ASTNode const& _node) +{ + m_currentLocation = _node.location(); +} diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.h b/libsolidity/codegen/ir/IRGeneratorForStatements.h index 09c9c7d27..e746e9ed0 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.h +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.h @@ -179,10 +179,13 @@ private: static Type const& type(Expression const& _expression); + void setLocation(ASTNode const& _node); + std::ostringstream m_code; IRGenerationContext& m_context; YulUtilFunctions& m_utils; std::optional m_currentLValue; + langutil::SourceLocation m_currentLocation; }; }