mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #7671 from ethereum/yul-ast-cleanup-FunctionalInstruction
Yul AST cleanup FunctionalInstruction
This commit is contained in:
		
						commit
						157fb44b44
					
				| @ -47,12 +47,6 @@ public: | ||||
| 	} | ||||
| 	void operator()(yul::Literal const&) {} | ||||
| 	void operator()(yul::Identifier const&) {} | ||||
| 	void operator()(yul::FunctionalInstruction const& _instr) | ||||
| 	{ | ||||
| 		checkInstruction(_instr.location, _instr.instruction); | ||||
| 		for (auto const& arg: _instr.arguments) | ||||
| 			boost::apply_visitor(*this, arg); | ||||
| 	} | ||||
| 	void operator()(yul::ExpressionStatement const& _expr) | ||||
| 	{ | ||||
| 		boost::apply_visitor(*this, _expr.expression); | ||||
|  | ||||
| @ -179,22 +179,6 @@ bool AsmAnalyzer::operator()(Identifier const& _identifier) | ||||
| 	return success; | ||||
| } | ||||
| 
 | ||||
| bool AsmAnalyzer::operator()(FunctionalInstruction const& _instr) | ||||
| { | ||||
| 	solAssert(m_dialect.flavour != AsmFlavour::Yul, ""); | ||||
| 	bool success = true; | ||||
| 	for (auto const& arg: _instr.arguments | boost::adaptors::reversed) | ||||
| 		if (!expectExpression(arg)) | ||||
| 			success = false; | ||||
| 	// Parser already checks that the number of arguments is correct.
 | ||||
| 	auto const& info = instructionInfo(_instr.instruction); | ||||
| 	solAssert(info.args == int(_instr.arguments.size()), ""); | ||||
| 	m_stackHeight += info.ret - info.args; | ||||
| 	m_info.stackHeightInfo[&_instr] = m_stackHeight; | ||||
| 	warnOnInstructions(_instr.instruction, _instr.location); | ||||
| 	return success; | ||||
| } | ||||
| 
 | ||||
| bool AsmAnalyzer::operator()(ExpressionStatement const& _statement) | ||||
| { | ||||
| 	int initialStackHeight = m_stackHeight; | ||||
|  | ||||
| @ -82,7 +82,6 @@ public: | ||||
| 	bool operator()(Instruction const&); | ||||
| 	bool operator()(Literal const& _literal); | ||||
| 	bool operator()(Identifier const&); | ||||
| 	bool operator()(FunctionalInstruction const& _functionalInstruction); | ||||
| 	bool operator()(ExpressionStatement const&); | ||||
| 	bool operator()(Assignment const& _assignment); | ||||
| 	bool operator()(VariableDeclaration const& _variableDeclaration); | ||||
|  | ||||
| @ -56,8 +56,6 @@ struct Identifier { langutil::SourceLocation location; YulString name; }; | ||||
| /// a single stack slot and expects a single expression on the right hand returning
 | ||||
| /// the same amount of items as the number of variables.
 | ||||
| struct Assignment { langutil::SourceLocation location; std::vector<Identifier> variableNames; std::unique_ptr<Expression> value; }; | ||||
| /// Functional instruction, e.g. "mul(mload(20:u256), add(2:u256, x))"
 | ||||
| struct FunctionalInstruction { langutil::SourceLocation location; dev::eth::Instruction instruction; std::vector<Expression> arguments; }; | ||||
| struct FunctionCall { langutil::SourceLocation location; Identifier functionName; std::vector<Expression> arguments; }; | ||||
| /// Statement that contains only a single expression
 | ||||
| struct ExpressionStatement { langutil::SourceLocation location; Expression expression; }; | ||||
|  | ||||
| @ -32,7 +32,6 @@ struct Label; | ||||
| struct Identifier; | ||||
| struct Assignment; | ||||
| struct VariableDeclaration; | ||||
| struct FunctionalInstruction; | ||||
| struct FunctionDefinition; | ||||
| struct FunctionCall; | ||||
| struct If; | ||||
| @ -47,7 +46,7 @@ struct Block; | ||||
| 
 | ||||
| struct TypedName; | ||||
| 
 | ||||
| using Expression = boost::variant<FunctionalInstruction, FunctionCall, Identifier, Literal>; | ||||
| using Expression = boost::variant<FunctionCall, Identifier, Literal>; | ||||
| using Statement = boost::variant<ExpressionStatement, Assignment, VariableDeclaration, FunctionDefinition, If, Switch, ForLoop, Break, Continue, Leave, Block>; | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -462,70 +462,22 @@ FunctionDefinition Parser::parseFunctionDefinition() | ||||
| Expression Parser::parseCall(Parser::ElementaryOperation&& _initialOp) | ||||
| { | ||||
| 	RecursionGuard recursionGuard(*this); | ||||
| 	if (_initialOp.type() == typeid(Instruction)) | ||||
| 	{ | ||||
| 		solAssert(m_dialect.flavour != AsmFlavour::Yul, "Instructions are invalid in Yul"); | ||||
| 		Instruction& instruction = boost::get<Instruction>(_initialOp); | ||||
| 		FunctionalInstruction ret; | ||||
| 		ret.instruction = instruction.instruction; | ||||
| 		ret.location = std::move(instruction.location); | ||||
| 		dev::eth::Instruction instr = ret.instruction; | ||||
| 		dev::eth::InstructionInfo instrInfo = instructionInfo(instr); | ||||
| 		if (dev::eth::isDupInstruction(instr)) | ||||
| 			fatalParserError("DUPi instructions not allowed for functional notation"); | ||||
| 		if (dev::eth::isSwapInstruction(instr)) | ||||
| 			fatalParserError("SWAPi instructions not allowed for functional notation"); | ||||
| 		expectToken(Token::LParen); | ||||
| 		unsigned args = unsigned(instrInfo.args); | ||||
| 		for (unsigned i = 0; i < args; ++i) | ||||
| 		{ | ||||
| 			/// check for premature closing parentheses
 | ||||
| 			if (currentToken() == Token::RParen) | ||||
| 				fatalParserError(string( | ||||
| 					"Expected expression (instruction \"" + | ||||
| 					instructionNames().at(instr) + | ||||
| 					"\" expects " + | ||||
| 					to_string(args) + | ||||
| 					" arguments)" | ||||
| 				)); | ||||
| 
 | ||||
| 			ret.arguments.emplace_back(parseExpression()); | ||||
| 			if (i != args - 1) | ||||
| 			{ | ||||
| 				if (currentToken() != Token::Comma) | ||||
| 					fatalParserError(string( | ||||
| 						"Expected ',' (instruction \"" + | ||||
| 						instructionNames().at(instr) + | ||||
| 						"\" expects " + | ||||
| 						to_string(args) + | ||||
| 						" arguments)" | ||||
| 					)); | ||||
| 				else | ||||
| 					advance(); | ||||
| 			} | ||||
| 		} | ||||
| 		ret.location.end = endPosition(); | ||||
| 		if (currentToken() == Token::Comma) | ||||
| 			fatalParserError(string( | ||||
| 				"Expected ')' (instruction \"" + | ||||
| 				instructionNames().at(instr) + | ||||
| 				"\" expects " + | ||||
| 				to_string(args) + | ||||
| 				" arguments)" | ||||
| 			)); | ||||
| 		expectToken(Token::RParen); | ||||
| 		return ret; | ||||
| 	} | ||||
| 	else if (_initialOp.type() == typeid(Identifier) || _initialOp.type() == typeid(FunctionCall)) | ||||
| 	{ | ||||
| 	FunctionCall ret; | ||||
| 	if (_initialOp.type() == typeid(Identifier)) | ||||
| 	{ | ||||
| 		ret.functionName = std::move(boost::get<Identifier>(_initialOp)); | ||||
| 		ret.location = ret.functionName.location; | ||||
| 	} | ||||
| 		else | ||||
| 	else if (_initialOp.type() == typeid(FunctionCall)) | ||||
| 		ret = std::move(boost::get<FunctionCall>(_initialOp)); | ||||
| 	else | ||||
| 		fatalParserError( | ||||
| 			m_dialect.flavour == AsmFlavour::Yul ? | ||||
| 			"Function name expected." : | ||||
| 			"Assembly instruction or function name required in front of \"(\")" | ||||
| 		); | ||||
| 
 | ||||
| 	expectToken(Token::LParen); | ||||
| 	if (currentToken() != Token::RParen) | ||||
| 	{ | ||||
| @ -540,15 +492,6 @@ Expression Parser::parseCall(Parser::ElementaryOperation&& _initialOp) | ||||
| 	expectToken(Token::RParen); | ||||
| 	return ret; | ||||
| } | ||||
| 	else | ||||
| 		fatalParserError( | ||||
| 			m_dialect.flavour == AsmFlavour::Yul ? | ||||
| 			"Function name expected." : | ||||
| 			"Assembly instruction or function name required in front of \"(\")" | ||||
| 		); | ||||
| 
 | ||||
| 	return {}; | ||||
| } | ||||
| 
 | ||||
| TypedName Parser::parseTypedName() | ||||
| { | ||||
|  | ||||
| @ -88,19 +88,6 @@ string AsmPrinter::operator()(Identifier const& _identifier) const | ||||
| 	return _identifier.name.str(); | ||||
| } | ||||
| 
 | ||||
| string AsmPrinter::operator()(FunctionalInstruction const& _functionalInstruction) const | ||||
| { | ||||
| 	solAssert(!m_yul, ""); | ||||
| 	solAssert(isValidInstruction(_functionalInstruction.instruction), "Invalid instruction"); | ||||
| 	return | ||||
| 		boost::to_lower_copy(instructionInfo(_functionalInstruction.instruction).name) + | ||||
| 		"(" + | ||||
| 		boost::algorithm::join( | ||||
| 			_functionalInstruction.arguments | boost::adaptors::transformed(boost::apply_visitor(*this)), | ||||
| 			", ") + | ||||
| 		")"; | ||||
| } | ||||
| 
 | ||||
| string AsmPrinter::operator()(ExpressionStatement const& _statement) const | ||||
| { | ||||
| 	return boost::apply_visitor(*this, _statement.expression); | ||||
|  | ||||
| @ -38,7 +38,6 @@ public: | ||||
| 
 | ||||
| 	std::string operator()(Literal const& _literal) const; | ||||
| 	std::string operator()(Identifier const& _identifier) const; | ||||
| 	std::string operator()(FunctionalInstruction const& _functionalInstruction) const; | ||||
| 	std::string operator()(ExpressionStatement const& _expr) const; | ||||
| 	std::string operator()(Assignment const& _assignment) const; | ||||
| 	std::string operator()(VariableDeclaration const& _variableDeclaration) const; | ||||
|  | ||||
| @ -51,7 +51,6 @@ public: | ||||
| 
 | ||||
| 	bool operator()(Literal const&) { return true; } | ||||
| 	bool operator()(Identifier const&) { return true; } | ||||
| 	bool operator()(FunctionalInstruction const&) { return true; } | ||||
| 	bool operator()(ExpressionStatement const& _expr); | ||||
| 	bool operator()(Assignment const&) { return true; } | ||||
| 	bool operator()(VariableDeclaration const& _variableDeclaration); | ||||
|  | ||||
| @ -69,10 +69,6 @@ struct MiniEVMInterpreter: boost::static_visitor<u256> | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	u256 operator()(FunctionalInstruction const& _instr) | ||||
| 	{ | ||||
| 		return eval(_instr.instruction, _instr.arguments); | ||||
| 	} | ||||
| 	u256 operator()(FunctionCall const& _funCall) | ||||
| 	{ | ||||
| 		BuiltinFunctionForEVM const* fun = m_dialect.builtin(_funCall.functionName.name); | ||||
|  | ||||
| @ -303,40 +303,6 @@ void CodeTransform::operator()(FunctionCall const& _call) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void CodeTransform::operator()(FunctionalInstruction const& _instruction) | ||||
| { | ||||
| 	if (m_evm15 && ( | ||||
| 		_instruction.instruction == dev::eth::Instruction::JUMP || | ||||
| 		_instruction.instruction == dev::eth::Instruction::JUMPI | ||||
| 	)) | ||||
| 	{ | ||||
| 		bool const isJumpI = _instruction.instruction == dev::eth::Instruction::JUMPI; | ||||
| 		if (isJumpI) | ||||
| 		{ | ||||
| 			solAssert(_instruction.arguments.size() == 2, ""); | ||||
| 			visitExpression(_instruction.arguments.at(1)); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			solAssert(_instruction.arguments.size() == 1, ""); | ||||
| 		} | ||||
| 		m_assembly.setSourceLocation(_instruction.location); | ||||
| 		auto label = labelFromIdentifier(boost::get<Identifier>(_instruction.arguments.at(0))); | ||||
| 		if (isJumpI) | ||||
| 			m_assembly.appendJumpToIf(label); | ||||
| 		else | ||||
| 			m_assembly.appendJumpTo(label); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		for (auto const& arg: _instruction.arguments | boost::adaptors::reversed) | ||||
| 			visitExpression(arg); | ||||
| 		m_assembly.setSourceLocation(_instruction.location); | ||||
| 		m_assembly.appendInstruction(_instruction.instruction); | ||||
| 	} | ||||
| 	checkStackHeight(&_instruction); | ||||
| } | ||||
| 
 | ||||
| void CodeTransform::operator()(Identifier const& _identifier) | ||||
| { | ||||
| 	m_assembly.setSourceLocation(_identifier.location); | ||||
|  | ||||
| @ -175,7 +175,6 @@ public: | ||||
| 	void operator()(Instruction const& _instruction); | ||||
| 	void operator()(Literal const& _literal); | ||||
| 	void operator()(Identifier const& _identifier); | ||||
| 	void operator()(FunctionalInstruction const& _instr); | ||||
| 	void operator()(FunctionCall const&); | ||||
| 	void operator()(ExpressionStatement const& _statement); | ||||
| 	void operator()(Assignment const& _assignment); | ||||
|  | ||||
| @ -85,12 +85,6 @@ void GasMeterVisitor::operator()(FunctionCall const& _funCall) | ||||
| 	yulAssert(false, "Functions not implemented."); | ||||
| } | ||||
| 
 | ||||
| void GasMeterVisitor::operator()(FunctionalInstruction const& _fun) | ||||
| { | ||||
| 	ASTWalker::operator()(_fun); | ||||
| 	instructionCostsInternal(_fun.instruction); | ||||
| } | ||||
| 
 | ||||
| void GasMeterVisitor::operator()(Literal const& _lit) | ||||
| { | ||||
| 	m_runGas += dev::eth::GasMeter::runGas(dev::eth::Instruction::PUSH1); | ||||
|  | ||||
| @ -81,7 +81,6 @@ public: | ||||
| 	{} | ||||
| 
 | ||||
| 	void operator()(FunctionCall const& _funCall) override; | ||||
| 	void operator()(FunctionalInstruction const& _instr) override; | ||||
| 	void operator()(Literal const& _literal) override; | ||||
| 	void operator()(Identifier const& _identifier) override; | ||||
| 
 | ||||
|  | ||||
| @ -110,12 +110,6 @@ wasm::Expression EWasmCodeTransform::operator()(ExpressionStatement const& _stat | ||||
| 	return visitReturnByValue(_statement.expression); | ||||
| } | ||||
| 
 | ||||
| wasm::Expression EWasmCodeTransform::operator()(FunctionalInstruction const& _f) | ||||
| { | ||||
| 	yulAssert(false, "EVM instruction in ewasm code: " + eth::instructionInfo(_f.instruction).name); | ||||
| 	return {}; | ||||
| } | ||||
| 
 | ||||
| wasm::Expression EWasmCodeTransform::operator()(FunctionCall const& _call) | ||||
| { | ||||
| 	bool typeConversionNeeded = false; | ||||
|  | ||||
| @ -40,7 +40,6 @@ public: | ||||
| public: | ||||
| 	wasm::Expression operator()(yul::Literal const& _literal); | ||||
| 	wasm::Expression operator()(yul::Identifier const& _identifier); | ||||
| 	wasm::Expression operator()(yul::FunctionalInstruction const& _instr); | ||||
| 	wasm::Expression operator()(yul::FunctionCall const&); | ||||
| 	wasm::Expression operator()(yul::ExpressionStatement const& _statement); | ||||
| 	wasm::Expression operator()(yul::Assignment const& _assignment); | ||||
|  | ||||
| @ -37,11 +37,6 @@ void WordSizeTransform::operator()(FunctionDefinition& _fd) | ||||
| 	(*this)(_fd.body); | ||||
| } | ||||
| 
 | ||||
| void WordSizeTransform::operator()(FunctionalInstruction& _ins) | ||||
| { | ||||
| 	rewriteFunctionCallArguments(_ins.arguments); | ||||
| } | ||||
| 
 | ||||
| void WordSizeTransform::operator()(FunctionCall& _fc) | ||||
| { | ||||
| 	if (BuiltinFunction const* fun = m_inputDialect.builtin(_fc.functionName.name)) | ||||
| @ -111,10 +106,7 @@ void WordSizeTransform::operator()(Block& _block) | ||||
| 							return {std::move(ret)}; | ||||
| 						} | ||||
| 
 | ||||
| 				if ( | ||||
| 					!varDecl.value || | ||||
| 					varDecl.value->type() == typeid(FunctionalInstruction) || | ||||
| 					varDecl.value->type() == typeid(FunctionCall) | ||||
| 				if (!varDecl.value || varDecl.value->type() == typeid(FunctionCall) | ||||
| 				) | ||||
| 				{ | ||||
| 					if (varDecl.value) visit(*varDecl.value); | ||||
| @ -171,10 +163,7 @@ void WordSizeTransform::operator()(Block& _block) | ||||
| 							return {std::move(ret)}; | ||||
| 						} | ||||
| 
 | ||||
| 				if ( | ||||
| 					assignment.value->type() == typeid(FunctionalInstruction) || | ||||
| 					assignment.value->type() == typeid(FunctionCall) | ||||
| 				) | ||||
| 				if (assignment.value->type() == typeid(FunctionCall)) | ||||
| 				{ | ||||
| 					if (assignment.value) visit(*assignment.value); | ||||
| 					rewriteIdentifierList(assignment.variableNames); | ||||
|  | ||||
| @ -37,11 +37,11 @@ namespace yul | ||||
|  * but wasm only supports values up to 64 bits, so we use four u64 values to simulate | ||||
|  * one u256 value. | ||||
|  * | ||||
|  * For FunctionalInstruction that accepts or returns u256 values, they accepts or returns | ||||
|  * For FunctionCall that accepts or returns u256 values, they accepts or returns | ||||
|  * four times the number of values after this transformation, with the order of significance, | ||||
|  * from the most significant to the least significant. | ||||
|  * | ||||
|  * For example, the FunctionalInstruction MUL supplied by code generator | ||||
|  * For example, the FunctionCall MUL supplied by code generator | ||||
|  * should take 8 arguments and return 4 values (instead of 2 and 1) after this transformation. | ||||
|  * | ||||
|  * mul(a1, a2, a3, a4, b1, b2, b3, b4) -> c1, c2, c3, c4 | ||||
| @ -61,7 +61,6 @@ class WordSizeTransform: public ASTModifier | ||||
| { | ||||
| public: | ||||
| 	void operator()(FunctionDefinition&) override; | ||||
| 	void operator()(FunctionalInstruction&) override; | ||||
| 	void operator()(FunctionCall&) override; | ||||
| 	void operator()(If&) override; | ||||
| 	void operator()(Switch&) override; | ||||
|  | ||||
| @ -62,15 +62,6 @@ Expression ASTCopier::operator()(FunctionCall const& _call) | ||||
| 	}; | ||||
| } | ||||
| 
 | ||||
| Expression ASTCopier::operator()(FunctionalInstruction const& _instruction) | ||||
| { | ||||
| 	return FunctionalInstruction{ | ||||
| 		_instruction.location, | ||||
| 		_instruction.instruction, | ||||
| 		translateVector(_instruction.arguments) | ||||
| 	}; | ||||
| } | ||||
| 
 | ||||
| Expression ASTCopier::operator()(Identifier const& _identifier) | ||||
| { | ||||
| 	return translate(_identifier); | ||||
|  | ||||
| @ -40,7 +40,6 @@ public: | ||||
| 	virtual ~ExpressionCopier() = default; | ||||
| 	virtual Expression operator()(Literal const& _literal) = 0; | ||||
| 	virtual Expression operator()(Identifier const& _identifier) = 0; | ||||
| 	virtual Expression operator()(FunctionalInstruction const& _instr) = 0; | ||||
| 	virtual Expression operator()(FunctionCall const&) = 0; | ||||
| }; | ||||
| 
 | ||||
| @ -71,7 +70,6 @@ public: | ||||
| 	virtual ~ASTCopier() = default; | ||||
| 	Expression operator()(Literal const& _literal) override; | ||||
| 	Expression operator()(Identifier const& _identifier) override; | ||||
| 	Expression operator()(FunctionalInstruction const& _instr) override; | ||||
| 	Expression operator()(FunctionCall const&) override; | ||||
| 	Statement operator()(ExpressionStatement const& _statement) override; | ||||
| 	Statement operator()(Assignment const& _assignment) override; | ||||
|  | ||||
| @ -28,11 +28,6 @@ using namespace std; | ||||
| using namespace dev; | ||||
| using namespace yul; | ||||
| 
 | ||||
| void ASTWalker::operator()(FunctionalInstruction const& _instr) | ||||
| { | ||||
| 	walkVector(_instr.arguments | boost::adaptors::reversed); | ||||
| } | ||||
| 
 | ||||
| void ASTWalker::operator()(FunctionCall const& _funCall) | ||||
| { | ||||
| 	// Does not visit _funCall.functionName on purpose
 | ||||
| @ -102,11 +97,6 @@ void ASTWalker::visit(Expression const& _e) | ||||
| 	boost::apply_visitor(*this, _e); | ||||
| } | ||||
| 
 | ||||
| void ASTModifier::operator()(FunctionalInstruction& _instr) | ||||
| { | ||||
| 	walkVector(_instr.arguments | boost::adaptors::reversed); | ||||
| } | ||||
| 
 | ||||
| void ASTModifier::operator()(FunctionCall& _funCall) | ||||
| { | ||||
| 	// Does not visit _funCall.functionName on purpose
 | ||||
|  | ||||
| @ -44,7 +44,6 @@ public: | ||||
| 	virtual ~ASTWalker() = default; | ||||
| 	virtual void operator()(Literal const&) {} | ||||
| 	virtual void operator()(Identifier const&) {} | ||||
| 	virtual void operator()(FunctionalInstruction const& _instr); | ||||
| 	virtual void operator()(FunctionCall const& _funCall); | ||||
| 	virtual void operator()(ExpressionStatement const& _statement); | ||||
| 	virtual void operator()(Assignment const& _assignment); | ||||
| @ -79,7 +78,6 @@ public: | ||||
| 	virtual ~ASTModifier() = default; | ||||
| 	virtual void operator()(Literal&) {} | ||||
| 	virtual void operator()(Identifier&) {} | ||||
| 	virtual void operator()(FunctionalInstruction& _instr); | ||||
| 	virtual void operator()(FunctionCall& _funCall); | ||||
| 	virtual void operator()(ExpressionStatement& _statement); | ||||
| 	virtual void operator()(Assignment& _assignment); | ||||
|  | ||||
| @ -76,14 +76,6 @@ void BlockHasher::operator()(Identifier const& _identifier) | ||||
| 	hash64(it->second.id); | ||||
| } | ||||
| 
 | ||||
| void BlockHasher::operator()(FunctionalInstruction const& _instr) | ||||
| { | ||||
| 	hash64(compileTimeLiteralHash("FunctionalInstruction")); | ||||
| 	hash8(static_cast<std::underlying_type_t<eth::Instruction>>(_instr.instruction)); | ||||
| 	hash64(_instr.arguments.size()); | ||||
| 	ASTWalker::operator()(_instr); | ||||
| } | ||||
| 
 | ||||
| void BlockHasher::operator()(FunctionCall const& _funCall) | ||||
| { | ||||
| 	hash64(compileTimeLiteralHash("FunctionCall")); | ||||
|  | ||||
| @ -49,7 +49,6 @@ public: | ||||
| 
 | ||||
| 	void operator()(Literal const&) override; | ||||
| 	void operator()(Identifier const&) override; | ||||
| 	void operator()(FunctionalInstruction const& _instr) override; | ||||
| 	void operator()(FunctionCall const& _funCall) override; | ||||
| 	void operator()(ExpressionStatement const& _statement) override; | ||||
| 	void operator()(Assignment const& _assignment) override; | ||||
|  | ||||
| @ -36,14 +36,6 @@ map<YulString, set<YulString>> CallGraphGenerator::callGraph(Block const& _ast) | ||||
| 	return std::move(gen.m_callGraph); | ||||
| } | ||||
| 
 | ||||
| void CallGraphGenerator::operator()(FunctionalInstruction const& _functionalInstruction) | ||||
| { | ||||
| 	string name = dev::eth::instructionInfo(_functionalInstruction.instruction).name; | ||||
| 	std::transform(name.begin(), name.end(), name.begin(), [](unsigned char _c) { return tolower(_c); }); | ||||
| 	m_callGraph[m_currentFunction].insert(YulString{name}); | ||||
| 	ASTWalker::operator()(_functionalInstruction); | ||||
| } | ||||
| 
 | ||||
| void CallGraphGenerator::operator()(FunctionCall const& _functionCall) | ||||
| { | ||||
| 	m_callGraph[m_currentFunction].insert(_functionCall.functionName.name); | ||||
|  | ||||
| @ -42,7 +42,6 @@ public: | ||||
| 	static std::map<YulString, std::set<YulString>> callGraph(Block const& _ast); | ||||
| 
 | ||||
| 	using ASTWalker::operator(); | ||||
| 	void operator()(FunctionalInstruction const& _functionalInstruction) override; | ||||
| 	void operator()(FunctionCall const& _functionCall) override; | ||||
| 	void operator()(FunctionDefinition const& _functionDefinition) override; | ||||
| 
 | ||||
|  | ||||
| @ -40,11 +40,6 @@ void ExpressionJoiner::run(OptimiserStepContext&, Block& _ast) | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void ExpressionJoiner::operator()(FunctionalInstruction& _instruction) | ||||
| { | ||||
| 	handleArguments(_instruction.arguments); | ||||
| } | ||||
| 
 | ||||
| void ExpressionJoiner::operator()(FunctionCall& _funCall) | ||||
| { | ||||
| 	handleArguments(_funCall.arguments); | ||||
|  | ||||
| @ -78,7 +78,6 @@ private: | ||||
| 	explicit ExpressionJoiner(Block& _ast); | ||||
| 
 | ||||
| 	void operator()(Block& _block) override; | ||||
| 	void operator()(FunctionalInstruction&) override; | ||||
| 	void operator()(FunctionCall&) override; | ||||
| 
 | ||||
| 	using ASTModifier::visit; | ||||
|  | ||||
| @ -41,12 +41,6 @@ void ExpressionSplitter::run(OptimiserStepContext& _context, Block& _ast) | ||||
| 	ExpressionSplitter{_context.dialect, _context.dispenser}(_ast); | ||||
| } | ||||
| 
 | ||||
| void ExpressionSplitter::operator()(FunctionalInstruction& _instruction) | ||||
| { | ||||
| 	for (auto& arg: _instruction.arguments | boost::adaptors::reversed) | ||||
| 		outlineExpression(arg); | ||||
| } | ||||
| 
 | ||||
| void ExpressionSplitter::operator()(FunctionCall& _funCall) | ||||
| { | ||||
| 	if (BuiltinFunction const* builtin = m_dialect.builtin(_funCall.functionName.name)) | ||||
|  | ||||
| @ -61,7 +61,6 @@ public: | ||||
| 	static constexpr char const* name{"ExpressionSplitter"}; | ||||
| 	static void run(OptimiserStepContext&, Block& _ast); | ||||
| 
 | ||||
| 	void operator()(FunctionalInstruction&) override; | ||||
| 	void operator()(FunctionCall&) override; | ||||
| 	void operator()(If&) override; | ||||
| 	void operator()(Switch&) override; | ||||
|  | ||||
| @ -77,9 +77,6 @@ Expression KnowledgeBase::simplify(Expression _expression) | ||||
| 	if (_expression.type() == typeid(FunctionCall)) | ||||
| 		for (Expression& arg: boost::get<FunctionCall>(_expression).arguments) | ||||
| 			arg = simplify(arg); | ||||
| 	else if (_expression.type() == typeid(FunctionalInstruction)) | ||||
| 		for (Expression& arg: boost::get<FunctionalInstruction>(_expression).arguments) | ||||
| 			arg = simplify(arg); | ||||
| 
 | ||||
| 	if (auto match = SimplificationRules::findFirstMatch(_expression, m_dialect, m_variableValues)) | ||||
| 		return simplify(match->action().toExpression(locationOf(_expression))); | ||||
|  | ||||
| @ -55,11 +55,6 @@ void LoadResolver::visit(Expression& _e) | ||||
| 			if (builtin->instruction) | ||||
| 				tryResolve(_e, *builtin->instruction, funCall.arguments); | ||||
| 	} | ||||
| 	else if (_e.type() == typeid(FunctionalInstruction)) | ||||
| 	{ | ||||
| 		FunctionalInstruction const& instruction = boost::get<FunctionalInstruction>(_e); | ||||
| 		tryResolve(_e, instruction.instruction, instruction.arguments); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void LoadResolver::tryResolve( | ||||
|  | ||||
| @ -120,13 +120,6 @@ void CodeCost::operator()(FunctionCall const& _funCall) | ||||
| 	m_cost += 49; | ||||
| } | ||||
| 
 | ||||
| void CodeCost::operator()(FunctionalInstruction const& _instr) | ||||
| { | ||||
| 	yulAssert(m_cost >= 1, "Should assign cost one in visit(Expression)."); | ||||
| 	addInstructionCost(_instr.instruction); | ||||
| 	ASTWalker::operator()(_instr); | ||||
| } | ||||
| 
 | ||||
| void CodeCost::operator()(Literal const& _literal) | ||||
| { | ||||
| 	yulAssert(m_cost >= 1, "Should assign cost one in visit(Expression)."); | ||||
|  | ||||
| @ -81,7 +81,6 @@ private: | ||||
| 	CodeCost(Dialect const& _dialect): m_dialect(_dialect) {} | ||||
| 
 | ||||
| 	void operator()(FunctionCall const& _funCall) override; | ||||
| 	void operator()(FunctionalInstruction const& _instr) override; | ||||
| 	void operator()(Literal const& _literal) override; | ||||
| 	void visit(Statement const& _statement) override; | ||||
| 	void visit(Expression const& _expression) override; | ||||
|  | ||||
| @ -61,13 +61,6 @@ SideEffectsCollector::SideEffectsCollector( | ||||
| 	operator()(_ast); | ||||
| } | ||||
| 
 | ||||
| void SideEffectsCollector::operator()(FunctionalInstruction const& _instr) | ||||
| { | ||||
| 	ASTWalker::operator()(_instr); | ||||
| 
 | ||||
| 	m_sideEffects += EVMDialect::sideEffectsOfInstruction(_instr.instruction); | ||||
| } | ||||
| 
 | ||||
| void SideEffectsCollector::operator()(FunctionCall const& _functionCall) | ||||
| { | ||||
| 	ASTWalker::operator()(_functionCall); | ||||
| @ -88,14 +81,6 @@ bool MSizeFinder::containsMSize(Dialect const& _dialect, Block const& _ast) | ||||
| 	return finder.m_msizeFound; | ||||
| } | ||||
| 
 | ||||
| void MSizeFinder::operator()(FunctionalInstruction const& _instr) | ||||
| { | ||||
| 	ASTWalker::operator()(_instr); | ||||
| 
 | ||||
| 	if (_instr.instruction == eth::Instruction::MSIZE) | ||||
| 		m_msizeFound = true; | ||||
| } | ||||
| 
 | ||||
| void MSizeFinder::operator()(FunctionCall const& _functionCall) | ||||
| { | ||||
| 	ASTWalker::operator()(_functionCall); | ||||
| @ -181,11 +166,7 @@ TerminationFinder::ControlFlow TerminationFinder::controlFlowKind(Statement cons | ||||
| 
 | ||||
| bool TerminationFinder::isTerminatingBuiltin(ExpressionStatement const& _exprStmnt) | ||||
| { | ||||
| 	if (_exprStmnt.expression.type() == typeid(FunctionalInstruction)) | ||||
| 		return eth::SemanticInformation::terminatesControlFlow( | ||||
| 			boost::get<FunctionalInstruction>(_exprStmnt.expression).instruction | ||||
| 		); | ||||
| 	else if (_exprStmnt.expression.type() == typeid(FunctionCall)) | ||||
| 	if (_exprStmnt.expression.type() == typeid(FunctionCall)) | ||||
| 		if (auto const* dialect = dynamic_cast<EVMDialect const*>(&m_dialect)) | ||||
| 			if (auto const* builtin = dialect->builtin(boost::get<FunctionCall>(_exprStmnt.expression).functionName.name)) | ||||
| 				if (builtin->instruction) | ||||
|  | ||||
| @ -54,7 +54,6 @@ public: | ||||
| 	); | ||||
| 
 | ||||
| 	using ASTWalker::operator(); | ||||
| 	void operator()(FunctionalInstruction const& _functionalInstruction) override; | ||||
| 	void operator()(FunctionCall const& _functionCall) override; | ||||
| 
 | ||||
| 	bool movable() const { return m_sideEffects.movable; } | ||||
| @ -104,7 +103,6 @@ public: | ||||
| 	static bool containsMSize(Dialect const& _dialect, Block const& _ast); | ||||
| 
 | ||||
| 	using ASTWalker::operator(); | ||||
| 	void operator()(FunctionalInstruction const& _instr); | ||||
| 	void operator()(FunctionCall const& _funCall); | ||||
| 
 | ||||
| private: | ||||
|  | ||||
| @ -67,9 +67,7 @@ bool SimplificationRules::isInitialized() const | ||||
| std::optional<std::pair<dev::eth::Instruction, vector<Expression> const*>> | ||||
| 	SimplificationRules::instructionAndArguments(Dialect const& _dialect, Expression const& _expr) | ||||
| { | ||||
| 	if (_expr.type() == typeid(FunctionalInstruction)) | ||||
| 		return make_pair(boost::get<FunctionalInstruction>(_expr).instruction, &boost::get<FunctionalInstruction>(_expr).arguments); | ||||
| 	else if (_expr.type() == typeid(FunctionCall)) | ||||
| 	if (_expr.type() == typeid(FunctionCall)) | ||||
| 		if (auto const* dialect = dynamic_cast<EVMDialect const*>(&_dialect)) | ||||
| 			if (auto const* builtin = dialect->builtin(boost::get<FunctionCall>(_expr).functionName.name)) | ||||
| 				if (builtin->instruction) | ||||
| @ -225,8 +223,15 @@ Expression Pattern::toExpression(SourceLocation const& _location) const | ||||
| 		vector<Expression> arguments; | ||||
| 		for (auto const& arg: m_arguments) | ||||
| 			arguments.emplace_back(arg.toExpression(_location)); | ||||
| 		// TODO convert to FunctionCall
 | ||||
| 		return FunctionalInstruction{_location, m_instruction, std::move(arguments)}; | ||||
| 
 | ||||
| 		string name = instructionInfo(m_instruction).name; | ||||
| 		transform(begin(name), end(name), begin(name), [](auto _c) { return tolower(_c); }); | ||||
| 
 | ||||
| 		return FunctionCall{ | ||||
| 			_location, | ||||
| 			Identifier{_location, YulString{name}}, | ||||
| 			std::move(arguments) | ||||
| 		}; | ||||
| 	} | ||||
| 	assertThrow(false, OptimizerException, "Pattern of kind 'any', but no match group."); | ||||
| } | ||||
|  | ||||
| @ -46,15 +46,6 @@ bool SyntacticallyEqual::operator()(Statement const& _lhs, Statement const& _rhs | ||||
| 	}, _lhs, _rhs); | ||||
| } | ||||
| 
 | ||||
| bool SyntacticallyEqual::expressionEqual(FunctionalInstruction const& _lhs, FunctionalInstruction const& _rhs) | ||||
| { | ||||
| 	return | ||||
| 		_lhs.instruction == _rhs.instruction && | ||||
| 		containerEqual(_lhs.arguments, _rhs.arguments, [this](Expression const& _lhsExpr, Expression const& _rhsExpr) -> bool { | ||||
| 			return (*this)(_lhsExpr, _rhsExpr); | ||||
| 		}); | ||||
| } | ||||
| 
 | ||||
| bool SyntacticallyEqual::expressionEqual(FunctionCall const& _lhs, FunctionCall const& _rhs) | ||||
| { | ||||
| 	return | ||||
|  | ||||
| @ -42,7 +42,6 @@ public: | ||||
| 	bool operator()(Expression const& _lhs, Expression const& _rhs); | ||||
| 	bool operator()(Statement const& _lhs, Statement const& _rhs); | ||||
| 
 | ||||
| 	bool expressionEqual(FunctionalInstruction const& _lhs, FunctionalInstruction const& _rhs); | ||||
| 	bool expressionEqual(FunctionCall const& _lhs, FunctionCall const& _rhs); | ||||
| 	bool expressionEqual(Identifier const& _lhs, Identifier const& _rhs); | ||||
| 	bool expressionEqual(Literal const& _lhs, Literal const& _rhs); | ||||
|  | ||||
| @ -227,15 +227,6 @@ void ExpressionEvaluator::operator()(Identifier const& _identifier) | ||||
| 	setValue(m_variables.at(_identifier.name)); | ||||
| } | ||||
| 
 | ||||
| void ExpressionEvaluator::operator()(FunctionalInstruction const& _instr) | ||||
| { | ||||
| 	evaluateArgs(_instr.arguments); | ||||
| 	EVMInstructionInterpreter interpreter(m_state); | ||||
| 	// The instruction might also return nothing, but it does not
 | ||||
| 	// hurt to set the value in that case.
 | ||||
| 	setValue(interpreter.eval(_instr.instruction, values())); | ||||
| } | ||||
| 
 | ||||
| void ExpressionEvaluator::operator()(FunctionCall const& _funCall) | ||||
| { | ||||
| 	evaluateArgs(_funCall.arguments); | ||||
|  | ||||
| @ -169,7 +169,6 @@ public: | ||||
| 
 | ||||
| 	void operator()(Literal const&) override; | ||||
| 	void operator()(Identifier const&) override; | ||||
| 	void operator()(FunctionalInstruction const& _instr) override; | ||||
| 	void operator()(FunctionCall const& _funCall) override; | ||||
| 
 | ||||
| 	/// Asserts that the expression has exactly one value and returns it.
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user