mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Make KnownState work with all instructions.
This commit is contained in:
parent
867101e409
commit
a2e3bcbd0c
@ -57,12 +57,15 @@ ExpressionClasses::Id ExpressionClasses::find(
|
||||
exp.arguments = _arguments;
|
||||
exp.sequenceNumber = _sequenceNumber;
|
||||
|
||||
if (SemanticInformation::isCommutativeOperation(_item))
|
||||
sort(exp.arguments.begin(), exp.arguments.end());
|
||||
if (SemanticInformation::isDeterministic(_item))
|
||||
{
|
||||
if (SemanticInformation::isCommutativeOperation(_item))
|
||||
sort(exp.arguments.begin(), exp.arguments.end());
|
||||
|
||||
auto it = m_expressions.find(exp);
|
||||
if (it != m_expressions.end())
|
||||
return it->id;
|
||||
auto it = m_expressions.find(exp);
|
||||
if (it != m_expressions.end())
|
||||
return it->id;
|
||||
}
|
||||
|
||||
if (_copyItem)
|
||||
exp.item = storeItem(_item);
|
||||
@ -286,7 +289,11 @@ ExpressionClasses::Id ExpressionClasses::tryToSimplify(Expression const& _expr,
|
||||
{
|
||||
static Rules rules;
|
||||
|
||||
if (!_expr.item || _expr.item->type() != Operation)
|
||||
if (
|
||||
!_expr.item ||
|
||||
_expr.item->type() != Operation ||
|
||||
!SemanticInformation::isDeterministic(*_expr.item)
|
||||
)
|
||||
return -1;
|
||||
|
||||
for (auto const& rule: rules.rules())
|
||||
|
@ -101,6 +101,7 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool
|
||||
vector<Id> arguments(info.args);
|
||||
for (int i = 0; i < info.args; ++i)
|
||||
arguments[i] = stackElement(m_stackHeight - i, _item.getLocation());
|
||||
|
||||
if (_item.instruction() == Instruction::SSTORE)
|
||||
op = storeInStorage(arguments[0], arguments[1], _item.getLocation());
|
||||
else if (_item.instruction() == Instruction::SLOAD)
|
||||
@ -121,10 +122,16 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool
|
||||
applySha3(arguments.at(0), arguments.at(1), _item.getLocation())
|
||||
);
|
||||
else
|
||||
{
|
||||
if (SemanticInformation::invalidatesMemory(_item.instruction()))
|
||||
resetMemory();
|
||||
if (SemanticInformation::invalidatesStorage(_item.instruction()))
|
||||
resetStorage();
|
||||
setStackElement(
|
||||
m_stackHeight + _item.deposit(),
|
||||
m_expressionClasses->find(_item, arguments, _copyItem)
|
||||
);
|
||||
}
|
||||
}
|
||||
m_stackHeight += _item.deposit();
|
||||
}
|
||||
|
@ -122,3 +122,57 @@ bool SemanticInformation::altersControlFlow(AssemblyItem const& _item)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool SemanticInformation::isDeterministic(AssemblyItem const& _item)
|
||||
{
|
||||
if (_item.type() != Operation)
|
||||
return true;
|
||||
assertThrow(!altersControlFlow(_item), OptimizerException, "");
|
||||
|
||||
switch (_item.instruction())
|
||||
{
|
||||
case Instruction::CALL:
|
||||
case Instruction::CALLCODE:
|
||||
case Instruction::CREATE:
|
||||
case Instruction::GAS:
|
||||
case Instruction::PC:
|
||||
case Instruction::MSIZE: // depends on previous writes and reads, not only on content
|
||||
case Instruction::BALANCE: // depends on previous calls
|
||||
case Instruction::EXTCODESIZE:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool SemanticInformation::invalidatesMemory(Instruction _instruction)
|
||||
{
|
||||
switch (_instruction)
|
||||
{
|
||||
case Instruction::CALLDATACOPY:
|
||||
case Instruction::CODECOPY:
|
||||
case Instruction::EXTCODECOPY:
|
||||
case Instruction::MSTORE:
|
||||
case Instruction::MSTORE8:
|
||||
case Instruction::CALL:
|
||||
case Instruction::CALLCODE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SemanticInformation::invalidatesStorage(Instruction _instruction)
|
||||
{
|
||||
switch (_instruction)
|
||||
{
|
||||
case Instruction::CALL:
|
||||
case Instruction::CALLCODE:
|
||||
case Instruction::CREATE:
|
||||
case Instruction::SSTORE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <libevmcore/Instruction.h>
|
||||
|
||||
namespace dev
|
||||
{
|
||||
@ -45,6 +46,14 @@ struct SemanticInformation
|
||||
static bool isSwapInstruction(AssemblyItem const& _item);
|
||||
static bool isJumpInstruction(AssemblyItem const& _item);
|
||||
static bool altersControlFlow(AssemblyItem const& _item);
|
||||
/// @returns false if the value put on the stack by _item depends on anything else than
|
||||
/// the information in the current block header, memory, storage or stack.
|
||||
/// @note should not be called for instructions that alter the control flow.
|
||||
static bool isDeterministic(AssemblyItem const& _item);
|
||||
/// @returns true if the given instruction modifies memory.
|
||||
static bool invalidatesMemory(Instruction _instruction);
|
||||
/// @returns true if the given instruction modifies storage (even indirectly).
|
||||
static bool invalidatesStorage(Instruction _instruction);
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user