Mark EVM instruction pc() as deprecated when used in inline assembly.

This commit is contained in:
Christian Parpart 2020-05-12 17:09:25 +02:00
parent b488627c79
commit b7fa5d5040
11 changed files with 74 additions and 31 deletions

View File

@ -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:

View File

@ -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;
} }

View File

@ -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 (

View File

@ -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);

View File

@ -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

View 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.

View File

@ -1,8 +0,0 @@
{
sstore(0, pc())
}
// ----
// Trace:
// INVALID()
// Memory dump:
// Storage dump:

View File

@ -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))

View File

@ -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) }
// } // }

View File

@ -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)

View 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.