mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Make KnownState work with all instructions.
This commit is contained in:
		
							parent
							
								
									867101e409
								
							
						
					
					
						commit
						a2e3bcbd0c
					
				| @ -57,12 +57,15 @@ ExpressionClasses::Id ExpressionClasses::find( | ||||
| 	exp.arguments = _arguments; | ||||
| 	exp.sequenceNumber = _sequenceNumber; | ||||
| 
 | ||||
| 	if (SemanticInformation::isCommutativeOperation(_item)) | ||||
| 		sort(exp.arguments.begin(), exp.arguments.end()); | ||||
| 	if (SemanticInformation::isDeterministic(_item)) | ||||
| 	{ | ||||
| 		if (SemanticInformation::isCommutativeOperation(_item)) | ||||
| 			sort(exp.arguments.begin(), exp.arguments.end()); | ||||
| 
 | ||||
| 	auto it = m_expressions.find(exp); | ||||
| 	if (it != m_expressions.end()) | ||||
| 		return it->id; | ||||
| 		auto it = m_expressions.find(exp); | ||||
| 		if (it != m_expressions.end()) | ||||
| 			return it->id; | ||||
| 	} | ||||
| 
 | ||||
| 	if (_copyItem) | ||||
| 		exp.item = storeItem(_item); | ||||
| @ -286,7 +289,11 @@ ExpressionClasses::Id ExpressionClasses::tryToSimplify(Expression const& _expr, | ||||
| { | ||||
| 	static Rules rules; | ||||
| 
 | ||||
| 	if (!_expr.item || _expr.item->type() != Operation) | ||||
| 	if ( | ||||
| 		!_expr.item || | ||||
| 		_expr.item->type() != Operation || | ||||
| 		!SemanticInformation::isDeterministic(*_expr.item) | ||||
| 	) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	for (auto const& rule: rules.rules()) | ||||
|  | ||||
| @ -101,6 +101,7 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool | ||||
| 			vector<Id> arguments(info.args); | ||||
| 			for (int i = 0; i < info.args; ++i) | ||||
| 				arguments[i] = stackElement(m_stackHeight - i, _item.getLocation()); | ||||
| 
 | ||||
| 			if (_item.instruction() == Instruction::SSTORE) | ||||
| 				op = storeInStorage(arguments[0], arguments[1], _item.getLocation()); | ||||
| 			else if (_item.instruction() == Instruction::SLOAD) | ||||
| @ -121,10 +122,16 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool | ||||
| 					applySha3(arguments.at(0), arguments.at(1), _item.getLocation()) | ||||
| 				); | ||||
| 			else | ||||
| 			{ | ||||
| 				if (SemanticInformation::invalidatesMemory(_item.instruction())) | ||||
| 					resetMemory(); | ||||
| 				if (SemanticInformation::invalidatesStorage(_item.instruction())) | ||||
| 					resetStorage(); | ||||
| 				setStackElement( | ||||
| 					m_stackHeight + _item.deposit(), | ||||
| 					m_expressionClasses->find(_item, arguments, _copyItem) | ||||
| 				); | ||||
| 			} | ||||
| 		} | ||||
| 		m_stackHeight += _item.deposit(); | ||||
| 	} | ||||
|  | ||||
| @ -122,3 +122,57 @@ bool SemanticInformation::altersControlFlow(AssemblyItem const& _item) | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| bool SemanticInformation::isDeterministic(AssemblyItem const& _item) | ||||
| { | ||||
| 	if (_item.type() != Operation) | ||||
| 		return true; | ||||
| 	assertThrow(!altersControlFlow(_item), OptimizerException, ""); | ||||
| 
 | ||||
| 	switch (_item.instruction()) | ||||
| 	{ | ||||
| 	case Instruction::CALL: | ||||
| 	case Instruction::CALLCODE: | ||||
| 	case Instruction::CREATE: | ||||
| 	case Instruction::GAS: | ||||
| 	case Instruction::PC: | ||||
| 	case Instruction::MSIZE: // depends on previous writes and reads, not only on content
 | ||||
| 	case Instruction::BALANCE: // depends on previous calls
 | ||||
| 	case Instruction::EXTCODESIZE: | ||||
| 		return false; | ||||
| 	default: | ||||
| 		return true; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| bool SemanticInformation::invalidatesMemory(Instruction _instruction) | ||||
| { | ||||
| 	switch (_instruction) | ||||
| 	{ | ||||
| 	case Instruction::CALLDATACOPY: | ||||
| 	case Instruction::CODECOPY: | ||||
| 	case Instruction::EXTCODECOPY: | ||||
| 	case Instruction::MSTORE: | ||||
| 	case Instruction::MSTORE8: | ||||
| 	case Instruction::CALL: | ||||
| 	case Instruction::CALLCODE: | ||||
| 		return true; | ||||
| 	default: | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| bool SemanticInformation::invalidatesStorage(Instruction _instruction) | ||||
| { | ||||
| 	switch (_instruction) | ||||
| 	{ | ||||
| 	case Instruction::CALL: | ||||
| 	case Instruction::CALLCODE: | ||||
| 	case Instruction::CREATE: | ||||
| 	case Instruction::SSTORE: | ||||
| 		return true; | ||||
| 	default: | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -23,6 +23,7 @@ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <libevmcore/Instruction.h> | ||||
| 
 | ||||
| namespace dev | ||||
| { | ||||
| @ -45,6 +46,14 @@ struct SemanticInformation | ||||
| 	static bool isSwapInstruction(AssemblyItem const& _item); | ||||
| 	static bool isJumpInstruction(AssemblyItem const& _item); | ||||
| 	static bool altersControlFlow(AssemblyItem const& _item); | ||||
| 	/// @returns false if the value put on the stack by _item depends on anything else than
 | ||||
| 	/// the information in the current block header, memory, storage or stack.
 | ||||
| 	/// @note should not be called for instructions that alter the control flow.
 | ||||
| 	static bool isDeterministic(AssemblyItem const& _item); | ||||
| 	/// @returns true if the given instruction modifies memory.
 | ||||
| 	static bool invalidatesMemory(Instruction _instruction); | ||||
| 	/// @returns true if the given instruction modifies storage (even indirectly).
 | ||||
| 	static bool invalidatesStorage(Instruction _instruction); | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user