diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 6cf006638..c7e825759 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -264,7 +264,7 @@ vector AsmAnalyzer::operator()(FunctionCall const& _funCall) if (f->literalArguments) needsLiteralArguments = &f->literalArguments.value(); - warnOnInstructions(_funCall); + validateInstructions(_funCall); } else if (!m_currentScope->lookup(_funCall.functionName.name, GenericVisitor{ [&](Scope::Variable const&) @@ -282,7 +282,7 @@ vector AsmAnalyzer::operator()(FunctionCall const& _funCall) } })) { - if (!warnOnInstructions(_funCall)) + if (!validateInstructions(_funCall)) m_errorReporter.declarationError(4619_error, _funCall.functionName.location, "Function not found."); yulAssert(!watcher.ok(), "Expected a reported error."); } @@ -541,16 +541,16 @@ void AsmAnalyzer::expectType(YulString _expectedType, YulString _givenType, Sour ); } -bool AsmAnalyzer::warnOnInstructions(std::string const& _instructionIdentifier, langutil::SourceLocation const& _location) +bool AsmAnalyzer::validateInstructions(std::string const& _instructionIdentifier, langutil::SourceLocation const& _location) { auto const builtin = EVMDialect::strictAssemblyForEVM(EVMVersion{}).builtin(YulString(_instructionIdentifier)); if (builtin && builtin->instruction.has_value()) - return warnOnInstructions(builtin->instruction.value(), _location); + return validateInstructions(builtin->instruction.value(), _location); else return false; } -bool AsmAnalyzer::warnOnInstructions(evmasm::Instruction _instr, SourceLocation const& _location) +bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocation const& _location) { // We assume that returndatacopy, returndatasize and staticcall are either all available // or all not available. @@ -558,9 +558,9 @@ bool AsmAnalyzer::warnOnInstructions(evmasm::Instruction _instr, SourceLocation // Similarly we assume bitwise shifting and create2 go together. yulAssert(m_evmVersion.hasBitwiseShifting() == m_evmVersion.hasCreate2(), ""); - auto errorForVM = [&](string const& vmKindMessage) { + auto errorForVM = [&](ErrorId _errorId, string const& vmKindMessage) { m_errorReporter.typeError( - 7079_error, + _errorId, _location, "The \"" + boost::to_lower_copy(instructionInfo(_instr).name) @@ -577,21 +577,21 @@ bool AsmAnalyzer::warnOnInstructions(evmasm::Instruction _instr, SourceLocation _instr == evmasm::Instruction::RETURNDATACOPY || _instr == evmasm::Instruction::RETURNDATASIZE ) && !m_evmVersion.supportsReturndata()) - errorForVM("only available for Byzantium-compatible"); + errorForVM(7756_error, "only available for Byzantium-compatible"); else if (_instr == evmasm::Instruction::STATICCALL && !m_evmVersion.hasStaticCall()) - errorForVM("only available for Byzantium-compatible"); + errorForVM(1503_error, "only available for Byzantium-compatible"); else if (( _instr == evmasm::Instruction::SHL || _instr == evmasm::Instruction::SHR || _instr == evmasm::Instruction::SAR ) && !m_evmVersion.hasBitwiseShifting()) - errorForVM("only available for Constantinople-compatible"); + errorForVM(6612_error, "only available for Constantinople-compatible"); else if (_instr == evmasm::Instruction::CREATE2 && !m_evmVersion.hasCreate2()) - errorForVM("only available for Constantinople-compatible"); + errorForVM(6166_error, "only available for Constantinople-compatible"); else if (_instr == evmasm::Instruction::EXTCODEHASH && !m_evmVersion.hasExtCodeHash()) - errorForVM("only available for Constantinople-compatible"); + errorForVM(7110_error, "only available for Constantinople-compatible"); else if (_instr == evmasm::Instruction::CHAINID && !m_evmVersion.hasChainID()) - errorForVM("only available for Istanbul-compatible"); + errorForVM(1561_error, "only available for Istanbul-compatible"); else if (_instr == evmasm::Instruction::PC) m_errorReporter.warning( 2450_error, @@ -601,7 +601,7 @@ bool AsmAnalyzer::warnOnInstructions(evmasm::Instruction _instr, SourceLocation "\" instruction is deprecated and will be removed in the next breaking release." ); else if (_instr == evmasm::Instruction::SELFBALANCE && !m_evmVersion.hasSelfBalance()) - errorForVM("only available for Istanbul-compatible"); + errorForVM(3672_error, "only available for Istanbul-compatible"); else if ( _instr == evmasm::Instruction::JUMP || _instr == evmasm::Instruction::JUMPI || diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index 29bfca2fd..e0a751b13 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -110,12 +110,12 @@ private: Scope& scope(Block const* _block); void expectValidType(YulString _type, langutil::SourceLocation const& _location); void expectType(YulString _expectedType, YulString _givenType, 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(FunctionCall const& _functionCall) + bool validateInstructions(evmasm::Instruction _instr, langutil::SourceLocation const& _location); + bool validateInstructions(std::string const& _instrIdentifier, langutil::SourceLocation const& _location); + bool validateInstructions(FunctionCall const& _functionCall) { - return warnOnInstructions(_functionCall.functionName.name.str(), _functionCall.functionName.location); + return validateInstructions(_functionCall.functionName.name.str(), _functionCall.functionName.location); } yul::ExternalIdentifierAccess::Resolver m_resolver; diff --git a/test/libsolidity/syntaxTests/inlineAssembly/evm_byzantium.sol b/test/libsolidity/syntaxTests/inlineAssembly/evm_byzantium.sol new file mode 100644 index 000000000..b08172ebe --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/evm_byzantium.sol @@ -0,0 +1,16 @@ +contract C { + function f() pure external { + assembly { + let s := returndatasize() + returndatacopy(0, 0, s) + } + } + function g() view external returns (uint ret) { + assembly { + ret := staticcall(0, gas(), 0, 0, 0, 0) + } + } +} +// ==== +// EVMVersion: >=byzantium +// ---- diff --git a/test/libsolidity/syntaxTests/inlineAssembly/evm_byzantium_on_homestead.sol b/test/libsolidity/syntaxTests/inlineAssembly/evm_byzantium_on_homestead.sol new file mode 100644 index 000000000..bbb32299f --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/evm_byzantium_on_homestead.sol @@ -0,0 +1,21 @@ +contract C { + function f() pure external { + assembly { + let s := returndatasize() + returndatacopy(0, 0, s) + } + } + function g() view external returns (uint ret) { + assembly { + ret := staticcall(0, gas(), 0, 0, 0, 0) + } + } +} +// ==== +// EVMVersion: =homestead +// ---- +// TypeError 7756: (86-100): The "returndatasize" instruction is only available for Byzantium-compatible VMs (you are currently compiling for "homestead"). +// DeclarationError 3812: (77-102): Variable count mismatch: 1 variables and 0 values. +// TypeError 7756: (115-129): The "returndatacopy" instruction is only available for Byzantium-compatible VMs (you are currently compiling for "homestead"). +// TypeError 1503: (245-255): The "staticcall" instruction is only available for Byzantium-compatible VMs (you are currently compiling for "homestead"). +// DeclarationError 8678: (238-277): Variable count does not match number of values (1 vs. 0) diff --git a/test/libsolidity/syntaxTests/inlineAssembly/evm_constantinople.sol b/test/libsolidity/syntaxTests/inlineAssembly/evm_constantinople.sol new file mode 100644 index 000000000..75d2f2895 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/evm_constantinople.sol @@ -0,0 +1,17 @@ +contract C { + function f() view external returns (uint ret) { + assembly { + ret := shl(gas(), 5) + ret := shr(ret, 2) + ret := sar(ret, 2) + } + } + function g() external returns (address ret) { + assembly { + ret := create2(0, 0, 0, 0) + } + } +} +// ==== +// EVMVersion: >=constantinople +// ---- diff --git a/test/libsolidity/syntaxTests/inlineAssembly/evm_constantinople_on_byzantium.sol b/test/libsolidity/syntaxTests/inlineAssembly/evm_constantinople_on_byzantium.sol new file mode 100644 index 000000000..1e6d85bf1 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/evm_constantinople_on_byzantium.sol @@ -0,0 +1,25 @@ +contract C { + function f() view external returns (uint ret) { + assembly { + ret := shl(gas(), 5) + ret := shr(ret, 2) + ret := sar(ret, 2) + } + } + function g() external returns (address ret) { + assembly { + ret := create2(0, 0, 0, 0) + } + } +} +// ==== +// EVMVersion: =byzantium +// ---- +// TypeError 6612: (103-106): The "shl" instruction is only available for Constantinople-compatible VMs (you are currently compiling for "byzantium"). +// DeclarationError 8678: (96-116): Variable count does not match number of values (1 vs. 0) +// TypeError 6612: (136-139): The "shr" instruction is only available for Constantinople-compatible VMs (you are currently compiling for "byzantium"). +// DeclarationError 8678: (129-147): Variable count does not match number of values (1 vs. 0) +// TypeError 6612: (167-170): The "sar" instruction is only available for Constantinople-compatible VMs (you are currently compiling for "byzantium"). +// DeclarationError 8678: (160-178): Variable count does not match number of values (1 vs. 0) +// TypeError 6166: (283-290): The "create2" instruction is only available for Constantinople-compatible VMs (you are currently compiling for "byzantium"). +// DeclarationError 8678: (276-302): Variable count does not match number of values (1 vs. 0) diff --git a/test/libsolidity/syntaxTests/inlineAssembly/istanbul.sol b/test/libsolidity/syntaxTests/inlineAssembly/evm_istanbul.sol similarity index 100% rename from test/libsolidity/syntaxTests/inlineAssembly/istanbul.sol rename to test/libsolidity/syntaxTests/inlineAssembly/evm_istanbul.sol diff --git a/test/libsolidity/syntaxTests/inlineAssembly/istanbul_on_petersburg.sol b/test/libsolidity/syntaxTests/inlineAssembly/evm_istanbul_on_petersburg.sol similarity index 83% rename from test/libsolidity/syntaxTests/inlineAssembly/istanbul_on_petersburg.sol rename to test/libsolidity/syntaxTests/inlineAssembly/evm_istanbul_on_petersburg.sol index dc15b61f9..66095a021 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/istanbul_on_petersburg.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/evm_istanbul_on_petersburg.sol @@ -13,7 +13,7 @@ contract C { // ==== // EVMVersion: =petersburg // ---- -// TypeError 7079: (101-108): The "chainid" instruction is only available for Istanbul-compatible VMs (you are currently compiling for "petersburg"). +// TypeError 1561: (101-108): The "chainid" instruction is only available for Istanbul-compatible VMs (you are currently compiling for "petersburg"). // DeclarationError 8678: (95-110): Variable count does not match number of values (1 vs. 0) -// TypeError 7079: (215-226): The "selfbalance" instruction is only available for Istanbul-compatible VMs (you are currently compiling for "petersburg"). +// TypeError 3672: (215-226): The "selfbalance" instruction is only available for Istanbul-compatible VMs (you are currently compiling for "petersburg"). // DeclarationError 8678: (209-228): Variable count does not match number of values (1 vs. 0)