mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #8913 from ethereum/yul-remove-pc-instr
Mark EVM instruction `pc()` as deprecated when used in inline assembly.
This commit is contained in:
		
						commit
						afa873fe9f
					
				| @ -2,6 +2,7 @@ | |||||||
| 
 | 
 | ||||||
| Language Features: | Language Features: | ||||||
|  * Permit calldata location for all variables. |  * Permit calldata location for all variables. | ||||||
|  |  * Yul: EVM instruction `pc()` is marked deprecated and will be removed in the next breaking release. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| Compiler Features: | Compiler Features: | ||||||
|  | |||||||
| @ -273,6 +273,7 @@ bool SyntaxChecker::visit(InlineAssembly const& _inlineAssembly) | |||||||
| 			"The msize instruction cannot be used when the Yul optimizer is activated because " | 			"The msize instruction cannot be used when the Yul optimizer is activated because " | ||||||
| 			"it can change its semantics. Either disable the Yul optimizer or do not use the instruction." | 			"it can change its semantics. Either disable the Yul optimizer or do not use the instruction." | ||||||
| 		); | 		); | ||||||
|  | 
 | ||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -73,7 +73,7 @@ AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect, | |||||||
| 		{}, | 		{}, | ||||||
| 		_object.dataNames() | 		_object.dataNames() | ||||||
| 	).analyze(*_object.code); | 	).analyze(*_object.code); | ||||||
| 	yulAssert(success && errorList.empty(), "Invalid assembly/yul code."); | 	yulAssert(success && !errors.hasErrors(), "Invalid assembly/yul code."); | ||||||
| 	return analysisInfo; | 	return analysisInfo; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -259,6 +259,8 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall) | |||||||
| 		returnTypes = &f->returns; | 		returnTypes = &f->returns; | ||||||
| 		if (f->literalArguments) | 		if (f->literalArguments) | ||||||
| 			needsLiteralArguments = &f->literalArguments.value(); | 			needsLiteralArguments = &f->literalArguments.value(); | ||||||
|  | 
 | ||||||
|  | 		warnOnInstructions(_funCall); | ||||||
| 	} | 	} | ||||||
| 	else if (!m_currentScope->lookup(_funCall.functionName.name, GenericVisitor{ | 	else if (!m_currentScope->lookup(_funCall.functionName.name, GenericVisitor{ | ||||||
| 		[&](Scope::Variable const&) | 		[&](Scope::Variable const&) | ||||||
| @ -275,10 +277,11 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall) | |||||||
| 		} | 		} | ||||||
| 	})) | 	})) | ||||||
| 	{ | 	{ | ||||||
| 		if (!warnOnInstructions(_funCall.functionName.name.str(), _funCall.functionName.location)) | 		if (!warnOnInstructions(_funCall)) | ||||||
| 			declarationError(_funCall.functionName.location, "Function not found."); | 			declarationError(_funCall.functionName.location, "Function not found."); | ||||||
| 		yulAssert(!watcher.ok(), "Expected a reported error."); | 		yulAssert(!watcher.ok(), "Expected a reported error."); | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
| 	if (parameterTypes && _funCall.arguments.size() != parameterTypes->size()) | 	if (parameterTypes && _funCall.arguments.size() != parameterTypes->size()) | ||||||
| 		typeError( | 		typeError( | ||||||
| 			_funCall.functionName.location, | 			_funCall.functionName.location, | ||||||
| @ -553,6 +556,14 @@ bool AsmAnalyzer::warnOnInstructions(evmasm::Instruction _instr, SourceLocation | |||||||
| 		errorForVM("only available for Constantinople-compatible"); | 		errorForVM("only available for Constantinople-compatible"); | ||||||
| 	else if (_instr == evmasm::Instruction::CHAINID && !m_evmVersion.hasChainID()) | 	else if (_instr == evmasm::Instruction::CHAINID && !m_evmVersion.hasChainID()) | ||||||
| 		errorForVM("only available for Istanbul-compatible"); | 		errorForVM("only available for Istanbul-compatible"); | ||||||
|  | 	else if (_instr == evmasm::Instruction::PC) | ||||||
|  | 		m_errorReporter.warning( | ||||||
|  | 			2450_error, | ||||||
|  | 			_location, | ||||||
|  | 			"The \"" + | ||||||
|  | 			boost::to_lower_copy(instructionInfo(_instr).name) + | ||||||
|  | 			"\" instruction is deprecated and will be removed in the next breaking release." | ||||||
|  | 		); | ||||||
| 	else if (_instr == evmasm::Instruction::SELFBALANCE && !m_evmVersion.hasSelfBalance()) | 	else if (_instr == evmasm::Instruction::SELFBALANCE && !m_evmVersion.hasSelfBalance()) | ||||||
| 		errorForVM("only available for Istanbul-compatible"); | 		errorForVM("only available for Istanbul-compatible"); | ||||||
| 	else if ( | 	else if ( | ||||||
|  | |||||||
| @ -112,6 +112,11 @@ private: | |||||||
| 	bool warnOnInstructions(evmasm::Instruction _instr, langutil::SourceLocation const& _location); | 	bool warnOnInstructions(evmasm::Instruction _instr, langutil::SourceLocation const& _location); | ||||||
| 	bool warnOnInstructions(std::string const& _instrIdentifier, langutil::SourceLocation const& _location); | 	bool warnOnInstructions(std::string const& _instrIdentifier, langutil::SourceLocation const& _location); | ||||||
| 
 | 
 | ||||||
|  | 	bool warnOnInstructions(FunctionCall const& _functionCall) | ||||||
|  | 	{ | ||||||
|  | 		return warnOnInstructions(_functionCall.functionName.name.str(), _functionCall.functionName.location); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	void typeError(langutil::SourceLocation const& _location, std::string const& _description); | 	void typeError(langutil::SourceLocation const& _location, std::string const& _description); | ||||||
| 	void declarationError(langutil::SourceLocation const& _location, std::string const& _description); | 	void declarationError(langutil::SourceLocation const& _location, std::string const& _description); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -90,7 +90,6 @@ void MSizeFinder::operator()(FunctionCall const& _functionCall) | |||||||
| 			m_msizeFound = true; | 			m_msizeFound = true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| map<YulString, SideEffects> SideEffectsPropagator::sideEffects( | map<YulString, SideEffects> SideEffectsPropagator::sideEffects( | ||||||
| 	Dialect const& _dialect, | 	Dialect const& _dialect, | ||||||
| 	CallGraph const& _directCallGraph | 	CallGraph const& _directCallGraph | ||||||
|  | |||||||
							
								
								
									
										9
									
								
								test/libsolidity/syntaxTests/inlineAssembly/pc.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								test/libsolidity/syntaxTests/inlineAssembly/pc.sol
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | contract C { | ||||||
|  | 	function f() pure public { | ||||||
|  | 		assembly { | ||||||
|  | 			pop(pc()) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | // ---- | ||||||
|  | // Warning: (61-63): The "pc" instruction is deprecated and will be removed in the next breaking release. | ||||||
| @ -1,8 +0,0 @@ | |||||||
| { |  | ||||||
|   sstore(0, pc()) |  | ||||||
| } |  | ||||||
| // ---- |  | ||||||
| // Trace: |  | ||||||
| //   INVALID() |  | ||||||
| // Memory dump: |  | ||||||
| // Storage dump: |  | ||||||
| @ -6,7 +6,6 @@ | |||||||
| 	pop(extcodehash(0)) | 	pop(extcodehash(0)) | ||||||
| 	pop(returndatasize()) | 	pop(returndatasize()) | ||||||
| 	pop(sload(0)) | 	pop(sload(0)) | ||||||
| 	pop(pc()) |  | ||||||
| 	pop(msize()) | 	pop(msize()) | ||||||
| 	pop(mload(0)) | 	pop(mload(0)) | ||||||
| 	pop(sload(0)) | 	pop(sload(0)) | ||||||
|  | |||||||
| @ -1,10 +1,23 @@ | |||||||
| { | { | ||||||
| 	let a | 	let a | ||||||
| 
 | 
 | ||||||
|  | 	function gcd(_a, _b) -> out | ||||||
|  | 	{ | ||||||
|  | 		// GCD algorithm. in order to test underlying stack compressor this function must not be inlined. | ||||||
|  | 		switch _b | ||||||
|  | 		case 0 { out := _a } | ||||||
|  | 		default { out := gcd(_b, mod(_a, _b)) } | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	function f() -> out | ||||||
|  | 	{ | ||||||
|  | 		out := gcd(10, 15) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	function foo_singlereturn_0() -> out | 	function foo_singlereturn_0() -> out | ||||||
| 	{ | 	{ | ||||||
| 		mstore(lt(or(gt(1,or(or(gt(or(or(or(1,gt(or(gt(or(or(keccak256(pc(),or(gt(not(pc()),1),1)),1),not(1)),pc()),1),pc())),lt(or(1,sub(pc(),1)),1)),pc()),1),1),gt(not(pc()),1))),1),1),1) | 		mstore(lt(or(gt(1,or(or(gt(or(or(or(1,gt(or(gt(or(or(keccak256(f(),or(gt(not(f()),1),1)),1),not(1)),f()),1),f())),lt(or(1,sub(f(),1)),1)),f()),1),1),gt(not(f()),1))),1),1),1) | ||||||
| 		sstore(not(pc()),1) | 		sstore(not(f()),1) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	function foo_singlereturn_1(in_1, in_2) -> out | 	function foo_singlereturn_1(in_1, in_2) -> out | ||||||
| @ -25,21 +38,27 @@ | |||||||
| // | // | ||||||
| // { | // { | ||||||
| //     { | //     { | ||||||
| //         let _1 := gt(not(pc()), 1) | //         let _1 := gt(not(gcd(10, 15)), 1) | ||||||
| //         let _2 := pc() | //         let _2 := gcd(10, 15) | ||||||
| //         let _3 := not(0) | //         let _3 := not(0) | ||||||
| //         let _4 := lt(or(1, add(pc(), _3)), 1) | //         let _4 := lt(or(1, add(gcd(10, 15), _3)), 1) | ||||||
| //         let _5 := pc() | //         let _5 := gcd(10, 15) | ||||||
| //         let _6 := pc() | //         let _6 := gcd(10, 15) | ||||||
| //         pop(keccak256(pc(), or(gt(not(pc()), 1), 1))) | //         pop(keccak256(gcd(10, 15), or(gt(not(gcd(10, 15)), 1), 1))) | ||||||
| //         mstore(lt(or(gt(1, or(or(gt(or(or(or(gt(or(gt(_3, _6), 1), _5), _4), _2), 1), 1), _1), 1)), 1), 1), 1) | //         mstore(lt(or(gt(1, or(or(gt(or(or(or(gt(or(gt(_3, _6), 1), _5), _4), _2), 1), 1), _1), 1)), 1), 1), 1) | ||||||
| //         sstore(not(pc()), 1) | //         sstore(not(gcd(10, 15)), 1) | ||||||
| //         sstore(0, 0) | //         sstore(0, 0) | ||||||
| //         sstore(2, 1) | //         sstore(2, 1) | ||||||
| //         pop(foo_singlereturn_1(calldataload(0), calldataload(3))) | //         pop(foo_singlereturn_1(calldataload(0), calldataload(3))) | ||||||
| //         sstore(0, 0) | //         sstore(0, 0) | ||||||
| //         sstore(3, 1) | //         sstore(3, 1) | ||||||
| //     } | //     } | ||||||
|  | //     function gcd(_a, _b) -> out | ||||||
|  | //     { | ||||||
|  | //         switch _b | ||||||
|  | //         case 0 { out := _a } | ||||||
|  | //         default { out := gcd(_b, mod(_a, _b)) } | ||||||
|  | //     } | ||||||
| //     function foo_singlereturn_1(in, in_1) -> out | //     function foo_singlereturn_1(in, in_1) -> out | ||||||
| //     { extcodecopy(1, msize(), 1, 1) } | //     { extcodecopy(1, msize(), 1, 1) } | ||||||
| // } | // } | ||||||
|  | |||||||
| @ -1,11 +1,11 @@ | |||||||
| { | { | ||||||
|     { |     { | ||||||
|         let _13_71 := 1 |         let _13_71 := 1 | ||||||
|         let _17_72 := pc() |         let _17_72 := msize() | ||||||
|         let _22_75 := pc() |         let _22_75 := msize() | ||||||
|         let _25_76 := pc() |         let _25_76 := msize() | ||||||
|         let _30_80 := pc() |         let _30_80 := msize() | ||||||
|         let _32_81 := pc() |         let _32_81 := msize() | ||||||
|         // This should not be removed |         // This should not be removed | ||||||
|         pop(keccak256(1, 2)) |         pop(keccak256(1, 2)) | ||||||
|         let _104 := gt(not(_17_72), _13_71) |         let _104 := gt(not(_17_72), _13_71) | ||||||
| @ -22,11 +22,11 @@ | |||||||
| // step: stackCompressor | // step: stackCompressor | ||||||
| // | // | ||||||
| // { | // { | ||||||
| //     let _17_72 := pc() | //     let _17_72 := msize() | ||||||
| //     let _22_75 := pc() | //     let _22_75 := msize() | ||||||
| //     let _25_76 := pc() | //     let _25_76 := msize() | ||||||
| //     let _30_80 := pc() | //     let _30_80 := msize() | ||||||
| //     let _32_81 := pc() | //     let _32_81 := msize() | ||||||
| //     pop(keccak256(1, 2)) | //     pop(keccak256(1, 2)) | ||||||
| //     let _105 := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | //     let _105 := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | ||||||
| //     mstore(lt(or(gt(1, or(or(gt(or(or(or(gt(or(gt(_105, _32_81), 1), _30_80), lt(or(1, add(_25_76, _105)), 1)), _22_75), 1), 1), gt(not(_17_72), 1)), 1)), 1), 1), 1) | //     mstore(lt(or(gt(1, or(or(gt(or(or(or(gt(or(gt(_105, _32_81), 1), _30_80), lt(or(1, add(_25_76, _105)), 1)), _22_75), 1), 1), gt(not(_17_72), 1)), 1)), 1), 1), 1) | ||||||
|  | |||||||
							
								
								
									
										7
									
								
								test/libyul/yulSyntaxTests/pc.yul
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								test/libyul/yulSyntaxTests/pc.yul
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | |||||||
|  | { | ||||||
|  |     pop(pc()) | ||||||
|  | } | ||||||
|  | // ==== | ||||||
|  | // dialect: evmTyped | ||||||
|  | // ---- | ||||||
|  | // Warning: (10-12): The "pc" instruction is deprecated and will be removed in the next breaking release. | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user