diff --git a/Changelog.md b/Changelog.md index ad568e6ae..9e58b2c17 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,7 @@ Language Features: * Permit calldata location for all variables. + * Yul: EVM instruction `pc()` is marked deprecated and will be removed in the next breaking release. Compiler Features: diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index 86204e88e..267d5764f 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -273,6 +273,7 @@ bool SyntaxChecker::visit(InlineAssembly const& _inlineAssembly) "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." ); + return false; } diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 80c90650d..fd8e44dfa 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -73,7 +73,7 @@ AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect, {}, _object.dataNames() ).analyze(*_object.code); - yulAssert(success && errorList.empty(), "Invalid assembly/yul code."); + yulAssert(success && !errors.hasErrors(), "Invalid assembly/yul code."); return analysisInfo; } @@ -259,6 +259,8 @@ vector AsmAnalyzer::operator()(FunctionCall const& _funCall) returnTypes = &f->returns; if (f->literalArguments) needsLiteralArguments = &f->literalArguments.value(); + + warnOnInstructions(_funCall); } else if (!m_currentScope->lookup(_funCall.functionName.name, GenericVisitor{ [&](Scope::Variable const&) @@ -275,10 +277,11 @@ vector AsmAnalyzer::operator()(FunctionCall const& _funCall) } })) { - if (!warnOnInstructions(_funCall.functionName.name.str(), _funCall.functionName.location)) + if (!warnOnInstructions(_funCall)) declarationError(_funCall.functionName.location, "Function not found."); yulAssert(!watcher.ok(), "Expected a reported error."); } + if (parameterTypes && _funCall.arguments.size() != parameterTypes->size()) typeError( _funCall.functionName.location, @@ -553,6 +556,14 @@ bool AsmAnalyzer::warnOnInstructions(evmasm::Instruction _instr, SourceLocation errorForVM("only available for Constantinople-compatible"); else if (_instr == evmasm::Instruction::CHAINID && !m_evmVersion.hasChainID()) 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()) errorForVM("only available for Istanbul-compatible"); else if ( diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index bbc37bedb..438c31bbd 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -112,6 +112,11 @@ private: bool warnOnInstructions(evmasm::Instruction _instr, 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 declarationError(langutil::SourceLocation const& _location, std::string const& _description); diff --git a/libyul/optimiser/Semantics.cpp b/libyul/optimiser/Semantics.cpp index 1e2dcb104..a6f41b844 100644 --- a/libyul/optimiser/Semantics.cpp +++ b/libyul/optimiser/Semantics.cpp @@ -90,7 +90,6 @@ void MSizeFinder::operator()(FunctionCall const& _functionCall) m_msizeFound = true; } - map SideEffectsPropagator::sideEffects( Dialect const& _dialect, CallGraph const& _directCallGraph diff --git a/test/libsolidity/syntaxTests/inlineAssembly/pc.sol b/test/libsolidity/syntaxTests/inlineAssembly/pc.sol new file mode 100644 index 000000000..08b023889 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/pc.sol @@ -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. diff --git a/test/libyul/ewasmTranslationTests/pc.yul b/test/libyul/ewasmTranslationTests/pc.yul deleted file mode 100644 index 16d98dec8..000000000 --- a/test/libyul/ewasmTranslationTests/pc.yul +++ /dev/null @@ -1,8 +0,0 @@ -{ - sstore(0, pc()) -} -// ---- -// Trace: -// INVALID() -// Memory dump: -// Storage dump: diff --git a/test/libyul/yulInterpreterTests/side_effect_free.yul b/test/libyul/yulInterpreterTests/side_effect_free.yul index 8eac1f5a9..1b8107646 100644 --- a/test/libyul/yulInterpreterTests/side_effect_free.yul +++ b/test/libyul/yulInterpreterTests/side_effect_free.yul @@ -6,7 +6,6 @@ pop(extcodehash(0)) pop(returndatasize()) pop(sload(0)) - pop(pc()) pop(msize()) pop(mload(0)) pop(sload(0)) diff --git a/test/libyul/yulOptimizerTests/fullSuite/stack_compressor_msize.yul b/test/libyul/yulOptimizerTests/fullSuite/stack_compressor_msize.yul index 961abd72c..56a2d6cfe 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/stack_compressor_msize.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/stack_compressor_msize.yul @@ -1,10 +1,23 @@ { 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 { - 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) - sstore(not(pc()),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(f()),1) } function foo_singlereturn_1(in_1, in_2) -> out @@ -25,21 +38,27 @@ // // { // { -// let _1 := gt(not(pc()), 1) -// let _2 := pc() +// let _1 := gt(not(gcd(10, 15)), 1) +// let _2 := gcd(10, 15) // let _3 := not(0) -// let _4 := lt(or(1, add(pc(), _3)), 1) -// let _5 := pc() -// let _6 := pc() -// pop(keccak256(pc(), or(gt(not(pc()), 1), 1))) +// let _4 := lt(or(1, add(gcd(10, 15), _3)), 1) +// let _5 := gcd(10, 15) +// let _6 := gcd(10, 15) +// 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) -// sstore(not(pc()), 1) +// sstore(not(gcd(10, 15)), 1) // sstore(0, 0) // sstore(2, 1) // pop(foo_singlereturn_1(calldataload(0), calldataload(3))) // sstore(0, 0) // 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 // { extcodecopy(1, msize(), 1, 1) } // } diff --git a/test/libyul/yulOptimizerTests/stackCompressor/unusedPrunerWithMSize.yul b/test/libyul/yulOptimizerTests/stackCompressor/unusedPrunerWithMSize.yul index 279c0d901..7e3acd9b6 100644 --- a/test/libyul/yulOptimizerTests/stackCompressor/unusedPrunerWithMSize.yul +++ b/test/libyul/yulOptimizerTests/stackCompressor/unusedPrunerWithMSize.yul @@ -1,11 +1,11 @@ { { let _13_71 := 1 - let _17_72 := pc() - let _22_75 := pc() - let _25_76 := pc() - let _30_80 := pc() - let _32_81 := pc() + let _17_72 := msize() + let _22_75 := msize() + let _25_76 := msize() + let _30_80 := msize() + let _32_81 := msize() // This should not be removed pop(keccak256(1, 2)) let _104 := gt(not(_17_72), _13_71) @@ -22,11 +22,11 @@ // step: stackCompressor // // { -// let _17_72 := pc() -// let _22_75 := pc() -// let _25_76 := pc() -// let _30_80 := pc() -// let _32_81 := pc() +// let _17_72 := msize() +// let _22_75 := msize() +// let _25_76 := msize() +// let _30_80 := msize() +// let _32_81 := msize() // pop(keccak256(1, 2)) // 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) diff --git a/test/libyul/yulSyntaxTests/pc.yul b/test/libyul/yulSyntaxTests/pc.yul new file mode 100644 index 000000000..04804f150 --- /dev/null +++ b/test/libyul/yulSyntaxTests/pc.yul @@ -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.