mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Add mini-interpreter to check representation.
This commit is contained in:
		
							parent
							
								
									1c16124a09
								
							
						
					
					
						commit
						cee1340113
					
				| @ -91,6 +91,20 @@ inline u256 s2u(s256 _u) | ||||
| 		return u256(c_end + _u); | ||||
| } | ||||
| 
 | ||||
| inline u256 exp256(u256 _base, u256 _exponent) | ||||
| { | ||||
| 	using boost::multiprecision::limb_type; | ||||
| 	u256 result = 1; | ||||
| 	while (_exponent) | ||||
| 	{ | ||||
| 		if (boost::multiprecision::bit_test(_exponent, 0)) | ||||
| 			result *= _base; | ||||
| 		_base *= _base; | ||||
| 		_exponent >>= 1; | ||||
| 	} | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| inline std::ostream& operator<<(std::ostream& os, bytes const& _bytes) | ||||
| { | ||||
| 	std::ostringstream ss; | ||||
|  | ||||
| @ -35,6 +35,63 @@ using namespace yul; | ||||
| 
 | ||||
| using Representation = ConstantOptimiser::Representation; | ||||
| 
 | ||||
| namespace | ||||
| { | ||||
| struct MiniEVMInterpreter: boost::static_visitor<u256> | ||||
| { | ||||
| 	explicit MiniEVMInterpreter(EVMDialect const& _dialect): m_dialect(_dialect) {} | ||||
| 
 | ||||
| 	u256 eval(Expression const& _expr) | ||||
| 	{ | ||||
| 		return boost::apply_visitor(*this, _expr); | ||||
| 	} | ||||
| 
 | ||||
| 	u256 eval(dev::eth::Instruction _instr, vector<Expression> const& _arguments) | ||||
| 	{ | ||||
| 		vector<u256> args; | ||||
| 		for (auto const& arg: _arguments) | ||||
| 			args.emplace_back(eval(arg)); | ||||
| 		switch (_instr) | ||||
| 		{ | ||||
| 		case eth::Instruction::ADD: | ||||
| 			return args.at(0) + args.at(1); | ||||
| 		case eth::Instruction::SUB: | ||||
| 			return args.at(0) - args.at(1); | ||||
| 		case eth::Instruction::MUL: | ||||
| 			return args.at(0) * args.at(1); | ||||
| 		case eth::Instruction::EXP: | ||||
| 			return exp256(args.at(0), args.at(1)); | ||||
| 		case eth::Instruction::SHL: | ||||
| 			return args.at(0) > 255 ? 0 : (args.at(1) << unsigned(args.at(0))); | ||||
| 		case eth::Instruction::NOT: | ||||
| 			return ~args.at(0); | ||||
| 		default: | ||||
| 			yulAssert(false, "Invalid operation generated in constant optimizer."); | ||||
| 		} | ||||
| 		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); | ||||
| 		yulAssert(fun, "Expected builtin function."); | ||||
| 		yulAssert(fun->instruction, "Expected EVM instruction."); | ||||
| 		return eval(*fun->instruction, _funCall.arguments); | ||||
| 	} | ||||
| 	u256 operator()(Literal const& _literal) | ||||
| 	{ | ||||
| 		return valueOfLiteral(_literal); | ||||
| 	} | ||||
| 	u256 operator()(Identifier const&) { yulAssert(false, ""); } | ||||
| 
 | ||||
| 	EVMDialect const& m_dialect; | ||||
| }; | ||||
| } | ||||
| 
 | ||||
| void ConstantOptimiser::visit(Expression& _e) | ||||
| { | ||||
| 	if (_e.type() == typeid(Literal)) | ||||
| @ -118,6 +175,7 @@ Representation const& RepresentationFinder::findRepresentation(dev::u256 const& | ||||
| 			m_maxSteps--; | ||||
| 		routine = min(move(routine), move(newRoutine)); | ||||
| 	} | ||||
| 	yulAssert(MiniEVMInterpreter{m_dialect}.eval(*routine.expression) == _value, "Invalid expression generated."); | ||||
| 	return m_cache[_value] = move(routine); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -37,20 +37,6 @@ using namespace yul::test; | ||||
| namespace | ||||
| { | ||||
| 
 | ||||
| u256 exp256(u256 _base, u256 _exponent) | ||||
| { | ||||
| 	using boost::multiprecision::limb_type; | ||||
| 	u256 result = 1; | ||||
| 	while (_exponent) | ||||
| 	{ | ||||
| 		if (boost::multiprecision::bit_test(_exponent, 0)) | ||||
| 			result *= _base; | ||||
| 		_base *= _base; | ||||
| 		_exponent >>= 1; | ||||
| 	} | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| /// Reads 32 bytes from @a _data at position @a _offset bytes while
 | ||||
| /// interpreting @a _data to be padded with an infinite number of zero
 | ||||
| /// bytes beyond its end.
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user