mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #10016 from ethereum/stackToMemoryMoverRefactor
Refactor stack to memory mover in preparation of moving function arguments.
This commit is contained in:
		
						commit
						9eed68f776
					
				| @ -49,6 +49,23 @@ vector<Statement> generateMemoryStore( | ||||
| 	}}); | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| FunctionCall generateMemoryLoad(Dialect const& _dialect, langutil::SourceLocation const& _loc, YulString _mpos) | ||||
| { | ||||
| 	BuiltinFunction const* memoryLoadFunction = _dialect.memoryLoadFunction(_dialect.defaultType); | ||||
| 	yulAssert(memoryLoadFunction, ""); | ||||
| 	return FunctionCall{ | ||||
| 		_loc, | ||||
| 		Identifier{_loc, memoryLoadFunction->name}, { | ||||
| 			Literal{ | ||||
| 				_loc, | ||||
| 				LiteralKind::Number, | ||||
| 				_mpos, | ||||
| 				{} | ||||
| 			} | ||||
| 		} | ||||
| 	}; | ||||
| } | ||||
| } | ||||
| 
 | ||||
| void StackToMemoryMover::run( | ||||
| @ -93,29 +110,34 @@ void StackToMemoryMover::operator()(FunctionDefinition& _functionDefinition) | ||||
| void StackToMemoryMover::operator()(Block& _block) | ||||
| { | ||||
| 	using OptionalStatements = std::optional<vector<Statement>>; | ||||
| 	auto containsVariableNeedingEscalation = [&](auto const& _variables) { | ||||
| 		return util::contains_if(_variables, [&](auto const& var) { | ||||
| 	auto rewriteAssignmentOrVariableDeclaration = [&]( | ||||
| 		auto& _stmt, | ||||
| 		auto const& _variables | ||||
| 	) -> OptionalStatements { | ||||
| 		using StatementType = decay_t<decltype(_stmt)>; | ||||
| 		if (_stmt.value) | ||||
| 			visit(*_stmt.value); | ||||
| 		bool leftHandSideNeedsMoving = util::contains_if(_variables, [&](auto const& var) { | ||||
| 			return m_memoryOffsetTracker(var.name); | ||||
| 		}); | ||||
| 	}; | ||||
| 	auto rewriteAssignmentOrVariableDeclaration = [&]( | ||||
| 		langutil::SourceLocation const& _loc, | ||||
| 		auto const& _variables, | ||||
| 		std::unique_ptr<Expression> _value | ||||
| 	) -> std::vector<Statement> { | ||||
| 		if (!leftHandSideNeedsMoving) | ||||
| 			return {}; | ||||
| 
 | ||||
| 		langutil::SourceLocation loc = _stmt.location; | ||||
| 
 | ||||
| 		if (_variables.size() == 1) | ||||
| 		{ | ||||
| 			optional<YulString> offset = m_memoryOffsetTracker(_variables.front().name); | ||||
| 			yulAssert(offset, ""); | ||||
| 			return generateMemoryStore( | ||||
| 				m_context.dialect, | ||||
| 				_loc, | ||||
| 				loc, | ||||
| 				*offset, | ||||
| 				_value ? *std::move(_value) : Literal{_loc, LiteralKind::Number, "0"_yulstring, {}} | ||||
| 				_stmt.value ? *std::move(_stmt.value) : Literal{loc, LiteralKind::Number, "0"_yulstring, {}} | ||||
| 			); | ||||
| 		} | ||||
| 
 | ||||
| 		VariableDeclaration tempDecl{_loc, {}, std::move(_value)}; | ||||
| 		VariableDeclaration tempDecl{loc, {}, std::move(_stmt.value)}; | ||||
| 		vector<Statement> memoryAssignments; | ||||
| 		vector<Statement> variableAssignments; | ||||
| 		for (auto& var: _variables) | ||||
| @ -126,19 +148,14 @@ void StackToMemoryMover::operator()(Block& _block) | ||||
| 			if (optional<YulString> offset = m_memoryOffsetTracker(var.name)) | ||||
| 				memoryAssignments += generateMemoryStore( | ||||
| 					m_context.dialect, | ||||
| 					_loc, | ||||
| 					loc, | ||||
| 					*offset, | ||||
| 					Identifier{_loc, tempVarName} | ||||
| 					Identifier{loc, tempVarName} | ||||
| 				); | ||||
| 			else if constexpr (std::is_same_v<std::decay_t<decltype(var)>, Identifier>) | ||||
| 				variableAssignments.emplace_back(Assignment{ | ||||
| 					_loc, { Identifier{var.location, var.name} }, | ||||
| 					make_unique<Expression>(Identifier{_loc, tempVarName}) | ||||
| 				}); | ||||
| 			else | ||||
| 				variableAssignments.emplace_back(VariableDeclaration{ | ||||
| 					_loc, {std::move(var)}, | ||||
| 					make_unique<Expression>(Identifier{_loc, tempVarName}) | ||||
| 				variableAssignments.emplace_back(StatementType{ | ||||
| 					loc, {move(var)}, | ||||
| 					make_unique<Expression>(Identifier{loc, tempVarName}) | ||||
| 				}); | ||||
| 		} | ||||
| 		std::vector<Statement> result; | ||||
| @ -147,65 +164,34 @@ void StackToMemoryMover::operator()(Block& _block) | ||||
| 		result += std::move(memoryAssignments); | ||||
| 		std::reverse(variableAssignments.begin(), variableAssignments.end()); | ||||
| 		result += std::move(variableAssignments); | ||||
| 		return result; | ||||
| 		return OptionalStatements{move(result)}; | ||||
| 	}; | ||||
| 
 | ||||
| 	util::iterateReplacing( | ||||
| 		_block.statements, | ||||
| 		[&](Statement& _statement) | ||||
| 		{ | ||||
| 			auto defaultVisit = [&]() { ASTModifier::visit(_statement); return OptionalStatements{}; }; | ||||
| 			return std::visit(util::GenericVisitor{ | ||||
| 				[&](Assignment& _assignment) -> OptionalStatements | ||||
| 				{ | ||||
| 					if (!containsVariableNeedingEscalation(_assignment.variableNames)) | ||||
| 						return defaultVisit(); | ||||
| 					visit(*_assignment.value); | ||||
| 					return {rewriteAssignmentOrVariableDeclaration( | ||||
| 						_assignment.location, | ||||
| 						_assignment.variableNames, | ||||
| 						std::move(_assignment.value) | ||||
| 					)}; | ||||
| 					return rewriteAssignmentOrVariableDeclaration(_assignment, _assignment.variableNames); | ||||
| 				}, | ||||
| 				[&](VariableDeclaration& _varDecl) -> OptionalStatements | ||||
| 				{ | ||||
| 					if (!containsVariableNeedingEscalation(_varDecl.variables)) | ||||
| 						return defaultVisit(); | ||||
| 					if (_varDecl.value) | ||||
| 						visit(*_varDecl.value); | ||||
| 					return {rewriteAssignmentOrVariableDeclaration( | ||||
| 						_varDecl.location, | ||||
| 						_varDecl.variables, | ||||
| 						std::move(_varDecl.value) | ||||
| 					)}; | ||||
| 					return rewriteAssignmentOrVariableDeclaration(_varDecl, _varDecl.variables); | ||||
| 				}, | ||||
| 				[&](auto&) { return defaultVisit(); } | ||||
| 				[&](auto& _stmt) -> OptionalStatements { (*this)(_stmt); return {}; } | ||||
| 			}, _statement); | ||||
| 		}); | ||||
| 		} | ||||
| 	); | ||||
| } | ||||
| 
 | ||||
| void StackToMemoryMover::visit(Expression& _expression) | ||||
| { | ||||
| 	ASTModifier::visit(_expression); | ||||
| 	if (Identifier* identifier = std::get_if<Identifier>(&_expression)) | ||||
| 		if (optional<YulString> offset = m_memoryOffsetTracker(identifier->name)) | ||||
| 		{ | ||||
| 			BuiltinFunction const* memoryLoadFunction = m_context.dialect.memoryLoadFunction(m_context.dialect.defaultType); | ||||
| 			yulAssert(memoryLoadFunction, ""); | ||||
| 			langutil::SourceLocation loc = identifier->location; | ||||
| 			_expression = FunctionCall{ | ||||
| 				loc, | ||||
| 				Identifier{loc, memoryLoadFunction->name}, { | ||||
| 					Literal{ | ||||
| 						loc, | ||||
| 						LiteralKind::Number, | ||||
| 						*offset, | ||||
| 						{} | ||||
| 					} | ||||
| 				} | ||||
| 			}; | ||||
| 			return; | ||||
| 		} | ||||
| 	ASTModifier::visit(_expression); | ||||
| 			_expression = generateMemoryLoad(m_context.dialect, identifier->location, *offset); | ||||
| } | ||||
| 
 | ||||
| optional<YulString> StackToMemoryMover::VariableMemoryOffsetTracker::operator()(YulString _variable) const | ||||
|  | ||||
| @ -126,7 +126,7 @@ void OptimiserSuite::run( | ||||
| 	{ | ||||
| 		yulAssert(_meter, ""); | ||||
| 		ConstantOptimiser{*dialect, *_meter}(ast); | ||||
| 		if (dialect->providesObjectAccess()) | ||||
| 		if (dialect->providesObjectAccess() && _optimizeStackAllocation) | ||||
| 			StackLimitEvader::run(suite.m_context, _object, CompilabilityChecker{ | ||||
| 				_dialect, | ||||
| 				_object, | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user