mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Store current source location in Yul IR generation.
This commit is contained in:
		
							parent
							
								
									5355e85639
								
							
						
					
					
						commit
						b1ccf73511
					
				| @ -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<ArrayType const&>(*_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<FunctionType const*>(&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<FunctionType const&>(*_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<FunctionType const*>(_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<MagicVariableDeclaration const*>(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(); | ||||
| } | ||||
|  | ||||
| @ -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<IRLValue> m_currentLValue; | ||||
| 	langutil::SourceLocation m_currentLocation; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user