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.arguments = _arguments;
|
||||||
exp.sequenceNumber = _sequenceNumber;
|
exp.sequenceNumber = _sequenceNumber;
|
||||||
|
|
||||||
if (SemanticInformation::isCommutativeOperation(_item))
|
if (SemanticInformation::isDeterministic(_item))
|
||||||
sort(exp.arguments.begin(), exp.arguments.end());
|
{
|
||||||
|
if (SemanticInformation::isCommutativeOperation(_item))
|
||||||
|
sort(exp.arguments.begin(), exp.arguments.end());
|
||||||
|
|
||||||
auto it = m_expressions.find(exp);
|
auto it = m_expressions.find(exp);
|
||||||
if (it != m_expressions.end())
|
if (it != m_expressions.end())
|
||||||
return it->id;
|
return it->id;
|
||||||
|
}
|
||||||
|
|
||||||
if (_copyItem)
|
if (_copyItem)
|
||||||
exp.item = storeItem(_item);
|
exp.item = storeItem(_item);
|
||||||
@ -286,7 +289,11 @@ ExpressionClasses::Id ExpressionClasses::tryToSimplify(Expression const& _expr,
|
|||||||
{
|
{
|
||||||
static Rules rules;
|
static Rules rules;
|
||||||
|
|
||||||
if (!_expr.item || _expr.item->type() != Operation)
|
if (
|
||||||
|
!_expr.item ||
|
||||||
|
_expr.item->type() != Operation ||
|
||||||
|
!SemanticInformation::isDeterministic(*_expr.item)
|
||||||
|
)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
for (auto const& rule: rules.rules())
|
for (auto const& rule: rules.rules())
|
||||||
|
@ -101,6 +101,7 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool
|
|||||||
vector<Id> arguments(info.args);
|
vector<Id> arguments(info.args);
|
||||||
for (int i = 0; i < info.args; ++i)
|
for (int i = 0; i < info.args; ++i)
|
||||||
arguments[i] = stackElement(m_stackHeight - i, _item.getLocation());
|
arguments[i] = stackElement(m_stackHeight - i, _item.getLocation());
|
||||||
|
|
||||||
if (_item.instruction() == Instruction::SSTORE)
|
if (_item.instruction() == Instruction::SSTORE)
|
||||||
op = storeInStorage(arguments[0], arguments[1], _item.getLocation());
|
op = storeInStorage(arguments[0], arguments[1], _item.getLocation());
|
||||||
else if (_item.instruction() == Instruction::SLOAD)
|
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())
|
applySha3(arguments.at(0), arguments.at(1), _item.getLocation())
|
||||||
);
|
);
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (SemanticInformation::invalidatesMemory(_item.instruction()))
|
||||||
|
resetMemory();
|
||||||
|
if (SemanticInformation::invalidatesStorage(_item.instruction()))
|
||||||
|
resetStorage();
|
||||||
setStackElement(
|
setStackElement(
|
||||||
m_stackHeight + _item.deposit(),
|
m_stackHeight + _item.deposit(),
|
||||||
m_expressionClasses->find(_item, arguments, _copyItem)
|
m_expressionClasses->find(_item, arguments, _copyItem)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m_stackHeight += _item.deposit();
|
m_stackHeight += _item.deposit();
|
||||||
}
|
}
|
||||||
|
@ -122,3 +122,57 @@ bool SemanticInformation::altersControlFlow(AssemblyItem const& _item)
|
|||||||
return false;
|
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
|
#pragma once
|
||||||
|
|
||||||
|
#include <libevmcore/Instruction.h>
|
||||||
|
|
||||||
namespace dev
|
namespace dev
|
||||||
{
|
{
|
||||||
@ -45,6 +46,14 @@ struct SemanticInformation
|
|||||||
static bool isSwapInstruction(AssemblyItem const& _item);
|
static bool isSwapInstruction(AssemblyItem const& _item);
|
||||||
static bool isJumpInstruction(AssemblyItem const& _item);
|
static bool isJumpInstruction(AssemblyItem const& _item);
|
||||||
static bool altersControlFlow(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