Refactor SideEffects struct

This commit is contained in:
Harikrishnan Mulackal
2020-08-18 14:53:59 +02:00
parent 58bfe0b0d2
commit 3cbe65e4f3
24 changed files with 290 additions and 126 deletions
+4 -3
View File
@@ -155,8 +155,10 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool
);
break;
default:
bool invMem = SemanticInformation::invalidatesMemory(_item.instruction());
bool invStor = SemanticInformation::invalidatesStorage(_item.instruction());
bool invMem =
SemanticInformation::memory(_item.instruction()) == SemanticInformation::Write;
bool invStor =
SemanticInformation::storage(_item.instruction()) == SemanticInformation::Write;
// We could be a bit more fine-grained here (CALL only invalidates part of
// memory, etc), but we do not for now.
if (invMem)
@@ -420,4 +422,3 @@ KnownState::Id KnownState::tagUnion(set<u256> _tags)
return id;
}
}
+79 -9
View File
@@ -233,7 +233,7 @@ bool SemanticInformation::movable(Instruction _instruction)
return true;
}
bool SemanticInformation::sideEffectFree(Instruction _instruction)
bool SemanticInformation::canBeRemoved(Instruction _instruction)
{
// These are not really functional.
assertThrow(!isDupInstruction(_instruction) && !isSwapInstruction(_instruction), AssemblyException, "");
@@ -241,15 +241,15 @@ bool SemanticInformation::sideEffectFree(Instruction _instruction)
return !instructionInfo(_instruction).sideEffects;
}
bool SemanticInformation::sideEffectFreeIfNoMSize(Instruction _instruction)
bool SemanticInformation::canBeRemovedIfNoMSize(Instruction _instruction)
{
if (_instruction == Instruction::KECCAK256 || _instruction == Instruction::MLOAD)
return true;
else
return sideEffectFree(_instruction);
return canBeRemoved(_instruction);
}
bool SemanticInformation::invalidatesMemory(Instruction _instruction)
SemanticInformation::Effect SemanticInformation::memory(Instruction _instruction)
{
switch (_instruction)
{
@@ -263,13 +263,47 @@ bool SemanticInformation::invalidatesMemory(Instruction _instruction)
case Instruction::CALLCODE:
case Instruction::DELEGATECALL:
case Instruction::STATICCALL:
return true;
return SemanticInformation::Write;
case Instruction::CREATE:
case Instruction::CREATE2:
case Instruction::KECCAK256:
case Instruction::MLOAD:
case Instruction::MSIZE:
case Instruction::RETURN:
case Instruction::REVERT:
case Instruction::LOG0:
case Instruction::LOG1:
case Instruction::LOG2:
case Instruction::LOG3:
case Instruction::LOG4:
return SemanticInformation::Read;
default:
return false;
return SemanticInformation::None;
}
}
bool SemanticInformation::invalidatesStorage(Instruction _instruction)
bool SemanticInformation::movableApartFromEffects(Instruction _instruction)
{
switch (_instruction)
{
case Instruction::EXTCODEHASH:
case Instruction::EXTCODESIZE:
case Instruction::RETURNDATASIZE:
case Instruction::BALANCE:
case Instruction::SELFBALANCE:
case Instruction::SLOAD:
case Instruction::KECCAK256:
case Instruction::MLOAD:
return true;
default:
return movable(_instruction);
}
}
SemanticInformation::Effect SemanticInformation::storage(Instruction _instruction)
{
switch (_instruction)
{
@@ -279,9 +313,45 @@ bool SemanticInformation::invalidatesStorage(Instruction _instruction)
case Instruction::CREATE:
case Instruction::CREATE2:
case Instruction::SSTORE:
return true;
return SemanticInformation::Write;
case Instruction::SLOAD:
case Instruction::STATICCALL:
return SemanticInformation::Read;
default:
return false;
return SemanticInformation::None;
}
}
SemanticInformation::Effect SemanticInformation::otherState(Instruction _instruction)
{
switch (_instruction)
{
case Instruction::CALL:
case Instruction::CALLCODE:
case Instruction::DELEGATECALL:
case Instruction::CREATE:
case Instruction::CREATE2:
case Instruction::SELFDESTRUCT:
case Instruction::STATICCALL: // because it can affect returndatasize
// Strictly speaking, log0, .., log4 writes to the state, but the EVM cannot read it, so they
// are just marked as having 'other side effects.'
return SemanticInformation::Write;
case Instruction::EXTCODESIZE:
case Instruction::EXTCODEHASH:
case Instruction::RETURNDATASIZE:
case Instruction::BALANCE:
case Instruction::SELFBALANCE:
case Instruction::RETURNDATACOPY:
case Instruction::EXTCODECOPY:
// PC and GAS are specifically excluded here. Instructions such as CALLER, CALLVALUE,
// ADDRESS are excluded because they cannot change during execution.
return SemanticInformation::Read;
default:
return SemanticInformation::None;
}
}
+18 -6
View File
@@ -36,6 +36,15 @@ class AssemblyItem;
*/
struct SemanticInformation
{
/// Corresponds to the effect that a YUL-builtin has on a generic data location (storage, memory
/// and other blockchain state).
enum Effect
{
None,
Read,
Write
};
/// @returns true if the given items starts a new block for common subexpression analysis.
/// @param _msizeImportant if false, consider an operation non-breaking if its only side-effect is that it modifies msize.
static bool breaksCSEAnalysisBlock(AssemblyItem const& _item, bool _msizeImportant);
@@ -57,20 +66,23 @@ struct SemanticInformation
/// without altering the semantics. This means it cannot depend on storage or memory,
/// cannot have any side-effects, but it can depend on a call-constant state of the blockchain.
static bool movable(Instruction _instruction);
/// If true, the expressions in this code can be moved or copied (together with their arguments)
/// across control flow branches and instructions as long as these instructions' 'effects' do
/// not influence the 'effects' of the aforementioned expressions.
static bool movableApartFromEffects(Instruction _instruction);
/// @returns true if the instruction can be removed without changing the semantics.
/// This does not mean that it has to be deterministic or retrieve information from
/// somewhere else than purely the values of its arguments.
static bool sideEffectFree(Instruction _instruction);
static bool canBeRemoved(Instruction _instruction);
/// @returns true if the instruction can be removed without changing the semantics.
/// This does not mean that it has to be deterministic or retrieve information from
/// somewhere else than purely the values of its arguments.
/// If true, the instruction is still allowed to influence the value returned by the
/// msize instruction.
static bool sideEffectFreeIfNoMSize(Instruction _instruction);
/// @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);
static bool canBeRemovedIfNoMSize(Instruction _instruction);
static Effect memory(Instruction _instruction);
static Effect storage(Instruction _instruction);
static Effect otherState(Instruction _instruction);
static bool invalidInPureFunctions(Instruction _instruction);
static bool invalidInViewFunctions(Instruction _instruction);
};