returndatacopy and bugfix.

This commit is contained in:
chriseth 2022-11-28 15:27:24 +01:00
parent b09a8c62bb
commit 1013419597
3 changed files with 34 additions and 34 deletions

View File

@ -78,12 +78,10 @@ void UnusedStoreEliminator::run(OptimiserStepContext& _context, Block& _ast)
ignoreMemory ignoreMemory
}; };
rse(_ast); rse(_ast);
if (
auto evmDialect = dynamic_cast<EVMDialect const*>(&_context.dialect); auto evmDialect = dynamic_cast<EVMDialect const*>(&_context.dialect);
evmDialect && evmDialect->providesObjectAccess() if (evmDialect && evmDialect->providesObjectAccess())
) rse.clearActive(Location::Memory);
{
}
else else
rse.markActiveAsUsed(Location::Memory); rse.markActiveAsUsed(Location::Memory);
rse.markActiveAsUsed(Location::Storage); rse.markActiveAsUsed(Location::Storage);
@ -168,25 +166,30 @@ void UnusedStoreEliminator::visit(Statement const& _statement)
yulAssert(isCandidateForRemoval == (isStorageWrite || (!m_ignoreMemory && isMemoryWrite))); yulAssert(isCandidateForRemoval == (isStorageWrite || (!m_ignoreMemory && isMemoryWrite)));
if (isCandidateForRemoval) if (isCandidateForRemoval)
{ {
// TODO what is this special case? if (*instruction == Instruction::RETURNDATACOPY)
//State initialState = State::Undecided; {
// if (*instruction == Instruction::RETURNDATACOPY) // Out-of-bounds access to the returndata buffer results in a revert,
// { // so we are careful not to remove a potentially reverting call to a builtin.
// initialState = State::Used; // The only way the Solidity compiler uses `returndatacopy` is
// auto startOffset = identifierNameIfSSA(funCall->arguments.at(1)); // `returndatacopy(X, 0, returndatasize())`, so we only allow to remove this pattern
// auto length = identifierNameIfSSA(funCall->arguments.at(2)); // (which is guaranteed to never cause an out-of-bounds revert).
// KnowledgeBase knowledge(m_dialect, [this](YulString _var) { return util::valueOrNullptr(m_ssaValues, _var); }); bool allowReturndatacopyToBeRemoved = false;
// if (length && startOffset) auto startOffset = identifierNameIfSSA(funCall->arguments.at(1));
// { auto length = identifierNameIfSSA(funCall->arguments.at(2));
// FunctionCall const* lengthCall = get_if<FunctionCall>(m_ssaValues.at(*length).value); KnowledgeBase knowledge(m_dialect, [this](YulString _var) { return util::valueOrNullptr(m_ssaValues, _var); });
// if ( if (length && startOffset)
// knowledge.knownToBeZero(*startOffset) && {
// lengthCall && FunctionCall const* lengthCall = get_if<FunctionCall>(m_ssaValues.at(*length).value);
// toEVMInstruction(m_dialect, lengthCall->functionName.name) == Instruction::RETURNDATASIZE if (
// ) knowledge.knownToBeZero(*startOffset) &&
// initialState = State::Undecided; lengthCall &&
// } toEVMInstruction(m_dialect, lengthCall->functionName.name) == Instruction::RETURNDATASIZE
// } )
allowReturndatacopyToBeRemoved = true;
}
if (!allowReturndatacopyToBeRemoved)
return;
}
m_allStores.insert(&_statement); m_allStores.insert(&_statement);
vector<Operation> operations = operationsFromFunctionCall(*funCall); vector<Operation> operations = operationsFromFunctionCall(*funCall);
yulAssert(operations.size() == 1, ""); yulAssert(operations.size() == 1, "");
@ -198,11 +201,6 @@ void UnusedStoreEliminator::visit(Statement const& _statement)
} }
} }
void UnusedStoreEliminator::finalizeFunctionDefinition(FunctionDefinition const&)
{
markActiveAsUsed();
}
vector<UnusedStoreEliminator::Operation> UnusedStoreEliminator::operationsFromFunctionCall( vector<UnusedStoreEliminator::Operation> UnusedStoreEliminator::operationsFromFunctionCall(
FunctionCall const& _functionCall FunctionCall const& _functionCall
) const ) const

View File

@ -98,14 +98,17 @@ public:
private: private:
std::set<Statement const*>& activeMemoryStores() { return m_activeStores["m"_yulstring]; } std::set<Statement const*>& activeMemoryStores() { return m_activeStores["m"_yulstring]; }
std::set<Statement const*>& activeStorageStores() { return m_activeStores["m"_yulstring]; } std::set<Statement const*>& activeStorageStores() { return m_activeStores["s"_yulstring]; }
void shortcutNestedLoop(ActiveStores const&) override void shortcutNestedLoop(ActiveStores const&) override
{ {
// We might only need to do this for newly introduced stores in the loop. // We might only need to do this for newly introduced stores in the loop.
markActiveAsUsed(); markActiveAsUsed();
} }
void finalizeFunctionDefinition(FunctionDefinition const&) override; void finalizeFunctionDefinition(FunctionDefinition const&) override
{
markActiveAsUsed();
}
std::vector<Operation> operationsFromFunctionCall(FunctionCall const& _functionCall) const; std::vector<Operation> operationsFromFunctionCall(FunctionCall const& _functionCall) const;
void applyOperation(Operation const& _operation); void applyOperation(Operation const& _operation);

View File

@ -39,8 +39,7 @@
// } // }
// if calldataload(2) // if calldataload(2)
// { // {
// let _17 := 7 // mstore8(2, 7)
// let _18 := 2
// calldatacopy(0, 0, 3) // calldatacopy(0, 0, 3)
// } // }
// if calldataload(3) // if calldataload(3)