Search & Replace

This commit is contained in:
Marenz 2022-10-04 19:23:16 +02:00
parent b44b9285e4
commit 513d5a3265
64 changed files with 2043 additions and 2040 deletions

View File

@ -83,10 +83,10 @@ public:
append(AssemblyItem(std::move(_data), _arguments, _returnVariables));
}
AssemblyItem appendJump() { auto ret = append(newPushTag()); append(Instruction::JUMP); return ret; }
AssemblyItem appendJumpI() { auto ret = append(newPushTag()); append(Instruction::JUMPI); return ret; }
AssemblyItem appendJump(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(Instruction::JUMP); return ret; }
AssemblyItem appendJumpI(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(Instruction::JUMPI); return ret; }
AssemblyItem appendJump() { auto ret = append(newPushTag()); append(InternalInstruction::JUMP); return ret; }
AssemblyItem appendJumpI() { auto ret = append(newPushTag()); append(InternalInstruction::JUMPI); return ret; }
AssemblyItem appendJump(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(InternalInstruction::JUMP); return ret; }
AssemblyItem appendJumpI(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(InternalInstruction::JUMPI); return ret; }
/// Adds a subroutine to the code (in the data section) and pushes its size (via a tag)
/// on the stack. @returns the pushsub assembly item.

View File

@ -329,7 +329,7 @@ ostream& solidity::evmasm::operator<<(ostream& _out, AssemblyItem const& _item)
{
case Operation:
_out << " " << instructionInfo(_item.instruction()).name;
if (_item.instruction() == Instruction::JUMP || _item.instruction() == Instruction::JUMPI)
if (_item.instruction() == InternalInstruction::JUMP || _item.instruction() == InternalInstruction::JUMPI)
_out << "\t" << _item.getJumpTypeAsString();
break;
case Push:

View File

@ -66,7 +66,7 @@ public:
AssemblyItem(u256 _push, langutil::SourceLocation _location = langutil::SourceLocation()):
AssemblyItem(Push, std::move(_push), std::move(_location)) { }
AssemblyItem(Instruction _i, langutil::SourceLocation _location = langutil::SourceLocation()):
AssemblyItem(InternalInstruction _i, langutil::SourceLocation _location = langutil::SourceLocation()):
m_type(Operation),
m_instruction(_i),
m_location(std::move(_location))
@ -76,7 +76,7 @@ public:
m_location(std::move(_location))
{
if (m_type == Operation)
m_instruction = Instruction(uint8_t(_data));
m_instruction = InternalInstruction(uint8_t(_data));
else
m_data = std::make_shared<u256>(std::move(_data));
}
@ -116,7 +116,7 @@ public:
bytes const& verbatimData() const { assertThrow(m_type == VerbatimBytecode, util::Exception, ""); return std::get<2>(*m_verbatimBytecode); }
/// @returns the instruction of this item (only valid if type() == Operation)
Instruction instruction() const { assertThrow(m_type == Operation, util::Exception, ""); return m_instruction; }
InternalInstruction instruction() const { assertThrow(m_type == Operation, util::Exception, ""); return m_instruction; }
/// @returns true if the type and data of the items are equal.
bool operator==(AssemblyItem const& _other) const
@ -145,11 +145,11 @@ public:
}
/// Shortcut that avoids constructing an AssemblyItem just to perform the comparison.
bool operator==(Instruction _instr) const
bool operator==(InternalInstruction _instr) const
{
return type() == Operation && instruction() == _instr;
}
bool operator!=(Instruction _instr) const { return !operator==(_instr); }
bool operator!=(InternalInstruction _instr) const { return !operator==(_instr); }
static std::string computeSourceMapping(
AssemblyItems const& _items,
@ -189,7 +189,7 @@ private:
size_t opcodeCount() const noexcept;
AssemblyItemType m_type;
Instruction m_instruction; ///< Only valid if m_type == Operation
InternalInstruction m_instruction; ///< Only valid if m_type == Operation
std::shared_ptr<u256> m_data; ///< Only valid if m_type != Operation
/// If m_type == VerbatimBytecode, this holds number of arguments, number of
/// return variables and verbatim bytecode.

View File

@ -132,7 +132,7 @@ BlockDeduplicator::BlockIterator& BlockDeduplicator::BlockIterator::operator++()
{
if (it == end)
return *this;
if (SemanticInformation::altersControlFlow(*it) && *it != AssemblyItem{Instruction::JUMPI})
if (SemanticInformation::altersControlFlow(*it) && *it != AssemblyItem{InternalInstruction::JUMPI})
it = end;
else
{

View File

@ -88,36 +88,36 @@ void CommonSubexpressionEliminator::optimizeBreakingItem()
ExpressionClasses& classes = m_state.expressionClasses();
SourceLocation const& itemLocation = m_breakingItem->location();
if (*m_breakingItem == AssemblyItem(Instruction::JUMPI))
if (*m_breakingItem == AssemblyItem(InternalInstruction::JUMPI))
{
AssemblyItem::JumpType jumpType = m_breakingItem->getJumpType();
Id condition = m_state.stackElement(m_state.stackHeight() - 1, itemLocation);
if (classes.knownNonZero(condition))
{
feedItem(AssemblyItem(Instruction::SWAP1, itemLocation), true);
feedItem(AssemblyItem(Instruction::POP, itemLocation), true);
feedItem(AssemblyItem(InternalInstruction::SWAP1, itemLocation), true);
feedItem(AssemblyItem(InternalInstruction::POP, itemLocation), true);
AssemblyItem item(Instruction::JUMP, itemLocation);
AssemblyItem item(InternalInstruction::JUMP, itemLocation);
item.setJumpType(jumpType);
m_breakingItem = classes.storeItem(item);
}
else if (classes.knownZero(condition))
{
AssemblyItem it(Instruction::POP, itemLocation);
AssemblyItem it(InternalInstruction::POP, itemLocation);
feedItem(it, true);
feedItem(it, true);
m_breakingItem = nullptr;
}
}
else if (*m_breakingItem == AssemblyItem(Instruction::RETURN))
else if (*m_breakingItem == AssemblyItem(InternalInstruction::RETURN))
{
Id size = m_state.stackElement(m_state.stackHeight() - 1, itemLocation);
if (classes.knownZero(size))
{
feedItem(AssemblyItem(Instruction::POP, itemLocation), true);
feedItem(AssemblyItem(Instruction::POP, itemLocation), true);
AssemblyItem item(Instruction::STOP, itemLocation);
feedItem(AssemblyItem(InternalInstruction::POP, itemLocation), true);
feedItem(AssemblyItem(InternalInstruction::POP, itemLocation), true);
AssemblyItem item(InternalInstruction::STOP, itemLocation);
m_breakingItem = classes.storeItem(item);
}
}
@ -233,15 +233,15 @@ void CSECodeGenerator::addDependencies(Id _c)
m_neededBy.insert(make_pair(argument, _c));
}
if (expr.item && expr.item->type() == Operation && (
expr.item->instruction() == Instruction::SLOAD ||
expr.item->instruction() == Instruction::MLOAD ||
expr.item->instruction() == Instruction::KECCAK256
expr.item->instruction() == InternalInstruction::SLOAD ||
expr.item->instruction() == InternalInstruction::MLOAD ||
expr.item->instruction() == InternalInstruction::KECCAK256
))
{
// this loads an unknown value from storage or memory and thus, in addition to its
// arguments, depends on all store operations to addresses where we do not know that
// they are different that occur before this load
StoreOperation::Target target = expr.item->instruction() == Instruction::SLOAD ?
StoreOperation::Target target = expr.item->instruction() == InternalInstruction::SLOAD ?
StoreOperation::Storage : StoreOperation::Memory;
Id slotToLoadFrom = expr.arguments.at(0);
for (auto const& p: m_storeOperations)
@ -255,16 +255,16 @@ void CSECodeGenerator::addDependencies(Id _c)
bool knownToBeIndependent = false;
switch (expr.item->instruction())
{
case Instruction::SLOAD:
case InternalInstruction::SLOAD:
knownToBeIndependent = m_expressionClasses.knownToBeDifferent(slot, slotToLoadFrom);
break;
case Instruction::MLOAD:
case InternalInstruction::MLOAD:
knownToBeIndependent = m_expressionClasses.knownToBeDifferentBy32(slot, slotToLoadFrom);
break;
case Instruction::KECCAK256:
case InternalInstruction::KECCAK256:
{
Id length = expr.arguments.at(1);
AssemblyItem offsetInstr(Instruction::SUB, expr.item->location());
AssemblyItem offsetInstr(InternalInstruction::SUB, expr.item->location());
Id offsetToStart = m_expressionClasses.find(offsetInstr, {slot, slotToLoadFrom});
u256 const* o = m_expressionClasses.knownConstant(offsetToStart);
u256 const* l = m_expressionClasses.knownConstant(length);
@ -397,7 +397,7 @@ void CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced)
while (SemanticInformation::isCommutativeOperation(*expr.item) &&
!m_generatedItems.empty() &&
m_generatedItems.back() == AssemblyItem(Instruction::SWAP1))
m_generatedItems.back() == AssemblyItem(InternalInstruction::SWAP1))
// this will not append a swap but remove the one that is already there
appendOrRemoveSwap(m_stackHeight - 1, itemLocation);
for (size_t i = 0; i < arguments.size(); ++i)
@ -464,7 +464,7 @@ bool CSECodeGenerator::removeStackTopIfPossible()
return false;
m_classPositions[m_stack[m_stackHeight]].erase(m_stackHeight);
m_stack.erase(m_stackHeight);
appendItem(AssemblyItem(Instruction::POP));
appendItem(AssemblyItem(InternalInstruction::POP));
return true;
}

View File

@ -84,10 +84,10 @@ bigint ConstantOptimisationMethod::simpleRunGas(AssemblyItems const& _items)
bigint gas = 0;
for (AssemblyItem const& item: _items)
if (item.type() == Push)
gas += GasMeter::runGas(Instruction::PUSH1);
gas += GasMeter::runGas(InternalInstruction::PUSH1);
else if (item.type() == Operation)
{
if (item.instruction() == Instruction::EXP)
if (item.instruction() == InternalInstruction::EXP)
gas += GasCosts::expGas;
else
gas += GasMeter::runGas(item.instruction());
@ -131,7 +131,7 @@ void ConstantOptimisationMethod::replaceConstants(
bigint LiteralMethod::gasNeeded() const
{
return combineGas(
simpleRunGas({Instruction::PUSH1}),
simpleRunGas({InternalInstruction::PUSH1}),
// PUSHX plus data
(m_params.isCreation ? GasCosts::txDataNonZeroGas(m_params.evmVersion) : GasCosts::createDataGas) + dataGas(toCompactBigEndian(m_value, 1)),
0
@ -167,22 +167,22 @@ AssemblyItems const& CodeCopyMethod::copyRoutine()
// back up memory
// mload(0)
Instruction::DUP1,
Instruction::MLOAD,
InternalInstruction::DUP1,
InternalInstruction::MLOAD,
// codecopy(0, <offset>, 32)
u256(32),
AssemblyItem(PushData, u256(1) << 16), // replaced above in actualCopyRoutine[4]
Instruction::DUP4,
Instruction::CODECOPY,
InternalInstruction::DUP4,
InternalInstruction::CODECOPY,
// mload(0)
Instruction::DUP2,
Instruction::MLOAD,
InternalInstruction::DUP2,
InternalInstruction::MLOAD,
// restore original memory
Instruction::SWAP2,
Instruction::MSTORE
InternalInstruction::SWAP2,
InternalInstruction::MSTORE
};
return copyRoutine;
}
@ -194,7 +194,7 @@ AssemblyItems ComputeMethod::findRepresentation(u256 const& _value)
return AssemblyItems{_value};
else if (numberEncodingSize(~_value) < numberEncodingSize(_value))
// Negated is shorter to represent
return findRepresentation(~_value) + AssemblyItems{Instruction::NOT};
return findRepresentation(~_value) + AssemblyItems{InternalInstruction::NOT};
else
{
// Decompose value into a * 2**k + b where abs(b) << 2**k
@ -226,18 +226,18 @@ AssemblyItems ComputeMethod::findRepresentation(u256 const& _value)
if (m_params.evmVersion.hasBitwiseShifting())
{
newRoutine += findRepresentation(upperPart);
newRoutine += AssemblyItems{u256(bits), Instruction::SHL};
newRoutine += AssemblyItems{u256(bits), InternalInstruction::SHL};
}
else
{
newRoutine += AssemblyItems{u256(bits), u256(2), Instruction::EXP};
newRoutine += AssemblyItems{u256(bits), u256(2), InternalInstruction::EXP};
if (upperPart != 1)
newRoutine += findRepresentation(upperPart) + AssemblyItems{Instruction::MUL};
newRoutine += findRepresentation(upperPart) + AssemblyItems{InternalInstruction::MUL};
}
if (lowerPart > 0)
newRoutine += AssemblyItems{Instruction::ADD};
newRoutine += AssemblyItems{InternalInstruction::ADD};
else if (lowerPart < 0)
newRoutine.push_back(Instruction::SUB);
newRoutine.push_back(InternalInstruction::SUB);
if (m_maxSteps > 0)
m_maxSteps--;
@ -267,24 +267,24 @@ bool ComputeMethod::checkRepresentation(u256 const& _value, AssemblyItems const&
u256* sp = &stack.back();
switch (item.instruction())
{
case Instruction::MUL:
case InternalInstruction::MUL:
sp[-1] = sp[0] * sp[-1];
break;
case Instruction::EXP:
case InternalInstruction::EXP:
if (sp[-1] > 0xff)
return false;
sp[-1] = boost::multiprecision::pow(sp[0], unsigned(sp[-1]));
break;
case Instruction::ADD:
case InternalInstruction::ADD:
sp[-1] = sp[0] + sp[-1];
break;
case Instruction::SUB:
case InternalInstruction::SUB:
sp[-1] = sp[0] - sp[-1];
break;
case Instruction::NOT:
case InternalInstruction::NOT:
sp[0] = ~sp[0];
break;
case Instruction::SHL:
case InternalInstruction::SHL:
assertThrow(
m_params.evmVersion.hasBitwiseShifting(),
OptimizerException,
@ -293,7 +293,7 @@ bool ComputeMethod::checkRepresentation(u256 const& _value, AssemblyItems const&
assertThrow(sp[0] <= u256(255), OptimizerException, "Invalid shift generated.");
sp[-1] = u256(bigint(sp[-1]) << unsigned(sp[0]));
break;
case Instruction::SHR:
case InternalInstruction::SHR:
assertThrow(
m_params.evmVersion.hasBitwiseShifting(),
OptimizerException,
@ -320,7 +320,7 @@ bool ComputeMethod::checkRepresentation(u256 const& _value, AssemblyItems const&
bigint ComputeMethod::gasNeeded(AssemblyItems const& _routine) const
{
auto numExps = static_cast<size_t>(count(_routine.begin(), _routine.end(), Instruction::EXP));
auto numExps = static_cast<size_t>(count(_routine.begin(), _routine.end(), InternalInstruction::EXP));
return combineGas(
simpleRunGas(_routine) + numExps * (GasCosts::expGas + GasCosts::expByteGas(m_params.evmVersion)),
// Data gas for routine: Some bytes are zero, but we ignore them.

View File

@ -92,9 +92,9 @@ void ControlFlowGraph::splitBlocks()
if (SemanticInformation::altersControlFlow(item))
{
m_blocks[id].end = static_cast<unsigned>(index + 1);
if (item == Instruction::JUMP)
if (item == InternalInstruction::JUMP)
m_blocks[id].endType = BasicBlock::EndType::JUMP;
else if (item == Instruction::JUMPI)
else if (item == InternalInstruction::JUMPI)
m_blocks[id].endType = BasicBlock::EndType::JUMPI;
else
m_blocks[id].endType = BasicBlock::EndType::STOP;

View File

@ -148,13 +148,13 @@ ExpressionClasses::Id ExpressionClasses::newClass(SourceLocation const& _locatio
bool ExpressionClasses::knownToBeDifferent(ExpressionClasses::Id _a, ExpressionClasses::Id _b)
{
// Try to simplify "_a - _b" and return true iff the value is a non-zero constant.
return knownNonZero(find(Instruction::SUB, {_a, _b}));
return knownNonZero(find(InternalInstruction::SUB, {_a, _b}));
}
bool ExpressionClasses::knownToBeDifferentBy32(ExpressionClasses::Id _a, ExpressionClasses::Id _b)
{
// Try to simplify "_a - _b" and return true iff the value is at least 32 away from zero.
u256 const* v = knownConstant(find(Instruction::SUB, {_a, _b}));
u256 const* v = knownConstant(find(InternalInstruction::SUB, {_a, _b}));
// forbidden interval is ["-31", 31]
return v && *v + 31 > u256(62);
}
@ -166,7 +166,7 @@ bool ExpressionClasses::knownZero(Id _c)
bool ExpressionClasses::knownNonZero(Id _c)
{
return Pattern(u256(0)).matches(representative(find(Instruction::ISZERO, {_c})), *this);
return Pattern(u256(0)).matches(representative(find(InternalInstruction::ISZERO, {_c})), *this);
}
u256 const* ExpressionClasses::knownConstant(Id _c)

View File

@ -52,17 +52,17 @@ GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item, bool _
case PushProgramSize:
case PushLibraryAddress:
case PushDeployTimeAddress:
gas = runGas(Instruction::PUSH1);
gas = runGas(InternalInstruction::PUSH1);
break;
case Tag:
gas = runGas(Instruction::JUMPDEST);
gas = runGas(InternalInstruction::JUMPDEST);
break;
case Operation:
{
ExpressionClasses& classes = m_state->expressionClasses();
switch (_item.instruction())
{
case Instruction::SSTORE:
case InternalInstruction::SSTORE:
{
ExpressionClasses::Id slot = m_state->relativeStackElement(0);
ExpressionClasses::Id value = m_state->relativeStackElement(-1);
@ -75,57 +75,57 @@ GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item, bool _
gas = GasCosts::totalSstoreSetGas(m_evmVersion);
break;
}
case Instruction::SLOAD:
case InternalInstruction::SLOAD:
gas = GasCosts::sloadGas(m_evmVersion);
break;
case Instruction::RETURN:
case Instruction::REVERT:
case InternalInstruction::RETURN:
case InternalInstruction::REVERT:
gas = runGas(_item.instruction());
gas += memoryGas(0, -1);
break;
case Instruction::MLOAD:
case Instruction::MSTORE:
case InternalInstruction::MLOAD:
case InternalInstruction::MSTORE:
gas = runGas(_item.instruction());
gas += memoryGas(classes.find(Instruction::ADD, {
gas += memoryGas(classes.find(InternalInstruction::ADD, {
m_state->relativeStackElement(0),
classes.find(AssemblyItem(32))
}));
break;
case Instruction::MSTORE8:
case InternalInstruction::MSTORE8:
gas = runGas(_item.instruction());
gas += memoryGas(classes.find(Instruction::ADD, {
gas += memoryGas(classes.find(InternalInstruction::ADD, {
m_state->relativeStackElement(0),
classes.find(AssemblyItem(1))
}));
break;
case Instruction::KECCAK256:
case InternalInstruction::KECCAK256:
gas = GasCosts::keccak256Gas;
gas += memoryGas(0, -1);
gas += wordGas(GasCosts::keccak256WordGas, m_state->relativeStackElement(-1));
break;
case Instruction::CALLDATACOPY:
case Instruction::CODECOPY:
case Instruction::RETURNDATACOPY:
case InternalInstruction::CALLDATACOPY:
case InternalInstruction::CODECOPY:
case InternalInstruction::RETURNDATACOPY:
gas = runGas(_item.instruction());
gas += memoryGas(0, -2);
gas += wordGas(GasCosts::copyGas, m_state->relativeStackElement(-2));
break;
case Instruction::EXTCODESIZE:
case InternalInstruction::EXTCODESIZE:
gas = GasCosts::extCodeGas(m_evmVersion);
break;
case Instruction::EXTCODEHASH:
case InternalInstruction::EXTCODEHASH:
gas = GasCosts::balanceGas(m_evmVersion);
break;
case Instruction::EXTCODECOPY:
case InternalInstruction::EXTCODECOPY:
gas = GasCosts::extCodeGas(m_evmVersion);
gas += memoryGas(-1, -3);
gas += wordGas(GasCosts::copyGas, m_state->relativeStackElement(-3));
break;
case Instruction::LOG0:
case Instruction::LOG1:
case Instruction::LOG2:
case Instruction::LOG3:
case Instruction::LOG4:
case InternalInstruction::LOG0:
case InternalInstruction::LOG1:
case InternalInstruction::LOG2:
case InternalInstruction::LOG3:
case InternalInstruction::LOG4:
{
gas = GasCosts::logGas + GasCosts::logTopicGas * getLogNumber(_item.instruction());
gas += memoryGas(0, -1);
@ -135,10 +135,10 @@ GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item, bool _
gas = GasConsumption::infinite();
break;
}
case Instruction::CALL:
case Instruction::CALLCODE:
case Instruction::DELEGATECALL:
case Instruction::STATICCALL:
case InternalInstruction::CALL:
case InternalInstruction::CALLCODE:
case InternalInstruction::DELEGATECALL:
case InternalInstruction::STATICCALL:
{
if (_includeExternalCosts)
// We assume that we do not know the target contract and thus, the consumption is infinite.
@ -150,10 +150,10 @@ GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item, bool _
gas += (*value);
else
gas = GasConsumption::infinite();
if (_item.instruction() == Instruction::CALL)
if (_item.instruction() == InternalInstruction::CALL)
gas += GasCosts::callNewAccountGas; // We very rarely know whether the address exists.
int valueSize = 1;
if (_item.instruction() == Instruction::DELEGATECALL || _item.instruction() == Instruction::STATICCALL)
if (_item.instruction() == InternalInstruction::DELEGATECALL || _item.instruction() == InternalInstruction::STATICCALL)
valueSize = 0;
else if (!classes.knownZero(m_state->relativeStackElement(-1 - valueSize)))
gas += GasCosts::callValueTransferGas;
@ -162,12 +162,12 @@ GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item, bool _
}
break;
}
case Instruction::SELFDESTRUCT:
case InternalInstruction::SELFDESTRUCT:
gas = GasCosts::selfdestructGas(m_evmVersion);
gas += GasCosts::callNewAccountGas; // We very rarely know whether the address exists.
break;
case Instruction::CREATE:
case Instruction::CREATE2:
case InternalInstruction::CREATE:
case InternalInstruction::CREATE2:
if (_includeExternalCosts)
// We assume that we do not know the target contract and thus, the consumption is infinite.
gas = GasConsumption::infinite();
@ -177,7 +177,7 @@ GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item, bool _
gas += memoryGas(-1, -2);
}
break;
case Instruction::EXP:
case InternalInstruction::EXP:
gas = GasCosts::expGas;
if (u256 const* value = classes.knownConstant(m_state->relativeStackElement(-1)))
{
@ -191,14 +191,14 @@ GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item, bool _
else
gas += GasCosts::expByteGas(m_evmVersion) * 32;
break;
case Instruction::BALANCE:
case InternalInstruction::BALANCE:
gas = GasCosts::balanceGas(m_evmVersion);
break;
case Instruction::CHAINID:
gas = runGas(Instruction::CHAINID);
case InternalInstruction::CHAINID:
gas = runGas(InternalInstruction::CHAINID);
break;
case Instruction::SELFBALANCE:
gas = runGas(Instruction::SELFBALANCE);
case InternalInstruction::SELFBALANCE:
gas = runGas(InternalInstruction::SELFBALANCE);
break;
default:
gas = runGas(_item.instruction());
@ -246,15 +246,15 @@ GasMeter::GasConsumption GasMeter::memoryGas(int _stackPosOffset, int _stackPosS
if (classes.knownZero(m_state->relativeStackElement(_stackPosSize)))
return GasConsumption(0);
else
return memoryGas(classes.find(Instruction::ADD, {
return memoryGas(classes.find(InternalInstruction::ADD, {
m_state->relativeStackElement(_stackPosOffset),
m_state->relativeStackElement(_stackPosSize)
}));
}
unsigned GasMeter::runGas(Instruction _instruction)
unsigned GasMeter::runGas(InternalInstruction _instruction)
{
if (_instruction == Instruction::JUMPDEST)
if (_instruction == InternalInstruction::JUMPDEST)
return 1;
switch (instructionInfo(_instruction).gasPriceTier)

View File

@ -221,7 +221,7 @@ public:
/// @returns gas costs for simple instructions with constant gas costs (that do not
/// change with EVM versions)
static unsigned runGas(Instruction _instruction);
static unsigned runGas(InternalInstruction _instruction);
/// @returns the gas cost of the supplied data, depending whether it is in creation code, or not.
/// In case of @a _inCreation, the data is only sent as a transaction and is not stored, whereas

View File

@ -85,7 +85,7 @@ bool Inliner::isInlineCandidate(size_t _tag, ranges::span<AssemblyItem const> _i
if (_items.back().type() != Operation)
return false;
if (
_items.back() != Instruction::JUMP &&
_items.back() != InternalInstruction::JUMP &&
!SemanticInformation::terminatesControlFlow(_items.back().instruction())
)
return false;
@ -150,13 +150,13 @@ bool Inliner::shouldInlineFullFunctionBody(size_t _tag, ranges::span<AssemblyIte
static AssemblyItems const uninlinedCallSitePattern = {
AssemblyItem{PushTag},
AssemblyItem{PushTag},
AssemblyItem{Instruction::JUMP},
AssemblyItem{InternalInstruction::JUMP},
AssemblyItem{Tag}
};
static AssemblyItems const uninlinedFunctionPattern = {
AssemblyItem{Tag},
// Actual function body of size functionBodySize. Handled separately below.
AssemblyItem{Instruction::JUMP}
AssemblyItem{InternalInstruction::JUMP}
};
// Both the call site and jump site pattern is executed for each call.
@ -201,12 +201,12 @@ bool Inliner::shouldInlineFullFunctionBody(size_t _tag, ranges::span<AssemblyIte
optional<AssemblyItem> Inliner::shouldInline(size_t _tag, AssemblyItem const& _jump, InlinableBlock const& _block) const
{
assertThrow(_jump == Instruction::JUMP, OptimizerException, "");
assertThrow(_jump == InternalInstruction::JUMP, OptimizerException, "");
AssemblyItem blockExit = _block.items.back();
if (
_jump.getJumpType() == AssemblyItem::JumpType::IntoFunction &&
blockExit == Instruction::JUMP &&
blockExit == InternalInstruction::JUMP &&
blockExit.getJumpType() == AssemblyItem::JumpType::OutOfFunction &&
shouldInlineFullFunctionBody(_tag, _block.items, _block.pushTagCount)
)
@ -223,7 +223,7 @@ optional<AssemblyItem> Inliner::shouldInline(size_t _tag, AssemblyItem const& _j
{
static AssemblyItems const jumpPattern = {
AssemblyItem{PushTag},
AssemblyItem{Instruction::JUMP},
AssemblyItem{InternalInstruction::JUMP},
};
if (
GasMeter::dataGas(codeSize(_block.items), m_isCreation, m_evmVersion) <=
@ -250,7 +250,7 @@ void Inliner::optimise()
if (next(it) != m_items.end())
{
AssemblyItem const& nextItem = *next(it);
if (item.type() == PushTag && nextItem == Instruction::JUMP)
if (item.type() == PushTag && nextItem == InternalInstruction::JUMP)
{
if (optional<size_t> tag = getLocalTag(item))
if (auto* inlinableBlock = util::valueOrNullptr(inlinableBlocks, *tag))

View File

@ -97,8 +97,8 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool
// Since AssignImmutable breaks blocks, it should be fine to only consider its changes to the stack, which
// is the same as two POPs.
// Note that the StoreOperation for POP is generic and _copyItem is ignored.
feedItem(AssemblyItem(Instruction::POP), _copyItem);
return feedItem(AssemblyItem(Instruction::POP), _copyItem);
feedItem(AssemblyItem(InternalInstruction::POP), _copyItem);
return feedItem(AssemblyItem(InternalInstruction::POP), _copyItem);
}
else if (_item.type() == VerbatimBytecode)
{
@ -129,48 +129,48 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool
}
else
{
Instruction instruction = _item.instruction();
InternalInstruction instruction = _item.instruction();
InstructionInfo info = instructionInfo(instruction);
if (SemanticInformation::isDupInstruction(_item))
setStackElement(
m_stackHeight + 1,
stackElement(
m_stackHeight - static_cast<int>(instruction) + static_cast<int>(Instruction::DUP1),
m_stackHeight - static_cast<int>(instruction) + static_cast<int>(InternalInstruction::DUP1),
_item.location()
)
);
else if (SemanticInformation::isSwapInstruction(_item))
swapStackElements(
m_stackHeight,
m_stackHeight - 1 - static_cast<int>(instruction) + static_cast<int>(Instruction::SWAP1),
m_stackHeight - 1 - static_cast<int>(instruction) + static_cast<int>(InternalInstruction::SWAP1),
_item.location()
);
else if (instruction != Instruction::POP)
else if (instruction != InternalInstruction::POP)
{
vector<Id> arguments(static_cast<size_t>(info.args));
for (size_t i = 0; i < static_cast<size_t>(info.args); ++i)
arguments[i] = stackElement(m_stackHeight - static_cast<int>(i), _item.location());
switch (_item.instruction())
{
case Instruction::SSTORE:
case InternalInstruction::SSTORE:
op = storeInStorage(arguments[0], arguments[1], _item.location());
break;
case Instruction::SLOAD:
case InternalInstruction::SLOAD:
setStackElement(
m_stackHeight + static_cast<int>(_item.deposit()),
loadFromStorage(arguments[0], _item.location())
);
break;
case Instruction::MSTORE:
case InternalInstruction::MSTORE:
op = storeInMemory(arguments[0], arguments[1], _item.location());
break;
case Instruction::MLOAD:
case InternalInstruction::MLOAD:
setStackElement(
m_stackHeight + static_cast<int>(_item.deposit()),
loadFromMemory(arguments[0], _item.location())
);
break;
case Instruction::KECCAK256:
case InternalInstruction::KECCAK256:
setStackElement(
m_stackHeight + static_cast<int>(_item.deposit()),
applyKeccak256(arguments.at(0), arguments.at(1), _item.location())
@ -335,7 +335,7 @@ KnownState::StoreOperation KnownState::storeInStorage(
storageContents.insert(storageItem);
m_storageContent = std::move(storageContents);
AssemblyItem item(Instruction::SSTORE, _location);
AssemblyItem item(InternalInstruction::SSTORE, _location);
Id id = m_expressionClasses->find(item, {_slot, _value}, true, m_sequenceNumber);
StoreOperation operation{StoreOperation::Storage, _slot, m_sequenceNumber, id};
m_storageContent[_slot] = _value;
@ -350,7 +350,7 @@ ExpressionClasses::Id KnownState::loadFromStorage(Id _slot, SourceLocation const
if (m_storageContent.count(_slot))
return m_storageContent.at(_slot);
AssemblyItem item(Instruction::SLOAD, _location);
AssemblyItem item(InternalInstruction::SLOAD, _location);
return m_storageContent[_slot] = m_expressionClasses->find(item, {_slot}, true, m_sequenceNumber);
}
@ -367,7 +367,7 @@ KnownState::StoreOperation KnownState::storeInMemory(Id _slot, Id _value, Source
memoryContents.insert(memoryItem);
m_memoryContent = std::move(memoryContents);
AssemblyItem item(Instruction::MSTORE, _location);
AssemblyItem item(InternalInstruction::MSTORE, _location);
Id id = m_expressionClasses->find(item, {_slot, _value}, true, m_sequenceNumber);
StoreOperation operation{StoreOperation::Memory, _slot, m_sequenceNumber, id};
m_memoryContent[_slot] = _value;
@ -381,7 +381,7 @@ ExpressionClasses::Id KnownState::loadFromMemory(Id _slot, SourceLocation const&
if (m_memoryContent.count(_slot))
return m_memoryContent.at(_slot);
AssemblyItem item(Instruction::MLOAD, _location);
AssemblyItem item(InternalInstruction::MLOAD, _location);
return m_memoryContent[_slot] = m_expressionClasses->find(item, {_slot}, true, m_sequenceNumber);
}
@ -391,7 +391,7 @@ KnownState::Id KnownState::applyKeccak256(
SourceLocation const& _location
)
{
AssemblyItem keccak256Item(Instruction::KECCAK256, _location);
AssemblyItem keccak256Item(InternalInstruction::KECCAK256, _location);
// Special logic if length is a short constant, otherwise we cannot tell.
u256 const* l = m_expressionClasses->knownConstant(_length);
// unknown or too large length
@ -402,7 +402,7 @@ KnownState::Id KnownState::applyKeccak256(
for (unsigned i = 0; i < length; i += 32)
{
Id slot = m_expressionClasses->find(
AssemblyItem(Instruction::ADD, _location),
AssemblyItem(InternalInstruction::ADD, _location),
{_start, m_expressionClasses->find(u256(i))}
);
arguments.push_back(loadFromMemory(slot, _location));

View File

@ -88,7 +88,7 @@ GasMeter::GasConsumption PathGasMeter::handleQueueItem()
bool branchStops = false;
jumpTags.clear();
AssemblyItem const& item = m_items.at(index);
if (item.type() == Tag || item == AssemblyItem(Instruction::JUMPDEST))
if (item.type() == Tag || item == AssemblyItem(InternalInstruction::JUMPDEST))
{
// Do not allow any backwards jump. This is quite restrictive but should work for
// the simplest things.
@ -96,14 +96,14 @@ GasMeter::GasConsumption PathGasMeter::handleQueueItem()
return GasMeter::GasConsumption::infinite();
path->visitedJumpdests.insert(index);
}
else if (item == AssemblyItem(Instruction::JUMP))
else if (item == AssemblyItem(InternalInstruction::JUMP))
{
branchStops = true;
jumpTags = state->tagsInExpression(state->relativeStackElement(0));
if (jumpTags.empty()) // unknown jump destination
return GasMeter::GasConsumption::infinite();
}
else if (item == AssemblyItem(Instruction::JUMPI))
else if (item == AssemblyItem(InternalInstruction::JUMPI))
{
ExpressionClasses::Id condition = state->relativeStackElement(-1);
if (classes.knownNonZero(condition) || !classes.knownZero(condition))

View File

@ -87,7 +87,7 @@ struct PushPop: SimplePeepholeOptimizerMethod<PushPop>
static bool applySimple(AssemblyItem const& _push, AssemblyItem const& _pop, std::back_insert_iterator<AssemblyItems>)
{
auto t = _push.type();
return _pop == Instruction::POP && (
return _pop == InternalInstruction::POP && (
SemanticInformation::isDupInstruction(_push) ||
t == Push || t == PushTag || t == PushSub ||
t == PushSubSize || t == PushProgramSize || t == PushData || t == PushLibraryAddress
@ -103,13 +103,13 @@ struct OpPop: SimplePeepholeOptimizerMethod<OpPop>
std::back_insert_iterator<AssemblyItems> _out
)
{
if (_pop == Instruction::POP && _op.type() == Operation)
if (_pop == InternalInstruction::POP && _op.type() == Operation)
{
Instruction instr = _op.instruction();
InternalInstruction instr = _op.instruction();
if (instructionInfo(instr).ret == 1 && !instructionInfo(instr).sideEffects)
{
for (int j = 0; j < instructionInfo(instr).args; j++)
*_out = {Instruction::POP, _op.location()};
*_out = {InternalInstruction::POP, _op.location()};
return true;
}
}
@ -125,20 +125,20 @@ struct OpStop: SimplePeepholeOptimizerMethod<OpStop>
std::back_insert_iterator<AssemblyItems> _out
)
{
if (_stop == Instruction::STOP)
if (_stop == InternalInstruction::STOP)
{
if (_op.type() == Operation)
{
Instruction instr = _op.instruction();
InternalInstruction instr = _op.instruction();
if (!instructionInfo(instr).sideEffects)
{
*_out = {Instruction::STOP, _op.location()};
*_out = {InternalInstruction::STOP, _op.location()};
return true;
}
}
else if (_op.type() == Push)
{
*_out = {Instruction::STOP, _op.location()};
*_out = {InternalInstruction::STOP, _op.location()};
return true;
}
}
@ -157,7 +157,7 @@ struct OpReturnRevert: SimplePeepholeOptimizerMethod<OpReturnRevert>
)
{
if (
(_returnRevert == Instruction::RETURN || _returnRevert == Instruction::REVERT) &&
(_returnRevert == InternalInstruction::RETURN || _returnRevert == InternalInstruction::REVERT) &&
_push.type() == Push &&
(_pushOrDup.type() == Push || _pushOrDup == dupInstruction(1))
)
@ -190,7 +190,7 @@ struct DoublePush: SimplePeepholeOptimizerMethod<DoublePush>
if (_push1.type() == Push && _push2.type() == Push && _push1.data() == _push2.data())
{
*_out = _push1;
*_out = {Instruction::DUP1, _push2.location()};
*_out = {InternalInstruction::DUP1, _push2.location()};
return true;
}
else
@ -204,7 +204,7 @@ struct CommutativeSwap: SimplePeepholeOptimizerMethod<CommutativeSwap>
{
// Remove SWAP1 if following instruction is commutative
if (
_swap == Instruction::SWAP1 &&
_swap == InternalInstruction::SWAP1 &&
SemanticInformation::isCommutativeOperation(_op)
)
{
@ -220,15 +220,15 @@ struct SwapComparison: SimplePeepholeOptimizerMethod<SwapComparison>
{
static bool applySimple(AssemblyItem const& _swap, AssemblyItem const& _op, std::back_insert_iterator<AssemblyItems> _out)
{
static map<Instruction, Instruction> const swappableOps{
{ Instruction::LT, Instruction::GT },
{ Instruction::GT, Instruction::LT },
{ Instruction::SLT, Instruction::SGT },
{ Instruction::SGT, Instruction::SLT }
static map<InternalInstruction, InternalInstruction> const swappableOps{
{ InternalInstruction::LT, InternalInstruction::GT },
{ InternalInstruction::GT, InternalInstruction::LT },
{ InternalInstruction::SLT, InternalInstruction::SGT },
{ InternalInstruction::SGT, InternalInstruction::SLT }
};
if (
_swap == Instruction::SWAP1 &&
_swap == InternalInstruction::SWAP1 &&
_op.type() == Operation &&
swappableOps.count(_op.instruction())
)
@ -276,10 +276,10 @@ struct IsZeroIsZeroJumpI: SimplePeepholeOptimizerMethod<IsZeroIsZeroJumpI>
)
{
if (
_iszero1 == Instruction::ISZERO &&
_iszero2 == Instruction::ISZERO &&
_iszero1 == InternalInstruction::ISZERO &&
_iszero2 == InternalInstruction::ISZERO &&
_pushTag.type() == PushTag &&
_jumpi == Instruction::JUMPI
_jumpi == InternalInstruction::JUMPI
)
{
*_out = _pushTag;
@ -302,13 +302,13 @@ struct EqIsZeroJumpI: SimplePeepholeOptimizerMethod<EqIsZeroJumpI>
)
{
if (
_eq == Instruction::EQ &&
_iszero == Instruction::ISZERO &&
_eq == InternalInstruction::EQ &&
_iszero == InternalInstruction::ISZERO &&
_pushTag.type() == PushTag &&
_jumpi == Instruction::JUMPI
_jumpi == InternalInstruction::JUMPI
)
{
*_out = AssemblyItem(Instruction::SUB, _eq.location());
*_out = AssemblyItem(InternalInstruction::SUB, _eq.location());
*_out = _pushTag;
*_out = _jumpi;
return true;
@ -332,14 +332,14 @@ struct DoubleJump: SimplePeepholeOptimizerMethod<DoubleJump>
{
if (
_pushTag1.type() == PushTag &&
_jumpi == Instruction::JUMPI &&
_jumpi == InternalInstruction::JUMPI &&
_pushTag2.type() == PushTag &&
_jump == Instruction::JUMP &&
_jump == InternalInstruction::JUMP &&
_tag1.type() == Tag &&
_pushTag1.data() == _tag1.data()
)
{
*_out = AssemblyItem(Instruction::ISZERO, _jumpi.location());
*_out = AssemblyItem(InternalInstruction::ISZERO, _jumpi.location());
*_out = _pushTag2;
*_out = _jumpi;
*_out = _tag1;
@ -361,13 +361,13 @@ struct JumpToNext: SimplePeepholeOptimizerMethod<JumpToNext>
{
if (
_pushTag.type() == PushTag &&
(_jump == Instruction::JUMP || _jump == Instruction::JUMPI) &&
(_jump == InternalInstruction::JUMP || _jump == InternalInstruction::JUMPI) &&
_tag.type() == Tag &&
_pushTag.data() == _tag.data()
)
{
if (_jump == Instruction::JUMPI)
*_out = AssemblyItem(Instruction::POP, _jump.location());
if (_jump == InternalInstruction::JUMPI)
*_out = AssemblyItem(InternalInstruction::POP, _jump.location());
*_out = _tag;
return true;
}
@ -385,7 +385,7 @@ struct TagConjunctions: SimplePeepholeOptimizerMethod<TagConjunctions>
std::back_insert_iterator<AssemblyItems> _out
)
{
if (_and != Instruction::AND)
if (_and != InternalInstruction::AND)
return false;
if (
_pushTag.type() == PushTag &&
@ -422,8 +422,8 @@ struct TruthyAnd: SimplePeepholeOptimizerMethod<TruthyAnd>
{
return (
_push.type() == Push && _push.data() == 0 &&
_not == Instruction::NOT &&
_and == Instruction::AND
_not == InternalInstruction::NOT &&
_and == InternalInstruction::AND
);
}
};
@ -438,12 +438,12 @@ struct UnreachableCode
if (it == end)
return false;
if (
it[0] != Instruction::JUMP &&
it[0] != Instruction::RETURN &&
it[0] != Instruction::STOP &&
it[0] != Instruction::INVALID &&
it[0] != Instruction::SELFDESTRUCT &&
it[0] != Instruction::REVERT
it[0] != InternalInstruction::JUMP &&
it[0] != InternalInstruction::RETURN &&
it[0] != InternalInstruction::STOP &&
it[0] != InternalInstruction::INVALID &&
it[0] != InternalInstruction::SELFDESTRUCT &&
it[0] != InternalInstruction::REVERT
)
return false;
@ -475,7 +475,7 @@ void applyMethods(OptimiserState& _state, Method, OtherMethods... _other)
size_t numberOfPops(AssemblyItems const& _items)
{
return static_cast<size_t>(std::count(_items.begin(), _items.end(), Instruction::POP));
return static_cast<size_t>(std::count(_items.begin(), _items.end(), InternalInstruction::POP));
}
}

View File

@ -367,10 +367,10 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleListPart5(
});
for (auto instr: {
Instruction::ADDRESS,
Instruction::CALLER,
Instruction::ORIGIN,
Instruction::COINBASE
InternalInstruction::ADDRESS,
InternalInstruction::CALLER,
InternalInstruction::ORIGIN,
InternalInstruction::COINBASE
})
{
assertThrow(Pattern::WordSize > 160, OptimizerException, "");
@ -402,11 +402,11 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleListPart6(
std::vector<SimplificationRule<Pattern>> rules;
// Double negation of opcodes with boolean result
for (auto instr: {
Instruction::EQ,
Instruction::LT,
Instruction::SLT,
Instruction::GT,
Instruction::SGT
InternalInstruction::EQ,
InternalInstruction::LT,
InternalInstruction::SLT,
InternalInstruction::GT,
InternalInstruction::SGT
})
{
typename Builtins::PatternGeneratorInstance op{instr};
@ -448,12 +448,12 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleListPart7(
std::vector<SimplificationRule<Pattern>> rules;
// Associative operations
for (auto&& instrAndFunc: std::vector<std::pair<Instruction, std::function<Word(Word, Word)>>>{
{Instruction::ADD, std::plus<Word>()},
{Instruction::MUL, std::multiplies<Word>()},
{Instruction::AND, std::bit_and<Word>()},
{Instruction::OR, std::bit_or<Word>()},
{Instruction::XOR, std::bit_xor<Word>()}
for (auto&& instrAndFunc: std::vector<std::pair<InternalInstruction, std::function<Word(Word, Word)>>>{
{InternalInstruction::ADD, std::plus<Word>()},
{InternalInstruction::MUL, std::multiplies<Word>()},
{InternalInstruction::AND, std::bit_and<Word>()},
{InternalInstruction::OR, std::bit_or<Word>()},
{InternalInstruction::XOR, std::bit_xor<Word>()}
})
{
typename Builtins::PatternGeneratorInstance op{instrAndFunc.first};
@ -544,12 +544,12 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleListPart7(
});
// Move AND with constant across SHL and SHR by constant
for (auto instr: {Instruction::SHL, Instruction::SHR})
for (auto instr: {InternalInstruction::SHL, InternalInstruction::SHR})
{
typename Builtins::PatternGeneratorInstance shiftOp{instr};
auto replacement = [=]() -> Pattern {
Word mask =
instr == Instruction::SHL ?
instr == InternalInstruction::SHL ?
shlWorkaround(A.d(), unsigned(B.d())) :
A.d() >> unsigned(B.d());
return Builtins::AND(shiftOp(B.d(), X), std::move(mask));
@ -743,8 +743,8 @@ std::vector<SimplificationRule<Pattern>> evmRuleList(
if (_evmVersion.hasSelfBalance())
rules.push_back({
Builtins::BALANCE(Instruction::ADDRESS),
[]() -> Pattern { return Instruction::SELFBALANCE; }
Builtins::BALANCE(InternalInstruction::ADDRESS),
[]() -> Pattern { return InternalInstruction::SELFBALANCE; }
});
rules.emplace_back(

View File

@ -29,12 +29,12 @@ using namespace std;
using namespace solidity;
using namespace solidity::evmasm;
vector<SemanticInformation::Operation> SemanticInformation::readWriteOperations(Instruction _instruction)
vector<SemanticInformation::Operation> SemanticInformation::readWriteOperations(InternalInstruction _instruction)
{
switch (_instruction)
{
case Instruction::SSTORE:
case Instruction::SLOAD:
case InternalInstruction::SSTORE:
case InternalInstruction::SLOAD:
{
assertThrow(memory(_instruction) == Effect::None, OptimizerException, "");
assertThrow(storage(_instruction) != Effect::None, OptimizerException, "");
@ -46,9 +46,9 @@ vector<SemanticInformation::Operation> SemanticInformation::readWriteOperations(
op.lengthConstant = 1;
return {op};
}
case Instruction::MSTORE:
case Instruction::MSTORE8:
case Instruction::MLOAD:
case InternalInstruction::MSTORE:
case InternalInstruction::MSTORE8:
case InternalInstruction::MLOAD:
{
assertThrow(memory(_instruction) != Effect::None, OptimizerException, "");
assertThrow(storage(_instruction) == Effect::None, OptimizerException, "");
@ -56,21 +56,21 @@ vector<SemanticInformation::Operation> SemanticInformation::readWriteOperations(
op.effect = memory(_instruction);
op.location = Location::Memory;
op.startParameter = 0;
if (_instruction == Instruction::MSTORE || _instruction == Instruction::MLOAD)
if (_instruction == InternalInstruction::MSTORE || _instruction == InternalInstruction::MLOAD)
op.lengthConstant = 32;
else if (_instruction == Instruction::MSTORE8)
else if (_instruction == InternalInstruction::MSTORE8)
op.lengthConstant = 1;
return {op};
}
case Instruction::REVERT:
case Instruction::RETURN:
case Instruction::KECCAK256:
case Instruction::LOG0:
case Instruction::LOG1:
case Instruction::LOG2:
case Instruction::LOG3:
case Instruction::LOG4:
case InternalInstruction::REVERT:
case InternalInstruction::RETURN:
case InternalInstruction::KECCAK256:
case InternalInstruction::LOG0:
case InternalInstruction::LOG1:
case InternalInstruction::LOG2:
case InternalInstruction::LOG3:
case InternalInstruction::LOG4:
{
assertThrow(storage(_instruction) == Effect::None, OptimizerException, "");
assertThrow(memory(_instruction) == Effect::Read, OptimizerException, "");
@ -81,7 +81,7 @@ vector<SemanticInformation::Operation> SemanticInformation::readWriteOperations(
op.lengthParameter = 1;
return {op};
}
case Instruction::EXTCODECOPY:
case InternalInstruction::EXTCODECOPY:
{
assertThrow(memory(_instruction) == Effect::Write, OptimizerException, "");
assertThrow(storage(_instruction) == Effect::None, OptimizerException, "");
@ -92,9 +92,9 @@ vector<SemanticInformation::Operation> SemanticInformation::readWriteOperations(
op.lengthParameter = 3;
return {op};
}
case Instruction::CODECOPY:
case Instruction::CALLDATACOPY:
case Instruction::RETURNDATACOPY:
case InternalInstruction::CODECOPY:
case InternalInstruction::CALLDATACOPY:
case InternalInstruction::RETURNDATACOPY:
{
assertThrow(memory(_instruction) == Effect::Write, OptimizerException, "");
assertThrow(storage(_instruction) == Effect::None, OptimizerException, "");
@ -105,17 +105,17 @@ vector<SemanticInformation::Operation> SemanticInformation::readWriteOperations(
op.lengthParameter = 2;
return {op};
}
case Instruction::STATICCALL:
case Instruction::CALL:
case Instruction::CALLCODE:
case Instruction::DELEGATECALL:
case InternalInstruction::STATICCALL:
case InternalInstruction::CALL:
case InternalInstruction::CALLCODE:
case InternalInstruction::DELEGATECALL:
{
size_t paramCount = static_cast<size_t>(instructionInfo(_instruction).args);
vector<Operation> operations{
Operation{Location::Memory, Effect::Read, paramCount - 4, paramCount - 3, {}},
Operation{Location::Storage, Effect::Read, {}, {}, {}}
};
if (_instruction != Instruction::STATICCALL)
if (_instruction != InternalInstruction::STATICCALL)
operations.emplace_back(Operation{Location::Storage, Effect::Write, {}, {}, {}});
operations.emplace_back(Operation{
Location::Memory,
@ -128,8 +128,8 @@ vector<SemanticInformation::Operation> SemanticInformation::readWriteOperations(
});
return operations;
}
case Instruction::CREATE:
case Instruction::CREATE2:
case InternalInstruction::CREATE:
case InternalInstruction::CREATE2:
return vector<Operation>{
Operation{
Location::Memory,
@ -141,7 +141,7 @@ vector<SemanticInformation::Operation> SemanticInformation::readWriteOperations(
Operation{Location::Storage, Effect::Read, {}, {}, {}},
Operation{Location::Storage, Effect::Write, {}, {}, {}}
};
case Instruction::MSIZE:
case InternalInstruction::MSIZE:
// This is just to satisfy the assert below.
return vector<Operation>{};
default:
@ -174,18 +174,18 @@ bool SemanticInformation::breaksCSEAnalysisBlock(AssemblyItem const& _item, bool
{
if (isSwapInstruction(_item) || isDupInstruction(_item))
return false;
if (_item.instruction() == Instruction::GAS || _item.instruction() == Instruction::PC)
if (_item.instruction() == InternalInstruction::GAS || _item.instruction() == InternalInstruction::PC)
return true; // GAS and PC assume a specific order of opcodes
if (_item.instruction() == Instruction::MSIZE)
if (_item.instruction() == InternalInstruction::MSIZE)
return true; // msize is modified already by memory access, avoid that for now
InstructionInfo info = instructionInfo(_item.instruction());
if (_item.instruction() == Instruction::SSTORE)
if (_item.instruction() == InternalInstruction::SSTORE)
return false;
if (_item.instruction() == Instruction::MSTORE)
if (_item.instruction() == InternalInstruction::MSTORE)
return false;
if (!_msizeImportant && (
_item.instruction() == Instruction::MLOAD ||
_item.instruction() == Instruction::KECCAK256
_item.instruction() == InternalInstruction::MLOAD ||
_item.instruction() == InternalInstruction::KECCAK256
))
return false;
//@todo: We do not handle the following memory instructions for now:
@ -204,12 +204,12 @@ bool SemanticInformation::isCommutativeOperation(AssemblyItem const& _item)
return false;
switch (_item.instruction())
{
case Instruction::ADD:
case Instruction::MUL:
case Instruction::EQ:
case Instruction::AND:
case Instruction::OR:
case Instruction::XOR:
case InternalInstruction::ADD:
case InternalInstruction::MUL:
case InternalInstruction::EQ:
case InternalInstruction::AND:
case InternalInstruction::OR:
case InternalInstruction::XOR:
return true;
default:
return false;
@ -232,7 +232,7 @@ bool SemanticInformation::isSwapInstruction(AssemblyItem const& _item)
bool SemanticInformation::isJumpInstruction(AssemblyItem const& _item)
{
return _item == Instruction::JUMP || _item == Instruction::JUMPI;
return _item == InternalInstruction::JUMP || _item == InternalInstruction::JUMPI;
}
bool SemanticInformation::altersControlFlow(AssemblyItem const& _item)
@ -243,40 +243,40 @@ bool SemanticInformation::altersControlFlow(AssemblyItem const& _item)
{
// note that CALL, CALLCODE and CREATE do not really alter the control flow, because we
// continue on the next instruction
case Instruction::JUMP:
case Instruction::JUMPI:
case Instruction::RETURN:
case Instruction::SELFDESTRUCT:
case Instruction::STOP:
case Instruction::INVALID:
case Instruction::REVERT:
case InternalInstruction::JUMP:
case InternalInstruction::JUMPI:
case InternalInstruction::RETURN:
case InternalInstruction::SELFDESTRUCT:
case InternalInstruction::STOP:
case InternalInstruction::INVALID:
case InternalInstruction::REVERT:
return true;
default:
return false;
}
}
bool SemanticInformation::terminatesControlFlow(Instruction _instruction)
bool SemanticInformation::terminatesControlFlow(InternalInstruction _instruction)
{
switch (_instruction)
{
case Instruction::RETURN:
case Instruction::SELFDESTRUCT:
case Instruction::STOP:
case Instruction::INVALID:
case Instruction::REVERT:
case InternalInstruction::RETURN:
case InternalInstruction::SELFDESTRUCT:
case InternalInstruction::STOP:
case InternalInstruction::INVALID:
case InternalInstruction::REVERT:
return true;
default:
return false;
}
}
bool SemanticInformation::reverts(Instruction _instruction)
bool SemanticInformation::reverts(InternalInstruction _instruction)
{
switch (_instruction)
{
case Instruction::INVALID:
case Instruction::REVERT:
case InternalInstruction::INVALID:
case InternalInstruction::REVERT:
return true;
default:
return false;
@ -292,28 +292,28 @@ bool SemanticInformation::isDeterministic(AssemblyItem const& _item)
switch (_item.instruction())
{
case Instruction::CALL:
case Instruction::CALLCODE:
case Instruction::DELEGATECALL:
case Instruction::STATICCALL:
case Instruction::CREATE:
case Instruction::CREATE2:
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::SELFBALANCE: // depends on previous calls
case Instruction::EXTCODESIZE:
case Instruction::EXTCODEHASH:
case Instruction::RETURNDATACOPY: // depends on previous calls
case Instruction::RETURNDATASIZE:
case InternalInstruction::CALL:
case InternalInstruction::CALLCODE:
case InternalInstruction::DELEGATECALL:
case InternalInstruction::STATICCALL:
case InternalInstruction::CREATE:
case InternalInstruction::CREATE2:
case InternalInstruction::GAS:
case InternalInstruction::PC:
case InternalInstruction::MSIZE: // depends on previous writes and reads, not only on content
case InternalInstruction::BALANCE: // depends on previous calls
case InternalInstruction::SELFBALANCE: // depends on previous calls
case InternalInstruction::EXTCODESIZE:
case InternalInstruction::EXTCODEHASH:
case InternalInstruction::RETURNDATACOPY: // depends on previous calls
case InternalInstruction::RETURNDATASIZE:
return false;
default:
return true;
}
}
bool SemanticInformation::movable(Instruction _instruction)
bool SemanticInformation::movable(InternalInstruction _instruction)
{
// These are not really functional.
if (isDupInstruction(_instruction) || isSwapInstruction(_instruction))
@ -323,16 +323,16 @@ bool SemanticInformation::movable(Instruction _instruction)
return false;
switch (_instruction)
{
case Instruction::KECCAK256:
case Instruction::BALANCE:
case Instruction::SELFBALANCE:
case Instruction::EXTCODESIZE:
case Instruction::EXTCODEHASH:
case Instruction::RETURNDATASIZE:
case Instruction::SLOAD:
case Instruction::PC:
case Instruction::MSIZE:
case Instruction::GAS:
case InternalInstruction::KECCAK256:
case InternalInstruction::BALANCE:
case InternalInstruction::SELFBALANCE:
case InternalInstruction::EXTCODESIZE:
case InternalInstruction::EXTCODEHASH:
case InternalInstruction::RETURNDATASIZE:
case InternalInstruction::SLOAD:
case InternalInstruction::PC:
case InternalInstruction::MSIZE:
case InternalInstruction::GAS:
return false;
default:
return true;
@ -340,7 +340,7 @@ bool SemanticInformation::movable(Instruction _instruction)
return true;
}
bool SemanticInformation::canBeRemoved(Instruction _instruction)
bool SemanticInformation::canBeRemoved(InternalInstruction _instruction)
{
// These are not really functional.
assertThrow(!isDupInstruction(_instruction) && !isSwapInstruction(_instruction), AssemblyException, "");
@ -348,42 +348,42 @@ bool SemanticInformation::canBeRemoved(Instruction _instruction)
return !instructionInfo(_instruction).sideEffects;
}
bool SemanticInformation::canBeRemovedIfNoMSize(Instruction _instruction)
bool SemanticInformation::canBeRemovedIfNoMSize(InternalInstruction _instruction)
{
if (_instruction == Instruction::KECCAK256 || _instruction == Instruction::MLOAD)
if (_instruction == InternalInstruction::KECCAK256 || _instruction == InternalInstruction::MLOAD)
return true;
else
return canBeRemoved(_instruction);
}
SemanticInformation::Effect SemanticInformation::memory(Instruction _instruction)
SemanticInformation::Effect SemanticInformation::memory(InternalInstruction _instruction)
{
switch (_instruction)
{
case Instruction::CALLDATACOPY:
case Instruction::CODECOPY:
case Instruction::EXTCODECOPY:
case Instruction::RETURNDATACOPY:
case Instruction::MSTORE:
case Instruction::MSTORE8:
case Instruction::CALL:
case Instruction::CALLCODE:
case Instruction::DELEGATECALL:
case Instruction::STATICCALL:
case InternalInstruction::CALLDATACOPY:
case InternalInstruction::CODECOPY:
case InternalInstruction::EXTCODECOPY:
case InternalInstruction::RETURNDATACOPY:
case InternalInstruction::MSTORE:
case InternalInstruction::MSTORE8:
case InternalInstruction::CALL:
case InternalInstruction::CALLCODE:
case InternalInstruction::DELEGATECALL:
case InternalInstruction::STATICCALL:
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:
case InternalInstruction::CREATE:
case InternalInstruction::CREATE2:
case InternalInstruction::KECCAK256:
case InternalInstruction::MLOAD:
case InternalInstruction::MSIZE:
case InternalInstruction::RETURN:
case InternalInstruction::REVERT:
case InternalInstruction::LOG0:
case InternalInstruction::LOG1:
case InternalInstruction::LOG2:
case InternalInstruction::LOG3:
case InternalInstruction::LOG4:
return SemanticInformation::Read;
default:
@ -391,18 +391,18 @@ SemanticInformation::Effect SemanticInformation::memory(Instruction _instruction
}
}
bool SemanticInformation::movableApartFromEffects(Instruction _instruction)
bool SemanticInformation::movableApartFromEffects(InternalInstruction _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:
case InternalInstruction::EXTCODEHASH:
case InternalInstruction::EXTCODESIZE:
case InternalInstruction::RETURNDATASIZE:
case InternalInstruction::BALANCE:
case InternalInstruction::SELFBALANCE:
case InternalInstruction::SLOAD:
case InternalInstruction::KECCAK256:
case InternalInstruction::MLOAD:
return true;
default:
@ -410,20 +410,20 @@ bool SemanticInformation::movableApartFromEffects(Instruction _instruction)
}
}
SemanticInformation::Effect SemanticInformation::storage(Instruction _instruction)
SemanticInformation::Effect SemanticInformation::storage(InternalInstruction _instruction)
{
switch (_instruction)
{
case Instruction::CALL:
case Instruction::CALLCODE:
case Instruction::DELEGATECALL:
case Instruction::CREATE:
case Instruction::CREATE2:
case Instruction::SSTORE:
case InternalInstruction::CALL:
case InternalInstruction::CALLCODE:
case InternalInstruction::DELEGATECALL:
case InternalInstruction::CREATE:
case InternalInstruction::CREATE2:
case InternalInstruction::SSTORE:
return SemanticInformation::Write;
case Instruction::SLOAD:
case Instruction::STATICCALL:
case InternalInstruction::SLOAD:
case InternalInstruction::STATICCALL:
return SemanticInformation::Read;
default:
@ -431,28 +431,28 @@ SemanticInformation::Effect SemanticInformation::storage(Instruction _instructio
}
}
SemanticInformation::Effect SemanticInformation::otherState(Instruction _instruction)
SemanticInformation::Effect SemanticInformation::otherState(InternalInstruction _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
case InternalInstruction::CALL:
case InternalInstruction::CALLCODE:
case InternalInstruction::DELEGATECALL:
case InternalInstruction::CREATE:
case InternalInstruction::CREATE2:
case InternalInstruction::SELFDESTRUCT:
case InternalInstruction::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:
case InternalInstruction::EXTCODESIZE:
case InternalInstruction::EXTCODEHASH:
case InternalInstruction::RETURNDATASIZE:
case InternalInstruction::BALANCE:
case InternalInstruction::SELFBALANCE:
case InternalInstruction::RETURNDATACOPY:
case InternalInstruction::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;
@ -462,31 +462,31 @@ SemanticInformation::Effect SemanticInformation::otherState(Instruction _instruc
}
}
bool SemanticInformation::invalidInPureFunctions(Instruction _instruction)
bool SemanticInformation::invalidInPureFunctions(InternalInstruction _instruction)
{
switch (_instruction)
{
case Instruction::ADDRESS:
case Instruction::SELFBALANCE:
case Instruction::BALANCE:
case Instruction::ORIGIN:
case Instruction::CALLER:
case Instruction::CALLVALUE:
case Instruction::CHAINID:
case Instruction::BASEFEE:
case Instruction::GAS:
case Instruction::GASPRICE:
case Instruction::EXTCODESIZE:
case Instruction::EXTCODECOPY:
case Instruction::EXTCODEHASH:
case Instruction::BLOCKHASH:
case Instruction::COINBASE:
case Instruction::TIMESTAMP:
case Instruction::NUMBER:
case Instruction::DIFFICULTY:
case Instruction::GASLIMIT:
case Instruction::STATICCALL:
case Instruction::SLOAD:
case InternalInstruction::ADDRESS:
case InternalInstruction::SELFBALANCE:
case InternalInstruction::BALANCE:
case InternalInstruction::ORIGIN:
case InternalInstruction::CALLER:
case InternalInstruction::CALLVALUE:
case InternalInstruction::CHAINID:
case InternalInstruction::BASEFEE:
case InternalInstruction::GAS:
case InternalInstruction::GASPRICE:
case InternalInstruction::EXTCODESIZE:
case InternalInstruction::EXTCODECOPY:
case InternalInstruction::EXTCODEHASH:
case InternalInstruction::BLOCKHASH:
case InternalInstruction::COINBASE:
case InternalInstruction::TIMESTAMP:
case InternalInstruction::NUMBER:
case InternalInstruction::DIFFICULTY:
case InternalInstruction::GASLIMIT:
case InternalInstruction::STATICCALL:
case InternalInstruction::SLOAD:
return true;
default:
break;
@ -494,24 +494,24 @@ bool SemanticInformation::invalidInPureFunctions(Instruction _instruction)
return invalidInViewFunctions(_instruction);
}
bool SemanticInformation::invalidInViewFunctions(Instruction _instruction)
bool SemanticInformation::invalidInViewFunctions(InternalInstruction _instruction)
{
switch (_instruction)
{
case Instruction::SSTORE:
case Instruction::JUMP:
case Instruction::JUMPI:
case Instruction::LOG0:
case Instruction::LOG1:
case Instruction::LOG2:
case Instruction::LOG3:
case Instruction::LOG4:
case Instruction::CREATE:
case Instruction::CALL:
case Instruction::CALLCODE:
case Instruction::DELEGATECALL:
case Instruction::CREATE2:
case Instruction::SELFDESTRUCT:
case InternalInstruction::SSTORE:
case InternalInstruction::JUMP:
case InternalInstruction::JUMPI:
case InternalInstruction::LOG0:
case InternalInstruction::LOG1:
case InternalInstruction::LOG2:
case InternalInstruction::LOG3:
case InternalInstruction::LOG4:
case InternalInstruction::CREATE:
case InternalInstruction::CALL:
case InternalInstruction::CALLCODE:
case InternalInstruction::DELEGATECALL:
case InternalInstruction::CREATE2:
case InternalInstruction::SELFDESTRUCT:
return true;
default:
break;

View File

@ -72,7 +72,7 @@ struct SemanticInformation
/// Order matters.
/// For external calls, there is just one unknown read and one unknown write operation,
/// event though there might be multiple.
static std::vector<Operation> readWriteOperations(Instruction _instruction);
static std::vector<Operation> readWriteOperations(InternalInstruction _instruction);
/// @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.
@ -84,34 +84,34 @@ struct SemanticInformation
static bool isSwapInstruction(AssemblyItem const& _item);
static bool isJumpInstruction(AssemblyItem const& _item);
static bool altersControlFlow(AssemblyItem const& _item);
static bool terminatesControlFlow(Instruction _instruction);
static bool reverts(Instruction _instruction);
static bool terminatesControlFlow(InternalInstruction _instruction);
static bool reverts(InternalInstruction _instruction);
/// @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.
static bool isDeterministic(AssemblyItem const& _item);
/// @returns true if the instruction can be moved or copied (together with its arguments)
/// 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);
static bool movable(InternalInstruction _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);
static bool movableApartFromEffects(InternalInstruction _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 canBeRemoved(Instruction _instruction);
static bool canBeRemoved(InternalInstruction _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 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);
static bool canBeRemovedIfNoMSize(InternalInstruction _instruction);
static Effect memory(InternalInstruction _instruction);
static Effect storage(InternalInstruction _instruction);
static Effect otherState(InternalInstruction _instruction);
static bool invalidInPureFunctions(InternalInstruction _instruction);
static bool invalidInViewFunctions(InternalInstruction _instruction);
};
}

View File

@ -54,9 +54,9 @@ struct SimplificationRule
template <typename Pattern>
struct EVMBuiltins
{
using InstrType = Instruction;
using InstrType = InternalInstruction;
template<Instruction inst>
template<InternalInstruction inst>
struct PatternGenerator
{
template<typename... Args> constexpr Pattern operator()(Args&&... _args) const
@ -67,7 +67,7 @@ struct EVMBuiltins
struct PatternGeneratorInstance
{
Instruction instruction;
InternalInstruction instruction;
template<typename... Args> constexpr Pattern operator()(Args&&... _args) const
{
return {instruction, {std::forward<Args>(_args)...}};
@ -75,83 +75,83 @@ struct EVMBuiltins
};
static auto constexpr STOP = PatternGenerator<Instruction::STOP>{};
static auto constexpr ADD = PatternGenerator<Instruction::ADD>{};
static auto constexpr SUB = PatternGenerator<Instruction::SUB>{};
static auto constexpr MUL = PatternGenerator<Instruction::MUL>{};
static auto constexpr DIV = PatternGenerator<Instruction::DIV>{};
static auto constexpr SDIV = PatternGenerator<Instruction::SDIV>{};
static auto constexpr MOD = PatternGenerator<Instruction::MOD>{};
static auto constexpr SMOD = PatternGenerator<Instruction::SMOD>{};
static auto constexpr EXP = PatternGenerator<Instruction::EXP>{};
static auto constexpr NOT = PatternGenerator<Instruction::NOT>{};
static auto constexpr LT = PatternGenerator<Instruction::LT>{};
static auto constexpr GT = PatternGenerator<Instruction::GT>{};
static auto constexpr SLT = PatternGenerator<Instruction::SLT>{};
static auto constexpr SGT = PatternGenerator<Instruction::SGT>{};
static auto constexpr EQ = PatternGenerator<Instruction::EQ>{};
static auto constexpr ISZERO = PatternGenerator<Instruction::ISZERO>{};
static auto constexpr AND = PatternGenerator<Instruction::AND>{};
static auto constexpr OR = PatternGenerator<Instruction::OR>{};
static auto constexpr XOR = PatternGenerator<Instruction::XOR>{};
static auto constexpr BYTE = PatternGenerator<Instruction::BYTE>{};
static auto constexpr SHL = PatternGenerator<Instruction::SHL>{};
static auto constexpr SHR = PatternGenerator<Instruction::SHR>{};
static auto constexpr SAR = PatternGenerator<Instruction::SAR>{};
static auto constexpr ADDMOD = PatternGenerator<Instruction::ADDMOD>{};
static auto constexpr MULMOD = PatternGenerator<Instruction::MULMOD>{};
static auto constexpr SIGNEXTEND = PatternGenerator<Instruction::SIGNEXTEND>{};
static auto constexpr KECCAK256 = PatternGenerator<Instruction::KECCAK256>{};
static auto constexpr ADDRESS = PatternGenerator<Instruction::ADDRESS>{};
static auto constexpr BALANCE = PatternGenerator<Instruction::BALANCE>{};
static auto constexpr ORIGIN = PatternGenerator<Instruction::ORIGIN>{};
static auto constexpr CALLER = PatternGenerator<Instruction::CALLER>{};
static auto constexpr CALLVALUE = PatternGenerator<Instruction::CALLVALUE>{};
static auto constexpr CALLDATALOAD = PatternGenerator<Instruction::CALLDATALOAD>{};
static auto constexpr CALLDATASIZE = PatternGenerator<Instruction::CALLDATASIZE>{};
static auto constexpr CALLDATACOPY = PatternGenerator<Instruction::CALLDATACOPY>{};
static auto constexpr CODESIZE = PatternGenerator<Instruction::CODESIZE>{};
static auto constexpr CODECOPY = PatternGenerator<Instruction::CODECOPY>{};
static auto constexpr GASPRICE = PatternGenerator<Instruction::GASPRICE>{};
static auto constexpr EXTCODESIZE = PatternGenerator<Instruction::EXTCODESIZE>{};
static auto constexpr EXTCODECOPY = PatternGenerator<Instruction::EXTCODECOPY>{};
static auto constexpr RETURNDATASIZE = PatternGenerator<Instruction::RETURNDATASIZE>{};
static auto constexpr RETURNDATACOPY = PatternGenerator<Instruction::RETURNDATACOPY>{};
static auto constexpr EXTCODEHASH = PatternGenerator<Instruction::EXTCODEHASH>{};
static auto constexpr BLOCKHASH = PatternGenerator<Instruction::BLOCKHASH>{};
static auto constexpr COINBASE = PatternGenerator<Instruction::COINBASE>{};
static auto constexpr TIMESTAMP = PatternGenerator<Instruction::TIMESTAMP>{};
static auto constexpr NUMBER = PatternGenerator<Instruction::NUMBER>{};
static auto constexpr DIFFICULTY = PatternGenerator<Instruction::DIFFICULTY>{};
static auto constexpr PREVRANDAO = PatternGenerator<Instruction::PREVRANDAO>{};
static auto constexpr GASLIMIT = PatternGenerator<Instruction::GASLIMIT>{};
static auto constexpr CHAINID = PatternGenerator<Instruction::CHAINID>{};
static auto constexpr SELFBALANCE = PatternGenerator<Instruction::SELFBALANCE>{};
static auto constexpr BASEFEE = PatternGenerator<Instruction::BASEFEE>{};
static auto constexpr POP = PatternGenerator<Instruction::POP>{};
static auto constexpr MLOAD = PatternGenerator<Instruction::MLOAD>{};
static auto constexpr MSTORE = PatternGenerator<Instruction::MSTORE>{};
static auto constexpr MSTORE8 = PatternGenerator<Instruction::MSTORE8>{};
static auto constexpr SLOAD = PatternGenerator<Instruction::SLOAD>{};
static auto constexpr SSTORE = PatternGenerator<Instruction::SSTORE>{};
static auto constexpr PC = PatternGenerator<Instruction::PC>{};
static auto constexpr MSIZE = PatternGenerator<Instruction::MSIZE>{};
static auto constexpr GAS = PatternGenerator<Instruction::GAS>{};
static auto constexpr LOG0 = PatternGenerator<Instruction::LOG0>{};
static auto constexpr LOG1 = PatternGenerator<Instruction::LOG1>{};
static auto constexpr LOG2 = PatternGenerator<Instruction::LOG2>{};
static auto constexpr LOG3 = PatternGenerator<Instruction::LOG3>{};
static auto constexpr LOG4 = PatternGenerator<Instruction::LOG4>{};
static auto constexpr CREATE = PatternGenerator<Instruction::CREATE>{};
static auto constexpr CALL = PatternGenerator<Instruction::CALL>{};
static auto constexpr CALLCODE = PatternGenerator<Instruction::CALLCODE>{};
static auto constexpr STATICCALL = PatternGenerator<Instruction::STATICCALL>{};
static auto constexpr RETURN = PatternGenerator<Instruction::RETURN>{};
static auto constexpr DELEGATECALL = PatternGenerator<Instruction::DELEGATECALL>{};
static auto constexpr CREATE2 = PatternGenerator<Instruction::CREATE2>{};
static auto constexpr REVERT = PatternGenerator<Instruction::REVERT>{};
static auto constexpr INVALID = PatternGenerator<Instruction::INVALID>{};
static auto constexpr SELFDESTRUCT = PatternGenerator<Instruction::SELFDESTRUCT>{};
static auto constexpr STOP = PatternGenerator<InternalInstruction::STOP>{};
static auto constexpr ADD = PatternGenerator<InternalInstruction::ADD>{};
static auto constexpr SUB = PatternGenerator<InternalInstruction::SUB>{};
static auto constexpr MUL = PatternGenerator<InternalInstruction::MUL>{};
static auto constexpr DIV = PatternGenerator<InternalInstruction::DIV>{};
static auto constexpr SDIV = PatternGenerator<InternalInstruction::SDIV>{};
static auto constexpr MOD = PatternGenerator<InternalInstruction::MOD>{};
static auto constexpr SMOD = PatternGenerator<InternalInstruction::SMOD>{};
static auto constexpr EXP = PatternGenerator<InternalInstruction::EXP>{};
static auto constexpr NOT = PatternGenerator<InternalInstruction::NOT>{};
static auto constexpr LT = PatternGenerator<InternalInstruction::LT>{};
static auto constexpr GT = PatternGenerator<InternalInstruction::GT>{};
static auto constexpr SLT = PatternGenerator<InternalInstruction::SLT>{};
static auto constexpr SGT = PatternGenerator<InternalInstruction::SGT>{};
static auto constexpr EQ = PatternGenerator<InternalInstruction::EQ>{};
static auto constexpr ISZERO = PatternGenerator<InternalInstruction::ISZERO>{};
static auto constexpr AND = PatternGenerator<InternalInstruction::AND>{};
static auto constexpr OR = PatternGenerator<InternalInstruction::OR>{};
static auto constexpr XOR = PatternGenerator<InternalInstruction::XOR>{};
static auto constexpr BYTE = PatternGenerator<InternalInstruction::BYTE>{};
static auto constexpr SHL = PatternGenerator<InternalInstruction::SHL>{};
static auto constexpr SHR = PatternGenerator<InternalInstruction::SHR>{};
static auto constexpr SAR = PatternGenerator<InternalInstruction::SAR>{};
static auto constexpr ADDMOD = PatternGenerator<InternalInstruction::ADDMOD>{};
static auto constexpr MULMOD = PatternGenerator<InternalInstruction::MULMOD>{};
static auto constexpr SIGNEXTEND = PatternGenerator<InternalInstruction::SIGNEXTEND>{};
static auto constexpr KECCAK256 = PatternGenerator<InternalInstruction::KECCAK256>{};
static auto constexpr ADDRESS = PatternGenerator<InternalInstruction::ADDRESS>{};
static auto constexpr BALANCE = PatternGenerator<InternalInstruction::BALANCE>{};
static auto constexpr ORIGIN = PatternGenerator<InternalInstruction::ORIGIN>{};
static auto constexpr CALLER = PatternGenerator<InternalInstruction::CALLER>{};
static auto constexpr CALLVALUE = PatternGenerator<InternalInstruction::CALLVALUE>{};
static auto constexpr CALLDATALOAD = PatternGenerator<InternalInstruction::CALLDATALOAD>{};
static auto constexpr CALLDATASIZE = PatternGenerator<InternalInstruction::CALLDATASIZE>{};
static auto constexpr CALLDATACOPY = PatternGenerator<InternalInstruction::CALLDATACOPY>{};
static auto constexpr CODESIZE = PatternGenerator<InternalInstruction::CODESIZE>{};
static auto constexpr CODECOPY = PatternGenerator<InternalInstruction::CODECOPY>{};
static auto constexpr GASPRICE = PatternGenerator<InternalInstruction::GASPRICE>{};
static auto constexpr EXTCODESIZE = PatternGenerator<InternalInstruction::EXTCODESIZE>{};
static auto constexpr EXTCODECOPY = PatternGenerator<InternalInstruction::EXTCODECOPY>{};
static auto constexpr RETURNDATASIZE = PatternGenerator<InternalInstruction::RETURNDATASIZE>{};
static auto constexpr RETURNDATACOPY = PatternGenerator<InternalInstruction::RETURNDATACOPY>{};
static auto constexpr EXTCODEHASH = PatternGenerator<InternalInstruction::EXTCODEHASH>{};
static auto constexpr BLOCKHASH = PatternGenerator<InternalInstruction::BLOCKHASH>{};
static auto constexpr COINBASE = PatternGenerator<InternalInstruction::COINBASE>{};
static auto constexpr TIMESTAMP = PatternGenerator<InternalInstruction::TIMESTAMP>{};
static auto constexpr NUMBER = PatternGenerator<InternalInstruction::NUMBER>{};
static auto constexpr DIFFICULTY = PatternGenerator<InternalInstruction::DIFFICULTY>{};
static auto constexpr PREVRANDAO = PatternGenerator<InternalInstruction::PREVRANDAO>{};
static auto constexpr GASLIMIT = PatternGenerator<InternalInstruction::GASLIMIT>{};
static auto constexpr CHAINID = PatternGenerator<InternalInstruction::CHAINID>{};
static auto constexpr SELFBALANCE = PatternGenerator<InternalInstruction::SELFBALANCE>{};
static auto constexpr BASEFEE = PatternGenerator<InternalInstruction::BASEFEE>{};
static auto constexpr POP = PatternGenerator<InternalInstruction::POP>{};
static auto constexpr MLOAD = PatternGenerator<InternalInstruction::MLOAD>{};
static auto constexpr MSTORE = PatternGenerator<InternalInstruction::MSTORE>{};
static auto constexpr MSTORE8 = PatternGenerator<InternalInstruction::MSTORE8>{};
static auto constexpr SLOAD = PatternGenerator<InternalInstruction::SLOAD>{};
static auto constexpr SSTORE = PatternGenerator<InternalInstruction::SSTORE>{};
static auto constexpr PC = PatternGenerator<InternalInstruction::PC>{};
static auto constexpr MSIZE = PatternGenerator<InternalInstruction::MSIZE>{};
static auto constexpr GAS = PatternGenerator<InternalInstruction::GAS>{};
static auto constexpr LOG0 = PatternGenerator<InternalInstruction::LOG0>{};
static auto constexpr LOG1 = PatternGenerator<InternalInstruction::LOG1>{};
static auto constexpr LOG2 = PatternGenerator<InternalInstruction::LOG2>{};
static auto constexpr LOG3 = PatternGenerator<InternalInstruction::LOG3>{};
static auto constexpr LOG4 = PatternGenerator<InternalInstruction::LOG4>{};
static auto constexpr CREATE = PatternGenerator<InternalInstruction::CREATE>{};
static auto constexpr CALL = PatternGenerator<InternalInstruction::CALL>{};
static auto constexpr CALLCODE = PatternGenerator<InternalInstruction::CALLCODE>{};
static auto constexpr STATICCALL = PatternGenerator<InternalInstruction::STATICCALL>{};
static auto constexpr RETURN = PatternGenerator<InternalInstruction::RETURN>{};
static auto constexpr DELEGATECALL = PatternGenerator<InternalInstruction::DELEGATECALL>{};
static auto constexpr CREATE2 = PatternGenerator<InternalInstruction::CREATE2>{};
static auto constexpr REVERT = PatternGenerator<InternalInstruction::REVERT>{};
static auto constexpr INVALID = PatternGenerator<InternalInstruction::INVALID>{};
static auto constexpr SELFDESTRUCT = PatternGenerator<InternalInstruction::SELFDESTRUCT>{};
};
}

View File

@ -58,7 +58,7 @@ SimplificationRule<Pattern> const* Rules::findFirstMatch(
bool Rules::isInitialized() const
{
return !m_rules[uint8_t(Instruction::ADD)].empty();
return !m_rules[uint8_t(InternalInstruction::ADD)].empty();
}
void Rules::addRules(std::vector<SimplificationRule<Pattern>> const& _rules)
@ -96,7 +96,7 @@ Rules::Rules()
assertThrow(isInitialized(), OptimizerException, "Rule list not properly initialized.");
}
Pattern::Pattern(Instruction _instruction, std::initializer_list<Pattern> _arguments):
Pattern::Pattern(InternalInstruction _instruction, std::initializer_list<Pattern> _arguments):
m_type(Operation),
m_instruction(_instruction),
m_arguments(_arguments)

View File

@ -103,7 +103,7 @@ public:
// Matches a specific assembly item type or anything if not given.
Pattern(AssemblyItemType _type = UndefinedItem): m_type(_type) {}
// Matches a given instruction with given arguments
Pattern(Instruction _instruction, std::initializer_list<Pattern> _arguments = {});
Pattern(InternalInstruction _instruction, std::initializer_list<Pattern> _arguments = {});
/// Sets this pattern to be part of the match group with the identifier @a _group.
/// Inside one rule, all patterns in the same match group have to match expressions from the
/// same expression equivalence class.
@ -122,7 +122,7 @@ public:
std::string toString() const;
AssemblyItemType type() const { return m_type; }
Instruction instruction() const
InternalInstruction instruction() const
{
assertThrow(type() == Operation, OptimizerException, "");
return m_instruction;
@ -135,7 +135,7 @@ private:
AssemblyItemType m_type;
bool m_requireDataMatch = false;
Instruction m_instruction; ///< Only valid if m_type is Operation
InternalInstruction m_instruction; ///< Only valid if m_type is Operation
std::shared_ptr<u256> m_data; ///< Only valid if m_type is not Operation
std::vector<Pattern> m_arguments;
unsigned m_matchGroup = 0;

View File

@ -25,28 +25,28 @@ using namespace solidity;
using namespace solidity::evmasm;
using namespace solidity::langutil;
bool EVMVersion::hasOpcode(Instruction _opcode) const
bool EVMVersion::hasInstruction(InternalInstruction _instruction) const
{
switch (_opcode)
switch (_instruction)
{
case Instruction::RETURNDATACOPY:
case Instruction::RETURNDATASIZE:
case InternalInstruction::RETURNDATACOPY:
case InternalInstruction::RETURNDATASIZE:
return supportsReturndata();
case Instruction::STATICCALL:
case InternalInstruction::STATICCALL:
return hasStaticCall();
case Instruction::SHL:
case Instruction::SHR:
case Instruction::SAR:
case InternalInstruction::SHL:
case InternalInstruction::SHR:
case InternalInstruction::SAR:
return hasBitwiseShifting();
case Instruction::CREATE2:
case InternalInstruction::CREATE2:
return hasCreate2();
case Instruction::EXTCODEHASH:
case InternalInstruction::EXTCODEHASH:
return hasExtCodeHash();
case Instruction::CHAINID:
case InternalInstruction::CHAINID:
return hasChainID();
case Instruction::SELFBALANCE:
case InternalInstruction::SELFBALANCE:
return hasSelfBalance();
case Instruction::BASEFEE:
case InternalInstruction::BASEFEE:
return hasBaseFee();
case InternalInstruction::DIFFICULTY:
return hasDifficulty();

View File

@ -112,7 +112,7 @@ public:
}
private:
void checkInstruction(SourceLocation _location, evmasm::Instruction _instruction)
void checkInstruction(SourceLocation _location, evmasm::InternalInstruction _instruction)
{
if (evmasm::SemanticInformation::invalidInViewFunctions(_instruction))
m_reportMutability(StateMutability::NonPayable, _location);

View File

@ -74,9 +74,9 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
if (fromCalldata && _sourceType.isDynamicallySized())
{
// stack: target_ref source_ref source_length
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
// stack: target_ref source_length source_ref
m_context << Instruction::DUP3;
m_context << InternalInstruction::DUP3;
// stack: target_ref source_length source_ref target_ref
m_context.callYulFunction(
m_context.utilFunctions().copyByteArrayToStorageFunction(_sourceType, _targetType),
@ -87,7 +87,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
else
{
// stack: target_ref source_ref
m_context << Instruction::DUP2;
m_context << InternalInstruction::DUP2;
// stack: target_ref source_ref target_ref
m_context.callYulFunction(
m_context.utilFunctions().copyByteArrayToStorageFunction(_sourceType, _targetType),
@ -105,8 +105,8 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
if (_sourceType.location() == DataLocation::Memory && _sourceType.isDynamicallySized())
{
// increment source pointer to point to data
m_context << Instruction::SWAP1 << u256(0x20);
m_context << Instruction::ADD << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1 << u256(0x20);
m_context << InternalInstruction::ADD << InternalInstruction::SWAP1;
}
// stack: target_ref source_ref source_length
@ -122,7 +122,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
ArrayType const& _sourceType = dynamic_cast<ArrayType const&>(*sourceType);
ArrayType const& _targetType = dynamic_cast<ArrayType const&>(*targetType);
// stack: target_ref source_ref source_length
_context << Instruction::DUP3;
_context << InternalInstruction::DUP3;
// stack: target_ref source_ref source_length target_ref
utils.retrieveLength(_targetType);
// stack: target_ref source_ref source_length target_ref target_length
@ -130,7 +130,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
{
// store new target length
solAssert(!_targetType.isByteArrayOrString());
_context << Instruction::DUP3 << Instruction::DUP3 << Instruction::SSTORE;
_context << InternalInstruction::DUP3 << InternalInstruction::DUP3 << InternalInstruction::SSTORE;
}
if (sourceBaseType->category() == Type::Category::Mapping)
{
@ -138,35 +138,35 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
solAssert(_sourceType.location() == DataLocation::Storage, "");
// nothing to copy
_context
<< Instruction::POP << Instruction::POP
<< Instruction::POP << Instruction::POP;
<< InternalInstruction::POP << InternalInstruction::POP
<< InternalInstruction::POP << InternalInstruction::POP;
return;
}
// stack: target_ref source_ref source_length target_ref target_length
// compute hashes (data positions)
_context << Instruction::SWAP1;
_context << InternalInstruction::SWAP1;
if (_targetType.isDynamicallySized())
CompilerUtils(_context).computeHashStatic();
// stack: target_ref source_ref source_length target_length target_data_pos
_context << Instruction::SWAP1;
_context << InternalInstruction::SWAP1;
utils.convertLengthToSize(_targetType);
_context << Instruction::DUP2 << Instruction::ADD;
_context << InternalInstruction::DUP2 << InternalInstruction::ADD;
// stack: target_ref source_ref source_length target_data_pos target_data_end
_context << Instruction::SWAP3;
_context << InternalInstruction::SWAP3;
// stack: target_ref target_data_end source_length target_data_pos source_ref
evmasm::AssemblyItem copyLoopEndWithoutByteOffset = _context.newTag();
solAssert(!_targetType.isByteArrayOrString());
// skip copying if source length is zero
_context << Instruction::DUP3 << Instruction::ISZERO;
_context << InternalInstruction::DUP3 << InternalInstruction::ISZERO;
_context.appendConditionalJumpTo(copyLoopEndWithoutByteOffset);
if (_sourceType.location() == DataLocation::Storage && _sourceType.isDynamicallySized())
CompilerUtils(_context).computeHashStatic();
// stack: target_ref target_data_end source_length target_data_pos source_data_pos
_context << Instruction::SWAP2;
_context << InternalInstruction::SWAP2;
utils.convertLengthToSize(_sourceType);
_context << Instruction::DUP3 << Instruction::ADD;
_context << InternalInstruction::DUP3 << InternalInstruction::ADD;
// stack: target_ref target_data_end source_data_pos target_data_pos source_data_end
if (haveByteOffsetTarget)
_context << u256(0);
@ -178,7 +178,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
// check for loop condition
_context
<< dupInstruction(3 + byteOffsetSize) << dupInstruction(2 + byteOffsetSize)
<< Instruction::GT << Instruction::ISZERO;
<< InternalInstruction::GT << InternalInstruction::ISZERO;
evmasm::AssemblyItem copyLoopEnd = _context.appendConditionalJump();
// stack: target_ref target_data_end source_data_pos target_data_pos source_data_end [target_byte_offset] [source_byte_offset]
// copy
@ -193,19 +193,19 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
!sourceBaseArrayType.isDynamicallySized(),
"Copying nested calldata dynamic arrays to storage is not implemented in the old code generator."
);
_context << Instruction::DUP3;
_context << InternalInstruction::DUP3;
if (sourceBaseArrayType.location() == DataLocation::Memory)
_context << Instruction::MLOAD;
_context << Instruction::DUP3;
_context << InternalInstruction::MLOAD;
_context << InternalInstruction::DUP3;
utils.copyArrayToStorage(dynamic_cast<ArrayType const&>(*targetBaseType), sourceBaseArrayType);
_context << Instruction::POP;
_context << InternalInstruction::POP;
}
else if (directCopy)
{
solAssert(byteOffsetSize == 0, "Byte offset for direct copy.");
_context
<< Instruction::DUP3 << Instruction::SLOAD
<< Instruction::DUP3 << Instruction::SSTORE;
<< InternalInstruction::DUP3 << InternalInstruction::SLOAD
<< InternalInstruction::DUP3 << InternalInstruction::SSTORE;
}
else
{
@ -217,7 +217,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
if (_sourceType.location() == DataLocation::Storage)
{
if (haveByteOffsetSource)
_context << Instruction::DUP2;
_context << InternalInstruction::DUP2;
else
_context << u256(0);
StorageItem(_context, *sourceBaseType).retrieveValue(SourceLocation(), true);
@ -254,7 +254,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
else
_context << sourceBaseType->calldataHeadSize();
_context
<< Instruction::ADD
<< InternalInstruction::ADD
<< swapInstruction(2 + byteOffsetSize);
}
// increment target
@ -264,7 +264,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
_context
<< swapInstruction(1 + byteOffsetSize)
<< targetBaseType->storageSize()
<< Instruction::ADD
<< InternalInstruction::ADD
<< swapInstruction(1 + byteOffsetSize);
_context.appendJumpTo(copyLoopStart);
_context << copyLoopEnd;
@ -272,7 +272,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
{
// clear elements that might be left over in the current slot in target
// stack: target_ref target_data_end source_data_pos target_data_pos source_data_end target_byte_offset [source_byte_offset]
_context << dupInstruction(byteOffsetSize) << Instruction::ISZERO;
_context << dupInstruction(byteOffsetSize) << InternalInstruction::ISZERO;
evmasm::AssemblyItem copyCleanupLoopEnd = _context.appendConditionalJump();
_context << dupInstruction(2 + byteOffsetSize) << dupInstruction(1 + byteOffsetSize);
StorageItem(_context, *targetBaseType).setToZero(SourceLocation(), true);
@ -280,21 +280,21 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
_context.appendJumpTo(copyLoopEnd);
_context << copyCleanupLoopEnd;
_context << Instruction::POP; // might pop the source, but then target is popped next
_context << InternalInstruction::POP; // might pop the source, but then target is popped next
}
if (haveByteOffsetSource)
_context << Instruction::POP;
_context << InternalInstruction::POP;
_context << copyLoopEndWithoutByteOffset;
// zero-out leftovers in target
// stack: target_ref target_data_end source_data_pos target_data_pos_updated source_data_end
_context << Instruction::POP << Instruction::SWAP1 << Instruction::POP;
_context << InternalInstruction::POP << InternalInstruction::SWAP1 << InternalInstruction::POP;
// stack: target_ref target_data_end target_data_pos_updated
if (targetBaseType->storageBytes() < 32)
utils.clearStorageLoop(TypeProvider::uint256());
else
utils.clearStorageLoop(targetBaseType);
_context << Instruction::POP;
_context << InternalInstruction::POP;
}
);
}
@ -323,7 +323,7 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
)";
routine += "target := add(target, len)\n";
m_context.appendInlineAssembly("{" + routine + "}", {"target", "source", "len"});
m_context << Instruction::POP << Instruction::POP;
m_context << InternalInstruction::POP << InternalInstruction::POP;
}
else if (_sourceType.location() == DataLocation::Memory)
{
@ -332,25 +332,25 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
if (!_sourceType.baseType()->isValueType())
{
// copy using a loop
m_context << u256(0) << Instruction::SWAP3;
m_context << u256(0) << InternalInstruction::SWAP3;
// stack: counter source length target
auto repeat = m_context.newTag();
m_context << repeat;
m_context << Instruction::DUP2 << Instruction::DUP5;
m_context << Instruction::LT << Instruction::ISZERO;
m_context << InternalInstruction::DUP2 << InternalInstruction::DUP5;
m_context << InternalInstruction::LT << InternalInstruction::ISZERO;
auto loopEnd = m_context.appendConditionalJump();
m_context << Instruction::DUP3 << Instruction::DUP5;
m_context << InternalInstruction::DUP3 << InternalInstruction::DUP5;
accessIndex(_sourceType, false);
MemoryItem(m_context, *_sourceType.baseType(), true).retrieveValue(SourceLocation(), true);
if (auto baseArray = dynamic_cast<ArrayType const*>(_sourceType.baseType()))
copyArrayToMemory(*baseArray, _padToWordBoundaries);
else
utils.storeInMemoryDynamic(*_sourceType.baseType());
m_context << Instruction::SWAP3 << u256(1) << Instruction::ADD;
m_context << Instruction::SWAP3;
m_context << InternalInstruction::SWAP3 << u256(1) << InternalInstruction::ADD;
m_context << InternalInstruction::SWAP3;
m_context.appendJumpTo(repeat);
m_context << loopEnd;
m_context << Instruction::SWAP3;
m_context << InternalInstruction::SWAP3;
utils.popStackSlots(3);
// stack: updated_target_pos
return;
@ -360,13 +360,13 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
if (_sourceType.isDynamicallySized())
{
// change pointer to data part
m_context << Instruction::SWAP1 << u256(32) << Instruction::ADD;
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1 << u256(32) << InternalInstruction::ADD;
m_context << InternalInstruction::SWAP1;
}
if (!_sourceType.isByteArrayOrString())
convertLengthToSize(_sourceType);
// stack: <target> <source> <size>
m_context << Instruction::DUP1 << Instruction::DUP4 << Instruction::DUP4;
m_context << InternalInstruction::DUP1 << InternalInstruction::DUP4 << InternalInstruction::DUP4;
// We can resort to copying full 32 bytes only if
// - the length is known to be a multiple of 32 or
// - we will pad to full 32 bytes later anyway.
@ -375,7 +375,7 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
else
utils.memoryCopy();
m_context << Instruction::SWAP1 << Instruction::POP;
m_context << InternalInstruction::SWAP1 << InternalInstruction::POP;
// stack: <target> <size>
bool paddingNeeded = _padToWordBoundaries && _sourceType.isByteArrayOrString();
@ -383,43 +383,43 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
if (paddingNeeded)
{
// stack: <target> <size>
m_context << Instruction::SWAP1 << Instruction::DUP2 << Instruction::ADD;
m_context << InternalInstruction::SWAP1 << InternalInstruction::DUP2 << InternalInstruction::ADD;
// stack: <length> <target + size>
m_context << Instruction::SWAP1 << u256(31) << Instruction::AND;
m_context << InternalInstruction::SWAP1 << u256(31) << InternalInstruction::AND;
// stack: <target + size> <remainder = size % 32>
evmasm::AssemblyItem skip = m_context.newTag();
if (_sourceType.isDynamicallySized())
{
m_context << Instruction::DUP1 << Instruction::ISZERO;
m_context << InternalInstruction::DUP1 << InternalInstruction::ISZERO;
m_context.appendConditionalJumpTo(skip);
}
// round off, load from there.
// stack <target + size> <remainder = size % 32>
m_context << Instruction::DUP1 << Instruction::DUP3;
m_context << Instruction::SUB;
m_context << InternalInstruction::DUP1 << InternalInstruction::DUP3;
m_context << InternalInstruction::SUB;
// stack: target+size remainder <target + size - remainder>
m_context << Instruction::DUP1 << Instruction::MLOAD;
m_context << InternalInstruction::DUP1 << InternalInstruction::MLOAD;
// Now we AND it with ~(2**(8 * (32 - remainder)) - 1)
m_context << u256(1);
m_context << Instruction::DUP4 << u256(32) << Instruction::SUB;
m_context << InternalInstruction::DUP4 << u256(32) << InternalInstruction::SUB;
// stack: ...<v> 1 <32 - remainder>
m_context << u256(0x100) << Instruction::EXP << Instruction::SUB;
m_context << Instruction::NOT << Instruction::AND;
m_context << u256(0x100) << InternalInstruction::EXP << InternalInstruction::SUB;
m_context << InternalInstruction::NOT << InternalInstruction::AND;
// stack: target+size remainder target+size-remainder <v & ...>
m_context << Instruction::DUP2 << Instruction::MSTORE;
m_context << InternalInstruction::DUP2 << InternalInstruction::MSTORE;
// stack: target+size remainder target+size-remainder
m_context << u256(32) << Instruction::ADD;
m_context << u256(32) << InternalInstruction::ADD;
// stack: target+size remainder <new_padded_end>
m_context << Instruction::SWAP2 << Instruction::POP;
m_context << InternalInstruction::SWAP2 << InternalInstruction::POP;
if (_sourceType.isDynamicallySized())
m_context << skip.tag();
// stack <target + "size"> <remainder = size % 32>
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
}
else
// stack: <target> <size>
m_context << Instruction::ADD;
m_context << InternalInstruction::ADD;
}
else
{
@ -431,48 +431,48 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
retrieveLength(_sourceType);
// stack here: memory_offset storage_offset length
// jump to end if length is zero
m_context << Instruction::DUP1 << Instruction::ISZERO;
m_context << InternalInstruction::DUP1 << InternalInstruction::ISZERO;
evmasm::AssemblyItem loopEnd = m_context.appendConditionalJump();
// Special case for tightly-stored byte arrays
if (_sourceType.isByteArrayOrString())
{
// stack here: memory_offset storage_offset length
m_context << Instruction::DUP1 << u256(31) << Instruction::LT;
m_context << InternalInstruction::DUP1 << u256(31) << InternalInstruction::LT;
evmasm::AssemblyItem longByteArray = m_context.appendConditionalJump();
// store the short byte array (discard lower-order byte)
m_context << u256(0x100) << Instruction::DUP1;
m_context << Instruction::DUP4 << Instruction::SLOAD;
m_context << Instruction::DIV << Instruction::MUL;
m_context << Instruction::DUP4 << Instruction::MSTORE;
m_context << u256(0x100) << InternalInstruction::DUP1;
m_context << InternalInstruction::DUP4 << InternalInstruction::SLOAD;
m_context << InternalInstruction::DIV << InternalInstruction::MUL;
m_context << InternalInstruction::DUP4 << InternalInstruction::MSTORE;
// stack here: memory_offset storage_offset length
// add 32 or length to memory offset
m_context << Instruction::SWAP2;
m_context << InternalInstruction::SWAP2;
if (_padToWordBoundaries)
m_context << u256(32);
else
m_context << Instruction::DUP3;
m_context << Instruction::ADD;
m_context << Instruction::SWAP2;
m_context << InternalInstruction::DUP3;
m_context << InternalInstruction::ADD;
m_context << InternalInstruction::SWAP2;
m_context.appendJumpTo(loopEnd);
m_context << longByteArray;
}
else
// convert length to memory size
m_context << _sourceType.baseType()->memoryHeadSize() << Instruction::MUL;
m_context << _sourceType.baseType()->memoryHeadSize() << InternalInstruction::MUL;
m_context << Instruction::DUP3 << Instruction::ADD << Instruction::SWAP2;
m_context << InternalInstruction::DUP3 << InternalInstruction::ADD << InternalInstruction::SWAP2;
if (_sourceType.isDynamicallySized())
{
// actual array data is stored at KECCAK256(storage_offset)
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
utils.computeHashStatic();
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
}
// stack here: memory_end_offset storage_data_offset memory_offset
bool haveByteOffset = !_sourceType.isByteArrayOrString() && storageBytes <= 16;
if (haveByteOffset)
m_context << u256(0) << Instruction::SWAP1;
m_context << u256(0) << InternalInstruction::SWAP1;
// stack here: memory_end_offset storage_data_offset [storage_byte_offset] memory_offset
evmasm::AssemblyItem loopStart = m_context.newTag();
m_context << loopStart;
@ -480,20 +480,20 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
if (_sourceType.isByteArrayOrString())
{
// Packed both in storage and memory.
m_context << Instruction::DUP2 << Instruction::SLOAD;
m_context << Instruction::DUP2 << Instruction::MSTORE;
m_context << InternalInstruction::DUP2 << InternalInstruction::SLOAD;
m_context << InternalInstruction::DUP2 << InternalInstruction::MSTORE;
// increment storage_data_offset by 1
m_context << Instruction::SWAP1 << u256(1) << Instruction::ADD;
m_context << InternalInstruction::SWAP1 << u256(1) << InternalInstruction::ADD;
// increment memory offset by 32
m_context << Instruction::SWAP1 << u256(32) << Instruction::ADD;
m_context << InternalInstruction::SWAP1 << u256(32) << InternalInstruction::ADD;
}
else
{
// stack here: memory_end_offset storage_data_offset [storage_byte_offset] memory_offset
if (haveByteOffset)
m_context << Instruction::DUP3 << Instruction::DUP3;
m_context << InternalInstruction::DUP3 << InternalInstruction::DUP3;
else
m_context << Instruction::DUP2 << u256(0);
m_context << InternalInstruction::DUP2 << u256(0);
StorageItem(m_context, *_sourceType.baseType()).retrieveValue(SourceLocation(), true);
if (auto baseArray = dynamic_cast<ArrayType const*>(_sourceType.baseType()))
copyArrayToMemory(*baseArray, _padToWordBoundaries);
@ -504,18 +504,18 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
incrementByteOffset(storageBytes, 2, 3);
else
{
m_context << Instruction::SWAP1;
m_context << storageSize << Instruction::ADD;
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
m_context << storageSize << InternalInstruction::ADD;
m_context << InternalInstruction::SWAP1;
}
}
// check for loop condition
m_context << Instruction::DUP1 << dupInstruction(haveByteOffset ? 5 : 4);
m_context << Instruction::GT;
m_context << InternalInstruction::DUP1 << dupInstruction(haveByteOffset ? 5 : 4);
m_context << InternalInstruction::GT;
m_context.appendConditionalJumpTo(loopStart);
// stack here: memory_end_offset storage_data_offset [storage_byte_offset] memory_offset
if (haveByteOffset)
m_context << Instruction::SWAP1 << Instruction::POP;
m_context << InternalInstruction::SWAP1 << InternalInstruction::POP;
if (!_sourceType.isByteArrayOrString())
{
solAssert(_sourceType.calldataStride() % 32 == 0, "");
@ -526,12 +526,12 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
// memory_end_offset - start is the actual length (we want to compute the ceil of).
// memory_offset - start is its next multiple of 32, but it might be off by 32.
// so we compute: memory_end_offset += (memory_offset - memory_end_offest) & 31
m_context << Instruction::DUP3 << Instruction::SWAP1 << Instruction::SUB;
m_context << u256(31) << Instruction::AND;
m_context << Instruction::DUP3 << Instruction::ADD;
m_context << Instruction::SWAP2;
m_context << InternalInstruction::DUP3 << InternalInstruction::SWAP1 << InternalInstruction::SUB;
m_context << u256(31) << InternalInstruction::AND;
m_context << InternalInstruction::DUP3 << InternalInstruction::ADD;
m_context << InternalInstruction::SWAP2;
}
m_context << loopEnd << Instruction::POP << Instruction::POP;
m_context << loopEnd << InternalInstruction::POP << InternalInstruction::POP;
}
}
@ -555,20 +555,20 @@ void ArrayUtils::clearArray(ArrayType const& _typeIn) const
if (_type.baseType()->isValueType())
solAssert(_type.baseType()->storageSize() <= 1, "Invalid size for value type.");
_context << Instruction::POP; // remove byte offset
_context << InternalInstruction::POP; // remove byte offset
if (_type.isDynamicallySized())
ArrayUtils(_context).clearDynamicArray(_type);
else if (_type.length() == 0 || _type.baseType()->category() == Type::Category::Mapping)
_context << Instruction::POP;
_context << InternalInstruction::POP;
else if (_type.baseType()->isValueType() && _type.storageSize() <= 5)
{
// unroll loop for small arrays @todo choose a good value
// Note that we loop over storage slots here, not elements.
for (unsigned i = 1; i < _type.storageSize(); ++i)
_context
<< u256(0) << Instruction::DUP2 << Instruction::SSTORE
<< u256(1) << Instruction::ADD;
_context << u256(0) << Instruction::SWAP1 << Instruction::SSTORE;
<< u256(0) << InternalInstruction::DUP2 << InternalInstruction::SSTORE
<< u256(1) << InternalInstruction::ADD;
_context << u256(0) << InternalInstruction::SWAP1 << InternalInstruction::SSTORE;
}
else if (!_type.baseType()->isValueType() && _type.length() <= 4)
{
@ -579,22 +579,22 @@ void ArrayUtils::clearArray(ArrayType const& _typeIn) const
_context << u256(0);
StorageItem(_context, *_type.baseType()).setToZero(SourceLocation(), false);
_context
<< Instruction::POP
<< u256(_type.baseType()->storageSize()) << Instruction::ADD;
<< InternalInstruction::POP
<< u256(_type.baseType()->storageSize()) << InternalInstruction::ADD;
}
_context << u256(0);
StorageItem(_context, *_type.baseType()).setToZero(SourceLocation(), true);
}
else
{
_context << Instruction::DUP1 << _type.length();
_context << InternalInstruction::DUP1 << _type.length();
ArrayUtils(_context).convertLengthToSize(_type);
_context << Instruction::ADD << Instruction::SWAP1;
_context << InternalInstruction::ADD << InternalInstruction::SWAP1;
if (_type.baseType()->storageBytes() < 32)
ArrayUtils(_context).clearStorageLoop(TypeProvider::uint256());
else
ArrayUtils(_context).clearStorageLoop(_type.baseType());
_context << Instruction::POP;
_context << InternalInstruction::POP;
}
solAssert(_context.stackHeight() == stackHeightStart - 2, "");
}
@ -609,15 +609,15 @@ void ArrayUtils::clearDynamicArray(ArrayType const& _type) const
// fetch length
retrieveLength(_type);
// set length to zero
m_context << u256(0) << Instruction::DUP3 << Instruction::SSTORE;
m_context << u256(0) << InternalInstruction::DUP3 << InternalInstruction::SSTORE;
// Special case: short byte arrays are stored togeher with their length
evmasm::AssemblyItem endTag = m_context.newTag();
if (_type.isByteArrayOrString())
{
// stack: ref old_length
m_context << Instruction::DUP1 << u256(31) << Instruction::LT;
m_context << InternalInstruction::DUP1 << u256(31) << InternalInstruction::LT;
evmasm::AssemblyItem longByteArray = m_context.appendConditionalJump();
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
m_context.appendJumpTo(endTag);
m_context.adjustStackOffset(1); // needed because of jump
m_context << longByteArray;
@ -625,11 +625,11 @@ void ArrayUtils::clearDynamicArray(ArrayType const& _type) const
// stack: ref old_length
convertLengthToSize(_type);
// compute data positions
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
CompilerUtils(m_context).computeHashStatic();
// stack: len data_pos
m_context << Instruction::SWAP1 << Instruction::DUP2 << Instruction::ADD
<< Instruction::SWAP1;
m_context << InternalInstruction::SWAP1 << InternalInstruction::DUP2 << InternalInstruction::ADD
<< InternalInstruction::SWAP1;
// stack: data_pos_end data_pos
if (_type.storageStride() < 32)
clearStorageLoop(TypeProvider::uint256());
@ -637,7 +637,7 @@ void ArrayUtils::clearDynamicArray(ArrayType const& _type) const
clearStorageLoop(_type.baseType());
// cleanup
m_context << endTag;
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
}
void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const
@ -670,13 +670,13 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const
evmasm::AssemblyItem regularPath = _context.newTag();
// We start by a large case-distinction about the old and new length of the byte array.
_context << Instruction::DUP3 << Instruction::SLOAD;
_context << InternalInstruction::DUP3 << InternalInstruction::SLOAD;
// stack: ref new_length current_length ref_value
solAssert(_context.stackHeight() - stackHeightStart == 4 - 2, "3");
_context << Instruction::DUP2 << u256(31) << Instruction::LT;
_context << InternalInstruction::DUP2 << u256(31) << InternalInstruction::LT;
evmasm::AssemblyItem currentIsLong = _context.appendConditionalJump();
_context << Instruction::DUP3 << u256(31) << Instruction::LT;
_context << InternalInstruction::DUP3 << u256(31) << InternalInstruction::LT;
evmasm::AssemblyItem newIsLong = _context.appendConditionalJump();
// Here: short -> short
@ -684,17 +684,17 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const
// Compute 1 << (256 - 8 * new_size)
evmasm::AssemblyItem shortToShort = _context.newTag();
_context << shortToShort;
_context << Instruction::DUP3 << u256(8) << Instruction::MUL;
_context << u256(0x100) << Instruction::SUB;
_context << u256(2) << Instruction::EXP;
_context << InternalInstruction::DUP3 << u256(8) << InternalInstruction::MUL;
_context << u256(0x100) << InternalInstruction::SUB;
_context << u256(2) << InternalInstruction::EXP;
// Divide and multiply by that value, clearing bits.
_context << Instruction::DUP1 << Instruction::SWAP2;
_context << Instruction::DIV << Instruction::MUL;
_context << InternalInstruction::DUP1 << InternalInstruction::SWAP2;
_context << InternalInstruction::DIV << InternalInstruction::MUL;
// Insert 2*length.
_context << Instruction::DUP3 << Instruction::DUP1 << Instruction::ADD;
_context << Instruction::OR;
_context << InternalInstruction::DUP3 << InternalInstruction::DUP1 << InternalInstruction::ADD;
_context << InternalInstruction::OR;
// Store.
_context << Instruction::DUP4 << Instruction::SSTORE;
_context << InternalInstruction::DUP4 << InternalInstruction::SSTORE;
solAssert(_context.stackHeight() - stackHeightStart == 3 - 2, "3");
_context.appendJumpTo(resizeEnd);
@ -705,24 +705,24 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const
// stack: ref new_length current_length ref_value
solAssert(_context.stackHeight() - stackHeightStart == 4 - 2, "3");
// Zero out lower-order byte.
_context << u256(0xff) << Instruction::NOT << Instruction::AND;
_context << u256(0xff) << InternalInstruction::NOT << InternalInstruction::AND;
// Store at data location.
_context << Instruction::DUP4;
_context << InternalInstruction::DUP4;
CompilerUtils(_context).computeHashStatic();
_context << Instruction::SSTORE;
_context << InternalInstruction::SSTORE;
// stack: ref new_length current_length
// Store new length: Compule 2*length + 1 and store it.
_context << Instruction::DUP2 << Instruction::DUP1 << Instruction::ADD;
_context << u256(1) << Instruction::ADD;
_context << InternalInstruction::DUP2 << InternalInstruction::DUP1 << InternalInstruction::ADD;
_context << u256(1) << InternalInstruction::ADD;
// stack: ref new_length current_length 2*new_length+1
_context << Instruction::DUP4 << Instruction::SSTORE;
_context << InternalInstruction::DUP4 << InternalInstruction::SSTORE;
solAssert(_context.stackHeight() - stackHeightStart == 3 - 2, "3");
_context.appendJumpTo(resizeEnd);
_context.adjustStackOffset(1); // we have to do that because of the jumps
_context << currentIsLong;
_context << Instruction::DUP3 << u256(31) << Instruction::LT;
_context << InternalInstruction::DUP3 << u256(31) << InternalInstruction::LT;
_context.appendConditionalJumpTo(regularPath);
// Here: long -> short
@ -731,51 +731,51 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const
// stack: ref new_length current_length ref_value
solAssert(_context.stackHeight() - stackHeightStart == 4 - 2, "3");
_context << Instruction::POP << Instruction::DUP3;
_context << InternalInstruction::POP << InternalInstruction::DUP3;
CompilerUtils(_context).computeHashStatic();
_context << Instruction::DUP1 << Instruction::SLOAD << Instruction::SWAP1;
_context << InternalInstruction::DUP1 << InternalInstruction::SLOAD << InternalInstruction::SWAP1;
// stack: ref new_length current_length first_word data_location
_context << Instruction::DUP3;
_context << InternalInstruction::DUP3;
ArrayUtils(_context).convertLengthToSize(_type);
_context << Instruction::DUP2 << Instruction::ADD << Instruction::SWAP1;
_context << InternalInstruction::DUP2 << InternalInstruction::ADD << InternalInstruction::SWAP1;
// stack: ref new_length current_length first_word data_location_end data_location
ArrayUtils(_context).clearStorageLoop(TypeProvider::uint256());
_context << Instruction::POP;
_context << InternalInstruction::POP;
// stack: ref new_length current_length first_word
solAssert(_context.stackHeight() - stackHeightStart == 4 - 2, "3");
_context.appendJumpTo(shortToShort);
_context << regularPath;
// stack: ref new_length current_length ref_value
_context << Instruction::POP;
_context << InternalInstruction::POP;
}
// Change of length for a regular array (i.e. length at location, data at KECCAK256(location)).
// stack: ref new_length old_length
// store new length
_context << Instruction::DUP2;
_context << InternalInstruction::DUP2;
if (_type.isByteArrayOrString())
// For a "long" byte array, store length as 2*length+1
_context << Instruction::DUP1 << Instruction::ADD << u256(1) << Instruction::ADD;
_context << Instruction::DUP4 << Instruction::SSTORE;
_context << InternalInstruction::DUP1 << InternalInstruction::ADD << u256(1) << InternalInstruction::ADD;
_context << InternalInstruction::DUP4 << InternalInstruction::SSTORE;
// skip if size is not reduced
_context << Instruction::DUP2 << Instruction::DUP2
<< Instruction::GT << Instruction::ISZERO;
_context << InternalInstruction::DUP2 << InternalInstruction::DUP2
<< InternalInstruction::GT << InternalInstruction::ISZERO;
_context.appendConditionalJumpTo(resizeEnd);
// size reduced, clear the end of the array
// stack: ref new_length old_length
ArrayUtils(_context).convertLengthToSize(_type);
_context << Instruction::DUP2;
_context << InternalInstruction::DUP2;
ArrayUtils(_context).convertLengthToSize(_type);
// stack: ref new_length old_size new_size
// compute data positions
_context << Instruction::DUP4;
_context << InternalInstruction::DUP4;
CompilerUtils(_context).computeHashStatic();
// stack: ref new_length old_size new_size data_pos
_context << Instruction::SWAP2 << Instruction::DUP3 << Instruction::ADD;
_context << InternalInstruction::SWAP2 << InternalInstruction::DUP3 << InternalInstruction::ADD;
// stack: ref new_length data_pos new_size delete_end
_context << Instruction::SWAP2 << Instruction::ADD;
_context << InternalInstruction::SWAP2 << InternalInstruction::ADD;
// stack: ref new_length delete_end delete_start
if (_type.storageStride() < 32)
ArrayUtils(_context).clearStorageLoop(TypeProvider::uint256());
@ -784,7 +784,7 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const
_context << resizeEnd;
// cleanup
_context << Instruction::POP << Instruction::POP << Instruction::POP;
_context << InternalInstruction::POP << InternalInstruction::POP << InternalInstruction::POP;
solAssert(_context.stackHeight() == stackHeightStart - 2, "");
}
);
@ -806,7 +806,7 @@ void ArrayUtils::incrementDynamicArraySize(ArrayType const& _type) const
// lowest-order byte (we actually use a mask with fewer bits) must
// be (31*2+0) = 62
m_context << Instruction::DUP1 << Instruction::SLOAD << Instruction::DUP1;
m_context << InternalInstruction::DUP1 << InternalInstruction::SLOAD << InternalInstruction::DUP1;
m_context.callYulFunction(m_context.utilFunctions().extractByteArrayLengthFunction(), 1, 1);
m_context.appendInlineAssembly(R"({
// We have to copy if length is exactly 31, because that marks
@ -824,7 +824,7 @@ void ArrayUtils::incrementDynamicArraySize(ArrayType const& _type) const
// return new length in ref
ref := add(length, 1)
})", {"ref", "data", "length"});
m_context << Instruction::POP << Instruction::POP;
m_context << InternalInstruction::POP << InternalInstruction::POP;
}
else
m_context.appendInlineAssembly(R"({
@ -843,7 +843,7 @@ void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const
if (_type.isByteArrayOrString())
{
m_context << Instruction::DUP1 << Instruction::SLOAD << Instruction::DUP1;
m_context << InternalInstruction::DUP1 << InternalInstruction::SLOAD << InternalInstruction::DUP1;
m_context.callYulFunction(m_context.utilFunctions().extractByteArrayLengthFunction(), 1, 1);
util::Whiskers code(R"({
if iszero(length) {
@ -892,25 +892,25 @@ void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const
code("panicSelector", util::selectorFromSignatureU256("Panic(uint256)").str());
code("emptyArrayPop", to_string(unsigned(util::PanicCode::EmptyArrayPop)));
m_context.appendInlineAssembly(code.render(), {"ref", "slot_value", "length"});
m_context << Instruction::POP << Instruction::POP << Instruction::POP;
m_context << InternalInstruction::POP << InternalInstruction::POP << InternalInstruction::POP;
}
else
{
// stack: ArrayReference
retrieveLength(_type);
// stack: ArrayReference oldLength
m_context << Instruction::DUP1;
m_context << InternalInstruction::DUP1;
// stack: ArrayReference oldLength oldLength
m_context << Instruction::ISZERO;
m_context << InternalInstruction::ISZERO;
m_context.appendConditionalPanic(util::PanicCode::EmptyArrayPop);
// Stack: ArrayReference oldLength
m_context << u256(1) << Instruction::SWAP1 << Instruction::SUB;
m_context << u256(1) << InternalInstruction::SWAP1 << InternalInstruction::SUB;
// Stack ArrayReference newLength
if (_type.baseType()->category() != Type::Category::Mapping)
{
m_context << Instruction::DUP2 << Instruction::DUP2;
m_context << InternalInstruction::DUP2 << InternalInstruction::DUP2;
// Stack ArrayReference newLength ArrayReference newLength;
accessIndex(_type, false);
// Stack: ArrayReference newLength storage_slot byte_offset
@ -918,7 +918,7 @@ void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const
}
// Stack: ArrayReference newLength
m_context << Instruction::SWAP1 << Instruction::SSTORE;
m_context << InternalInstruction::SWAP1 << InternalInstruction::SSTORE;
}
}
@ -934,7 +934,7 @@ void ArrayUtils::clearStorageLoop(Type const* _type) const
unsigned stackHeightStart = _context.stackHeight();
if (_type->category() == Type::Category::Mapping)
{
_context << Instruction::POP;
_context << InternalInstruction::POP;
return;
}
// stack: end_pos pos
@ -943,22 +943,22 @@ void ArrayUtils::clearStorageLoop(Type const* _type) const
_context << loopStart;
// check for loop condition
_context <<
Instruction::DUP1 <<
Instruction::DUP3 <<
Instruction::GT <<
Instruction::ISZERO;
InternalInstruction::DUP1 <<
InternalInstruction::DUP3 <<
InternalInstruction::GT <<
InternalInstruction::ISZERO;
evmasm::AssemblyItem zeroLoopEnd = _context.newTag();
_context.appendConditionalJumpTo(zeroLoopEnd);
// delete
_context << u256(0);
StorageItem(_context, *_type).setToZero(SourceLocation(), false);
_context << Instruction::POP;
_context << InternalInstruction::POP;
// increment
_context << _type->storageSize() << Instruction::ADD;
_context << _type->storageSize() << InternalInstruction::ADD;
_context.appendJumpTo(loopStart);
// cleanup
_context << zeroLoopEnd;
_context << Instruction::POP;
_context << InternalInstruction::POP;
solAssert(_context.stackHeight() == stackHeightStart - 1, "");
}
@ -973,17 +973,17 @@ void ArrayUtils::convertLengthToSize(ArrayType const& _arrayType, bool _pad) con
{
unsigned baseBytes = _arrayType.baseType()->storageBytes();
if (baseBytes == 0)
m_context << Instruction::POP << u256(1);
m_context << InternalInstruction::POP << u256(1);
else if (baseBytes <= 16)
{
unsigned itemsPerSlot = 32 / baseBytes;
m_context
<< u256(itemsPerSlot - 1) << Instruction::ADD
<< u256(itemsPerSlot) << Instruction::SWAP1 << Instruction::DIV;
<< u256(itemsPerSlot - 1) << InternalInstruction::ADD
<< u256(itemsPerSlot) << InternalInstruction::SWAP1 << InternalInstruction::DIV;
}
}
else
m_context << _arrayType.baseType()->storageSize() << Instruction::MUL;
m_context << _arrayType.baseType()->storageSize() << InternalInstruction::MUL;
}
else
{
@ -993,12 +993,12 @@ void ArrayUtils::convertLengthToSize(ArrayType const& _arrayType, bool _pad) con
m_context << _arrayType.memoryStride();
else
m_context << _arrayType.calldataStride();
m_context << Instruction::MUL;
m_context << InternalInstruction::MUL;
}
else if (_pad)
m_context << u256(31) << Instruction::ADD
<< u256(32) << Instruction::DUP1
<< Instruction::SWAP2 << Instruction::DIV << Instruction::MUL;
m_context << u256(31) << InternalInstruction::ADD
<< u256(32) << InternalInstruction::DUP1
<< InternalInstruction::SWAP2 << InternalInstruction::DIV << InternalInstruction::MUL;
}
}
@ -1015,10 +1015,10 @@ void ArrayUtils::retrieveLength(ArrayType const& _arrayType, unsigned _stackDept
// length is stored on the stack
break;
case DataLocation::Memory:
m_context << Instruction::MLOAD;
m_context << InternalInstruction::MLOAD;
break;
case DataLocation::Storage:
m_context << Instruction::SLOAD;
m_context << InternalInstruction::SLOAD;
if (_arrayType.isByteArrayOrString())
m_context.callYulFunction(m_context.utilFunctions().extractByteArrayLengthFunction(), 1, 1);
break;
@ -1037,13 +1037,13 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck, b
ArrayUtils::retrieveLength(_arrayType, 1);
// Stack: ref [length] index length
// check out-of-bounds access
m_context << Instruction::DUP2 << Instruction::LT << Instruction::ISZERO;
m_context << InternalInstruction::DUP2 << InternalInstruction::LT << InternalInstruction::ISZERO;
// out-of-bounds access throws exception
m_context.appendConditionalPanic(util::PanicCode::ArrayOutOfBounds);
}
if (location == DataLocation::CallData && _arrayType.isDynamicallySized())
// remove length if present
m_context << Instruction::SWAP1 << Instruction::POP;
m_context << InternalInstruction::SWAP1 << InternalInstruction::POP;
// stack: <base_ref> <index>
switch (location)
@ -1051,46 +1051,46 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck, b
case DataLocation::Memory:
// stack: <base_ref> <index>
if (!_arrayType.isByteArrayOrString())
m_context << u256(_arrayType.memoryHeadSize()) << Instruction::MUL;
m_context << u256(_arrayType.memoryHeadSize()) << InternalInstruction::MUL;
if (_arrayType.isDynamicallySized())
m_context << u256(32) << Instruction::ADD;
m_context << u256(32) << InternalInstruction::ADD;
if (_keepReference)
m_context << Instruction::DUP2;
m_context << Instruction::ADD;
m_context << InternalInstruction::DUP2;
m_context << InternalInstruction::ADD;
break;
case DataLocation::CallData:
if (!_arrayType.isByteArrayOrString())
{
m_context << _arrayType.calldataStride();
m_context << Instruction::MUL;
m_context << InternalInstruction::MUL;
}
// stack: <base_ref> <index * size>
if (_keepReference)
m_context << Instruction::DUP2;
m_context << Instruction::ADD;
m_context << InternalInstruction::DUP2;
m_context << InternalInstruction::ADD;
break;
case DataLocation::Storage:
{
if (_keepReference)
m_context << Instruction::DUP2;
m_context << InternalInstruction::DUP2;
else
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
// stack: [<base_ref>] <index> <base_ref>
evmasm::AssemblyItem endTag = m_context.newTag();
if (_arrayType.isByteArrayOrString())
{
// Special case of short byte arrays.
m_context << Instruction::SWAP1;
m_context << Instruction::DUP2 << Instruction::SLOAD;
m_context << u256(1) << Instruction::AND << Instruction::ISZERO;
m_context << InternalInstruction::SWAP1;
m_context << InternalInstruction::DUP2 << InternalInstruction::SLOAD;
m_context << u256(1) << InternalInstruction::AND << InternalInstruction::ISZERO;
// No action needed for short byte arrays.
m_context.appendConditionalJumpTo(endTag);
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
}
if (_arrayType.isDynamicallySized())
CompilerUtils(m_context).computeHashStatic();
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
if (_arrayType.baseType()->storageBytes() <= 16)
{
// stack: <data_ref> <index>
@ -1099,22 +1099,22 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck, b
unsigned byteSize = _arrayType.baseType()->storageBytes();
solAssert(byteSize != 0, "");
unsigned itemsPerSlot = 32 / byteSize;
m_context << u256(itemsPerSlot) << Instruction::SWAP2;
m_context << u256(itemsPerSlot) << InternalInstruction::SWAP2;
// stack: itemsPerSlot index data_ref
m_context
<< Instruction::DUP3 << Instruction::DUP3
<< Instruction::DIV << Instruction::ADD
<< InternalInstruction::DUP3 << InternalInstruction::DUP3
<< InternalInstruction::DIV << InternalInstruction::ADD
// stack: itemsPerSlot index (data_ref + index / itemsPerSlot)
<< Instruction::SWAP2 << Instruction::SWAP1
<< Instruction::MOD;
<< InternalInstruction::SWAP2 << InternalInstruction::SWAP1
<< InternalInstruction::MOD;
if (byteSize != 1)
m_context << u256(byteSize) << Instruction::MUL;
m_context << u256(byteSize) << InternalInstruction::MUL;
}
else
{
if (_arrayType.baseType()->storageSize() != 1)
m_context << _arrayType.baseType()->storageSize() << Instruction::MUL;
m_context << Instruction::ADD << u256(0);
m_context << _arrayType.baseType()->storageSize() << InternalInstruction::MUL;
m_context << InternalInstruction::ADD << u256(0);
}
m_context << endTag;
break;
@ -1179,26 +1179,26 @@ void ArrayUtils::incrementByteOffset(unsigned _byteSize, unsigned _byteOffsetPos
// }
if (_byteOffsetPosition > 1)
m_context << swapInstruction(_byteOffsetPosition - 1);
m_context << u256(_byteSize) << Instruction::ADD;
m_context << u256(_byteSize) << InternalInstruction::ADD;
if (_byteOffsetPosition > 1)
m_context << swapInstruction(_byteOffsetPosition - 1);
// compute, X := (byteOffset + byteSize - 1) / 32, should be 1 iff byteOffset + bytesize > 32
m_context
<< u256(32) << dupInstruction(1 + _byteOffsetPosition) << u256(_byteSize - 1)
<< Instruction::ADD << Instruction::DIV;
<< InternalInstruction::ADD << InternalInstruction::DIV;
// increment storage offset if X == 1 (just add X to it)
// stack: X
m_context
<< swapInstruction(_storageOffsetPosition) << dupInstruction(_storageOffsetPosition + 1)
<< Instruction::ADD << swapInstruction(_storageOffsetPosition);
<< InternalInstruction::ADD << swapInstruction(_storageOffsetPosition);
// stack: X
// set source_byte_offset to zero if X == 1 (using source_byte_offset *= 1 - X)
m_context << u256(1) << Instruction::SUB;
m_context << u256(1) << InternalInstruction::SUB;
// stack: 1 - X
if (_byteOffsetPosition == 1)
m_context << Instruction::MUL;
m_context << InternalInstruction::MUL;
else
m_context
<< dupInstruction(_byteOffsetPosition + 1) << Instruction::MUL
<< swapInstruction(_byteOffsetPosition) << Instruction::POP;
<< dupInstruction(_byteOffsetPosition + 1) << InternalInstruction::MUL
<< swapInstruction(_byteOffsetPosition) << InternalInstruction::POP;
}

View File

@ -329,7 +329,7 @@ pair<u256, unsigned> CompilerContext::storageLocationOfVariable(Declaration cons
CompilerContext& CompilerContext::appendJump(evmasm::AssemblyItem::JumpType _jumpType)
{
evmasm::AssemblyItem item(Instruction::JUMP);
evmasm::AssemblyItem item(InternalInstruction::JUMP);
item.setJumpType(_jumpType);
return *this << item;
}
@ -342,7 +342,7 @@ CompilerContext& CompilerContext::appendPanic(util::PanicCode _code)
CompilerContext& CompilerContext::appendConditionalPanic(util::PanicCode _code)
{
*this << Instruction::ISZERO;
*this << InternalInstruction::ISZERO;
evmasm::AssemblyItem afterTag = appendConditionalJump();
appendPanic(_code);
*this << afterTag;
@ -366,7 +366,7 @@ CompilerContext& CompilerContext::appendConditionalRevert(bool _forwardReturnDat
})", {"condition"});
else
appendInlineAssembly("{ if condition { " + revertReasonIfDebug(_message) + " } }", {"condition"});
*this << Instruction::POP;
*this << InternalInstruction::POP;
return *this;
}
@ -430,7 +430,7 @@ void CompilerContext::appendInlineAssembly(
else
{
_assembly.appendInstruction(swapInstruction(static_cast<unsigned>(stackDiff)));
_assembly.appendInstruction(Instruction::POP);
_assembly.appendInstruction(InternalInstruction::POP);
}
};

View File

@ -251,7 +251,7 @@ public:
/// Append elements to the current instruction list and adjust @a m_stackOffset.
CompilerContext& operator<<(evmasm::AssemblyItem const& _item) { m_asm->append(_item); return *this; }
CompilerContext& operator<<(evmasm::Instruction _instruction) { m_asm->append(_instruction); return *this; }
CompilerContext& operator<<(evmasm::InternalInstruction _instruction) { m_asm->append(_instruction); return *this; }
CompilerContext& operator<<(u256 const& _value) { m_asm->append(_value); return *this; }
CompilerContext& operator<<(bytes const& _data) { m_asm->append(_data); return *this; }

View File

@ -62,33 +62,33 @@ void CompilerUtils::initialiseFreeMemoryPointer()
void CompilerUtils::fetchFreeMemoryPointer()
{
m_context << u256(freeMemoryPointer) << Instruction::MLOAD;
m_context << u256(freeMemoryPointer) << InternalInstruction::MLOAD;
}
void CompilerUtils::storeFreeMemoryPointer()
{
m_context << u256(freeMemoryPointer) << Instruction::MSTORE;
m_context << u256(freeMemoryPointer) << InternalInstruction::MSTORE;
}
void CompilerUtils::allocateMemory()
{
fetchFreeMemoryPointer();
m_context << Instruction::SWAP1 << Instruction::DUP2 << Instruction::ADD;
m_context << InternalInstruction::SWAP1 << InternalInstruction::DUP2 << InternalInstruction::ADD;
storeFreeMemoryPointer();
}
void CompilerUtils::allocateMemory(u256 const& size)
{
fetchFreeMemoryPointer();
m_context << Instruction::DUP1 << size << Instruction::ADD;
m_context << InternalInstruction::DUP1 << size << InternalInstruction::ADD;
storeFreeMemoryPointer();
}
void CompilerUtils::toSizeAfterFreeMemoryPointer()
{
fetchFreeMemoryPointer();
m_context << Instruction::DUP1 << Instruction::SWAP2 << Instruction::SUB;
m_context << Instruction::SWAP1;
m_context << InternalInstruction::DUP1 << InternalInstruction::SWAP2 << InternalInstruction::SUB;
m_context << InternalInstruction::SWAP1;
}
void CompilerUtils::revertWithStringData(Type const& _argumentType)
@ -96,12 +96,12 @@ void CompilerUtils::revertWithStringData(Type const& _argumentType)
solAssert(_argumentType.isImplicitlyConvertibleTo(*TypeProvider::fromElementaryTypeName("string memory")));
fetchFreeMemoryPointer();
m_context << util::selectorFromSignatureU256("Error(string)");
m_context << Instruction::DUP2 << Instruction::MSTORE;
m_context << u256(4) << Instruction::ADD;
m_context << InternalInstruction::DUP2 << InternalInstruction::MSTORE;
m_context << u256(4) << InternalInstruction::ADD;
// Stack: <string data> <mem pos of encoding start>
abiEncode({&_argumentType}, {TypeProvider::array(DataLocation::Memory, true)});
toSizeAfterFreeMemoryPointer();
m_context << Instruction::REVERT;
m_context << InternalInstruction::REVERT;
}
void CompilerUtils::revertWithError(
@ -112,19 +112,19 @@ void CompilerUtils::revertWithError(
{
fetchFreeMemoryPointer();
m_context << util::selectorFromSignatureU256(_signature);
m_context << Instruction::DUP2 << Instruction::MSTORE;
m_context << u256(4) << Instruction::ADD;
m_context << InternalInstruction::DUP2 << InternalInstruction::MSTORE;
m_context << u256(4) << InternalInstruction::ADD;
// Stack: <arguments...> <mem pos of encoding start>
abiEncode(_argumentTypes, _parameterTypes);
toSizeAfterFreeMemoryPointer();
m_context << Instruction::REVERT;
m_context << InternalInstruction::REVERT;
}
void CompilerUtils::returnDataToArray()
{
if (m_context.evmVersion().supportsReturndata())
{
m_context << Instruction::RETURNDATASIZE;
m_context << InternalInstruction::RETURNDATASIZE;
m_context.appendInlineAssembly(R"({
switch v case 0 {
v := 0x60
@ -142,7 +142,7 @@ void CompilerUtils::returnDataToArray()
void CompilerUtils::accessCalldataTail(Type const& _type)
{
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
m_context.callYulFunction(
m_context.utilFunctions().accessCalldataTailFunction(_type),
2,
@ -170,7 +170,7 @@ void CompilerUtils::loadFromMemoryDynamic(
)
{
if (_keepUpdatedMemoryOffset)
m_context << Instruction::DUP1;
m_context << InternalInstruction::DUP1;
if (auto arrayType = dynamic_cast<ArrayType const*>(&_type))
{
@ -178,7 +178,7 @@ void CompilerUtils::loadFromMemoryDynamic(
solAssert(!_fromCalldata);
solAssert(_padToWordBoundaries);
if (_keepUpdatedMemoryOffset)
m_context << arrayType->memoryDataSize() << Instruction::ADD;
m_context << arrayType->memoryDataSize() << InternalInstruction::ADD;
}
else
{
@ -187,7 +187,7 @@ void CompilerUtils::loadFromMemoryDynamic(
{
// update memory counter
moveToStackTop(_type.sizeOnStack());
m_context << u256(numBytes) << Instruction::ADD;
m_context << u256(numBytes) << InternalInstruction::ADD;
}
}
}
@ -196,7 +196,7 @@ void CompilerUtils::storeInMemory(unsigned _offset)
{
unsigned numBytes = prepareMemoryStore(*TypeProvider::uint256(), true);
if (numBytes > 0)
m_context << u256(_offset) << Instruction::MSTORE;
m_context << u256(_offset) << InternalInstruction::MSTORE;
}
void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBoundaries, bool _cleanup)
@ -212,13 +212,13 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound
}
else if (auto str = dynamic_cast<StringLiteralType const*>(&_type))
{
m_context << Instruction::DUP1;
m_context << InternalInstruction::DUP1;
storeStringData(bytesConstRef(str->value()));
if (_padToWordBoundaries)
m_context << u256(max<size_t>(32, ((str->value().size() + 31) / 32) * 32));
else
m_context << u256(str->value().size());
m_context << Instruction::ADD;
m_context << InternalInstruction::ADD;
}
else if (
_type.category() == Type::Category::Function &&
@ -226,14 +226,14 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound
)
{
combineExternalFunctionType(true);
m_context << Instruction::DUP2 << Instruction::MSTORE;
m_context << u256(_padToWordBoundaries ? 32 : 24) << Instruction::ADD;
m_context << InternalInstruction::DUP2 << InternalInstruction::MSTORE;
m_context << u256(_padToWordBoundaries ? 32 : 24) << InternalInstruction::ADD;
}
else if (_type.isValueType())
{
unsigned numBytes = prepareMemoryStore(_type, _padToWordBoundaries, _cleanup);
m_context << Instruction::DUP2 << Instruction::MSTORE;
m_context << u256(numBytes) << Instruction::ADD;
m_context << InternalInstruction::DUP2 << InternalInstruction::MSTORE;
m_context << u256(numBytes) << InternalInstruction::ADD;
}
else // Should never happen
{
@ -268,12 +268,12 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
templ("revertString", m_context.revertReasonIfDebug("Calldata too short"));
m_context.appendInlineAssembly(templ.render(), {"len"});
m_context << Instruction::DUP2 << Instruction::ADD;
m_context << Instruction::SWAP1;
m_context << InternalInstruction::DUP2 << InternalInstruction::ADD;
m_context << InternalInstruction::SWAP1;
/// Stack: <input_end> <source_offset>
// Retain the offset pointer as base_offset, the point from which the data offsets are computed.
m_context << Instruction::DUP1;
m_context << InternalInstruction::DUP1;
for (Type const* parameterType: _typeParameters)
{
// stack: v1 v2 ... v(k-1) input_end base_offset current_offset
@ -295,14 +295,14 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
if (arrayType.isDynamicallySized())
{
// compute data pointer
m_context << Instruction::DUP1 << Instruction::MLOAD;
m_context << InternalInstruction::DUP1 << InternalInstruction::MLOAD;
// stack: v1 v2 ... v(k-1) input_end base_offset current_offset data_offset
fetchFreeMemoryPointer();
// stack: v1 v2 ... v(k-1) input_end base_offset current_offset data_offset dstmem
moveIntoStack(4);
// stack: v1 v2 ... v(k-1) dstmem input_end base_offset current_offset data_offset
m_context << Instruction::DUP5;
m_context << InternalInstruction::DUP5;
// stack: v1 v2 ... v(k-1) dstmem input_end base_offset current_offset data_offset dstmem
// Check that the data pointer is valid and that length times
@ -327,19 +327,19 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
templ("revertStringLength", m_context.revertReasonIfDebug("ABI memory decoding: invalid data length"));
m_context.appendInlineAssembly(templ.render(), {"input_end", "base_offset", "offset", "ptr", "dst"});
// stack: v1 v2 ... v(k-1) dstmem input_end base_offset current_offset data_ptr dstdata
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
// stack: v1 v2 ... v(k-1) dstmem input_end base_offset current_offset dstdata data_ptr
ArrayUtils(m_context).copyArrayToMemory(arrayType, true);
// stack: v1 v2 ... v(k-1) dstmem input_end base_offset current_offset mem_end
storeFreeMemoryPointer();
m_context << u256(0x20) << Instruction::ADD;
m_context << u256(0x20) << InternalInstruction::ADD;
}
else
{
// Size has already been checked for this one.
moveIntoStack(2);
m_context << Instruction::DUP3;
m_context << u256(arrayType.calldataHeadSize()) << Instruction::ADD;
m_context << InternalInstruction::DUP3;
m_context << u256(arrayType.calldataHeadSize()) << InternalInstruction::ADD;
}
}
else
@ -350,7 +350,7 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
{
// put on stack: data_pointer length
loadFromMemoryDynamic(*TypeProvider::uint256(), !_fromMemory);
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
// stack: input_end base_offset next_pointer data_offset
m_context.appendInlineAssembly(Whiskers(R"({
if gt(data_offset, 0x100000000) { <revertString> }
@ -358,7 +358,7 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
// TODO add test
("revertString", m_context.revertReasonIfDebug("ABI calldata decoding: invalid data offset"))
.render(), {"data_offset"});
m_context << Instruction::DUP3 << Instruction::ADD;
m_context << InternalInstruction::DUP3 << InternalInstruction::ADD;
// stack: input_end base_offset next_pointer array_head_ptr
m_context.appendInlineAssembly(Whiskers(R"({
if gt(add(array_head_ptr, 0x20), input_end) { <revertString> }
@ -369,7 +369,7 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
// retrieve length
loadFromMemoryDynamic(*TypeProvider::uint256(), !_fromMemory, true);
// stack: input_end base_offset next_pointer array_length data_pointer
m_context << Instruction::SWAP2;
m_context << InternalInstruction::SWAP2;
// stack: input_end base_offset data_pointer array_length next_pointer
m_context.appendInlineAssembly(Whiskers(R"({
if or(
@ -384,8 +384,8 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
{
// size has already been checked
// stack: input_end base_offset data_offset
m_context << Instruction::DUP1;
m_context << u256(calldataType->calldataHeadSize()) << Instruction::ADD;
m_context << InternalInstruction::DUP1;
m_context << u256(calldataType->calldataHeadSize()) << InternalInstruction::ADD;
}
if (arrayType.location() == DataLocation::Memory)
{
@ -400,10 +400,10 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
// move input_end up
// stack: input_end base_offset calldata_ref [length] next_calldata
moveToStackTop(2 + arrayType.sizeOnStack());
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
// stack: base_offset calldata_ref [length] input_end next_calldata
moveToStackTop(2 + arrayType.sizeOnStack());
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
// stack: calldata_ref [length] input_end base_offset next_calldata
}
}
@ -460,7 +460,7 @@ void CompilerUtils::encodeToMemory(
// of the nth dynamic parameter, which is filled once the dynamic parts are processed.
// store memory start pointer
m_context << Instruction::DUP1;
m_context << InternalInstruction::DUP1;
unsigned argSize = CompilerUtils::sizeOnStack(_givenTypes);
unsigned stackPos = 0; // advances through the argument values
@ -472,7 +472,7 @@ void CompilerUtils::encodeToMemory(
if (targetType->isDynamicallySized() && !_copyDynamicDataInPlace)
{
// leave end_of_mem as dyn head pointer
m_context << Instruction::DUP1 << u256(32) << Instruction::ADD;
m_context << InternalInstruction::DUP1 << u256(32) << InternalInstruction::ADD;
dynPointers++;
assertThrow(
(argSize + dynPointers) < 16,
@ -540,10 +540,10 @@ void CompilerUtils::encodeToMemory(
StackTooDeepError,
util::stackTooDeepString
);
m_context << dupInstruction(2 + dynPointers) << Instruction::DUP2;
m_context << Instruction::SUB;
m_context << dupInstruction(2 + dynPointers) << InternalInstruction::DUP2;
m_context << InternalInstruction::SUB;
m_context << dupInstruction(2 + dynPointers - thisDynPointer);
m_context << Instruction::MSTORE;
m_context << InternalInstruction::MSTORE;
// stack: ... <end_of_mem>
if (_givenTypes[i]->category() == Type::Category::StringLiteral)
{
@ -589,7 +589,7 @@ void CompilerUtils::encodeToMemory(
storeInMemoryDynamic(*TypeProvider::uint256(), true);
// stack: ... <end_of_mem> <value...> <end_of_mem''>
// copy the new memory pointer
m_context << swapInstruction(arrayType->sizeOnStack() + 1) << Instruction::POP;
m_context << swapInstruction(arrayType->sizeOnStack() + 1) << InternalInstruction::POP;
// stack: ... <end_of_mem''> <value...>
// copy data part
ArrayUtils(m_context).copyArrayToMemory(*arrayType, _padToWordBoundaries);
@ -628,8 +628,8 @@ void CompilerUtils::abiEncodeV2(
void CompilerUtils::abiDecodeV2(TypePointers const& _parameterTypes, bool _fromMemory)
{
// stack: <source_offset> <length> [stack top]
m_context << Instruction::DUP2 << Instruction::ADD;
m_context << Instruction::SWAP1;
m_context << InternalInstruction::DUP2 << InternalInstruction::ADD;
m_context << InternalInstruction::SWAP1;
// stack: <end> <start>
string decoderName = m_context.abiFunctions().tupleDecoder(_parameterTypes, _fromMemory);
m_context.callYulFunction(decoderName, 2, sizeOnStack(_parameterTypes));
@ -655,12 +655,12 @@ void CompilerUtils::zeroInitialiseMemoryArray(ArrayType const& _type)
m_context << repeat;
pushZeroValue(*_type.baseType());
storeInMemoryDynamic(*_type.baseType());
m_context << Instruction::SWAP1 << u256(1) << Instruction::SWAP1;
m_context << Instruction::SUB << Instruction::SWAP1;
m_context << Instruction::DUP2;
m_context << InternalInstruction::SWAP1 << u256(1) << InternalInstruction::SWAP1;
m_context << InternalInstruction::SUB << InternalInstruction::SWAP1;
m_context << InternalInstruction::DUP2;
m_context.appendConditionalJumpTo(repeat);
}
m_context << Instruction::SWAP1 << Instruction::POP;
m_context << InternalInstruction::SWAP1 << InternalInstruction::POP;
}
void CompilerUtils::memoryCopy32()
@ -676,7 +676,7 @@ void CompilerUtils::memoryCopy32()
)",
{ "len", "dst", "src" }
);
m_context << Instruction::POP << Instruction::POP << Instruction::POP;
m_context << InternalInstruction::POP << InternalInstruction::POP << InternalInstruction::POP;
}
void CompilerUtils::memoryCopy()
@ -705,7 +705,7 @@ void CompilerUtils::memoryCopy()
)",
{ "len", "dst", "src" }
);
m_context << Instruction::POP << Instruction::POP << Instruction::POP;
m_context << InternalInstruction::POP << InternalInstruction::POP << InternalInstruction::POP;
}
void CompilerUtils::splitExternalFunctionType(bool _leftAligned)
@ -714,29 +714,29 @@ void CompilerUtils::splitExternalFunctionType(bool _leftAligned)
// address (right aligned), function identifier (right aligned)
if (_leftAligned)
{
m_context << Instruction::DUP1;
m_context << InternalInstruction::DUP1;
rightShiftNumberOnStack(64 + 32);
// <input> <address>
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
rightShiftNumberOnStack(64);
}
else
{
m_context << Instruction::DUP1;
m_context << InternalInstruction::DUP1;
rightShiftNumberOnStack(32);
m_context << ((u256(1) << 160) - 1) << Instruction::AND << Instruction::SWAP1;
m_context << ((u256(1) << 160) - 1) << InternalInstruction::AND << InternalInstruction::SWAP1;
}
m_context << u256(0xffffffffUL) << Instruction::AND;
m_context << u256(0xffffffffUL) << InternalInstruction::AND;
}
void CompilerUtils::combineExternalFunctionType(bool _leftAligned)
{
// <address> <function_id>
m_context << u256(0xffffffffUL) << Instruction::AND << Instruction::SWAP1;
m_context << u256(0xffffffffUL) << InternalInstruction::AND << InternalInstruction::SWAP1;
if (!_leftAligned)
m_context << ((u256(1) << 160) - 1) << Instruction::AND;
m_context << ((u256(1) << 160) - 1) << InternalInstruction::AND;
leftShiftNumberOnStack(32);
m_context << Instruction::OR;
m_context << InternalInstruction::OR;
if (_leftAligned)
leftShiftNumberOnStack(64);
}
@ -752,7 +752,7 @@ void CompilerUtils::pushCombinedFunctionEntryLabel(Declaration const& _function,
if (_runtimeOnly)
m_context <<
rtc->functionEntryLabel(_function).toSubAssemblyTag(m_context.runtimeSub()) <<
Instruction::OR;
InternalInstruction::OR;
}
}
@ -839,12 +839,12 @@ void CompilerUtils::convertType(
solAssert(targetTypeCategory == Type::Category::FixedBytes, "Invalid type conversion requested.");
FixedBytesType const& targetType = dynamic_cast<FixedBytesType const&>(_targetType);
if (typeOnStack.numBytes() == 0 || targetType.numBytes() == 0)
m_context << Instruction::POP << u256(0);
m_context << InternalInstruction::POP << u256(0);
else if (targetType.numBytes() > typeOnStack.numBytes() || _cleanupNeeded)
{
unsigned bytes = min(typeOnStack.numBytes(), targetType.numBytes());
m_context << ((u256(1) << (256 - bytes * 8)) - 1);
m_context << Instruction::NOT << Instruction::AND;
m_context << InternalInstruction::NOT << InternalInstruction::AND;
}
}
break;
@ -855,7 +855,7 @@ void CompilerUtils::convertType(
{
EnumType const& enumType = dynamic_cast<decltype(enumType)>(_typeOnStack);
solAssert(enumType.numberOfMembers() > 0, "empty enum should have caused a parser error.");
m_context << u256(enumType.numberOfMembers() - 1) << Instruction::DUP2 << Instruction::GT;
m_context << u256(enumType.numberOfMembers() - 1) << InternalInstruction::DUP2 << InternalInstruction::GT;
if (_asPartOfArgumentDecoding)
m_context.appendConditionalRevert(false, "Enum out of range");
else
@ -897,7 +897,7 @@ void CompilerUtils::convertType(
convertType(_typeOnStack, *_typeOnStack.mobileType(), true);
EnumType const& enumType = dynamic_cast<decltype(enumType)>(_targetType);
solAssert(enumType.numberOfMembers() > 0, "empty enum should have caused a parser error.");
m_context << u256(enumType.numberOfMembers() - 1) << Instruction::DUP2 << Instruction::GT;
m_context << u256(enumType.numberOfMembers() - 1) << InternalInstruction::DUP2 << InternalInstruction::GT;
m_context.appendConditionalPanic(util::PanicCode::EnumConversionError);
enumOverflowCheckPending = false;
}
@ -951,7 +951,7 @@ void CompilerUtils::convertType(
if (targetType.numBits() < 256)
m_context
<< ((u256(1) << targetType.numBits()) - 1)
<< Instruction::AND;
<< InternalInstruction::AND;
chopSignBitsPending = false;
}
}
@ -975,7 +975,7 @@ void CompilerUtils::convertType(
size_t storageSize = 32 + ((data.size() + 31) / 32) * 32;
allocateMemory(storageSize);
// stack: mempos
m_context << Instruction::DUP1 << u256(data.size());
m_context << InternalInstruction::DUP1 << u256(data.size());
storeInMemoryDynamic(*TypeProvider::uint256());
// stack: mempos datapos
storeStringData(data);
@ -1001,7 +1001,7 @@ void CompilerUtils::convertType(
bool fromCalldata = typeOnStack.dataStoredIn(DataLocation::CallData);
solAssert(typeOnStack.sizeOnStack() == (fromCalldata ? 2 : 1));
if (fromCalldata)
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
m_context.callYulFunction(
m_context.utilFunctions().bytesToFixedBytesConversionFunction(
@ -1039,7 +1039,7 @@ void CompilerUtils::convertType(
// stack: offset length(optional in case of dynamically sized array)
solAssert(typeOnStack.sizeOnStack() == (typeOnStack.isDynamicallySized() ? 2 : 1));
if (typeOnStack.isDynamicallySized())
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
m_context.callYulFunction(
m_context.utilFunctions().conversionFunction(typeOnStack, targetType),
@ -1055,18 +1055,18 @@ void CompilerUtils::convertType(
// allocate memory
// stack: <source ref> (variably sized) <length>
m_context << Instruction::DUP1;
m_context << InternalInstruction::DUP1;
ArrayUtils(m_context).convertLengthToSize(targetType, true);
// stack: <source ref> (variably sized) <length> <size>
if (targetType.isDynamicallySized())
m_context << u256(0x20) << Instruction::ADD;
m_context << u256(0x20) << InternalInstruction::ADD;
allocateMemory();
// stack: <source ref> (variably sized) <length> <mem start>
m_context << Instruction::DUP1;
m_context << InternalInstruction::DUP1;
moveIntoStack(2 + stackSize);
if (targetType.isDynamicallySized())
{
m_context << Instruction::DUP2;
m_context << InternalInstruction::DUP2;
storeInMemoryDynamic(*TypeProvider::uint256());
}
// stack: <mem start> <source ref> (variably sized) <length> <mem data pos>
@ -1077,12 +1077,12 @@ void CompilerUtils::convertType(
}
else
{
m_context << u256(0) << Instruction::SWAP1;
m_context << u256(0) << InternalInstruction::SWAP1;
// stack: <mem start> <source ref> (variably sized) <length> <counter> <mem data pos>
auto repeat = m_context.newTag();
m_context << repeat;
m_context << Instruction::DUP3 << Instruction::DUP3;
m_context << Instruction::LT << Instruction::ISZERO;
m_context << InternalInstruction::DUP3 << InternalInstruction::DUP3;
m_context << InternalInstruction::LT << InternalInstruction::ISZERO;
auto loopEnd = m_context.appendConditionalJump();
copyToStackTop(3 + stackSize, stackSize);
copyToStackTop(2 + stackSize, 1);
@ -1091,11 +1091,11 @@ void CompilerUtils::convertType(
StorageItem(m_context, *typeOnStack.baseType()).retrieveValue(SourceLocation(), true);
convertType(*typeOnStack.baseType(), *targetType.baseType(), _cleanupNeeded);
storeInMemoryDynamic(*targetType.baseType(), true);
m_context << Instruction::SWAP1 << u256(1) << Instruction::ADD;
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1 << u256(1) << InternalInstruction::ADD;
m_context << InternalInstruction::SWAP1;
m_context.appendJumpTo(repeat);
m_context << loopEnd;
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
}
// stack: <mem start> <source ref> (variably sized) <length> <mem data pos updated>
popStackSlots(2 + stackSize);
@ -1127,7 +1127,7 @@ void CompilerUtils::convertType(
solAssert(typeOnStack.dataStoredIn(DataLocation::CallData));
solAssert(typeOnStack.sizeOnStack() == 2);
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
m_context.callYulFunction(
m_context.utilFunctions().bytesToFixedBytesConversionFunction(
typeOnStack.arrayType(),
@ -1181,13 +1181,13 @@ void CompilerUtils::convertType(
CompilerUtils utils(_context);
// stack: <source ref>
utils.allocateMemory(typeOnStack->memoryDataSize());
_context << Instruction::SWAP1 << Instruction::DUP2;
_context << InternalInstruction::SWAP1 << InternalInstruction::DUP2;
// stack: <memory ptr> <source ref> <memory ptr>
for (auto const& member: typeOnStack->members(nullptr))
{
solAssert(!member.type->containsNestedMapping());
pair<u256, unsigned> const& offsets = typeOnStack->storageOffsetsOfMember(member.name);
_context << offsets.first << Instruction::DUP3 << Instruction::ADD;
_context << offsets.first << InternalInstruction::DUP3 << InternalInstruction::ADD;
_context << u256(offsets.second);
StorageItem(_context, *member.type).retrieveValue(SourceLocation(), true);
Type const* targetMemberType = targetType->memberType(member.name);
@ -1195,7 +1195,7 @@ void CompilerUtils::convertType(
utils.convertType(*member.type, *targetMemberType, true);
utils.storeInMemoryDynamic(*targetMemberType, true);
}
_context << Instruction::POP << Instruction::POP;
_context << InternalInstruction::POP << InternalInstruction::POP;
};
if (typeOnStack.recursive())
m_context.callLowLevelFunction(
@ -1221,9 +1221,9 @@ void CompilerUtils::convertType(
}
else
{
m_context << Instruction::DUP1;
m_context << Instruction::CALLDATASIZE;
m_context << Instruction::SUB;
m_context << InternalInstruction::DUP1;
m_context << InternalInstruction::CALLDATASIZE;
m_context << InternalInstruction::SUB;
abiDecode({&targetType}, false);
}
break;
@ -1271,12 +1271,12 @@ void CompilerUtils::convertType(
for (unsigned j = 0; j < min(sourceSize, targetSize); ++j)
m_context <<
swapInstruction(depth + targetSize - sourceSize) <<
Instruction::POP;
InternalInstruction::POP;
// Value shrank
for (unsigned j = targetSize; j < sourceSize; ++j)
{
moveToStackTop(depth + targetSize - sourceSize, 1);
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
}
// Value grew
if (targetSize > sourceSize)
@ -1290,7 +1290,7 @@ void CompilerUtils::convertType(
case Type::Category::Bool:
solAssert(_targetType == _typeOnStack, "Invalid conversion for bool.");
if (_cleanupNeeded)
m_context << Instruction::ISZERO << Instruction::ISZERO;
m_context << InternalInstruction::ISZERO << InternalInstruction::ISZERO;
break;
default:
// we used to allow conversions from function to address
@ -1314,7 +1314,7 @@ void CompilerUtils::convertType(
if (_cleanupNeeded && _targetType.canBeStored() && _targetType.storageBytes() < 32)
m_context
<< ((u256(1) << (8 * _targetType.storageBytes())) - 1)
<< Instruction::AND;
<< InternalInstruction::AND;
break;
}
@ -1337,7 +1337,7 @@ void CompilerUtils::pushZeroValue(Type const& _type)
m_context << runCon->lowLevelFunctionTag("$invalidFunction", 0, 0, [](CompilerContext& _context) {
_context.appendPanic(util::PanicCode::InvalidInternalFunction);
}).toSubAssemblyTag(m_context.runtimeSub());
m_context << Instruction::OR;
m_context << InternalInstruction::OR;
}
return;
}
@ -1352,7 +1352,7 @@ void CompilerUtils::pushZeroValue(Type const& _type)
if (referenceType->location() == DataLocation::CallData)
{
solAssert(referenceType->sizeOnStack() == 1 || referenceType->sizeOnStack() == 2);
m_context << Instruction::CALLDATASIZE;
m_context << InternalInstruction::CALLDATASIZE;
if (referenceType->sizeOnStack() == 2)
m_context << 0;
return;
@ -1376,7 +1376,7 @@ void CompilerUtils::pushZeroValue(Type const& _type)
CompilerUtils utils(_context);
utils.allocateMemory(max<u256>(32u, type->memoryDataSize()));
_context << Instruction::DUP1;
_context << InternalInstruction::DUP1;
if (auto structType = dynamic_cast<StructType const*>(type))
for (auto const& member: structType->members(nullptr))
@ -1389,7 +1389,7 @@ void CompilerUtils::pushZeroValue(Type const& _type)
solAssert(!arrayType->isDynamicallySized());
if (arrayType->length() > 0)
{
_context << arrayType->length() << Instruction::SWAP1;
_context << arrayType->length() << InternalInstruction::SWAP1;
// stack: items_to_do memory_pos
utils.zeroInitialiseMemoryArray(*arrayType);
// stack: updated_memory_pos
@ -1399,7 +1399,7 @@ void CompilerUtils::pushZeroValue(Type const& _type)
solAssert(false, "Requested initialisation for unknown type: " + type->toString());
// remove the updated memory pointer
_context << Instruction::POP;
_context << InternalInstruction::POP;
}
);
}
@ -1422,7 +1422,7 @@ void CompilerUtils::moveToStackVariable(VariableDeclaration const& _variable)
util::errinfo_comment(util::stackTooDeepString)
);
for (unsigned i = 0; i < size; ++i)
m_context << swapInstruction(stackPosition - size + 1) << Instruction::POP;
m_context << swapInstruction(stackPosition - size + 1) << InternalInstruction::POP;
}
void CompilerUtils::copyToStackTop(unsigned _stackDepth, unsigned _itemSize)
@ -1481,7 +1481,7 @@ void CompilerUtils::popStackElement(Type const& _type)
void CompilerUtils::popStackSlots(size_t _amount)
{
for (size_t i = 0; i < _amount; ++i)
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
}
void CompilerUtils::popAndJump(unsigned _toHeight, evmasm::AssemblyItem const& _jumpTo)
@ -1504,7 +1504,7 @@ unsigned CompilerUtils::sizeOnStack(vector<Type const*> const& _variableTypes)
void CompilerUtils::computeHashStatic()
{
storeInMemory(0);
m_context << u256(32) << u256(0) << Instruction::KECCAK256;
m_context << u256(32) << u256(0) << InternalInstruction::KECCAK256;
}
void CompilerUtils::copyContractCodeToMemory(ContractDefinition const& contract, bool _creation)
@ -1523,9 +1523,9 @@ void CompilerUtils::copyContractCodeToMemory(ContractDefinition const& contract,
_context.compiledContractRuntime(contract);
// pushes size
auto subroutine = _context.addSubroutine(assembly);
_context << Instruction::DUP1 << subroutine;
_context << Instruction::DUP4 << Instruction::CODECOPY;
_context << Instruction::ADD;
_context << InternalInstruction::DUP1 << subroutine;
_context << InternalInstruction::DUP4 << InternalInstruction::CODECOPY;
_context << InternalInstruction::ADD;
}
);
}
@ -1541,14 +1541,14 @@ void CompilerUtils::storeStringData(bytesConstRef _data)
m_context << u256(h256(_data.cropped(i), h256::AlignLeft));
storeInMemoryDynamic(*TypeProvider::uint256());
}
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
}
else
{
// stack: mempos mempos_data
m_context.appendData(_data.toBytes());
m_context << u256(_data.size()) << Instruction::SWAP2;
m_context << Instruction::CODECOPY;
m_context << u256(_data.size()) << InternalInstruction::SWAP2;
m_context << InternalInstruction::CODECOPY;
}
}
@ -1566,11 +1566,11 @@ unsigned CompilerUtils::loadFromMemoryHelper(Type const& _type, bool _fromCallda
isExternalFunctionType = true;
if (numBytes == 0)
{
m_context << Instruction::POP << u256(0);
m_context << InternalInstruction::POP << u256(0);
return numBytes;
}
solAssert(numBytes <= 32, "Static memory load of more than 32 bytes requested.");
m_context << (_fromCalldata ? Instruction::CALLDATALOAD : Instruction::MLOAD);
m_context << (_fromCalldata ? InternalInstruction::CALLDATALOAD : InternalInstruction::MLOAD);
bool cleanupNeeded = true;
if (isExternalFunctionType)
splitExternalFunctionType(true);
@ -1599,18 +1599,18 @@ void CompilerUtils::cleanHigherOrderBits(IntegerType const& _typeOnStack)
if (_typeOnStack.numBits() == 256)
return;
else if (_typeOnStack.isSigned())
m_context << u256(_typeOnStack.numBits() / 8 - 1) << Instruction::SIGNEXTEND;
m_context << u256(_typeOnStack.numBits() / 8 - 1) << InternalInstruction::SIGNEXTEND;
else
m_context << ((u256(1) << _typeOnStack.numBits()) - 1) << Instruction::AND;
m_context << ((u256(1) << _typeOnStack.numBits()) - 1) << InternalInstruction::AND;
}
void CompilerUtils::leftShiftNumberOnStack(unsigned _bits)
{
solAssert(_bits < 256);
if (m_context.evmVersion().hasBitwiseShifting())
m_context << _bits << Instruction::SHL;
m_context << _bits << InternalInstruction::SHL;
else
m_context << (u256(1) << _bits) << Instruction::MUL;
m_context << (u256(1) << _bits) << InternalInstruction::MUL;
}
void CompilerUtils::rightShiftNumberOnStack(unsigned _bits)
@ -1618,9 +1618,9 @@ void CompilerUtils::rightShiftNumberOnStack(unsigned _bits)
solAssert(_bits < 256);
// NOTE: If we add signed right shift, SAR rounds differently than SDIV
if (m_context.evmVersion().hasBitwiseShifting())
m_context << _bits << Instruction::SHR;
m_context << _bits << InternalInstruction::SHR;
else
m_context << (u256(1) << _bits) << Instruction::SWAP1 << Instruction::DIV;
m_context << (u256(1) << _bits) << InternalInstruction::SWAP1 << InternalInstruction::DIV;
}
unsigned CompilerUtils::prepareMemoryStore(Type const& _type, bool _padToWords, bool _cleanup)

View File

@ -142,7 +142,7 @@ void ContractCompiler::initializeContext(
void ContractCompiler::appendCallValueCheck()
{
// Throw if function is not payable but call contained ether.
m_context << Instruction::CALLVALUE;
m_context << InternalInstruction::CALLVALUE;
m_context.appendConditionalRevert(false, "Ether sent to non-payable function");
}
@ -201,9 +201,9 @@ size_t ContractCompiler::packIntoContractCreator(ContractDefinition const& _cont
);
m_context.pushSubroutineSize(m_context.runtimeSub());
if (immutables.empty())
m_context << Instruction::DUP1;
m_context << InternalInstruction::DUP1;
m_context.pushSubroutineOffset(m_context.runtimeSub());
m_context << u256(0) << Instruction::CODECOPY;
m_context << u256(0) << InternalInstruction::CODECOPY;
// Assign immutable values from stack in reversed order.
for (auto const& immutable: immutables | ranges::views::reverse)
{
@ -216,7 +216,7 @@ size_t ContractCompiler::packIntoContractCreator(ContractDefinition const& _cont
}
if (!immutables.empty())
m_context.pushSubroutineSize(m_context.runtimeSub());
m_context << u256(0) << Instruction::RETURN;
m_context << u256(0) << InternalInstruction::RETURN;
return m_context.runtimeSub();
}
@ -298,13 +298,13 @@ void ContractCompiler::appendConstructor(FunctionDefinition const& _constructor)
// which is the size of the generated code (``programSize``)
// plus the constructor arguments added to the transaction payload.
m_context.appendProgramSize();
m_context << Instruction::CODESIZE << Instruction::SUB;
m_context << InternalInstruction::CODESIZE << InternalInstruction::SUB;
// stack: <memptr> <argument size>
m_context << Instruction::DUP1;
m_context << InternalInstruction::DUP1;
m_context.appendProgramSize();
m_context << Instruction::DUP4 << Instruction::CODECOPY;
m_context << InternalInstruction::DUP4 << InternalInstruction::CODECOPY;
// stack: <memptr> <argument size>
m_context << Instruction::DUP2 << Instruction::DUP2 << Instruction::ADD;
m_context << InternalInstruction::DUP2 << InternalInstruction::DUP2 << InternalInstruction::ADD;
// stack: <memptr> <argument size> <mem end>
CompilerUtils(m_context).storeFreeMemoryPointer();
// stack: <memptr> <argument size>
@ -318,7 +318,7 @@ void ContractCompiler::appendDelegatecallCheck()
// Special constant that will be replaced by the address at deploy time.
// At compilation time, this is just "PUSH20 00...000".
m_context.appendDeployTimeAddress();
m_context << Instruction::ADDRESS << Instruction::EQ;
m_context << InternalInstruction::ADDRESS << InternalInstruction::EQ;
// The result on the stack is
// "We have not been called via DELEGATECALL".
}
@ -366,7 +366,7 @@ void ContractCompiler::appendInternalSelector(
{
size_t pivotIndex = _ids.size() / 2;
FixedHash<4> pivot{_ids.at(pivotIndex)};
m_context << dupInstruction(1) << u256(FixedHash<4>::Arith(pivot)) << Instruction::GT;
m_context << dupInstruction(1) << u256(FixedHash<4>::Arith(pivot)) << InternalInstruction::GT;
evmasm::AssemblyItem lessTag{m_context.appendConditionalJump()};
// Here, we have funid >= pivot
vector<FixedHash<4>> larger{_ids.begin() + static_cast<ptrdiff_t>(pivotIndex), _ids.end()};
@ -380,7 +380,7 @@ void ContractCompiler::appendInternalSelector(
{
for (auto const& id: _ids)
{
m_context << dupInstruction(1) << u256(FixedHash<4>::Arith(id)) << Instruction::EQ;
m_context << dupInstruction(1) << u256(FixedHash<4>::Arith(id)) << InternalInstruction::EQ;
m_context.appendConditionalJumpTo(_entryPoints.at(id));
}
m_context.appendJumpTo(_notFoundTag);
@ -439,7 +439,7 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac
// directly jump to fallback or ether receiver if the data is too short to contain a function selector
// also guards against short data
m_context << u256(4) << Instruction::CALLDATASIZE << Instruction::LT;
m_context << u256(4) << InternalInstruction::CALLDATASIZE << InternalInstruction::LT;
m_context.appendConditionalJumpTo(notFoundOrReceiveEther);
// retrieve the function signature hash from the calldata
@ -467,7 +467,7 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac
if (etherReceiver)
{
// directly jump to fallback, if there is calldata
m_context << Instruction::CALLDATASIZE;
m_context << InternalInstruction::CALLDATASIZE;
m_context.appendConditionalJumpTo(notFound);
solAssert(!_contract.isLibrary(), "");
@ -475,7 +475,7 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac
solAssert(FunctionType(*etherReceiver).parameterTypes().empty(), "");
solAssert(FunctionType(*etherReceiver).returnParameterTypes().empty(), "");
etherReceiver->accept(*this);
m_context << Instruction::STOP;
m_context << InternalInstruction::STOP;
}
m_context << notFound;
@ -489,17 +489,17 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac
m_context.setStackOffset(0);
if (!FunctionType(*fallback).parameterTypes().empty())
m_context << u256(0) << Instruction::CALLDATASIZE;
m_context << u256(0) << InternalInstruction::CALLDATASIZE;
fallback->accept(*this);
if (FunctionType(*fallback).returnParameterTypes().empty())
m_context << Instruction::STOP;
m_context << InternalInstruction::STOP;
else
{
m_context << Instruction::DUP1 << Instruction::MLOAD << Instruction::SWAP1;
m_context << u256(0x20) << Instruction::ADD;
m_context << Instruction::RETURN;
m_context << InternalInstruction::DUP1 << InternalInstruction::MLOAD << InternalInstruction::SWAP1;
m_context << u256(0x20) << InternalInstruction::ADD;
m_context << InternalInstruction::RETURN;
}
}
else
@ -534,7 +534,7 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac
{
// Parameter for calldataUnpacker
m_context << CompilerUtils::dataStartOffset;
m_context << Instruction::DUP1 << Instruction::CALLDATASIZE << Instruction::SUB;
m_context << InternalInstruction::DUP1 << InternalInstruction::CALLDATASIZE << InternalInstruction::SUB;
CompilerUtils(m_context).abiDecode(functionType->parameterTypes());
}
m_context.appendJumpTo(
@ -557,7 +557,7 @@ void ContractCompiler::appendReturnValuePacker(TypePointers const& _typeParamete
{
CompilerUtils utils(m_context);
if (_typeParameters.empty())
m_context << Instruction::STOP;
m_context << InternalInstruction::STOP;
else
{
utils.fetchFreeMemoryPointer();
@ -565,7 +565,7 @@ void ContractCompiler::appendReturnValuePacker(TypePointers const& _typeParamete
// its data to add the needed parts and we avoid a memory copy.
utils.abiEncode(_typeParameters, _typeParameters, _isLibrary);
utils.toSizeAfterFreeMemoryPointer();
m_context << Instruction::RETURN;
m_context << InternalInstruction::RETURN;
}
}
@ -678,7 +678,7 @@ bool ContractCompiler::visit(FunctionDefinition const& _function)
while (!stackLayout.empty() && stackLayout.back() != static_cast<int>(stackLayout.size() - 1))
if (stackLayout.back() < 0)
{
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
stackLayout.pop_back();
}
else
@ -920,7 +920,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
util::errinfo_comment(util::stackTooDeepString)
);
_assembly.appendInstruction(swapInstruction(stackDiff));
_assembly.appendInstruction(Instruction::POP);
_assembly.appendInstruction(InternalInstruction::POP);
}
};
@ -1046,17 +1046,17 @@ void ContractCompiler::handleCatch(vector<ASTPointer<TryCatchClause>> const& _ca
solAssert(m_context.evmVersion().supportsReturndata(), "");
// stack: <selector>
m_context << Instruction::DUP1 << util::selectorFromSignatureU32("Error(string)") << Instruction::EQ;
m_context << Instruction::ISZERO;
m_context << InternalInstruction::DUP1 << util::selectorFromSignatureU32("Error(string)") << InternalInstruction::EQ;
m_context << InternalInstruction::ISZERO;
m_context.appendConditionalJumpTo(panicTag);
m_context << Instruction::POP; // remove selector
m_context << InternalInstruction::POP; // remove selector
// Try to decode the error message.
// If this fails, leaves 0 on the stack, otherwise the pointer to the data string.
m_context.callYulFunction(m_context.utilFunctions().tryDecodeErrorMessageFunction(), 0, 1);
m_context << Instruction::DUP1;
m_context << InternalInstruction::DUP1;
AssemblyItem decodeSuccessTag = m_context.appendConditionalJump();
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
m_context.appendJumpTo(fallbackTag);
m_context.adjustStackOffset(1);
@ -1078,15 +1078,15 @@ void ContractCompiler::handleCatch(vector<ASTPointer<TryCatchClause>> const& _ca
solAssert(m_context.evmVersion().supportsReturndata(), "");
// stack: <selector>
m_context << util::selectorFromSignatureU32("Panic(uint256)") << Instruction::EQ;
m_context << Instruction::ISZERO;
m_context << util::selectorFromSignatureU32("Panic(uint256)") << InternalInstruction::EQ;
m_context << InternalInstruction::ISZERO;
m_context.appendConditionalJumpTo(fallbackTag);
m_context.callYulFunction(m_context.utilFunctions().tryDecodePanicDataFunction(), 0, 2);
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
// stack: <code> <success>
AssemblyItem decodeSuccessTag = m_context.appendConditionalJump();
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
m_context.appendJumpTo(fallbackTag);
m_context.adjustStackOffset(1);
@ -1096,7 +1096,7 @@ void ContractCompiler::handleCatch(vector<ASTPointer<TryCatchClause>> const& _ca
m_context.adjustStackOffset(1);
}
if (error || panic)
m_context << Instruction::POP; // selector
m_context << InternalInstruction::POP; // selector
m_context << fallbackTag;
if (fallback)
{
@ -1156,7 +1156,7 @@ bool ContractCompiler::visit(IfStatement const& _ifStatement)
StackHeightChecker checker(m_context);
CompilerContext::LocationSetter locationSetter(m_context, _ifStatement);
compileExpression(_ifStatement.condition());
m_context << Instruction::ISZERO;
m_context << InternalInstruction::ISZERO;
evmasm::AssemblyItem falseTag = m_context.appendConditionalJump();
evmasm::AssemblyItem endTag = falseTag;
_ifStatement.trueStatement().accept(*this);
@ -1192,14 +1192,14 @@ bool ContractCompiler::visit(WhileStatement const& _whileStatement)
m_context << condition;
compileExpression(_whileStatement.condition());
m_context << Instruction::ISZERO << Instruction::ISZERO;
m_context << InternalInstruction::ISZERO << InternalInstruction::ISZERO;
m_context.appendConditionalJumpTo(loopStart);
}
else
{
m_continueTags.emplace_back(loopStart, m_context.stackHeight());
compileExpression(_whileStatement.condition());
m_context << Instruction::ISZERO;
m_context << InternalInstruction::ISZERO;
m_context.appendConditionalJumpTo(loopEnd);
_whileStatement.body().accept(*this);
@ -1236,7 +1236,7 @@ bool ContractCompiler::visit(ForStatement const& _forStatement)
if (_forStatement.condition())
{
compileExpression(*_forStatement.condition());
m_context << Instruction::ISZERO;
m_context << InternalInstruction::ISZERO;
m_context.appendConditionalJumpTo(loopEnd);
}

View File

@ -150,7 +150,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
solAssert(CompilerUtils::freeMemoryPointer >= 0x40, "");
// pop offset
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
if (paramTypes[i]->isDynamicallySized())
{
solAssert(
@ -175,7 +175,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
slot_pos := hash
})", {"slot_pos", "key_ptr"});
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
}
else
{
@ -188,7 +188,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
utils().copyToStackTop(static_cast<unsigned>(paramTypes.size() - i), 1);
utils().storeInMemory(0);
m_context << u256(64) << u256(0);
m_context << Instruction::KECCAK256;
m_context << InternalInstruction::KECCAK256;
}
// push offset
@ -198,15 +198,15 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
else if (auto arrayType = dynamic_cast<ArrayType const*>(returnType))
{
// pop offset
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
utils().copyToStackTop(static_cast<unsigned>(paramTypes.size() - i + 1), 1);
ArrayUtils(m_context).retrieveLength(*arrayType, 1);
// Stack: ref [length] index length
// check out-of-bounds access
m_context << Instruction::DUP2 << Instruction::LT;
m_context << InternalInstruction::DUP2 << InternalInstruction::LT;
auto tag = m_context.appendConditionalJump();
m_context << u256(0) << Instruction::DUP1 << Instruction::REVERT;
m_context << u256(0) << InternalInstruction::DUP1 << InternalInstruction::REVERT;
m_context << tag;
ArrayUtils(m_context).accessIndex(*arrayType, false);
@ -217,11 +217,11 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
}
// remove index arguments.
if (paramTypes.size() == 1)
m_context << Instruction::SWAP2 << Instruction::POP << Instruction::SWAP1;
m_context << InternalInstruction::SWAP2 << InternalInstruction::POP << InternalInstruction::SWAP1;
else if (paramTypes.size() >= 2)
{
m_context << swapInstruction(static_cast<unsigned>(paramTypes.size()));
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
m_context << swapInstruction(static_cast<unsigned>(paramTypes.size()));
utils().popStackSlots(paramTypes.size() - 1);
}
@ -232,7 +232,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
{
solAssert(!_varDecl.immutable(), "");
// remove offset
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
auto const& names = accessorType.returnParameterNames();
// struct
for (size_t i = 0; i < names.size(); ++i)
@ -243,7 +243,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
if (!arrayType->isByteArrayOrString())
continue;
pair<u256, unsigned> const& offsets = structType->storageOffsetsOfMember(names[i]);
m_context << Instruction::DUP1 << u256(offsets.first) << Instruction::ADD << u256(offsets.second);
m_context << InternalInstruction::DUP1 << u256(offsets.first) << InternalInstruction::ADD << u256(offsets.second);
Type const* memberType = structType->memberType(names[i]);
StorageItem(m_context, *memberType).retrieveValue(SourceLocation(), true);
utils().convertType(*memberType, *returnTypes[i]);
@ -251,7 +251,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
retSizeOnStack += returnTypes[i]->sizeOnStack();
}
// remove slot
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
}
else
{
@ -355,7 +355,7 @@ bool ExpressionCompiler::visit(Assignment const& _assignment)
);
// value [lvalue_ref] updated_value
for (unsigned i = 0; i < itemSize; ++i)
m_context << swapInstruction(itemSize + lvalueSize) << Instruction::POP;
m_context << swapInstruction(itemSize + lvalueSize) << InternalInstruction::POP;
}
m_currentLValue->storeValue(*_assignment.annotation().type, _assignment.location());
}
@ -371,7 +371,7 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple)
solAssert(!arrayType.isDynamicallySized(), "Cannot create dynamically sized inline array.");
utils().allocateMemory(max(u256(32u), arrayType.memoryDataSize()));
m_context << Instruction::DUP1;
m_context << InternalInstruction::DUP1;
for (auto const& component: _tuple.components())
{
@ -379,7 +379,7 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple)
utils().storeInMemoryDynamic(*arrayType.baseType(), true);
}
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
}
else
{
@ -422,10 +422,10 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation)
switch (_unaryOperation.getOperator())
{
case Token::Not: // !
m_context << Instruction::ISZERO;
m_context << InternalInstruction::ISZERO;
break;
case Token::BitNot: // ~
m_context << Instruction::NOT;
m_context << InternalInstruction::NOT;
break;
case Token::Delete: // delete
solAssert(!!m_currentLValue, "LValue not retrieved.");
@ -444,7 +444,7 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation)
{
// store value for later
solUnimplementedAssert(type.sizeOnStack() == 1, "Stack size != 1 not implemented.");
m_context << Instruction::DUP1;
m_context << InternalInstruction::DUP1;
if (m_currentLValue->sizeOnStack() > 0)
for (unsigned i = 1 + m_currentLValue->sizeOnStack(); i > 0; --i)
m_context << swapInstruction(i);
@ -456,7 +456,7 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation)
else
{
m_context << u256(1);
m_context << Instruction::ADD;
m_context << InternalInstruction::ADD;
}
}
else
@ -466,7 +466,7 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation)
else
{
m_context << u256(1);
m_context << Instruction::SWAP1 << Instruction::SUB;
m_context << InternalInstruction::SWAP1 << InternalInstruction::SUB;
}
}
// Stack for prefix: [ref...] (*ref)+-1
@ -489,7 +489,7 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation)
if (m_context.arithmetic() == Arithmetic::Checked)
m_context.callYulFunction(m_context.utilFunctions().negateNumberCheckedFunction(type), 1, 1);
else
m_context << u256(0) << Instruction::SUB;
m_context << u256(0) << InternalInstruction::SUB;
break;
default:
solAssert(false, "Invalid unary operator: " + string(TokenTraits::toString(_unaryOperation.getOperator())));
@ -600,14 +600,14 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
auto const& structType = dynamic_cast<StructType const&>(*type.actualType());
utils().allocateMemory(max(u256(32u), structType.memoryDataSize()));
m_context << Instruction::DUP1;
m_context << InternalInstruction::DUP1;
for (unsigned i = 0; i < arguments.size(); ++i)
{
acceptAndConvert(*arguments[i], *functionType->parameterTypes()[i]);
utils().storeInMemoryDynamic(*functionType->parameterTypes()[i]);
}
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
}
else
{
@ -670,7 +670,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
utils().rightShiftNumberOnStack(32);
else
// Extract the runtime part.
m_context << ((u256(1) << 32) - 1) << Instruction::AND;
m_context << ((u256(1) << 32) - 1) << InternalInstruction::AND;
m_context.appendJump(evmasm::AssemblyItem::JumpType::IntoFunction);
m_context << returnLabel;
@ -716,7 +716,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
if (function.saltSet())
{
m_context << dupInstruction(2 + (function.valueSet() ? 1 : 0));
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
}
// now: [salt], [value], [salt], memory_end_ptr
@ -730,19 +730,19 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
// now: [salt], [value], [salt], size, offset, value
if (function.saltSet())
m_context << Instruction::CREATE2;
m_context << InternalInstruction::CREATE2;
else
m_context << Instruction::CREATE;
m_context << InternalInstruction::CREATE;
// now: [salt], [value], address
if (function.valueSet())
m_context << swapInstruction(1) << Instruction::POP;
m_context << swapInstruction(1) << InternalInstruction::POP;
if (function.saltSet())
m_context << swapInstruction(1) << Instruction::POP;
m_context << swapInstruction(1) << InternalInstruction::POP;
// Check if zero (reverted)
m_context << Instruction::DUP1 << Instruction::ISZERO;
m_context << InternalInstruction::DUP1 << InternalInstruction::ISZERO;
if (_functionCall.annotation().tryCall)
{
// If this is a try call, return "<address> 1" in the success case and
@ -767,7 +767,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
if (stackDepth > 0)
m_context << swapInstruction(stackDepth);
if (function.gasSet())
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
break;
}
case FunctionType::Kind::SetValue:
@ -776,7 +776,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
// Note that function is not the original function, but the ".value" function.
// Its values of gasSet and valueSet is equal to the original function's though.
if (function.valueSet())
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
arguments.front()->accept(*this);
break;
case FunctionType::Kind::Send:
@ -788,8 +788,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
m_context << u256(evmasm::GasCosts::callStipend);
acceptAndConvert(*arguments.front(), *function.parameterTypes().front(), true);
// gas <- gas * !value
m_context << Instruction::SWAP1 << Instruction::DUP2;
m_context << Instruction::ISZERO << Instruction::MUL << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1 << InternalInstruction::DUP2;
m_context << InternalInstruction::ISZERO << InternalInstruction::MUL << InternalInstruction::SWAP1;
FunctionType::Options callOptions;
callOptions.valueSet = true;
callOptions.gasSet = true;
@ -810,7 +810,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
if (function.kind() == FunctionType::Kind::Transfer)
{
// Check if zero (out of stack or not enough balance).
m_context << Instruction::ISZERO;
m_context << InternalInstruction::ISZERO;
// Revert message bubbles up.
m_context.appendConditionalRevert(true);
}
@ -818,7 +818,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
}
case FunctionType::Kind::Selfdestruct:
acceptAndConvert(*arguments.front(), *function.parameterTypes().front(), true);
m_context << Instruction::SELFDESTRUCT;
m_context << InternalInstruction::SELFDESTRUCT;
break;
case FunctionType::Kind::Revert:
{
@ -861,15 +861,15 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
// Optimization: If type is bytes or string, then do not encode,
// but directly compute keccak256 on memory.
ArrayUtils(m_context).retrieveLength(*TypeProvider::bytesMemory());
m_context << Instruction::SWAP1 << u256(0x20) << Instruction::ADD;
m_context << Instruction::KECCAK256;
m_context << InternalInstruction::SWAP1 << u256(0x20) << InternalInstruction::ADD;
m_context << InternalInstruction::KECCAK256;
}
else
{
utils().fetchFreeMemoryPointer();
utils().packedEncode({argType}, TypePointers());
utils().toSizeAfterFreeMemoryPointer();
m_context << Instruction::KECCAK256;
m_context << InternalInstruction::KECCAK256;
}
break;
}
@ -893,7 +893,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
{referenceType}
);
utils().toSizeAfterFreeMemoryPointer();
m_context << Instruction::KECCAK256;
m_context << InternalInstruction::KECCAK256;
}
else
{
@ -993,21 +993,21 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
case FunctionType::Kind::BlockHash:
{
acceptAndConvert(*arguments[0], *function.parameterTypes()[0], true);
m_context << Instruction::BLOCKHASH;
m_context << InternalInstruction::BLOCKHASH;
break;
}
case FunctionType::Kind::AddMod:
case FunctionType::Kind::MulMod:
{
acceptAndConvert(*arguments[2], *TypeProvider::uint256());
m_context << Instruction::DUP1 << Instruction::ISZERO;
m_context << InternalInstruction::DUP1 << InternalInstruction::ISZERO;
m_context.appendConditionalPanic(util::PanicCode::DivisionByZero);
for (unsigned i = 1; i < 3; i ++)
acceptAndConvert(*arguments[2 - i], *TypeProvider::uint256());
if (function.kind() == FunctionType::Kind::AddMod)
m_context << Instruction::ADDMOD;
m_context << InternalInstruction::ADDMOD;
else
m_context << Instruction::MULMOD;
m_context << InternalInstruction::MULMOD;
break;
}
case FunctionType::Kind::ECRecover:
@ -1041,10 +1041,10 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
solAssert(arrayType, "");
// stack: ArrayReference
m_context << u256(1) << Instruction::DUP2;
m_context << u256(1) << InternalInstruction::DUP2;
ArrayUtils(m_context).incrementDynamicArraySize(*arrayType);
// stack: ArrayReference 1 newLength
m_context << Instruction::SUB;
m_context << InternalInstruction::SUB;
// stack: ArrayReference (newLength-1)
ArrayUtils(m_context).accessIndex(*arrayType, false);
@ -1067,10 +1067,10 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
// stack: ArrayReference argValue
utils().moveToStackTop(argType->sizeOnStack(), 1);
// stack: argValue ArrayReference
m_context << Instruction::DUP1;
m_context << InternalInstruction::DUP1;
ArrayUtils(m_context).incrementDynamicArraySize(*arrayType);
// stack: argValue ArrayReference newLength
m_context << u256(1) << Instruction::SWAP1 << Instruction::SUB;
m_context << u256(1) << InternalInstruction::SWAP1 << InternalInstruction::SUB;
// stack: argValue ArrayReference (newLength-1)
ArrayUtils(m_context).accessIndex(*arrayType, false);
// stack: argValue storageSlot slotOffset
@ -1137,13 +1137,13 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
}
utils().fetchFreeMemoryPointer();
// stack: <arg1> <arg2> ... <argn> <free mem>
m_context << u256(32) << Instruction::ADD;
m_context << u256(32) << InternalInstruction::ADD;
utils().packedEncode(argumentTypes, targetTypes);
utils().fetchFreeMemoryPointer();
m_context.appendInlineAssembly(R"({
mstore(mem_ptr, sub(sub(mem_end, mem_ptr), 0x20))
})", {"mem_end", "mem_ptr"});
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
utils().storeFreeMemoryPointer();
break;
@ -1159,42 +1159,42 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
// Make sure we can allocate memory without overflow
m_context << u256(0xffffffffffffffff);
m_context << Instruction::DUP2;
m_context << Instruction::GT;
m_context << InternalInstruction::DUP2;
m_context << InternalInstruction::GT;
m_context.appendConditionalPanic(PanicCode::ResourceError);
// Stack: requested_length
utils().fetchFreeMemoryPointer();
// Stack: requested_length memptr
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
// Stack: memptr requested_length
// store length
m_context << Instruction::DUP1 << Instruction::DUP3 << Instruction::MSTORE;
m_context << InternalInstruction::DUP1 << InternalInstruction::DUP3 << InternalInstruction::MSTORE;
// Stack: memptr requested_length
// update free memory pointer
m_context << Instruction::DUP1;
m_context << InternalInstruction::DUP1;
// Stack: memptr requested_length requested_length
if (arrayType.isByteArrayOrString())
// Round up to multiple of 32
m_context << u256(31) << Instruction::ADD << u256(31) << Instruction::NOT << Instruction::AND;
m_context << u256(31) << InternalInstruction::ADD << u256(31) << InternalInstruction::NOT << InternalInstruction::AND;
else
m_context << arrayType.baseType()->memoryHeadSize() << Instruction::MUL;
m_context << arrayType.baseType()->memoryHeadSize() << InternalInstruction::MUL;
// stacK: memptr requested_length data_size
m_context << u256(32) << Instruction::ADD;
m_context << Instruction::DUP3 << Instruction::ADD;
m_context << u256(32) << InternalInstruction::ADD;
m_context << InternalInstruction::DUP3 << InternalInstruction::ADD;
utils().storeFreeMemoryPointer();
// Stack: memptr requested_length
// Check if length is zero
m_context << Instruction::DUP1 << Instruction::ISZERO;
m_context << InternalInstruction::DUP1 << InternalInstruction::ISZERO;
auto skipInit = m_context.appendConditionalJump();
// Always initialize because the free memory pointer might point at
// a dirty memory area.
m_context << Instruction::DUP2 << u256(32) << Instruction::ADD;
m_context << InternalInstruction::DUP2 << u256(32) << InternalInstruction::ADD;
utils().zeroInitialiseMemoryArray(arrayType);
m_context << skipInit;
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
break;
}
case FunctionType::Kind::Assert:
@ -1227,7 +1227,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
}
// Stack: <error string (unconverted)> <condition>
// jump if condition was met
m_context << Instruction::ISZERO << Instruction::ISZERO;
m_context << InternalInstruction::ISZERO << InternalInstruction::ISZERO;
auto success = m_context.appendConditionalJump();
if (function.kind() == FunctionType::Kind::Assert)
// condition was not met, flag an error
@ -1291,7 +1291,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
// stack now: [<selector/functionPointer/signature>] <arg1> .. <argN> <free_mem>
// adjust by 32(+4) bytes to accommodate the length(+selector)
m_context << u256(32 + (hasSelectorOrSignature ? 4 : 0)) << Instruction::ADD;
m_context << u256(32 + (hasSelectorOrSignature ? 4 : 0)) << InternalInstruction::ADD;
// stack now: [<selector/functionPointer/signature>] <arg1> .. <argN> <data_encoding_area_start>
if (isPacked)
@ -1311,7 +1311,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
m_context.appendInlineAssembly(R"({
mstore(mem_ptr, sub(sub(mem_end, mem_ptr), 0x20))
})", {"mem_end", "mem_ptr"});
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
utils().storeFreeMemoryPointer();
// stack: [<selector/functionPointer/signature>] <memory ptr>
@ -1338,7 +1338,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
// stack: <memory pointer> <signature> <free mem ptr>
utils().packedEncode(TypePointers{selectorType}, TypePointers());
utils().toSizeAfterFreeMemoryPointer();
m_context << Instruction::KECCAK256;
m_context << InternalInstruction::KECCAK256;
// stack: <memory pointer> <hash>
dataOnStack = TypeProvider::fixedBytes(32);
@ -1358,7 +1358,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
solAssert(selectorType->sizeOnStack() == 2);
// stack: <memory pointer> <functionPointer>
// Extract selector from the stack
m_context << Instruction::SWAP1 << Instruction::POP;
m_context << InternalInstruction::SWAP1 << InternalInstruction::POP;
}
// Conversion will be done below
dataOnStack = TypeProvider::uint(32);
@ -1378,7 +1378,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
let mask := )" + mask + R"(
mstore(data_start, or(and(data, mask), selector))
})", {"mem_ptr", "selector"});
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
}
// stack now: <memory pointer>
@ -1405,8 +1405,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
else
{
utils().convertType(*firstArgType, *TypeProvider::bytesMemory());
m_context << Instruction::DUP1 << u256(32) << Instruction::ADD;
m_context << Instruction::SWAP1 << Instruction::MLOAD;
m_context << InternalInstruction::DUP1 << u256(32) << InternalInstruction::ADD;
m_context << InternalInstruction::SWAP1 << InternalInstruction::MLOAD;
// stack now: <mem_pos> <length>
utils().abiDecode(targetTypes, true);
@ -1414,7 +1414,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
break;
}
case FunctionType::Kind::GasLeft:
m_context << Instruction::GAS;
m_context << InternalInstruction::GAS;
break;
case FunctionType::Kind::MetaType:
// No code to generate.
@ -1649,7 +1649,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
dynamic_cast<MagicVariableDeclaration const*>(arg->annotation().referencedDeclaration)
)
{
m_context << Instruction::SELFBALANCE;
m_context << InternalInstruction::SELFBALANCE;
return false;
}
@ -1671,7 +1671,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
*TypeProvider::address(),
true
);
m_context << Instruction::EXTCODESIZE;
m_context << InternalInstruction::EXTCODESIZE;
return false;
}
@ -1713,7 +1713,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
*TypeProvider::address(),
true
);
m_context << Instruction::BALANCE;
m_context << InternalInstruction::BALANCE;
}
else if (member == "code")
{
@ -1724,28 +1724,28 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
true
);
m_context << Instruction::DUP1 << Instruction::EXTCODESIZE;
m_context << InternalInstruction::DUP1 << InternalInstruction::EXTCODESIZE;
// Stack post: <address> <size>
m_context << Instruction::DUP1;
m_context << InternalInstruction::DUP1;
// Account for the size field of `bytes memory`
m_context << u256(32) << Instruction::ADD;
m_context << u256(32) << InternalInstruction::ADD;
utils().allocateMemory();
// Stack post: <address> <size> <mem_offset>
// Store size at mem_offset
m_context << Instruction::DUP2 << Instruction::DUP2 << Instruction::MSTORE;
m_context << InternalInstruction::DUP2 << InternalInstruction::DUP2 << InternalInstruction::MSTORE;
m_context << u256(0) << Instruction::SWAP1 << Instruction::DUP1;
m_context << u256(0) << InternalInstruction::SWAP1 << InternalInstruction::DUP1;
// Stack post: <address> <size> 0 <mem_offset> <mem_offset>
m_context << u256(32) << Instruction::ADD << Instruction::SWAP1;
m_context << u256(32) << InternalInstruction::ADD << InternalInstruction::SWAP1;
// Stack post: <address> <size> 0 <mem_offset_adjusted> <mem_offset>
m_context << Instruction::SWAP4;
m_context << InternalInstruction::SWAP4;
// Stack post: <mem_offset> <size> 0 <mem_offset_adjusted> <address>
m_context << Instruction::EXTCODECOPY;
m_context << InternalInstruction::EXTCODECOPY;
// Stack post: <mem_offset>
}
else if (member == "codehash")
@ -1755,7 +1755,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
*TypeProvider::address(),
true
);
m_context << Instruction::EXTCODEHASH;
m_context << InternalInstruction::EXTCODEHASH;
}
else if ((set<string>{"send", "transfer"}).count(member))
{
@ -1785,7 +1785,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
if (functionType.kind() == FunctionType::Kind::External)
CompilerUtils(m_context).popStackSlots(functionType.sizeOnStack() - 2);
m_context << Instruction::SWAP1 << Instruction::POP;
m_context << InternalInstruction::SWAP1 << InternalInstruction::POP;
/// need to store it as bytes4
utils().leftShiftNumberOnStack(224);
@ -1805,34 +1805,34 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
case Type::Category::Magic:
// we can ignore the kind of magic and only look at the name of the member
if (member == "coinbase")
m_context << Instruction::COINBASE;
m_context << InternalInstruction::COINBASE;
else if (member == "timestamp")
m_context << Instruction::TIMESTAMP;
m_context << InternalInstruction::TIMESTAMP;
else if (member == "difficulty")
m_context << Instruction::DIFFICULTY;
m_context << InternalInstruction::DIFFICULTY;
else if (member == "prevrandao")
m_context << Instruction::PREVRANDAO;
m_context << InternalInstruction::PREVRANDAO;
else if (member == "number")
m_context << Instruction::NUMBER;
m_context << InternalInstruction::NUMBER;
else if (member == "gaslimit")
m_context << Instruction::GASLIMIT;
m_context << InternalInstruction::GASLIMIT;
else if (member == "sender")
m_context << Instruction::CALLER;
m_context << InternalInstruction::CALLER;
else if (member == "value")
m_context << Instruction::CALLVALUE;
m_context << InternalInstruction::CALLVALUE;
else if (member == "origin")
m_context << Instruction::ORIGIN;
m_context << InternalInstruction::ORIGIN;
else if (member == "gasprice")
m_context << Instruction::GASPRICE;
m_context << InternalInstruction::GASPRICE;
else if (member == "chainid")
m_context << Instruction::CHAINID;
m_context << InternalInstruction::CHAINID;
else if (member == "basefee")
m_context << Instruction::BASEFEE;
m_context << InternalInstruction::BASEFEE;
else if (member == "data")
m_context << u256(0) << Instruction::CALLDATASIZE;
m_context << u256(0) << InternalInstruction::CALLDATASIZE;
else if (member == "sig")
m_context << u256(0) << Instruction::CALLDATALOAD
<< (u256(0xffffffff) << (256 - 32)) << Instruction::AND;
m_context << u256(0) << InternalInstruction::CALLDATALOAD
<< (u256(0xffffffff) << (256 - 32)) << InternalInstruction::AND;
else if (member == "gas")
solAssert(false, "Gas has been removed.");
else if (member == "blockhash")
@ -1844,7 +1844,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
solAssert(!contractType.isSuper(), "");
ContractDefinition const& contract = contractType.contractDefinition();
utils().fetchFreeMemoryPointer();
m_context << Instruction::DUP1 << u256(32) << Instruction::ADD;
m_context << InternalInstruction::DUP1 << u256(32) << InternalInstruction::ADD;
utils().copyContractCodeToMemory(contract, member == "creationCode");
// Stack: start end
m_context.appendInlineAssembly(
@ -1854,7 +1854,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
})")("free", to_string(CompilerUtils::freeMemoryPointer)).render(),
{"start", "end"}
);
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
}
else if (member == "name")
{
@ -1865,9 +1865,9 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
dynamic_cast<ContractType const&>(*arg).contractDefinition();
utils().allocateMemory(((contract.name().length() + 31) / 32) * 32 + 32);
// store string length
m_context << u256(contract.name().length()) << Instruction::DUP2 << Instruction::MSTORE;
m_context << u256(contract.name().length()) << InternalInstruction::DUP2 << InternalInstruction::MSTORE;
// adjust pointer
m_context << Instruction::DUP1 << u256(32) << Instruction::ADD;
m_context << InternalInstruction::DUP1 << u256(32) << InternalInstruction::ADD;
utils().storeStringData(contract.name());
}
else if (member == "interfaceId")
@ -1903,13 +1903,13 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
case DataLocation::Storage:
{
pair<u256, unsigned> const& offsets = type.storageOffsetsOfMember(member);
m_context << offsets.first << Instruction::ADD << u256(offsets.second);
m_context << offsets.first << InternalInstruction::ADD << u256(offsets.second);
setLValueToStorageItem(_memberAccess);
break;
}
case DataLocation::Memory:
{
m_context << type.memoryOffsetOfMember(member) << Instruction::ADD;
m_context << type.memoryOffsetOfMember(member) << InternalInstruction::ADD;
setLValue<MemoryItem>(_memberAccess, *memberType);
break;
}
@ -1917,13 +1917,13 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
{
if (_memberAccess.annotation().type->isDynamicallyEncoded())
{
m_context << Instruction::DUP1;
m_context << type.calldataOffsetOfMember(member) << Instruction::ADD;
m_context << InternalInstruction::DUP1;
m_context << type.calldataOffsetOfMember(member) << InternalInstruction::ADD;
CompilerUtils(m_context).accessCalldataTail(*memberType);
}
else
{
m_context << type.calldataOffsetOfMember(member) << Instruction::ADD;
m_context << type.calldataOffsetOfMember(member) << InternalInstruction::ADD;
// For non-value types the calldata offset is returned directly.
if (memberType->isValueType())
{
@ -1971,14 +1971,14 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
switch (type.location())
{
case DataLocation::CallData:
m_context << Instruction::SWAP1 << Instruction::POP;
m_context << InternalInstruction::SWAP1 << InternalInstruction::POP;
break;
case DataLocation::Storage:
ArrayUtils(m_context).retrieveLength(type);
m_context << Instruction::SWAP1 << Instruction::POP;
m_context << InternalInstruction::SWAP1 << InternalInstruction::POP;
break;
case DataLocation::Memory:
m_context << Instruction::MLOAD;
m_context << InternalInstruction::MLOAD;
break;
}
}
@ -2066,7 +2066,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
TypePointers{_indexAccess.indexExpression()->annotation().type},
TypePointers{keyType}
);
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
utils().storeInMemoryDynamic(*TypeProvider::uint256());
utils().toSizeAfterFreeMemoryPointer();
}
@ -2074,12 +2074,12 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
{
m_context << u256(0); // memory position
appendExpressionCopyToMemory(*keyType, *_indexAccess.indexExpression());
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
solAssert(CompilerUtils::freeMemoryPointer >= 0x40, "");
utils().storeInMemoryDynamic(*TypeProvider::uint256());
m_context << u256(0);
}
m_context << Instruction::KECCAK256;
m_context << InternalInstruction::KECCAK256;
m_context << u256(0);
setLValueToStorageItem(_indexAccess);
break;
@ -2138,11 +2138,11 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
// stack layout: <value> <index>
// check out-of-bounds access
m_context << u256(fixedBytesType.numBytes());
m_context << Instruction::DUP2 << Instruction::LT << Instruction::ISZERO;
m_context << InternalInstruction::DUP2 << InternalInstruction::LT << InternalInstruction::ISZERO;
// out-of-bounds access throws exception
m_context.appendConditionalPanic(util::PanicCode::ArrayOutOfBounds);
m_context << Instruction::BYTE;
m_context << InternalInstruction::BYTE;
utils().leftShiftNumberOnStack(256 - 8);
break;
}
@ -2187,16 +2187,16 @@ bool ExpressionCompiler::visit(IndexRangeAccess const& _indexAccess)
m_context << u256(0);
// stack: offset length sliceStart
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
// stack: offset sliceStart length
if (_indexAccess.endExpression())
acceptAndConvert(*_indexAccess.endExpression(), *TypeProvider::uint256());
else
m_context << Instruction::DUP1;
m_context << InternalInstruction::DUP1;
// stack: offset sliceStart length sliceEnd
m_context << Instruction::SWAP3;
m_context << InternalInstruction::SWAP3;
// stack: sliceEnd sliceStart length offset
m_context.callYulFunction(m_context.utilFunctions().calldataArrayIndexRangeAccess(*arrayType), 4, 2);
@ -2216,7 +2216,7 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier)
if (dynamic_cast<ContractType const*>(magicVar->type()))
{
solAssert(_identifier.name() == "this", "");
m_context << Instruction::ADDRESS;
m_context << InternalInstruction::ADDRESS;
}
break;
default:
@ -2294,11 +2294,11 @@ void ExpressionCompiler::appendAndOrOperatorCode(BinaryOperation const& _binaryO
solAssert(c_op == Token::Or || c_op == Token::And, "");
_binaryOperation.leftExpression().accept(*this);
m_context << Instruction::DUP1;
m_context << InternalInstruction::DUP1;
if (c_op == Token::And)
m_context << Instruction::ISZERO;
m_context << InternalInstruction::ISZERO;
evmasm::AssemblyItem endLabel = m_context.appendConditionalJump();
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
_binaryOperation.rightExpression().accept(*this);
m_context << endLabel;
}
@ -2311,18 +2311,18 @@ void ExpressionCompiler::appendCompareOperatorCode(Token _operator, Type const&
if (functionType && functionType->kind() == FunctionType::Kind::External)
{
solUnimplementedAssert(functionType->sizeOnStack() == 2, "");
m_context << Instruction::SWAP3;
m_context << InternalInstruction::SWAP3;
m_context << ((u256(1) << 160) - 1) << Instruction::AND;
m_context << Instruction::SWAP1;
m_context << ((u256(1) << 160) - 1) << Instruction::AND;
m_context << Instruction::EQ;
m_context << Instruction::SWAP2;
m_context << ((u256(1) << 32) - 1) << Instruction::AND;
m_context << Instruction::SWAP1;
m_context << ((u256(1) << 32) - 1) << Instruction::AND;
m_context << Instruction::EQ;
m_context << Instruction::AND;
m_context << ((u256(1) << 160) - 1) << InternalInstruction::AND;
m_context << InternalInstruction::SWAP1;
m_context << ((u256(1) << 160) - 1) << InternalInstruction::AND;
m_context << InternalInstruction::EQ;
m_context << InternalInstruction::SWAP2;
m_context << ((u256(1) << 32) - 1) << InternalInstruction::AND;
m_context << InternalInstruction::SWAP1;
m_context << ((u256(1) << 32) - 1) << InternalInstruction::AND;
m_context << InternalInstruction::EQ;
m_context << InternalInstruction::AND;
}
else
{
@ -2331,14 +2331,14 @@ void ExpressionCompiler::appendCompareOperatorCode(Token _operator, Type const&
{
// We have to remove the upper bits (construction time value) because they might
// be "unknown" in one of the operands and not in the other.
m_context << ((u256(1) << 32) - 1) << Instruction::AND;
m_context << Instruction::SWAP1;
m_context << ((u256(1) << 32) - 1) << Instruction::AND;
m_context << ((u256(1) << 32) - 1) << InternalInstruction::AND;
m_context << InternalInstruction::SWAP1;
m_context << ((u256(1) << 32) - 1) << InternalInstruction::AND;
}
m_context << Instruction::EQ;
m_context << InternalInstruction::EQ;
}
if (_operator == Token::NotEqual)
m_context << Instruction::ISZERO;
m_context << InternalInstruction::ISZERO;
}
else
{
@ -2351,19 +2351,19 @@ void ExpressionCompiler::appendCompareOperatorCode(Token _operator, Type const&
{
case Token::GreaterThanOrEqual:
m_context <<
(isSigned ? Instruction::SLT : Instruction::LT) <<
Instruction::ISZERO;
(isSigned ? InternalInstruction::SLT : InternalInstruction::LT) <<
InternalInstruction::ISZERO;
break;
case Token::LessThanOrEqual:
m_context <<
(isSigned ? Instruction::SGT : Instruction::GT) <<
Instruction::ISZERO;
(isSigned ? InternalInstruction::SGT : InternalInstruction::GT) <<
InternalInstruction::ISZERO;
break;
case Token::GreaterThan:
m_context << (isSigned ? Instruction::SGT : Instruction::GT);
m_context << (isSigned ? InternalInstruction::SGT : InternalInstruction::GT);
break;
case Token::LessThan:
m_context << (isSigned ? Instruction::SLT : Instruction::LT);
m_context << (isSigned ? InternalInstruction::SLT : InternalInstruction::LT);
break;
default:
solAssert(false, "Unknown comparison operator.");
@ -2422,25 +2422,25 @@ void ExpressionCompiler::appendArithmeticOperatorCode(Token _operator, Type cons
switch (_operator)
{
case Token::Add:
m_context << Instruction::ADD;
m_context << InternalInstruction::ADD;
break;
case Token::Sub:
m_context << Instruction::SUB;
m_context << InternalInstruction::SUB;
break;
case Token::Mul:
m_context << Instruction::MUL;
m_context << InternalInstruction::MUL;
break;
case Token::Div:
case Token::Mod:
{
// Test for division by zero
m_context << Instruction::DUP2 << Instruction::ISZERO;
m_context << InternalInstruction::DUP2 << InternalInstruction::ISZERO;
m_context.appendConditionalPanic(util::PanicCode::DivisionByZero);
if (_operator == Token::Div)
m_context << (c_isSigned ? Instruction::SDIV : Instruction::DIV);
m_context << (c_isSigned ? InternalInstruction::SDIV : InternalInstruction::DIV);
else
m_context << (c_isSigned ? Instruction::SMOD : Instruction::MOD);
m_context << (c_isSigned ? InternalInstruction::SMOD : InternalInstruction::MOD);
break;
}
default:
@ -2454,13 +2454,13 @@ void ExpressionCompiler::appendBitOperatorCode(Token _operator)
switch (_operator)
{
case Token::BitOr:
m_context << Instruction::OR;
m_context << InternalInstruction::OR;
break;
case Token::BitAnd:
m_context << Instruction::AND;
m_context << InternalInstruction::AND;
break;
case Token::BitXor:
m_context << Instruction::XOR;
m_context << InternalInstruction::XOR;
break;
default:
solAssert(false, "Unknown bit operator.");
@ -2489,20 +2489,20 @@ void ExpressionCompiler::appendShiftOperatorCode(Token _operator, Type const& _v
else
solAssert(false, "Invalid shift amount type.");
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
// stack: value_to_shift shift_amount
switch (_operator)
{
case Token::SHL:
if (m_context.evmVersion().hasBitwiseShifting())
m_context << Instruction::SHL;
m_context << InternalInstruction::SHL;
else
m_context << u256(2) << Instruction::EXP << Instruction::MUL;
m_context << u256(2) << InternalInstruction::EXP << InternalInstruction::MUL;
break;
case Token::SAR:
if (m_context.evmVersion().hasBitwiseShifting())
m_context << (c_valueSigned ? Instruction::SAR : Instruction::SHR);
m_context << (c_valueSigned ? InternalInstruction::SAR : InternalInstruction::SHR);
else
{
if (c_valueSigned)
@ -2528,7 +2528,7 @@ void ExpressionCompiler::appendShiftOperatorCode(Token _operator, Type const& _v
m_context.appendInlineAssembly(R"({
value_to_shift := div(value_to_shift, exp(2, shift_amount))
})", {"value_to_shift", "shift_amount"});
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
}
break;
@ -2550,7 +2550,7 @@ void ExpressionCompiler::appendExpOperatorCode(Type const& _valueType, Type cons
dynamic_cast<IntegerType const&>(_exponentType)
), 2, 1);
else
m_context << Instruction::EXP;
m_context << InternalInstruction::EXP;
}
void ExpressionCompiler::appendExternalFunctionCall(
@ -2626,8 +2626,8 @@ void ExpressionCompiler::appendExternalFunctionCall(
// zero bytes (which we cannot detect).
solAssert(0 < retSize && retSize <= 32, "");
utils().fetchFreeMemoryPointer();
m_context << u256(0) << Instruction::DUP2 << Instruction::MSTORE;
m_context << u256(32) << Instruction::ADD;
m_context << u256(0) << InternalInstruction::DUP2 << InternalInstruction::MSTORE;
m_context << u256(32) << InternalInstruction::ADD;
utils().storeFreeMemoryPointer();
}
@ -2642,7 +2642,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
m_context << u256(0);
utils().fetchFreeMemoryPointer();
// This touches too much, but that way we save some rounding arithmetic
m_context << u256(retSize) << Instruction::ADD << Instruction::MSTORE;
m_context << u256(retSize) << InternalInstruction::ADD << InternalInstruction::MSTORE;
}
}
@ -2687,15 +2687,15 @@ void ExpressionCompiler::appendExternalFunctionCall(
if (funKind == FunctionType::Kind::ECRecover)
{
// In this case, output is 32 bytes before input and has already been cleared.
m_context << u256(32) << Instruction::DUP2 << Instruction::SUB << Instruction::SWAP1;
m_context << u256(32) << InternalInstruction::DUP2 << InternalInstruction::SUB << InternalInstruction::SWAP1;
// Here: <input end> <output size> <outpos> <input pos>
m_context << Instruction::DUP1 << Instruction::DUP5 << Instruction::SUB;
m_context << Instruction::SWAP1;
m_context << InternalInstruction::DUP1 << InternalInstruction::DUP5 << InternalInstruction::SUB;
m_context << InternalInstruction::SWAP1;
}
else
{
m_context << Instruction::DUP1 << Instruction::DUP4 << Instruction::SUB;
m_context << Instruction::DUP2;
m_context << InternalInstruction::DUP1 << InternalInstruction::DUP4 << InternalInstruction::SUB;
m_context << InternalInstruction::DUP2;
}
// CALL arguments: outSize, outOff, inSize, inOff (already present up to here)
@ -2725,7 +2725,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
m_context.revertStrings() >= RevertStrings::Debug
)
{
m_context << Instruction::DUP1 << Instruction::EXTCODESIZE << Instruction::ISZERO;
m_context << InternalInstruction::DUP1 << InternalInstruction::EXTCODESIZE << InternalInstruction::ISZERO;
m_context.appendConditionalRevert(false, "Target contract does not contain code");
existenceChecked = true;
}
@ -2735,7 +2735,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
m_context << dupInstruction(m_context.baseToCurrentStackOffset(gasStackPos));
else if (m_context.evmVersion().canOverchargeGasForCall())
// Send all gas (requires tangerine whistle EVM)
m_context << Instruction::GAS;
m_context << InternalInstruction::GAS;
else
{
// send all gas except the amount needed to execute "SUB" and "CALL"
@ -2745,15 +2745,15 @@ void ExpressionCompiler::appendExternalFunctionCall(
gasNeededByCaller += evmasm::GasCosts::callValueTransferGas;
if (!existenceChecked)
gasNeededByCaller += evmasm::GasCosts::callNewAccountGas; // we never know
m_context << gasNeededByCaller << Instruction::GAS << Instruction::SUB;
m_context << gasNeededByCaller << InternalInstruction::GAS << InternalInstruction::SUB;
}
// Order is important here, STATICCALL might overlap with DELEGATECALL.
if (isDelegateCall)
m_context << Instruction::DELEGATECALL;
m_context << InternalInstruction::DELEGATECALL;
else if (useStaticCall)
m_context << Instruction::STATICCALL;
m_context << InternalInstruction::STATICCALL;
else
m_context << Instruction::CALL;
m_context << InternalInstruction::CALL;
unsigned remainsSize =
2u + // contract address, input_memory_end
@ -2766,7 +2766,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
if (!returnSuccessConditionAndReturndata && !_tryCall)
{
// Propagate error condition (if CALL pushes 0 on stack).
m_context << Instruction::ISZERO;
m_context << InternalInstruction::ISZERO;
m_context.appendConditionalRevert(true);
}
else
@ -2777,9 +2777,9 @@ void ExpressionCompiler::appendExternalFunctionCall(
if (_tryCall)
{
m_context << Instruction::DUP1 << Instruction::ISZERO;
m_context << InternalInstruction::DUP1 << InternalInstruction::ISZERO;
m_context.appendConditionalJumpTo(endTag);
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
}
if (returnSuccessConditionAndReturndata)
@ -2804,7 +2804,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
// Failing ecrecover cannot be detected, so we clear output before the call.
m_context << u256(32);
utils().fetchFreeMemoryPointer();
m_context << Instruction::SUB << Instruction::MLOAD;
m_context << InternalInstruction::SUB << InternalInstruction::MLOAD;
}
else if (!returnTypes.empty())
{
@ -2832,7 +2832,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
solAssert(retSize > 0, "");
// Always use the actual return length, and not our calculated expected length, if returndatacopy is supported.
// This ensures it can catch badly formatted input from external calls.
m_context << (haveReturndatacopy ? evmasm::AssemblyItem(Instruction::RETURNDATASIZE) : u256(retSize));
m_context << (haveReturndatacopy ? evmasm::AssemblyItem(InternalInstruction::RETURNDATASIZE) : u256(retSize));
// Stack: return_data_start return_data_size
if (needToUpdateFreeMemoryPtr)
m_context.appendInlineAssembly(R"({

View File

@ -70,7 +70,7 @@ void StackVariable::storeValue(Type const&, SourceLocation const& _location, boo
);
else if (stackDiff > 0)
for (unsigned i = 0; i < m_size; ++i)
m_context << swapInstruction(stackDiff) << Instruction::POP;
m_context << swapInstruction(stackDiff) << InternalInstruction::POP;
if (!_move)
retrieveValue(_location);
}
@ -92,11 +92,11 @@ void MemoryItem::retrieveValue(SourceLocation const&, bool _remove) const
if (m_dataType->isValueType())
{
if (!_remove)
m_context << Instruction::DUP1;
m_context << InternalInstruction::DUP1;
CompilerUtils(m_context).loadFromMemoryDynamic(*m_dataType, false, m_padded, false);
}
else
m_context << Instruction::MLOAD;
m_context << InternalInstruction::MLOAD;
}
void MemoryItem::storeValue(Type const& _sourceType, SourceLocation const&, bool _move) const
@ -117,13 +117,13 @@ void MemoryItem::storeValue(Type const& _sourceType, SourceLocation const&, bool
solAssert(m_dataType->calldataEncodedSize(false) == 1, "Invalid non-padded type.");
solAssert(m_dataType->category() != Type::Category::UserDefinedValueType, "");
if (m_dataType->category() == Type::Category::FixedBytes)
m_context << u256(0) << Instruction::BYTE;
m_context << Instruction::SWAP1 << Instruction::MSTORE8;
m_context << u256(0) << InternalInstruction::BYTE;
m_context << InternalInstruction::SWAP1 << InternalInstruction::MSTORE8;
}
else
{
utils.storeInMemoryDynamic(*m_dataType, m_padded);
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
}
}
else
@ -132,10 +132,10 @@ void MemoryItem::storeValue(Type const& _sourceType, SourceLocation const&, bool
solAssert(m_dataType->sizeOnStack() == 1, "");
if (!_move)
m_context << Instruction::DUP2 << Instruction::SWAP1;
m_context << InternalInstruction::DUP2 << InternalInstruction::SWAP1;
// stack: [value] value lvalue
// only store the reference
m_context << Instruction::MSTORE;
m_context << InternalInstruction::MSTORE;
}
}
@ -145,7 +145,7 @@ void MemoryItem::setToZero(SourceLocation const&, bool _removeReference) const
solAssert(_removeReference, "");
utils.pushZeroValue(*m_dataType);
utils.storeInMemoryDynamic(*m_dataType, m_padded);
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
}
@ -184,7 +184,7 @@ void ImmutableItem::storeValue(Type const& _sourceType, SourceLocation const&, b
else
utils.copyToStackTop(m_dataType->sizeOnStack() + 1, m_dataType->sizeOnStack());
utils.storeInMemoryDynamic(*m_dataType);
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
}
void ImmutableItem::setToZero(SourceLocation const&, bool) const
@ -218,15 +218,15 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const
{
solAssert(m_dataType->sizeOnStack() == 1, "Invalid storage ref size.");
if (_remove)
m_context << Instruction::POP; // remove byte offset
m_context << InternalInstruction::POP; // remove byte offset
else
m_context << Instruction::DUP2;
m_context << InternalInstruction::DUP2;
return;
}
if (!_remove)
CompilerUtils(m_context).copyToStackTop(sizeOnStack(), sizeOnStack());
if (m_dataType->storageBytes() == 32)
m_context << Instruction::POP << Instruction::SLOAD;
m_context << InternalInstruction::POP << InternalInstruction::SLOAD;
else
{
Type const* type = m_dataType;
@ -234,8 +234,8 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const
type = type->encodingType();
bool cleaned = false;
m_context
<< Instruction::SWAP1 << Instruction::SLOAD << Instruction::SWAP1
<< u256(0x100) << Instruction::EXP << Instruction::SWAP1 << Instruction::DIV;
<< InternalInstruction::SWAP1 << InternalInstruction::SLOAD << InternalInstruction::SWAP1
<< u256(0x100) << InternalInstruction::EXP << InternalInstruction::SWAP1 << InternalInstruction::DIV;
if (type->category() == Type::Category::FixedPoint)
// implementation should be very similar to the integer case.
solUnimplemented("Not yet implemented - FixedPointType.");
@ -248,9 +248,9 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const
}
else if (fun->kind() == FunctionType::Kind::Internal)
{
m_context << Instruction::DUP1 << Instruction::ISZERO;
m_context << InternalInstruction::DUP1 << InternalInstruction::ISZERO;
CompilerUtils(m_context).pushZeroValue(*fun);
m_context << Instruction::MUL << Instruction::OR;
m_context << InternalInstruction::MUL << InternalInstruction::OR;
}
}
else if (type->leftAligned())
@ -263,14 +263,14 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const
dynamic_cast<IntegerType const&>(*type).isSigned()
)
{
m_context << u256(type->storageBytes() - 1) << Instruction::SIGNEXTEND;
m_context << u256(type->storageBytes() - 1) << InternalInstruction::SIGNEXTEND;
cleaned = true;
}
if (!cleaned)
{
solAssert(type->sizeOnStack() == 1, "");
m_context << ((u256(0x1) << (8 * type->storageBytes())) - 1) << Instruction::AND;
m_context << ((u256(0x1) << (8 * type->storageBytes())) - 1) << InternalInstruction::AND;
}
}
}
@ -289,29 +289,29 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
{
solAssert(m_dataType->sizeOnStack() == 1, "Invalid stack size.");
// offset should be zero
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
if (!_move)
m_context << Instruction::DUP2 << Instruction::SWAP1;
m_context << InternalInstruction::DUP2 << InternalInstruction::SWAP1;
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
utils.convertType(_sourceType, *m_dataType, true);
m_context << Instruction::SWAP1;
m_context << InternalInstruction::SWAP1;
m_context << Instruction::SSTORE;
m_context << InternalInstruction::SSTORE;
}
else
{
// OR the value into the other values in the storage slot
m_context << u256(0x100) << Instruction::EXP;
m_context << u256(0x100) << InternalInstruction::EXP;
// stack: value storage_ref multiplier
// fetch old value
m_context << Instruction::DUP2 << Instruction::SLOAD;
m_context << InternalInstruction::DUP2 << InternalInstruction::SLOAD;
// stack: value storage_ref multiplier old_full_value
// clear bytes in old value
m_context
<< Instruction::DUP2 << ((u256(1) << (8 * m_dataType->storageBytes())) - 1)
<< Instruction::MUL;
m_context << Instruction::NOT << Instruction::AND << Instruction::SWAP1;
<< InternalInstruction::DUP2 << ((u256(1) << (8 * m_dataType->storageBytes())) - 1)
<< InternalInstruction::MUL;
m_context << InternalInstruction::NOT << InternalInstruction::AND << InternalInstruction::SWAP1;
// stack: value storage_ref cleared_value multiplier
utils.copyToStackTop(3 + m_dataType->sizeOnStack(), m_dataType->sizeOnStack());
// stack: value storage_ref cleared_value multiplier value
@ -333,7 +333,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
solAssert(fun->sizeOnStack() == 1, "");
m_context <<
((u256(1) << (8 * m_dataType->storageBytes())) - 1) <<
Instruction::AND;
InternalInstruction::AND;
}
}
else if (m_dataType->leftAligned())
@ -350,9 +350,9 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
// remove the higher order bits
utils.convertType(_sourceType, *m_dataType, true, true);
}
m_context << Instruction::MUL << Instruction::OR;
m_context << InternalInstruction::MUL << InternalInstruction::OR;
// stack: value storage_ref updated_value
m_context << Instruction::SWAP1 << Instruction::SSTORE;
m_context << InternalInstruction::SWAP1 << InternalInstruction::SSTORE;
if (_move)
utils.popStackElement(*m_dataType);
}
@ -365,19 +365,19 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
);
if (m_dataType->category() == Type::Category::Array)
{
m_context << Instruction::POP; // remove byte offset
m_context << InternalInstruction::POP; // remove byte offset
ArrayUtils(m_context).copyArrayToStorage(
dynamic_cast<ArrayType const&>(*m_dataType),
dynamic_cast<ArrayType const&>(_sourceType)
);
if (_move)
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
}
else if (m_dataType->category() == Type::Category::Struct)
{
// stack layout: source_ref target_ref target_offset
// note that we have structs, so offset should be zero and are ignored
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
auto const& structType = dynamic_cast<StructType const&>(*m_dataType);
auto const& sourceType = dynamic_cast<StructType const&>(_sourceType);
solAssert(
@ -389,7 +389,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
{
solAssert(sourceType.sizeOnStack() == 1, "");
solAssert(structType.sizeOnStack() == 1, "");
m_context << Instruction::DUP2 << Instruction::DUP2;
m_context << InternalInstruction::DUP2 << InternalInstruction::DUP2;
m_context.callYulFunction(m_context.utilFunctions().updateStorageValueFunction(sourceType, structType, 0), 2, 0);
}
else
@ -404,7 +404,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
{
// stack layout: source_ref target_ref
pair<u256, unsigned> const& offsets = sourceType.storageOffsetsOfMember(member.name);
m_context << offsets.first << Instruction::DUP3 << Instruction::ADD;
m_context << offsets.first << InternalInstruction::DUP3 << InternalInstruction::ADD;
m_context << u256(offsets.second);
// stack: source_ref target_ref source_member_ref source_member_off
StorageItem(m_context, *sourceMemberType).retrieveValue(_location, true);
@ -415,13 +415,13 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
solAssert(sourceType.location() == DataLocation::Memory, "");
// stack layout: source_ref target_ref
m_context << sourceType.memoryOffsetOfMember(member.name);
m_context << Instruction::DUP3 << Instruction::ADD;
m_context << InternalInstruction::DUP3 << InternalInstruction::ADD;
MemoryItem(m_context, *sourceMemberType).retrieveValue(_location, true);
// stack layout: source_ref target_ref source_value...
}
unsigned stackSize = sourceMemberType->sizeOnStack();
pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member.name);
m_context << dupInstruction(1 + stackSize) << offsets.first << Instruction::ADD;
m_context << dupInstruction(1 + stackSize) << offsets.first << InternalInstruction::ADD;
m_context << u256(offsets.second);
// stack: source_ref target_ref target_off source_value... target_member_ref target_member_byte_off
StorageItem(m_context, *memberType).storeValue(*sourceMemberType, _location, true);
@ -432,7 +432,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
if (_move)
utils.popStackSlots(2);
else
m_context << Instruction::SWAP1 << Instruction::POP;
m_context << InternalInstruction::SWAP1 << InternalInstruction::POP;
}
else
BOOST_THROW_EXCEPTION(
@ -464,12 +464,12 @@ void StorageItem::setToZero(SourceLocation const&, bool _removeReference) const
continue;
pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member.name);
m_context
<< offsets.first << Instruction::DUP3 << Instruction::ADD
<< offsets.first << InternalInstruction::DUP3 << InternalInstruction::ADD
<< u256(offsets.second);
StorageItem(m_context, *memberType).setToZero();
}
if (_removeReference)
m_context << Instruction::POP << Instruction::POP;
m_context << InternalInstruction::POP << InternalInstruction::POP;
}
else
{
@ -480,23 +480,23 @@ void StorageItem::setToZero(SourceLocation const&, bool _removeReference) const
{
// offset should be zero
m_context
<< Instruction::POP << u256(0)
<< Instruction::SWAP1 << Instruction::SSTORE;
<< InternalInstruction::POP << u256(0)
<< InternalInstruction::SWAP1 << InternalInstruction::SSTORE;
}
else
{
m_context << u256(0x100) << Instruction::EXP;
m_context << u256(0x100) << InternalInstruction::EXP;
// stack: storage_ref multiplier
// fetch old value
m_context << Instruction::DUP2 << Instruction::SLOAD;
m_context << InternalInstruction::DUP2 << InternalInstruction::SLOAD;
// stack: storage_ref multiplier old_full_value
// clear bytes in old value
m_context
<< Instruction::SWAP1 << ((u256(1) << (8 * m_dataType->storageBytes())) - 1)
<< Instruction::MUL;
m_context << Instruction::NOT << Instruction::AND;
<< InternalInstruction::SWAP1 << ((u256(1) << (8 * m_dataType->storageBytes())) - 1)
<< InternalInstruction::MUL;
m_context << InternalInstruction::NOT << InternalInstruction::AND;
// stack: storage_ref cleared_value
m_context << Instruction::SWAP1 << Instruction::SSTORE;
m_context << InternalInstruction::SWAP1 << InternalInstruction::SSTORE;
}
}
}
@ -510,47 +510,47 @@ void StorageByteArrayElement::retrieveValue(SourceLocation const&, bool _remove)
{
// stack: ref byte_number
if (_remove)
m_context << Instruction::SWAP1 << Instruction::SLOAD
<< Instruction::SWAP1 << Instruction::BYTE;
m_context << InternalInstruction::SWAP1 << InternalInstruction::SLOAD
<< InternalInstruction::SWAP1 << InternalInstruction::BYTE;
else
m_context << Instruction::DUP2 << Instruction::SLOAD
<< Instruction::DUP2 << Instruction::BYTE;
m_context << (u256(1) << (256 - 8)) << Instruction::MUL;
m_context << InternalInstruction::DUP2 << InternalInstruction::SLOAD
<< InternalInstruction::DUP2 << InternalInstruction::BYTE;
m_context << (u256(1) << (256 - 8)) << InternalInstruction::MUL;
}
void StorageByteArrayElement::storeValue(Type const&, SourceLocation const&, bool _move) const
{
// stack: value ref byte_number
m_context << u256(31) << Instruction::SUB << u256(0x100) << Instruction::EXP;
m_context << u256(31) << InternalInstruction::SUB << u256(0x100) << InternalInstruction::EXP;
// stack: value ref (1<<(8*(31-byte_number)))
m_context << Instruction::DUP2 << Instruction::SLOAD;
m_context << InternalInstruction::DUP2 << InternalInstruction::SLOAD;
// stack: value ref (1<<(8*(31-byte_number))) old_full_value
// clear byte in old value
m_context << Instruction::DUP2 << u256(0xff) << Instruction::MUL
<< Instruction::NOT << Instruction::AND;
m_context << InternalInstruction::DUP2 << u256(0xff) << InternalInstruction::MUL
<< InternalInstruction::NOT << InternalInstruction::AND;
// stack: value ref (1<<(32-byte_number)) old_full_value_with_cleared_byte
m_context << Instruction::SWAP1;
m_context << (u256(1) << (256 - 8)) << Instruction::DUP5 << Instruction::DIV
<< Instruction::MUL << Instruction::OR;
m_context << InternalInstruction::SWAP1;
m_context << (u256(1) << (256 - 8)) << InternalInstruction::DUP5 << InternalInstruction::DIV
<< InternalInstruction::MUL << InternalInstruction::OR;
// stack: value ref new_full_value
m_context << Instruction::SWAP1 << Instruction::SSTORE;
m_context << InternalInstruction::SWAP1 << InternalInstruction::SSTORE;
if (_move)
m_context << Instruction::POP;
m_context << InternalInstruction::POP;
}
void StorageByteArrayElement::setToZero(SourceLocation const&, bool _removeReference) const
{
// stack: ref byte_number
solAssert(_removeReference, "");
m_context << u256(31) << Instruction::SUB << u256(0x100) << Instruction::EXP;
m_context << u256(31) << InternalInstruction::SUB << u256(0x100) << InternalInstruction::EXP;
// stack: ref (1<<(8*(31-byte_number)))
m_context << Instruction::DUP2 << Instruction::SLOAD;
m_context << InternalInstruction::DUP2 << InternalInstruction::SLOAD;
// stack: ref (1<<(8*(31-byte_number))) old_full_value
// clear byte in old value
m_context << Instruction::SWAP1 << u256(0xff) << Instruction::MUL;
m_context << Instruction::NOT << Instruction::AND;
m_context << InternalInstruction::SWAP1 << u256(0xff) << InternalInstruction::MUL;
m_context << InternalInstruction::NOT << InternalInstruction::AND;
// stack: ref old_full_value_with_cleared_byte
m_context << Instruction::SWAP1 << Instruction::SSTORE;
m_context << InternalInstruction::SWAP1 << InternalInstruction::SSTORE;
}
TupleObject::TupleObject(

View File

@ -56,26 +56,26 @@ GasEstimator::GasConsumption GasEstimator::functionalEstimation(
using Id = ExpressionClasses::Id;
using Ids = vector<Id>;
Id hashValue = classes.find(u256(util::selectorFromSignatureU32(_signature)));
Id calldata = classes.find(Instruction::CALLDATALOAD, Ids{classes.find(u256(0))});
Id calldata = classes.find(InternalInstruction::CALLDATALOAD, Ids{classes.find(u256(0))});
if (!m_evmVersion.hasBitwiseShifting())
// div(calldataload(0), 1 << 224) equals to hashValue
classes.forceEqual(
hashValue,
Instruction::DIV,
InternalInstruction::DIV,
Ids{calldata, classes.find(u256(1) << 224)}
);
else
// shr(0xe0, calldataload(0)) equals to hashValue
classes.forceEqual(
hashValue,
Instruction::SHR,
InternalInstruction::SHR,
Ids{classes.find(u256(0xe0)), calldata}
);
// lt(calldatasize(), 4) equals to 0 (ignore the shortcut for fallback functions)
classes.forceEqual(
classes.find(u256(0)),
Instruction::LT,
Ids{classes.find(Instruction::CALLDATASIZE), classes.find(u256(4))}
InternalInstruction::LT,
Ids{classes.find(InternalInstruction::CALLDATASIZE), classes.find(u256(4))}
);
}

View File

@ -702,7 +702,7 @@ bool AsmAnalyzer::validateInstructions(std::string const& _instructionIdentifier
return false;
}
bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocation const& _location)
bool AsmAnalyzer::validateInstructions(evmasm::InternalInstruction _instr, SourceLocation const& _location)
{
// We assume that returndatacopy, returndatasize and staticcall are either all available
// or all not available.
@ -712,9 +712,9 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio
// These instructions are disabled in the dialect.
yulAssert(
_instr != evmasm::Instruction::JUMP &&
_instr != evmasm::Instruction::JUMPI &&
_instr != evmasm::Instruction::JUMPDEST,
_instr != evmasm::InternalInstruction::JUMP &&
_instr != evmasm::InternalInstruction::JUMPI &&
_instr != evmasm::InternalInstruction::JUMPDEST,
"");
bool returnValue = true;
@ -733,29 +733,29 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio
returnValue = false;
};
if (_instr == evmasm::Instruction::RETURNDATACOPY && !m_evmVersion.supportsReturndata())
if (_instr == evmasm::InternalInstruction::RETURNDATACOPY && !m_evmVersion.supportsReturndata())
errorForVM(7756_error, "only available for Byzantium-compatible");
else if (_instr == evmasm::Instruction::RETURNDATASIZE && !m_evmVersion.supportsReturndata())
else if (_instr == evmasm::InternalInstruction::RETURNDATASIZE && !m_evmVersion.supportsReturndata())
errorForVM(4778_error, "only available for Byzantium-compatible");
else if (_instr == evmasm::Instruction::STATICCALL && !m_evmVersion.hasStaticCall())
else if (_instr == evmasm::InternalInstruction::STATICCALL && !m_evmVersion.hasStaticCall())
errorForVM(1503_error, "only available for Byzantium-compatible");
else if (_instr == evmasm::Instruction::SHL && !m_evmVersion.hasBitwiseShifting())
else if (_instr == evmasm::InternalInstruction::SHL && !m_evmVersion.hasBitwiseShifting())
errorForVM(6612_error, "only available for Constantinople-compatible");
else if (_instr == evmasm::Instruction::SHR && !m_evmVersion.hasBitwiseShifting())
else if (_instr == evmasm::InternalInstruction::SHR && !m_evmVersion.hasBitwiseShifting())
errorForVM(7458_error, "only available for Constantinople-compatible");
else if (_instr == evmasm::Instruction::SAR && !m_evmVersion.hasBitwiseShifting())
else if (_instr == evmasm::InternalInstruction::SAR && !m_evmVersion.hasBitwiseShifting())
errorForVM(2054_error, "only available for Constantinople-compatible");
else if (_instr == evmasm::Instruction::CREATE2 && !m_evmVersion.hasCreate2())
else if (_instr == evmasm::InternalInstruction::CREATE2 && !m_evmVersion.hasCreate2())
errorForVM(6166_error, "only available for Constantinople-compatible");
else if (_instr == evmasm::Instruction::EXTCODEHASH && !m_evmVersion.hasExtCodeHash())
else if (_instr == evmasm::InternalInstruction::EXTCODEHASH && !m_evmVersion.hasExtCodeHash())
errorForVM(7110_error, "only available for Constantinople-compatible");
else if (_instr == evmasm::Instruction::CHAINID && !m_evmVersion.hasChainID())
else if (_instr == evmasm::InternalInstruction::CHAINID && !m_evmVersion.hasChainID())
errorForVM(1561_error, "only available for Istanbul-compatible");
else if (_instr == evmasm::Instruction::SELFBALANCE && !m_evmVersion.hasSelfBalance())
else if (_instr == evmasm::InternalInstruction::SELFBALANCE && !m_evmVersion.hasSelfBalance())
errorForVM(7721_error, "only available for Istanbul-compatible");
else if (_instr == evmasm::Instruction::BASEFEE && !m_evmVersion.hasBaseFee())
else if (_instr == evmasm::InternalInstruction::BASEFEE && !m_evmVersion.hasBaseFee())
errorForVM(5430_error, "only available for London-compatible");
else if (_instr == evmasm::Instruction::PC)
else if (_instr == evmasm::InternalInstruction::PC)
m_errorReporter.error(
2450_error,
Error::Type::SyntaxError,

View File

@ -114,7 +114,7 @@ private:
void expectValidType(YulString _type, langutil::SourceLocation const& _location);
void expectType(YulString _expectedType, YulString _givenType, langutil::SourceLocation const& _location);
bool validateInstructions(evmasm::Instruction _instr, langutil::SourceLocation const& _location);
bool validateInstructions(evmasm::InternalInstruction _instr, langutil::SourceLocation const& _location);
bool validateInstructions(std::string const& _instrIdentifier, langutil::SourceLocation const& _location);
bool validateInstructions(FunctionCall const& _functionCall);

View File

@ -40,7 +40,7 @@ struct SourceLocation;
namespace solidity::evmasm
{
enum class Instruction: uint8_t;
enum class InternalInstruction: uint8_t;
}
namespace solidity::yul
@ -66,7 +66,7 @@ public:
virtual int stackHeight() const = 0;
virtual void setStackHeight(int height) = 0;
/// Append an EVM instruction.
virtual void appendInstruction(evmasm::Instruction _instruction) = 0;
virtual void appendInstruction(evmasm::InternalInstruction _instruction) = 0;
/// Append a constant.
virtual void appendConstant(u256 const& _constant) = 0;
/// Append a label.

View File

@ -48,24 +48,24 @@ struct MiniEVMInterpreter
return std::visit(*this, _expr);
}
u256 eval(evmasm::Instruction _instr, vector<Expression> const& _arguments)
u256 eval(evmasm::InternalInstruction _instr, vector<Expression> const& _arguments)
{
vector<u256> args;
for (auto const& arg: _arguments)
args.emplace_back(eval(arg));
switch (_instr)
{
case evmasm::Instruction::ADD:
case evmasm::InternalInstruction::ADD:
return args.at(0) + args.at(1);
case evmasm::Instruction::SUB:
case evmasm::InternalInstruction::SUB:
return args.at(0) - args.at(1);
case evmasm::Instruction::MUL:
case evmasm::InternalInstruction::MUL:
return args.at(0) * args.at(1);
case evmasm::Instruction::EXP:
case evmasm::InternalInstruction::EXP:
return exp256(args.at(0), args.at(1));
case evmasm::Instruction::SHL:
case evmasm::InternalInstruction::SHL:
return args.at(0) > 255 ? 0 : (args.at(1) << unsigned(args.at(0)));
case evmasm::Instruction::NOT:
case evmasm::InternalInstruction::NOT:
return ~args.at(0);
default:
yulAssert(false, "Invalid operation generated in constant optimizer.");

View File

@ -118,7 +118,7 @@ void CodeTransform::freeUnusedVariables(bool _popUnusedSlotsAtStackTop)
while (m_unusedStackSlots.count(m_assembly.stackHeight() - 1))
{
yulAssert(m_unusedStackSlots.erase(m_assembly.stackHeight() - 1), "");
m_assembly.appendInstruction(evmasm::Instruction::POP);
m_assembly.appendInstruction(evmasm::InternalInstruction::POP);
}
}
@ -168,7 +168,7 @@ void CodeTransform::operator()(VariableDeclaration const& _varDecl)
if (atTopOfStack)
{
m_context->variableStackHeights.erase(&var);
m_assembly.appendInstruction(evmasm::Instruction::POP);
m_assembly.appendInstruction(evmasm::InternalInstruction::POP);
}
else
m_variablesScheduledForDeletion.insert(&var);
@ -186,7 +186,7 @@ void CodeTransform::operator()(VariableDeclaration const& _varDecl)
m_context->variableStackHeights[&var] = slot;
if (size_t heightDiff = variableHeightDiff(var, varName, true))
m_assembly.appendInstruction(evmasm::swapInstruction(static_cast<unsigned>(heightDiff - 1)));
m_assembly.appendInstruction(evmasm::Instruction::POP);
m_assembly.appendInstruction(evmasm::InternalInstruction::POP);
break;
}
if (!foundUnusedSlot)
@ -197,10 +197,10 @@ void CodeTransform::operator()(VariableDeclaration const& _varDecl)
void CodeTransform::stackError(StackTooDeepError _error, int _targetStackHeight)
{
m_assembly.appendInstruction(evmasm::Instruction::INVALID);
m_assembly.appendInstruction(evmasm::InternalInstruction::INVALID);
// Correct the stack.
while (m_assembly.stackHeight() > _targetStackHeight)
m_assembly.appendInstruction(evmasm::Instruction::POP);
m_assembly.appendInstruction(evmasm::InternalInstruction::POP);
while (m_assembly.stackHeight() < _targetStackHeight)
m_assembly.appendConstant(u256(0));
// Store error.
@ -303,7 +303,7 @@ void CodeTransform::operator()(If const& _if)
{
visitExpression(*_if.condition);
m_assembly.setSourceLocation(originLocationOf(_if));
m_assembly.appendInstruction(evmasm::Instruction::ISZERO);
m_assembly.appendInstruction(evmasm::InternalInstruction::ISZERO);
AbstractAssembly::LabelID end = m_assembly.newLabelId();
m_assembly.appendJumpToIf(end);
(*this)(_if.body);
@ -327,7 +327,7 @@ void CodeTransform::operator()(Switch const& _switch)
caseBodies[&c] = bodyLabel;
yulAssert(m_assembly.stackHeight() == expressionHeight + 1, "");
m_assembly.appendInstruction(evmasm::dupInstruction(2));
m_assembly.appendInstruction(evmasm::Instruction::EQ);
m_assembly.appendInstruction(evmasm::InternalInstruction::EQ);
m_assembly.appendJumpToIf(bodyLabel);
}
else
@ -353,7 +353,7 @@ void CodeTransform::operator()(Switch const& _switch)
m_assembly.setSourceLocation(originLocationOf(_switch));
m_assembly.appendLabel(end);
m_assembly.appendInstruction(evmasm::Instruction::POP);
m_assembly.appendInstruction(evmasm::InternalInstruction::POP);
}
void CodeTransform::operator()(FunctionDefinition const& _function)
@ -471,7 +471,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
while (!stackLayout.empty() && stackLayout.back() != static_cast<int>(stackLayout.size() - 1))
if (stackLayout.back() < 0)
{
m_assembly.appendInstruction(evmasm::Instruction::POP);
m_assembly.appendInstruction(evmasm::InternalInstruction::POP);
stackLayout.pop_back();
}
else
@ -508,7 +508,7 @@ void CodeTransform::operator()(ForLoop const& _forLoop)
visitExpression(*_forLoop.condition);
m_assembly.setSourceLocation(originLocationOf(_forLoop));
m_assembly.appendInstruction(evmasm::Instruction::ISZERO);
m_assembly.appendInstruction(evmasm::InternalInstruction::ISZERO);
m_assembly.appendJumpToIf(loopEnd);
int const stackHeightBody = m_assembly.stackHeight();
@ -533,7 +533,7 @@ int CodeTransform::appendPopUntil(int _targetDepth)
{
int const stackDiffAfter = m_assembly.stackHeight() - _targetDepth;
for (int i = 0; i < stackDiffAfter; ++i)
m_assembly.appendInstruction(evmasm::Instruction::POP);
m_assembly.appendInstruction(evmasm::InternalInstruction::POP);
return stackDiffAfter;
}
@ -733,7 +733,7 @@ void CodeTransform::finalizeBlock(Block const& _block, optional<int> blockStartS
yulAssert(!m_context->variableReferences.count(&var), "");
}
else
m_assembly.appendInstruction(evmasm::Instruction::POP);
m_assembly.appendInstruction(evmasm::InternalInstruction::POP);
}
if (blockStartStackHeight)
@ -758,7 +758,7 @@ void CodeTransform::generateAssignment(Identifier const& _variableName)
Scope::Variable const& _var = std::get<Scope::Variable>(*var);
if (size_t heightDiff = variableHeightDiff(_var, _variableName.name, true))
m_assembly.appendInstruction(evmasm::swapInstruction(static_cast<unsigned>(heightDiff - 1)));
m_assembly.appendInstruction(evmasm::Instruction::POP);
m_assembly.appendInstruction(evmasm::InternalInstruction::POP);
decreaseReference(_variableName.name, _var);
}
else

View File

@ -48,7 +48,7 @@ namespace
pair<YulString, BuiltinFunctionForEVM> createEVMFunction(
string const& _name,
evmasm::Instruction _instruction
evmasm::InternalInstruction _instruction
)
{
evmasm::InstructionInfo info = evmasm::instructionInfo(_instruction);
@ -71,7 +71,7 @@ pair<YulString, BuiltinFunctionForEVM> createEVMFunction(
f.controlFlowSideEffects.canRevert = false;
}
}
f.isMSize = _instruction == evmasm::Instruction::MSIZE;
f.isMSize = _instruction == evmasm::InternalInstruction::MSIZE;
f.literalArguments.clear();
f.instruction = _instruction;
f.generateCode = [_instruction](
@ -114,9 +114,9 @@ set<YulString> createReservedIdentifiers(langutil::EVMVersion _evmVersion)
{
// TODO remove this in 0.9.0. We allow creating functions or identifiers in Yul with the name
// basefee for VMs before london.
auto baseFeeException = [&](evmasm::Instruction _instr) -> bool
auto baseFeeException = [&](evmasm::InternalInstruction _instr) -> bool
{
return _instr == evmasm::Instruction::BASEFEE && _evmVersion < langutil::EVMVersion::london();
return _instr == evmasm::InternalInstruction::BASEFEE && _evmVersion < langutil::EVMVersion::london();
};
// TODO remove this in 0.9.0. We allow creating functions or identifiers in Yul with the name
// prevrandao for VMs before paris.
@ -162,12 +162,12 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
instruction = evmasm::InternalInstruction::DIFFICULTY;
if (
!evmasm::isDupInstruction(opcode) &&
!evmasm::isSwapInstruction(opcode) &&
!evmasm::isPushInstruction(opcode) &&
opcode != evmasm::Instruction::JUMP &&
opcode != evmasm::Instruction::JUMPI &&
opcode != evmasm::Instruction::JUMPDEST &&
!evmasm::isDupInstruction(instruction) &&
!evmasm::isSwapInstruction(instruction) &&
!evmasm::isPushInstruction(instruction) &&
instruction != evmasm::InternalInstruction::JUMP &&
instruction != evmasm::InternalInstruction::JUMPI &&
instruction != evmasm::InternalInstruction::JUMPDEST &&
_evmVersion.hasInstruction(instruction)
)
builtins.emplace(createEVMFunction(name, instruction));
@ -256,7 +256,7 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
AbstractAssembly& _assembly,
BuiltinContext&
) {
_assembly.appendInstruction(evmasm::Instruction::CODECOPY);
_assembly.appendInstruction(evmasm::InternalInstruction::CODECOPY);
}
));
builtins.emplace(createFunction(
@ -352,7 +352,7 @@ EVMDialect const& EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion _
return *dialects[_version];
}
SideEffects EVMDialect::sideEffectsOfInstruction(evmasm::Instruction _instruction)
SideEffects EVMDialect::sideEffectsOfInstruction(evmasm::InternalInstruction _instruction)
{
auto translate = [](evmasm::SemanticInformation::Effect _e) -> SideEffects::Effect
{
@ -465,11 +465,11 @@ EVMDialectTyped::EVMDialectTyped(langutil::EVMVersion _evmVersion, bool _objectA
// TODO this should use a Panic.
// A value larger than 1 causes an invalid instruction.
_assembly.appendConstant(2);
_assembly.appendInstruction(evmasm::Instruction::DUP2);
_assembly.appendInstruction(evmasm::Instruction::LT);
_assembly.appendInstruction(evmasm::InternalInstruction::DUP2);
_assembly.appendInstruction(evmasm::InternalInstruction::LT);
AbstractAssembly::LabelID inRange = _assembly.newLabelId();
_assembly.appendJumpToIf(inRange);
_assembly.appendInstruction(evmasm::Instruction::INVALID);
_assembly.appendInstruction(evmasm::InternalInstruction::INVALID);
_assembly.appendLabel(inRange);
}));
m_functions["u256_to_bool"_yulstring].parameters = {"u256"_yulstring};

View File

@ -50,7 +50,7 @@ struct BuiltinContext
struct BuiltinFunctionForEVM: public BuiltinFunction
{
std::optional<evmasm::Instruction> instruction;
std::optional<evmasm::InternalInstruction> instruction;
/// Function to generate code for the given function call and append it to the abstract
/// assembly. Expects all non-literal arguments of the call to be on stack in reverse order
/// (i.e. right-most argument pushed first).
@ -91,7 +91,7 @@ struct EVMDialect: public Dialect
bool providesObjectAccess() const { return m_objectAccess; }
static SideEffects sideEffectsOfInstruction(evmasm::Instruction _instruction);
static SideEffects sideEffectsOfInstruction(evmasm::InternalInstruction _instruction);
protected:
BuiltinFunctionForEVM const* verbatimFunction(size_t _arguments, size_t _returnVariables) const;

View File

@ -41,7 +41,7 @@ bigint GasMeter::costs(Expression const& _expression) const
return combineCosts(GasMeterVisitor::costs(_expression, m_dialect, m_isCreation));
}
bigint GasMeter::instructionCosts(evmasm::Instruction _instruction) const
bigint GasMeter::instructionCosts(evmasm::InternalInstruction _instruction) const
{
return combineCosts(GasMeterVisitor::instructionCosts(_instruction, m_dialect, m_isCreation));
}
@ -64,7 +64,7 @@ pair<bigint, bigint> GasMeterVisitor::costs(
}
pair<bigint, bigint> GasMeterVisitor::instructionCosts(
evmasm::Instruction _instruction,
evmasm::InternalInstruction _instruction,
EVMDialect const& _dialect,
bool _isCreation
)
@ -88,7 +88,7 @@ void GasMeterVisitor::operator()(FunctionCall const& _funCall)
void GasMeterVisitor::operator()(Literal const& _lit)
{
m_runGas += evmasm::GasMeter::runGas(evmasm::Instruction::PUSH1);
m_runGas += evmasm::GasMeter::runGas(evmasm::InternalInstruction::PUSH1);
m_dataGas +=
singleByteDataGas() +
evmasm::GasMeter::dataGas(
@ -100,7 +100,7 @@ void GasMeterVisitor::operator()(Literal const& _lit)
void GasMeterVisitor::operator()(Identifier const&)
{
m_runGas += evmasm::GasMeter::runGas(evmasm::Instruction::DUP1);
m_runGas += evmasm::GasMeter::runGas(evmasm::InternalInstruction::DUP1);
m_dataGas += singleByteDataGas();
}
@ -112,11 +112,11 @@ bigint GasMeterVisitor::singleByteDataGas() const
return evmasm::GasCosts::createDataGas;
}
void GasMeterVisitor::instructionCostsInternal(evmasm::Instruction _instruction)
void GasMeterVisitor::instructionCostsInternal(evmasm::InternalInstruction _instruction)
{
if (_instruction == evmasm::Instruction::EXP)
if (_instruction == evmasm::InternalInstruction::EXP)
m_runGas += evmasm::GasCosts::expGas + evmasm::GasCosts::expByteGas(m_dialect.evmVersion());
else if (_instruction == evmasm::Instruction::KECCAK256)
else if (_instruction == evmasm::InternalInstruction::KECCAK256)
// Assumes that Keccak-256 is computed on a single word (rounded up).
m_runGas += evmasm::GasCosts::keccak256Gas + evmasm::GasCosts::keccak256WordGas;
else

View File

@ -53,7 +53,7 @@ public:
bigint costs(Expression const& _expression) const;
/// @returns the combined costs of deploying and running the instruction, not including
/// the costs for its arguments.
bigint instructionCosts(evmasm::Instruction _instruction) const;
bigint instructionCosts(evmasm::InternalInstruction _instruction) const;
private:
bigint combineCosts(std::pair<bigint, bigint> _costs) const;
@ -73,7 +73,7 @@ public:
);
static std::pair<bigint, bigint> instructionCosts(
evmasm::Instruction _instruction,
evmasm::InternalInstruction _instruction,
EVMDialect const& _dialect,
bool _isCreation = false
);
@ -93,7 +93,7 @@ private:
/// Computes the cost of storing and executing the single instruction (excluding its arguments).
/// For EXP, it assumes that the exponent is at most 255.
/// Does not work particularly exact for anything apart from arithmetic.
void instructionCostsInternal(evmasm::Instruction _instruction);
void instructionCostsInternal(evmasm::InternalInstruction _instruction);
EVMDialect const& m_dialect;
bool m_isCreation = false;

View File

@ -59,7 +59,7 @@ void EthAssemblyAdapter::setStackHeight(int height)
m_assembly.setDeposit(height);
}
void EthAssemblyAdapter::appendInstruction(evmasm::Instruction _instruction)
void EthAssemblyAdapter::appendInstruction(evmasm::InternalInstruction _instruction)
{
m_assembly.append(_instruction);
}
@ -101,7 +101,7 @@ void EthAssemblyAdapter::appendVerbatim(bytes _data, size_t _arguments, size_t _
void EthAssemblyAdapter::appendJump(int _stackDiffAfter, JumpType _jumpType)
{
appendJumpInstruction(evmasm::Instruction::JUMP, _jumpType);
appendJumpInstruction(evmasm::InternalInstruction::JUMP, _jumpType);
m_assembly.adjustDeposit(_stackDiffAfter);
}
@ -114,7 +114,7 @@ void EthAssemblyAdapter::appendJumpTo(LabelID _labelId, int _stackDiffAfter, Jum
void EthAssemblyAdapter::appendJumpToIf(LabelID _labelId, JumpType _jumpType)
{
appendLabelReference(_labelId);
appendJumpInstruction(evmasm::Instruction::JUMPI, _jumpType);
appendJumpInstruction(evmasm::InternalInstruction::JUMPI, _jumpType);
}
void EthAssemblyAdapter::appendAssemblySize()
@ -188,9 +188,9 @@ EthAssemblyAdapter::LabelID EthAssemblyAdapter::assemblyTagToIdentifier(evmasm::
return LabelID(id);
}
void EthAssemblyAdapter::appendJumpInstruction(evmasm::Instruction _instruction, JumpType _jumpType)
void EthAssemblyAdapter::appendJumpInstruction(evmasm::InternalInstruction _instruction, JumpType _jumpType)
{
yulAssert(_instruction == evmasm::Instruction::JUMP || _instruction == evmasm::Instruction::JUMPI, "");
yulAssert(_instruction == evmasm::InternalInstruction::JUMP || _instruction == evmasm::InternalInstruction::JUMPI, "");
evmasm::AssemblyItem jump(_instruction);
switch (_jumpType)
{

View File

@ -43,7 +43,7 @@ public:
void setSourceLocation(langutil::SourceLocation const& _location) override;
int stackHeight() const override;
void setStackHeight(int height) override;
void appendInstruction(evmasm::Instruction _instruction) override;
void appendInstruction(evmasm::InternalInstruction _instruction) override;
void appendConstant(u256 const& _constant) override;
void appendLabel(LabelID _labelId) override;
void appendLabelReference(LabelID _labelId) override;
@ -69,7 +69,7 @@ public:
private:
static LabelID assemblyTagToIdentifier(evmasm::AssemblyItem const& _tag);
void appendJumpInstruction(evmasm::Instruction _instruction, JumpType _jumpType);
void appendJumpInstruction(evmasm::InternalInstruction _instruction, JumpType _jumpType);
evmasm::Assembly& m_assembly;
std::map<SubID, u256> m_dataHashBySubId;

View File

@ -35,7 +35,7 @@ using namespace solidity::util;
using namespace solidity::langutil;
void NoOutputAssembly::appendInstruction(evmasm::Instruction _instr)
void NoOutputAssembly::appendInstruction(evmasm::InternalInstruction _instr)
{
m_stackHeight += instructionInfo(_instr).ret - instructionInfo(_instr).args;
}
@ -47,7 +47,7 @@ void NoOutputAssembly::appendConstant(u256 const&)
void NoOutputAssembly::appendLabel(LabelID)
{
appendInstruction(evmasm::Instruction::JUMPDEST);
appendInstruction(evmasm::InternalInstruction::JUMPDEST);
}
void NoOutputAssembly::appendLabelReference(LabelID)
@ -77,7 +77,7 @@ void NoOutputAssembly::appendVerbatim(bytes, size_t _arguments, size_t _returnVa
void NoOutputAssembly::appendJump(int _stackDiffAfter, JumpType)
{
appendInstruction(evmasm::Instruction::JUMP);
appendInstruction(evmasm::InternalInstruction::JUMP);
m_stackHeight += _stackDiffAfter;
}
@ -90,12 +90,12 @@ void NoOutputAssembly::appendJumpTo(LabelID _labelId, int _stackDiffAfter, JumpT
void NoOutputAssembly::appendJumpToIf(LabelID _labelId, JumpType)
{
appendLabelReference(_labelId);
appendInstruction(evmasm::Instruction::JUMPI);
appendInstruction(evmasm::InternalInstruction::JUMPI);
}
void NoOutputAssembly::appendAssemblySize()
{
appendInstruction(evmasm::Instruction::PUSH1);
appendInstruction(evmasm::InternalInstruction::PUSH1);
}
pair<shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> NoOutputAssembly::createSubAssembly(bool, std::string)
@ -106,12 +106,12 @@ pair<shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> NoOutputAssembly::cr
void NoOutputAssembly::appendDataOffset(std::vector<AbstractAssembly::SubID> const&)
{
appendInstruction(evmasm::Instruction::PUSH1);
appendInstruction(evmasm::InternalInstruction::PUSH1);
}
void NoOutputAssembly::appendDataSize(std::vector<AbstractAssembly::SubID> const&)
{
appendInstruction(evmasm::Instruction::PUSH1);
appendInstruction(evmasm::InternalInstruction::PUSH1);
}
AbstractAssembly::SubID NoOutputAssembly::appendData(bytes const&)
@ -140,7 +140,7 @@ NoOutputEVMDialect::NoOutputEVMDialect(EVMDialect const& _copyFrom):
{
for (size_t i: ranges::views::iota(0u, _call.arguments.size()))
if (!fun.second.literalArgument(i))
_assembly.appendInstruction(evmasm::Instruction::POP);
_assembly.appendInstruction(evmasm::InternalInstruction::POP);
for (size_t i = 0; i < returns; i++)
_assembly.appendConstant(u256(0));

View File

@ -51,7 +51,7 @@ public:
void setSourceLocation(langutil::SourceLocation const&) override {}
int stackHeight() const override { return m_stackHeight; }
void setStackHeight(int height) override { m_stackHeight = height; }
void appendInstruction(evmasm::Instruction _instruction) override;
void appendInstruction(evmasm::InternalInstruction _instruction) override;
void appendConstant(u256 const& _constant) override;
void appendLabel(LabelID _labelId) override;
void appendLabelReference(LabelID _labelId) override;

View File

@ -345,14 +345,14 @@ void OptimizedEVMCodeTransform::createStackLayout(std::shared_ptr<DebugData cons
[&](JunkSlot const&)
{
// Note: this will always be popped, so we can push anything.
m_assembly.appendInstruction(evmasm::Instruction::CODESIZE);
m_assembly.appendInstruction(evmasm::InternalInstruction::CODESIZE);
}
}, _slot);
},
// Pop callback.
[&]()
{
m_assembly.appendInstruction(evmasm::Instruction::POP);
m_assembly.appendInstruction(evmasm::InternalInstruction::POP);
}
);
yulAssert(m_assembly.stackHeight() == static_cast<int>(m_stack.size()), "");
@ -407,7 +407,7 @@ void OptimizedEVMCodeTransform::operator()(CFG::BasicBlock const& _block)
std::visit(util::GenericVisitor{
[&](CFG::BasicBlock::MainExit const&)
{
m_assembly.appendInstruction(evmasm::Instruction::STOP);
m_assembly.appendInstruction(evmasm::InternalInstruction::STOP);
},
[&](CFG::BasicBlock::Jump const& _jump)
{

View File

@ -763,7 +763,7 @@ void StackLayoutGenerator::fillInJunk(CFG::BasicBlock const& _block)
opGas += 1000;
}
};
auto pop = [&]() { opGas += evmasm::GasMeter::runGas(evmasm::Instruction::POP); };
auto pop = [&]() { opGas += evmasm::GasMeter::runGas(evmasm::InternalInstruction::POP); };
createStackLayout(_source, _target, swap, dupOrPush, pop);
return opGas;
};

View File

@ -50,7 +50,7 @@ void ExpressionSimplifier::visit(Expression& _expression)
_expression = match->action().toExpression(debugDataOf(_expression));
if (auto* functionCall = get_if<FunctionCall>(&_expression))
if (optional<evmasm::Instruction> instruction = toEVMInstruction(m_dialect, functionCall->functionName.name))
if (optional<evmasm::InternalInstruction> instruction = toEVMInstruction(m_dialect, functionCall->functionName.name))
for (auto op: evmasm::SemanticInformation::readWriteOperations(*instruction))
if (op.startParameter && op.lengthParameter)
{

View File

@ -178,7 +178,7 @@ void CodeCost::visit(Expression const& _expression)
ASTWalker::visit(_expression);
}
void CodeCost::addInstructionCost(evmasm::Instruction _instruction)
void CodeCost::addInstructionCost(evmasm::InternalInstruction _instruction)
{
evmasm::Tier gasPriceTier = evmasm::instructionInfo(_instruction).gasPriceTier;
if (gasPriceTier < evmasm::Tier::VeryLow)

View File

@ -124,7 +124,7 @@ private:
void visit(Expression const& _expression) override;
private:
void addInstructionCost(evmasm::Instruction _instruction);
void addInstructionCost(evmasm::InternalInstruction _instruction);
Dialect const& m_dialect;
size_t m_cost = 0;

View File

@ -50,7 +50,7 @@ bool yul::isRestrictedIdentifier(Dialect const& _dialect, YulString const& _iden
return _identifier.empty() || TokenTraits::isYulKeyword(_identifier.str()) || _dialect.reservedIdentifier(_identifier);
}
optional<evmasm::Instruction> yul::toEVMInstruction(Dialect const& _dialect, YulString const& _name)
optional<evmasm::InternalInstruction> yul::toEVMInstruction(Dialect const& _dialect, YulString const& _name)
{
if (auto const* dialect = dynamic_cast<EVMDialect const*>(&_dialect))
if (BuiltinFunctionForEVM const* builtin = dialect->builtin(_name))

View File

@ -31,7 +31,7 @@
namespace solidity::evmasm
{
enum class Instruction: uint8_t;
enum class InternalInstruction: uint8_t;
}
namespace solidity::yul
@ -47,7 +47,7 @@ void removeEmptyBlocks(Block& _block);
bool isRestrictedIdentifier(Dialect const& _dialect, YulString const& _identifier);
/// Helper function that returns the instruction, if the `_name` is a BuiltinFunction
std::optional<evmasm::Instruction> toEVMInstruction(Dialect const& _dialect, YulString const& _name);
std::optional<evmasm::InternalInstruction> toEVMInstruction(Dialect const& _dialect, YulString const& _name);
class StatementRemover: public ASTModifier
{

View File

@ -109,7 +109,7 @@ ReasoningBasedSimplifier::ReasoningBasedSimplifier(
smtutil::Expression ReasoningBasedSimplifier::encodeEVMBuiltin(
evmasm::Instruction _instruction,
evmasm::InternalInstruction _instruction,
vector<yul::Expression> const& _arguments
)
{
@ -119,19 +119,19 @@ smtutil::Expression ReasoningBasedSimplifier::encodeEVMBuiltin(
);
switch (_instruction)
{
case evmasm::Instruction::ADD:
case evmasm::InternalInstruction::ADD:
return wrap(arguments.at(0) + arguments.at(1));
case evmasm::Instruction::MUL:
case evmasm::InternalInstruction::MUL:
return wrap(arguments.at(0) * arguments.at(1));
case evmasm::Instruction::SUB:
case evmasm::InternalInstruction::SUB:
return wrap(arguments.at(0) - arguments.at(1));
case evmasm::Instruction::DIV:
case evmasm::InternalInstruction::DIV:
return smtutil::Expression::ite(
arguments.at(1) == constantValue(0),
constantValue(0),
arguments.at(0) / arguments.at(1)
);
case evmasm::Instruction::SDIV:
case evmasm::InternalInstruction::SDIV:
return smtutil::Expression::ite(
arguments.at(1) == constantValue(0),
constantValue(0),
@ -143,13 +143,13 @@ smtutil::Expression ReasoningBasedSimplifier::encodeEVMBuiltin(
twosComplementToSigned(arguments.at(1))
))
);
case evmasm::Instruction::MOD:
case evmasm::InternalInstruction::MOD:
return smtutil::Expression::ite(
arguments.at(1) == constantValue(0),
constantValue(0),
arguments.at(0) % arguments.at(1)
);
case evmasm::Instruction::SMOD:
case evmasm::InternalInstruction::SMOD:
return smtutil::Expression::ite(
arguments.at(1) == constantValue(0),
constantValue(0),
@ -158,61 +158,61 @@ smtutil::Expression ReasoningBasedSimplifier::encodeEVMBuiltin(
twosComplementToSigned(arguments.at(1))
))
);
case evmasm::Instruction::LT:
case evmasm::InternalInstruction::LT:
return booleanValue(arguments.at(0) < arguments.at(1));
case evmasm::Instruction::SLT:
case evmasm::InternalInstruction::SLT:
return booleanValue(twosComplementToSigned(arguments.at(0)) < twosComplementToSigned(arguments.at(1)));
case evmasm::Instruction::GT:
case evmasm::InternalInstruction::GT:
return booleanValue(arguments.at(0) > arguments.at(1));
case evmasm::Instruction::SGT:
case evmasm::InternalInstruction::SGT:
return booleanValue(twosComplementToSigned(arguments.at(0)) > twosComplementToSigned(arguments.at(1)));
case evmasm::Instruction::EQ:
case evmasm::InternalInstruction::EQ:
return booleanValue(arguments.at(0) == arguments.at(1));
case evmasm::Instruction::ISZERO:
case evmasm::InternalInstruction::ISZERO:
return booleanValue(arguments.at(0) == constantValue(0));
case evmasm::Instruction::AND:
case evmasm::InternalInstruction::AND:
return smtutil::Expression::ite(
(arguments.at(0) == 0 || arguments.at(0) == 1) &&
(arguments.at(1) == 0 || arguments.at(1) == 1),
booleanValue(arguments.at(0) == 1 && arguments.at(1) == 1),
bv2int(int2bv(arguments.at(0)) & int2bv(arguments.at(1)))
);
case evmasm::Instruction::OR:
case evmasm::InternalInstruction::OR:
return smtutil::Expression::ite(
(arguments.at(0) == 0 || arguments.at(0) == 1) &&
(arguments.at(1) == 0 || arguments.at(1) == 1),
booleanValue(arguments.at(0) == 1 || arguments.at(1) == 1),
bv2int(int2bv(arguments.at(0)) | int2bv(arguments.at(1)))
);
case evmasm::Instruction::XOR:
case evmasm::InternalInstruction::XOR:
return bv2int(int2bv(arguments.at(0)) ^ int2bv(arguments.at(1)));
case evmasm::Instruction::NOT:
case evmasm::InternalInstruction::NOT:
return smtutil::Expression(u256(-1)) - arguments.at(0);
case evmasm::Instruction::SHL:
case evmasm::InternalInstruction::SHL:
return smtutil::Expression::ite(
arguments.at(0) > 255,
constantValue(0),
bv2int(int2bv(arguments.at(1)) << int2bv(arguments.at(0)))
);
case evmasm::Instruction::SHR:
case evmasm::InternalInstruction::SHR:
return smtutil::Expression::ite(
arguments.at(0) > 255,
constantValue(0),
bv2int(int2bv(arguments.at(1)) >> int2bv(arguments.at(0)))
);
case evmasm::Instruction::SAR:
case evmasm::InternalInstruction::SAR:
return smtutil::Expression::ite(
arguments.at(0) > 255,
constantValue(0),
bv2int(smtutil::Expression::ashr(int2bv(arguments.at(1)), int2bv(arguments.at(0))))
);
case evmasm::Instruction::ADDMOD:
case evmasm::InternalInstruction::ADDMOD:
return smtutil::Expression::ite(
arguments.at(2) == constantValue(0),
constantValue(0),
(arguments.at(0) + arguments.at(1)) % arguments.at(2)
);
case evmasm::Instruction::MULMOD:
case evmasm::InternalInstruction::MULMOD:
return smtutil::Expression::ite(
arguments.at(2) == constantValue(0),
constantValue(0),

View File

@ -65,7 +65,7 @@ private:
);
smtutil::Expression encodeEVMBuiltin(
evmasm::Instruction _instruction,
evmasm::InternalInstruction _instruction,
std::vector<Expression> const& _arguments
) override;

View File

@ -58,7 +58,7 @@ protected:
/// The encoding for a builtin. The type of encoding determines what we are
/// solving for.
virtual smtutil::Expression encodeEVMBuiltin(
evmasm::Instruction _instruction,
evmasm::InternalInstruction _instruction,
std::vector<Expression> const& _arguments
) = 0;

View File

@ -72,10 +72,10 @@ SimplificationRules::Rule const* SimplificationRules::findFirstMatch(
bool SimplificationRules::isInitialized() const
{
return !m_rules[uint8_t(evmasm::Instruction::ADD)].empty();
return !m_rules[uint8_t(evmasm::InternalInstruction::ADD)].empty();
}
std::optional<std::pair<evmasm::Instruction, vector<Expression> const*>>
std::optional<std::pair<evmasm::InternalInstruction, vector<Expression> const*>>
SimplificationRules::instructionAndArguments(Dialect const& _dialect, Expression const& _expr)
{
if (holds_alternative<FunctionCall>(_expr))
@ -122,7 +122,7 @@ SimplificationRules::SimplificationRules(std::optional<langutil::EVMVersion> _ev
assertThrow(isInitialized(), OptimizerException, "Rule list not properly initialized.");
}
yul::Pattern::Pattern(evmasm::Instruction _instruction, initializer_list<Pattern> _arguments):
yul::Pattern::Pattern(evmasm::InternalInstruction _instruction, initializer_list<Pattern> _arguments):
m_kind(PatternKind::Operation),
m_instruction(_instruction),
m_arguments(_arguments)
@ -229,7 +229,7 @@ bool Pattern::matches(
return true;
}
evmasm::Instruction Pattern::instruction() const
evmasm::InternalInstruction Pattern::instruction() const
{
assertThrow(m_kind == PatternKind::Operation, OptimizerException, "");
return m_instruction;

View File

@ -69,7 +69,7 @@ public:
/// by the constructor, but we had some issues with static initialization.
bool isInitialized() const;
static std::optional<std::pair<evmasm::Instruction, std::vector<Expression> const*>>
static std::optional<std::pair<evmasm::InternalInstruction, std::vector<Expression> const*>>
instructionAndArguments(Dialect const& _dialect, Expression const& _expr);
private:
@ -110,7 +110,7 @@ public:
// Matches a specific constant value.
Pattern(u256 const& _value): m_kind(PatternKind::Constant), m_data(std::make_shared<u256>(_value)) {}
// Matches a given instruction with given arguments
Pattern(evmasm::Instruction _instruction, std::initializer_list<Pattern> _arguments = {});
Pattern(evmasm::InternalInstruction _instruction, std::initializer_list<Pattern> _arguments = {});
/// Sets this pattern to be part of the match group with the identifier @a _group.
/// Inside one rule, all patterns in the same match group have to match expressions from the
/// same expression equivalence class.
@ -127,7 +127,7 @@ public:
/// @returns the data of the matched expression if this pattern is part of a match group.
u256 d() const;
evmasm::Instruction instruction() const;
evmasm::InternalInstruction instruction() const;
/// Turns this pattern into an actual expression. Should only be called
/// for patterns resulting from an action, i.e. with match groups assigned.
@ -137,7 +137,7 @@ private:
Expression const& matchGroupValue() const;
PatternKind m_kind = PatternKind::Any;
evmasm::Instruction m_instruction; ///< Only valid if m_kind is Operation
evmasm::InternalInstruction m_instruction; ///< Only valid if m_kind is Operation
std::shared_ptr<u256> m_data; ///< Only valid if m_kind is Constant
std::vector<Pattern> m_arguments;
unsigned m_matchGroup = 0;

View File

@ -129,7 +129,7 @@ void UnusedStoreEliminator::operator()(Leave const&)
void UnusedStoreEliminator::visit(Statement const& _statement)
{
using evmasm::Instruction;
using evmasm::InternalInstruction;
UnusedStoreBase::visit(_statement);
@ -139,7 +139,7 @@ void UnusedStoreEliminator::visit(Statement const& _statement)
FunctionCall const* funCall = get_if<FunctionCall>(&exprStatement->expression);
yulAssert(funCall);
optional<Instruction> instruction = toEVMInstruction(m_dialect, funCall->functionName.name);
optional<InternalInstruction> instruction = toEVMInstruction(m_dialect, funCall->functionName.name);
if (!instruction)
return;
@ -152,14 +152,14 @@ void UnusedStoreEliminator::visit(Statement const& _statement)
// both by querying a combination of semantic information and by listing the instructions.
// This way the assert below should be triggered on any change.
using evmasm::SemanticInformation;
bool isStorageWrite = (*instruction == Instruction::SSTORE);
bool isStorageWrite = (*instruction == InternalInstruction::SSTORE);
bool isMemoryWrite =
*instruction == Instruction::EXTCODECOPY ||
*instruction == Instruction::CODECOPY ||
*instruction == Instruction::CALLDATACOPY ||
*instruction == Instruction::RETURNDATACOPY ||
*instruction == Instruction::MSTORE ||
*instruction == Instruction::MSTORE8;
*instruction == InternalInstruction::EXTCODECOPY ||
*instruction == InternalInstruction::CODECOPY ||
*instruction == InternalInstruction::CALLDATACOPY ||
*instruction == InternalInstruction::RETURNDATACOPY ||
*instruction == InternalInstruction::MSTORE ||
*instruction == InternalInstruction::MSTORE8;
bool isCandidateForRemoval =
SemanticInformation::otherState(*instruction) != SemanticInformation::Write && (
SemanticInformation::storage(*instruction) == SemanticInformation::Write ||
@ -169,7 +169,7 @@ void UnusedStoreEliminator::visit(Statement const& _statement)
if (isCandidateForRemoval)
{
State initialState = State::Undecided;
if (*instruction == Instruction::RETURNDATACOPY)
if (*instruction == InternalInstruction::RETURNDATACOPY)
{
initialState = State::Used;
auto startOffset = identifierNameIfSSA(funCall->arguments.at(1));
@ -181,7 +181,7 @@ void UnusedStoreEliminator::visit(Statement const& _statement)
if (
knowledge.knownToBeZero(*startOffset) &&
lengthCall &&
toEVMInstruction(m_dialect, lengthCall->functionName.name) == Instruction::RETURNDATASIZE
toEVMInstruction(m_dialect, lengthCall->functionName.name) == InternalInstruction::RETURNDATASIZE
)
initialState = State::Undecided;
}
@ -203,7 +203,7 @@ vector<UnusedStoreEliminator::Operation> UnusedStoreEliminator::operationsFromFu
FunctionCall const& _functionCall
) const
{
using evmasm::Instruction;
using evmasm::InternalInstruction;
YulString functionName = _functionCall.functionName.name;
SideEffects sideEffects;
@ -212,7 +212,7 @@ vector<UnusedStoreEliminator::Operation> UnusedStoreEliminator::operationsFromFu
else
sideEffects = m_functionSideEffects.at(functionName);
optional<Instruction> instruction = toEVMInstruction(m_dialect, functionName);
optional<InternalInstruction> instruction = toEVMInstruction(m_dialect, functionName);
if (!instruction)
{
vector<Operation> result;

View File

@ -74,12 +74,12 @@ BOOST_AUTO_TEST_CASE(all_assembly_items)
// PushImmutable
_subAsm.appendImmutable("someImmutable");
_subAsm.append(AssemblyItem(PushTag, 0));
_subAsm.append(Instruction::INVALID);
_subAsm.append(InternalInstruction::INVALID);
shared_ptr<Assembly> _subAsmPtr = make_shared<Assembly>(_subAsm);
_verbatimAsm.appendVerbatim({0xff,0xff}, 0, 0);
_verbatimAsm.appendVerbatim({0x74, 0x65, 0x73, 0x74}, 0, 1);
_verbatimAsm.append(Instruction::MSTORE);
_verbatimAsm.append(InternalInstruction::MSTORE);
shared_ptr<Assembly> _verbatimAsmPtr = make_shared<Assembly>(_verbatimAsm);
// Tag
@ -89,7 +89,7 @@ BOOST_AUTO_TEST_CASE(all_assembly_items)
_assembly.append(u256(1));
_assembly.append(u256(2));
// Push
auto keccak256 = AssemblyItem(Instruction::KECCAK256);
auto keccak256 = AssemblyItem(InternalInstruction::KECCAK256);
_assembly.m_currentModifierDepth = 1;
_assembly.append(keccak256);
_assembly.m_currentModifierDepth = 0;
@ -117,7 +117,7 @@ BOOST_AUTO_TEST_CASE(all_assembly_items)
_assembly.append(u256(2));
_assembly.appendImmutableAssignment("someImmutable");
// Operation
_assembly.append(Instruction::STOP);
_assembly.append(InternalInstruction::STOP);
_assembly.appendToAuxiliaryData(bytes{0x42, 0x66});
_assembly.appendToAuxiliaryData(bytes{0xee, 0xaa});

File diff suppressed because it is too large Load Diff

View File

@ -197,7 +197,7 @@ BOOST_AUTO_TEST_CASE(literal_true)
)";
bytes code = compileFirstExpression(sourceCode);
bytes expectation({uint8_t(Instruction::PUSH1), 0x1});
bytes expectation({uint8_t(InternalInstruction::PUSH1), 0x1});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
@ -210,7 +210,7 @@ BOOST_AUTO_TEST_CASE(literal_false)
)";
bytes code = compileFirstExpression(sourceCode);
bytes expectation({uint8_t(Instruction::PUSH1), 0x0});
bytes expectation({uint8_t(InternalInstruction::PUSH1), 0x0});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
@ -223,7 +223,7 @@ BOOST_AUTO_TEST_CASE(int_literal)
)";
bytes code = compileFirstExpression(sourceCode);
bytes expectation({uint8_t(Instruction::PUSH10), 0x12, 0x34, 0x56, 0x78, 0x90,
bytes expectation({uint8_t(InternalInstruction::PUSH10), 0x12, 0x34, 0x56, 0x78, 0x90,
0x12, 0x34, 0x56, 0x78, 0x90});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
@ -239,7 +239,7 @@ BOOST_AUTO_TEST_CASE(int_with_wei_ether_subdenomination)
)";
bytes code = compileFirstExpression(sourceCode);
bytes expectation({uint8_t(Instruction::PUSH1), 0x1});
bytes expectation({uint8_t(InternalInstruction::PUSH1), 0x1});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
@ -254,7 +254,7 @@ BOOST_AUTO_TEST_CASE(int_with_gwei_ether_subdenomination)
)";
bytes code = compileFirstExpression(sourceCode);
bytes expectation({uint8_t(Instruction::PUSH4), 0x3b, 0x9a, 0xca, 0x00});
bytes expectation({uint8_t(InternalInstruction::PUSH4), 0x3b, 0x9a, 0xca, 0x00});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
@ -269,7 +269,7 @@ BOOST_AUTO_TEST_CASE(int_with_ether_ether_subdenomination)
)";
bytes code = compileFirstExpression(sourceCode);
bytes expectation({uint8_t(Instruction::PUSH8), 0xd, 0xe0, 0xb6, 0xb3, 0xa7, 0x64, 0x00, 0x00});
bytes expectation({uint8_t(InternalInstruction::PUSH8), 0xd, 0xe0, 0xb6, 0xb3, 0xa7, 0x64, 0x00, 0x00});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
@ -285,22 +285,22 @@ BOOST_AUTO_TEST_CASE(comparison)
bytes expectation;
if (solidity::test::CommonOptions::get().optimize)
expectation = {
uint8_t(Instruction::PUSH2), 0x11, 0xaa,
uint8_t(Instruction::PUSH2), 0x10, 0xaa,
uint8_t(Instruction::LT), uint8_t(Instruction::ISZERO), uint8_t(Instruction::ISZERO),
uint8_t(Instruction::PUSH1), 0x1,
uint8_t(Instruction::ISZERO), uint8_t(Instruction::ISZERO),
uint8_t(Instruction::EQ),
uint8_t(Instruction::ISZERO)
uint8_t(InternalInstruction::PUSH2), 0x11, 0xaa,
uint8_t(InternalInstruction::PUSH2), 0x10, 0xaa,
uint8_t(InternalInstruction::LT), uint8_t(InternalInstruction::ISZERO), uint8_t(InternalInstruction::ISZERO),
uint8_t(InternalInstruction::PUSH1), 0x1,
uint8_t(InternalInstruction::ISZERO), uint8_t(InternalInstruction::ISZERO),
uint8_t(InternalInstruction::EQ),
uint8_t(InternalInstruction::ISZERO)
};
else
expectation = {
uint8_t(Instruction::PUSH1), 0x1, uint8_t(Instruction::ISZERO), uint8_t(Instruction::ISZERO),
uint8_t(Instruction::PUSH2), 0x11, 0xaa,
uint8_t(Instruction::PUSH2), 0x10, 0xaa,
uint8_t(Instruction::LT), uint8_t(Instruction::ISZERO), uint8_t(Instruction::ISZERO),
uint8_t(Instruction::EQ),
uint8_t(Instruction::ISZERO)
uint8_t(InternalInstruction::PUSH1), 0x1, uint8_t(InternalInstruction::ISZERO), uint8_t(InternalInstruction::ISZERO),
uint8_t(InternalInstruction::PUSH2), 0x11, 0xaa,
uint8_t(InternalInstruction::PUSH2), 0x10, 0xaa,
uint8_t(InternalInstruction::LT), uint8_t(InternalInstruction::ISZERO), uint8_t(InternalInstruction::ISZERO),
uint8_t(InternalInstruction::EQ),
uint8_t(InternalInstruction::ISZERO)
};
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
@ -315,23 +315,23 @@ BOOST_AUTO_TEST_CASE(short_circuiting)
bytes code = compileFirstExpression(sourceCode);
bytes expectation{
uint8_t(Instruction::PUSH1), 0x12, // 8 + 10
uint8_t(Instruction::PUSH1), 0x4,
uint8_t(Instruction::GT),
uint8_t(Instruction::ISZERO), // after this we have 4 <= 8 + 10
uint8_t(Instruction::DUP1),
uint8_t(Instruction::PUSH1), 0x11,
uint8_t(Instruction::JUMPI), // short-circuit if it is true
uint8_t(Instruction::POP),
uint8_t(Instruction::PUSH1), 0x2,
uint8_t(Instruction::PUSH1), 0x9,
uint8_t(Instruction::EQ),
uint8_t(Instruction::ISZERO), // after this we have 9 != 2
uint8_t(Instruction::JUMPDEST),
uint8_t(Instruction::ISZERO), uint8_t(Instruction::ISZERO),
uint8_t(Instruction::PUSH1), 0x1, uint8_t(Instruction::ISZERO), uint8_t(Instruction::ISZERO),
uint8_t(Instruction::EQ),
uint8_t(Instruction::ISZERO)
uint8_t(InternalInstruction::PUSH1), 0x12, // 8 + 10
uint8_t(InternalInstruction::PUSH1), 0x4,
uint8_t(InternalInstruction::GT),
uint8_t(InternalInstruction::ISZERO), // after this we have 4 <= 8 + 10
uint8_t(InternalInstruction::DUP1),
uint8_t(InternalInstruction::PUSH1), 0x11,
uint8_t(InternalInstruction::JUMPI), // short-circuit if it is true
uint8_t(InternalInstruction::POP),
uint8_t(InternalInstruction::PUSH1), 0x2,
uint8_t(InternalInstruction::PUSH1), 0x9,
uint8_t(InternalInstruction::EQ),
uint8_t(InternalInstruction::ISZERO), // after this we have 9 != 2
uint8_t(InternalInstruction::JUMPDEST),
uint8_t(InternalInstruction::ISZERO), uint8_t(InternalInstruction::ISZERO),
uint8_t(InternalInstruction::PUSH1), 0x1, uint8_t(InternalInstruction::ISZERO), uint8_t(InternalInstruction::ISZERO),
uint8_t(InternalInstruction::EQ),
uint8_t(InternalInstruction::ISZERO)
};
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
@ -347,108 +347,108 @@ BOOST_AUTO_TEST_CASE(arithmetic)
bytes panic =
bytes{
uint8_t(Instruction::JUMPDEST),
uint8_t(Instruction::PUSH32)
uint8_t(InternalInstruction::JUMPDEST),
uint8_t(InternalInstruction::PUSH32)
} +
util::fromHex("4E487B7100000000000000000000000000000000000000000000000000000000") +
bytes{
uint8_t(Instruction::PUSH1), 0x0,
uint8_t(Instruction::MSTORE),
uint8_t(Instruction::PUSH1), 0x12,
uint8_t(Instruction::PUSH1), 0x4,
uint8_t(Instruction::MSTORE),
uint8_t(Instruction::PUSH1), 0x24,
uint8_t(Instruction::PUSH1), 0x0,
uint8_t(Instruction::REVERT),
uint8_t(Instruction::JUMPDEST),
uint8_t(Instruction::JUMP),
uint8_t(Instruction::JUMPDEST)
uint8_t(InternalInstruction::PUSH1), 0x0,
uint8_t(InternalInstruction::MSTORE),
uint8_t(InternalInstruction::PUSH1), 0x12,
uint8_t(InternalInstruction::PUSH1), 0x4,
uint8_t(InternalInstruction::MSTORE),
uint8_t(InternalInstruction::PUSH1), 0x24,
uint8_t(InternalInstruction::PUSH1), 0x0,
uint8_t(InternalInstruction::REVERT),
uint8_t(InternalInstruction::JUMPDEST),
uint8_t(InternalInstruction::JUMP),
uint8_t(InternalInstruction::JUMPDEST)
};
bytes expectation;
if (solidity::test::CommonOptions::get().optimize)
expectation = bytes{
uint8_t(Instruction::PUSH1), 0x2,
uint8_t(Instruction::PUSH1), 0x3,
uint8_t(Instruction::PUSH1), 0x5,
uint8_t(Instruction::DUP4),
uint8_t(Instruction::PUSH1), 0x8,
uint8_t(Instruction::XOR),
uint8_t(Instruction::PUSH1), 0x7,
uint8_t(Instruction::AND),
uint8_t(Instruction::PUSH1), 0x6,
uint8_t(Instruction::OR),
uint8_t(Instruction::SUB),
uint8_t(Instruction::PUSH1), 0x4,
uint8_t(Instruction::ADD),
uint8_t(Instruction::DUP2),
uint8_t(Instruction::ISZERO),
uint8_t(Instruction::ISZERO),
uint8_t(Instruction::PUSH1), 0x20,
uint8_t(Instruction::JUMPI),
uint8_t(Instruction::PUSH1), 0x1f,
uint8_t(Instruction::PUSH1), 0x36,
uint8_t(Instruction::JUMP),
uint8_t(Instruction::JUMPDEST),
uint8_t(Instruction::JUMPDEST),
uint8_t(Instruction::MOD),
uint8_t(Instruction::DUP2),
uint8_t(Instruction::ISZERO),
uint8_t(Instruction::ISZERO),
uint8_t(Instruction::PUSH1), 0x2e,
uint8_t(Instruction::JUMPI),
uint8_t(Instruction::PUSH1), 0x2d,
uint8_t(Instruction::PUSH1), 0x36,
uint8_t(Instruction::JUMP),
uint8_t(Instruction::JUMPDEST),
uint8_t(Instruction::JUMPDEST),
uint8_t(Instruction::DIV),
uint8_t(Instruction::PUSH1), 0x1,
uint8_t(Instruction::MUL),
uint8_t(Instruction::PUSH1), 0x67,
uint8_t(Instruction::JUMP)
uint8_t(InternalInstruction::PUSH1), 0x2,
uint8_t(InternalInstruction::PUSH1), 0x3,
uint8_t(InternalInstruction::PUSH1), 0x5,
uint8_t(InternalInstruction::DUP4),
uint8_t(InternalInstruction::PUSH1), 0x8,
uint8_t(InternalInstruction::XOR),
uint8_t(InternalInstruction::PUSH1), 0x7,
uint8_t(InternalInstruction::AND),
uint8_t(InternalInstruction::PUSH1), 0x6,
uint8_t(InternalInstruction::OR),
uint8_t(InternalInstruction::SUB),
uint8_t(InternalInstruction::PUSH1), 0x4,
uint8_t(InternalInstruction::ADD),
uint8_t(InternalInstruction::DUP2),
uint8_t(InternalInstruction::ISZERO),
uint8_t(InternalInstruction::ISZERO),
uint8_t(InternalInstruction::PUSH1), 0x20,
uint8_t(InternalInstruction::JUMPI),
uint8_t(InternalInstruction::PUSH1), 0x1f,
uint8_t(InternalInstruction::PUSH1), 0x36,
uint8_t(InternalInstruction::JUMP),
uint8_t(InternalInstruction::JUMPDEST),
uint8_t(InternalInstruction::JUMPDEST),
uint8_t(InternalInstruction::MOD),
uint8_t(InternalInstruction::DUP2),
uint8_t(InternalInstruction::ISZERO),
uint8_t(InternalInstruction::ISZERO),
uint8_t(InternalInstruction::PUSH1), 0x2e,
uint8_t(InternalInstruction::JUMPI),
uint8_t(InternalInstruction::PUSH1), 0x2d,
uint8_t(InternalInstruction::PUSH1), 0x36,
uint8_t(InternalInstruction::JUMP),
uint8_t(InternalInstruction::JUMPDEST),
uint8_t(InternalInstruction::JUMPDEST),
uint8_t(InternalInstruction::DIV),
uint8_t(InternalInstruction::PUSH1), 0x1,
uint8_t(InternalInstruction::MUL),
uint8_t(InternalInstruction::PUSH1), 0x67,
uint8_t(InternalInstruction::JUMP)
} + panic;
else
expectation = bytes{
uint8_t(Instruction::PUSH1), 0x1,
uint8_t(Instruction::PUSH1), 0x2,
uint8_t(Instruction::PUSH1), 0x3,
uint8_t(Instruction::PUSH1), 0x4,
uint8_t(Instruction::PUSH1), 0x5,
uint8_t(Instruction::PUSH1), 0x6,
uint8_t(Instruction::PUSH1), 0x7,
uint8_t(Instruction::PUSH1), 0x8,
uint8_t(Instruction::DUP9),
uint8_t(Instruction::XOR),
uint8_t(Instruction::AND),
uint8_t(Instruction::OR),
uint8_t(Instruction::SUB),
uint8_t(Instruction::ADD),
uint8_t(Instruction::DUP2),
uint8_t(Instruction::ISZERO),
uint8_t(Instruction::ISZERO),
uint8_t(Instruction::PUSH1), 0x22,
uint8_t(Instruction::JUMPI),
uint8_t(Instruction::PUSH1), 0x21,
uint8_t(Instruction::PUSH1), 0x36,
uint8_t(Instruction::JUMP),
uint8_t(Instruction::JUMPDEST),
uint8_t(Instruction::JUMPDEST),
uint8_t(Instruction::MOD),
uint8_t(Instruction::DUP2),
uint8_t(Instruction::ISZERO),
uint8_t(Instruction::ISZERO),
uint8_t(Instruction::PUSH1), 0x30,
uint8_t(Instruction::JUMPI),
uint8_t(Instruction::PUSH1), 0x2f,
uint8_t(Instruction::PUSH1), 0x36,
uint8_t(Instruction::JUMP),
uint8_t(Instruction::JUMPDEST),
uint8_t(Instruction::JUMPDEST),
uint8_t(Instruction::DIV),
uint8_t(Instruction::MUL),
uint8_t(Instruction::PUSH1), 0x67,
uint8_t(Instruction::JUMP)
uint8_t(InternalInstruction::PUSH1), 0x1,
uint8_t(InternalInstruction::PUSH1), 0x2,
uint8_t(InternalInstruction::PUSH1), 0x3,
uint8_t(InternalInstruction::PUSH1), 0x4,
uint8_t(InternalInstruction::PUSH1), 0x5,
uint8_t(InternalInstruction::PUSH1), 0x6,
uint8_t(InternalInstruction::PUSH1), 0x7,
uint8_t(InternalInstruction::PUSH1), 0x8,
uint8_t(InternalInstruction::DUP9),
uint8_t(InternalInstruction::XOR),
uint8_t(InternalInstruction::AND),
uint8_t(InternalInstruction::OR),
uint8_t(InternalInstruction::SUB),
uint8_t(InternalInstruction::ADD),
uint8_t(InternalInstruction::DUP2),
uint8_t(InternalInstruction::ISZERO),
uint8_t(InternalInstruction::ISZERO),
uint8_t(InternalInstruction::PUSH1), 0x22,
uint8_t(InternalInstruction::JUMPI),
uint8_t(InternalInstruction::PUSH1), 0x21,
uint8_t(InternalInstruction::PUSH1), 0x36,
uint8_t(InternalInstruction::JUMP),
uint8_t(InternalInstruction::JUMPDEST),
uint8_t(InternalInstruction::JUMPDEST),
uint8_t(InternalInstruction::MOD),
uint8_t(InternalInstruction::DUP2),
uint8_t(InternalInstruction::ISZERO),
uint8_t(InternalInstruction::ISZERO),
uint8_t(InternalInstruction::PUSH1), 0x30,
uint8_t(InternalInstruction::JUMPI),
uint8_t(InternalInstruction::PUSH1), 0x2f,
uint8_t(InternalInstruction::PUSH1), 0x36,
uint8_t(InternalInstruction::JUMP),
uint8_t(InternalInstruction::JUMPDEST),
uint8_t(InternalInstruction::JUMPDEST),
uint8_t(InternalInstruction::DIV),
uint8_t(InternalInstruction::MUL),
uint8_t(InternalInstruction::PUSH1), 0x67,
uint8_t(InternalInstruction::JUMP)
} + panic;
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
@ -466,23 +466,23 @@ BOOST_AUTO_TEST_CASE(unary_operators)
bytes expectation;
if (solidity::test::CommonOptions::get().optimize)
expectation = {
uint8_t(Instruction::DUP1),
uint8_t(Instruction::PUSH1), 0x0,
uint8_t(Instruction::SUB),
uint8_t(Instruction::NOT),
uint8_t(Instruction::PUSH1), 0x2,
uint8_t(Instruction::EQ),
uint8_t(Instruction::ISZERO)
uint8_t(InternalInstruction::DUP1),
uint8_t(InternalInstruction::PUSH1), 0x0,
uint8_t(InternalInstruction::SUB),
uint8_t(InternalInstruction::NOT),
uint8_t(InternalInstruction::PUSH1), 0x2,
uint8_t(InternalInstruction::EQ),
uint8_t(InternalInstruction::ISZERO)
};
else
expectation = {
uint8_t(Instruction::PUSH1), 0x2,
uint8_t(Instruction::DUP2),
uint8_t(Instruction::PUSH1), 0x0,
uint8_t(Instruction::SUB),
uint8_t(Instruction::NOT),
uint8_t(Instruction::EQ),
uint8_t(Instruction::ISZERO)
uint8_t(InternalInstruction::PUSH1), 0x2,
uint8_t(InternalInstruction::DUP2),
uint8_t(InternalInstruction::PUSH1), 0x0,
uint8_t(InternalInstruction::SUB),
uint8_t(InternalInstruction::NOT),
uint8_t(InternalInstruction::EQ),
uint8_t(InternalInstruction::ISZERO)
};
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
@ -498,47 +498,47 @@ BOOST_AUTO_TEST_CASE(unary_inc_dec)
// Stack: a, x
bytes expectation{
uint8_t(Instruction::DUP2),
uint8_t(Instruction::DUP1),
uint8_t(Instruction::PUSH1), 0x1,
uint8_t(Instruction::ADD),
uint8_t(InternalInstruction::DUP2),
uint8_t(InternalInstruction::DUP1),
uint8_t(InternalInstruction::PUSH1), 0x1,
uint8_t(InternalInstruction::ADD),
// Stack here: a x a (a+1)
uint8_t(Instruction::SWAP3),
uint8_t(Instruction::POP), // first ++
uint8_t(InternalInstruction::SWAP3),
uint8_t(InternalInstruction::POP), // first ++
// Stack here: (a+1) x a
uint8_t(Instruction::DUP3),
uint8_t(Instruction::PUSH1), 0x1,
uint8_t(Instruction::ADD),
uint8_t(InternalInstruction::DUP3),
uint8_t(InternalInstruction::PUSH1), 0x1,
uint8_t(InternalInstruction::ADD),
// Stack here: (a+1) x a (a+2)
uint8_t(Instruction::SWAP3),
uint8_t(Instruction::POP),
uint8_t(InternalInstruction::SWAP3),
uint8_t(InternalInstruction::POP),
// Stack here: (a+2) x a
uint8_t(Instruction::DUP3), // second ++
uint8_t(Instruction::XOR),
uint8_t(InternalInstruction::DUP3), // second ++
uint8_t(InternalInstruction::XOR),
// Stack here: (a+2) x a^(a+2)
uint8_t(Instruction::DUP3),
uint8_t(Instruction::DUP1),
uint8_t(Instruction::PUSH1), 0x1,
uint8_t(Instruction::SWAP1),
uint8_t(Instruction::SUB),
uint8_t(InternalInstruction::DUP3),
uint8_t(InternalInstruction::DUP1),
uint8_t(InternalInstruction::PUSH1), 0x1,
uint8_t(InternalInstruction::SWAP1),
uint8_t(InternalInstruction::SUB),
// Stack here: (a+2) x a^(a+2) (a+2) (a+1)
uint8_t(Instruction::SWAP4),
uint8_t(Instruction::POP), // first --
uint8_t(Instruction::XOR),
uint8_t(InternalInstruction::SWAP4),
uint8_t(InternalInstruction::POP), // first --
uint8_t(InternalInstruction::XOR),
// Stack here: (a+1) x a^(a+2)^(a+2)
uint8_t(Instruction::DUP3),
uint8_t(Instruction::PUSH1), 0x1,
uint8_t(Instruction::SWAP1),
uint8_t(Instruction::SUB),
uint8_t(InternalInstruction::DUP3),
uint8_t(InternalInstruction::PUSH1), 0x1,
uint8_t(InternalInstruction::SWAP1),
uint8_t(InternalInstruction::SUB),
// Stack here: (a+1) x a^(a+2)^(a+2) a
uint8_t(Instruction::SWAP3),
uint8_t(Instruction::POP), // second ++
uint8_t(InternalInstruction::SWAP3),
uint8_t(InternalInstruction::POP), // second ++
// Stack here: a x a^(a+2)^(a+2)
uint8_t(Instruction::DUP3), // will change
uint8_t(Instruction::XOR),
uint8_t(Instruction::SWAP1),
uint8_t(Instruction::POP),
uint8_t(Instruction::DUP1)
uint8_t(InternalInstruction::DUP3), // will change
uint8_t(InternalInstruction::XOR),
uint8_t(InternalInstruction::SWAP1),
uint8_t(InternalInstruction::POP),
uint8_t(InternalInstruction::DUP1)
};
// Stack here: a x a^(a+2)^(a+2)^a
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
@ -557,27 +557,27 @@ BOOST_AUTO_TEST_CASE(assignment)
bytes expectation;
if (solidity::test::CommonOptions::get().optimize)
expectation = {
uint8_t(Instruction::DUP1),
uint8_t(Instruction::DUP3),
uint8_t(Instruction::ADD),
uint8_t(Instruction::SWAP2),
uint8_t(Instruction::POP),
uint8_t(Instruction::DUP2),
uint8_t(Instruction::PUSH1), 0x2,
uint8_t(Instruction::MUL)
uint8_t(InternalInstruction::DUP1),
uint8_t(InternalInstruction::DUP3),
uint8_t(InternalInstruction::ADD),
uint8_t(InternalInstruction::SWAP2),
uint8_t(InternalInstruction::POP),
uint8_t(InternalInstruction::DUP2),
uint8_t(InternalInstruction::PUSH1), 0x2,
uint8_t(InternalInstruction::MUL)
};
else
expectation = {
uint8_t(Instruction::PUSH1), 0x2,
uint8_t(Instruction::DUP2),
uint8_t(Instruction::DUP4),
uint8_t(Instruction::ADD),
uint8_t(InternalInstruction::PUSH1), 0x2,
uint8_t(InternalInstruction::DUP2),
uint8_t(InternalInstruction::DUP4),
uint8_t(InternalInstruction::ADD),
// Stack here: a b 2 a+b
uint8_t(Instruction::SWAP3),
uint8_t(Instruction::POP),
uint8_t(Instruction::DUP3),
uint8_t(InternalInstruction::SWAP3),
uint8_t(InternalInstruction::POP),
uint8_t(InternalInstruction::DUP3),
// Stack here: a+b b 2 a+b
uint8_t(Instruction::MUL)
uint8_t(InternalInstruction::MUL)
};
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
@ -591,7 +591,7 @@ BOOST_AUTO_TEST_CASE(negative_literals_8bits)
)";
bytes code = compileFirstExpression(sourceCode);
bytes expectation(bytes({uint8_t(Instruction::PUSH32)}) + bytes(31, 0xff) + bytes(1, 0x80));
bytes expectation(bytes({uint8_t(InternalInstruction::PUSH32)}) + bytes(31, 0xff) + bytes(1, 0x80));
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
@ -604,7 +604,7 @@ BOOST_AUTO_TEST_CASE(negative_literals_16bits)
)";
bytes code = compileFirstExpression(sourceCode);
bytes expectation(bytes({uint8_t(Instruction::PUSH32)}) + bytes(30, 0xff) + bytes{0xf5, 0x43});
bytes expectation(bytes({uint8_t(InternalInstruction::PUSH32)}) + bytes(30, 0xff) + bytes{0xf5, 0x43});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
@ -619,7 +619,7 @@ BOOST_AUTO_TEST_CASE(intermediately_overflowing_literals)
)";
bytes code = compileFirstExpression(sourceCode);
bytes expectation(bytes({uint8_t(Instruction::PUSH1), 0xbf}));
bytes expectation(bytes({uint8_t(InternalInstruction::PUSH1), 0xbf}));
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
@ -635,8 +635,8 @@ BOOST_AUTO_TEST_CASE(blockhash)
bytes code = compileFirstExpression(sourceCode, {}, {});
bytes expectation({uint8_t(Instruction::PUSH1), 0x03,
uint8_t(Instruction::BLOCKHASH)});
bytes expectation({uint8_t(InternalInstruction::PUSH1), 0x03,
uint8_t(InternalInstruction::BLOCKHASH)});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
@ -651,7 +651,7 @@ BOOST_AUTO_TEST_CASE(gas_left)
)";
bytes code = compileFirstExpression(sourceCode, {}, {});
bytes expectation = bytes({uint8_t(Instruction::GAS)});
bytes expectation = bytes({uint8_t(InternalInstruction::GAS)});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
@ -669,7 +669,7 @@ BOOST_AUTO_TEST_CASE(selfbalance)
if (solidity::test::CommonOptions::get().evmVersion().hasSelfBalance())
{
bytes expectation({uint8_t(Instruction::SELFBALANCE)});
bytes expectation({uint8_t(InternalInstruction::SELFBALANCE)});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
}

View File

@ -104,12 +104,12 @@ public:
/// @returns the number of instructions in the given bytecode, not taking the metadata hash
/// into account.
size_t numInstructions(bytes const& _bytecode, std::optional<Instruction> _which = std::optional<Instruction>{})
size_t numInstructions(bytes const& _bytecode, std::optional<InternalInstruction> _which = std::optional<InternalInstruction>{})
{
bytes realCode = bytecodeSansMetadata(_bytecode);
BOOST_REQUIRE_MESSAGE(!realCode.empty(), "Invalid or missing metadata in bytecode.");
size_t instructions = 0;
evmasm::eachInstruction(realCode, [&](Instruction _instr, u256 const&) {
evmasm::eachInstruction(realCode, langutil::EVMVersion(), [&](InternalInstruction _instr, u256 const&) {
if (!_which || *_which == _instr)
instructions++;
});
@ -287,8 +287,8 @@ BOOST_AUTO_TEST_CASE(retain_information_in_branches)
bytes optimizedBytecode = compileAndRunWithOptimizer(sourceCode, 0, "c", true);
size_t numSHA3s = 0;
eachInstruction(optimizedBytecode, [&](Instruction _instr, u256 const&) {
if (_instr == Instruction::KECCAK256)
eachInstruction(optimizedBytecode, langutil::EVMVersion(), [&](InternalInstruction _instr, u256 const&) {
if (_instr == InternalInstruction::KECCAK256)
numSHA3s++;
});
// TEST DISABLED - OPTIMIZER IS NOT EFFECTIVE ON THIS ONE ANYMORE
@ -330,8 +330,8 @@ BOOST_AUTO_TEST_CASE(store_tags_as_unions)
bytes optimizedBytecode = compileAndRunWithOptimizer(sourceCode, 0, "test", true);
size_t numSHA3s = 0;
eachInstruction(optimizedBytecode, [&](Instruction _instr, u256 const&) {
if (_instr == Instruction::KECCAK256)
eachInstruction(optimizedBytecode, langutil::EVMVersion(), [&](InternalInstruction _instr, u256 const&) {
if (_instr == InternalInstruction::KECCAK256)
numSHA3s++;
});
// TEST DISABLED UNTIL 93693404 IS IMPLEMENTED
@ -635,8 +635,8 @@ BOOST_AUTO_TEST_CASE(optimise_multi_stores)
)";
compileBothVersions(sourceCode);
compareVersions("f()");
BOOST_CHECK_EQUAL(numInstructions(m_nonOptimizedBytecode, Instruction::SSTORE), 8);
BOOST_CHECK_EQUAL(numInstructions(m_optimizedBytecode, Instruction::SSTORE), 7);
BOOST_CHECK_EQUAL(numInstructions(m_nonOptimizedBytecode, InternalInstruction::SSTORE), 8);
BOOST_CHECK_EQUAL(numInstructions(m_optimizedBytecode, InternalInstruction::SSTORE), 7);
}
BOOST_AUTO_TEST_CASE(optimise_constant_to_codecopy)
@ -672,8 +672,8 @@ BOOST_AUTO_TEST_CASE(optimise_constant_to_codecopy)
compareVersions("h()");
compareVersions("i()");
// This is counting in the deployed code.
BOOST_CHECK_EQUAL(numInstructions(m_nonOptimizedBytecode, Instruction::CODECOPY), 0);
BOOST_CHECK_EQUAL(numInstructions(m_optimizedBytecode, Instruction::CODECOPY), 4);
BOOST_CHECK_EQUAL(numInstructions(m_nonOptimizedBytecode, InternalInstruction::CODECOPY), 0);
BOOST_CHECK_EQUAL(numInstructions(m_optimizedBytecode, InternalInstruction::CODECOPY), 4);
}
BOOST_AUTO_TEST_CASE(byte_access)
@ -722,7 +722,7 @@ BOOST_AUTO_TEST_CASE(avoid_double_cleanup)
)";
compileBothVersions(sourceCode, 0, "C", 50);
// Check that there is no double AND instruction in the resulting code
BOOST_CHECK_EQUAL(numInstructions(m_nonOptimizedBytecode, Instruction::AND), 1);
BOOST_CHECK_EQUAL(numInstructions(m_nonOptimizedBytecode, InternalInstruction::AND), 1);
}
BOOST_AUTO_TEST_SUITE_END()

View File

@ -87,12 +87,12 @@ void copyZeroExtended(
using u512 = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<512, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>;
u256 EVMInstructionInterpreter::eval(
evmasm::Instruction _instruction,
evmasm::InternalInstruction _instruction,
vector<u256> const& _arguments
)
{
using namespace solidity::evmasm;
using evmasm::Instruction;
using evmasm::InternalInstruction;
auto info = instructionInfo(_instruction);
yulAssert(static_cast<size_t>(info.args) == _arguments.size(), "");
@ -100,53 +100,53 @@ u256 EVMInstructionInterpreter::eval(
auto const& arg = _arguments;
switch (_instruction)
{
case Instruction::STOP:
case InternalInstruction::STOP:
logTrace(_instruction);
BOOST_THROW_EXCEPTION(ExplicitlyTerminated());
// --------------- arithmetic ---------------
case Instruction::ADD:
case InternalInstruction::ADD:
return arg[0] + arg[1];
case Instruction::MUL:
case InternalInstruction::MUL:
return arg[0] * arg[1];
case Instruction::SUB:
case InternalInstruction::SUB:
return arg[0] - arg[1];
case Instruction::DIV:
case InternalInstruction::DIV:
return arg[1] == 0 ? 0 : arg[0] / arg[1];
case Instruction::SDIV:
case InternalInstruction::SDIV:
return arg[1] == 0 ? 0 : s2u(u2s(arg[0]) / u2s(arg[1]));
case Instruction::MOD:
case InternalInstruction::MOD:
return arg[1] == 0 ? 0 : arg[0] % arg[1];
case Instruction::SMOD:
case InternalInstruction::SMOD:
return arg[1] == 0 ? 0 : s2u(u2s(arg[0]) % u2s(arg[1]));
case Instruction::EXP:
case InternalInstruction::EXP:
return exp256(arg[0], arg[1]);
case Instruction::NOT:
case InternalInstruction::NOT:
return ~arg[0];
case Instruction::LT:
case InternalInstruction::LT:
return arg[0] < arg[1] ? 1 : 0;
case Instruction::GT:
case InternalInstruction::GT:
return arg[0] > arg[1] ? 1 : 0;
case Instruction::SLT:
case InternalInstruction::SLT:
return u2s(arg[0]) < u2s(arg[1]) ? 1 : 0;
case Instruction::SGT:
case InternalInstruction::SGT:
return u2s(arg[0]) > u2s(arg[1]) ? 1 : 0;
case Instruction::EQ:
case InternalInstruction::EQ:
return arg[0] == arg[1] ? 1 : 0;
case Instruction::ISZERO:
case InternalInstruction::ISZERO:
return arg[0] == 0 ? 1 : 0;
case Instruction::AND:
case InternalInstruction::AND:
return arg[0] & arg[1];
case Instruction::OR:
case InternalInstruction::OR:
return arg[0] | arg[1];
case Instruction::XOR:
case InternalInstruction::XOR:
return arg[0] ^ arg[1];
case Instruction::BYTE:
case InternalInstruction::BYTE:
return arg[0] >= 32 ? 0 : (arg[1] >> unsigned(8 * (31 - arg[0]))) & 0xff;
case Instruction::SHL:
case InternalInstruction::SHL:
return arg[0] > 255 ? 0 : (arg[1] << unsigned(arg[0]));
case Instruction::SHR:
case InternalInstruction::SHR:
return arg[0] > 255 ? 0 : (arg[1] >> unsigned(arg[0]));
case Instruction::SAR:
case InternalInstruction::SAR:
{
static u256 const hibit = u256(1) << 255;
if (arg[0] >= 256)
@ -160,11 +160,11 @@ u256 EVMInstructionInterpreter::eval(
return v;
}
}
case Instruction::ADDMOD:
case InternalInstruction::ADDMOD:
return arg[2] == 0 ? 0 : u256((u512(arg[0]) + u512(arg[1])) % arg[2]);
case Instruction::MULMOD:
case InternalInstruction::MULMOD:
return arg[2] == 0 ? 0 : u256((u512(arg[0]) * u512(arg[1])) % arg[2]);
case Instruction::SIGNEXTEND:
case InternalInstruction::SIGNEXTEND:
if (arg[0] >= 31)
return arg[1];
else
@ -179,7 +179,7 @@ u256 EVMInstructionInterpreter::eval(
return ret;
}
// --------------- blockchain stuff ---------------
case Instruction::KECCAK256:
case InternalInstruction::KECCAK256:
{
if (!accessMemory(arg[0], arg[1]))
return u256("0x1234cafe1234cafe1234cafe") + arg[0];
@ -187,26 +187,26 @@ u256 EVMInstructionInterpreter::eval(
uint64_t size = uint64_t(arg[1] & uint64_t(-1));
return u256(keccak256(readMemory(offset, size)));
}
case Instruction::ADDRESS:
case InternalInstruction::ADDRESS:
return h256(m_state.address, h256::AlignRight);
case Instruction::BALANCE:
case InternalInstruction::BALANCE:
if (arg[0] == h256(m_state.address, h256::AlignRight))
return m_state.selfbalance;
else
return m_state.balance;
case Instruction::SELFBALANCE:
case InternalInstruction::SELFBALANCE:
return m_state.selfbalance;
case Instruction::ORIGIN:
case InternalInstruction::ORIGIN:
return h256(m_state.origin, h256::AlignRight);
case Instruction::CALLER:
case InternalInstruction::CALLER:
return h256(m_state.caller, h256::AlignRight);
case Instruction::CALLVALUE:
case InternalInstruction::CALLVALUE:
return m_state.callvalue;
case Instruction::CALLDATALOAD:
case InternalInstruction::CALLDATALOAD:
return readZeroExtended(m_state.calldata, arg[0]);
case Instruction::CALLDATASIZE:
case InternalInstruction::CALLDATASIZE:
return m_state.calldata.size();
case Instruction::CALLDATACOPY:
case InternalInstruction::CALLDATACOPY:
logTrace(_instruction, arg);
if (accessMemory(arg[0], arg[2]))
copyZeroExtended(
@ -214,9 +214,9 @@ u256 EVMInstructionInterpreter::eval(
size_t(arg[0]), size_t(arg[1]), size_t(arg[2])
);
return 0;
case Instruction::CODESIZE:
case InternalInstruction::CODESIZE:
return m_state.code.size();
case Instruction::CODECOPY:
case InternalInstruction::CODECOPY:
logTrace(_instruction, arg);
if (accessMemory(arg[0], arg[2]))
copyZeroExtended(
@ -224,17 +224,17 @@ u256 EVMInstructionInterpreter::eval(
size_t(arg[0]), size_t(arg[1]), size_t(arg[2])
);
return 0;
case Instruction::GASPRICE:
case InternalInstruction::GASPRICE:
return m_state.gasprice;
case Instruction::CHAINID:
case InternalInstruction::CHAINID:
return m_state.chainid;
case Instruction::BASEFEE:
case InternalInstruction::BASEFEE:
return m_state.basefee;
case Instruction::EXTCODESIZE:
case InternalInstruction::EXTCODESIZE:
return u256(keccak256(h256(arg[0]))) & 0xffffff;
case Instruction::EXTCODEHASH:
case InternalInstruction::EXTCODEHASH:
return u256(keccak256(h256(arg[0] + 1)));
case Instruction::EXTCODECOPY:
case InternalInstruction::EXTCODECOPY:
logTrace(_instruction, arg);
if (accessMemory(arg[1], arg[3]))
// TODO this way extcodecopy and codecopy do the same thing.
@ -243,9 +243,9 @@ u256 EVMInstructionInterpreter::eval(
size_t(arg[1]), size_t(arg[2]), size_t(arg[3])
);
return 0;
case Instruction::RETURNDATASIZE:
case InternalInstruction::RETURNDATASIZE:
return m_state.returndata.size();
case Instruction::RETURNDATACOPY:
case InternalInstruction::RETURNDATACOPY:
logTrace(_instruction, arg);
if (accessMemory(arg[0], arg[2]))
copyZeroExtended(
@ -253,87 +253,89 @@ u256 EVMInstructionInterpreter::eval(
size_t(arg[0]), size_t(arg[1]), size_t(arg[2])
);
return 0;
case Instruction::BLOCKHASH:
case InternalInstruction::BLOCKHASH:
if (arg[0] >= m_state.blockNumber || arg[0] + 256 < m_state.blockNumber)
return 0;
else
return 0xaaaaaaaa + (arg[0] - m_state.blockNumber - 256);
case Instruction::COINBASE:
case InternalInstruction::COINBASE:
return h256(m_state.coinbase, h256::AlignRight);
case Instruction::TIMESTAMP:
case InternalInstruction::TIMESTAMP:
return m_state.timestamp;
case Instruction::NUMBER:
case InternalInstruction::NUMBER:
return m_state.blockNumber;
case Instruction::DIFFICULTY:
case InternalInstruction::DIFFICULTY:
// TODO should be properly implemented
case InternalInstruction::PREVRANDAO:
return m_state.difficulty;
case Instruction::GASLIMIT:
case InternalInstruction::GASLIMIT:
return m_state.gaslimit;
// --------------- memory / storage / logs ---------------
case Instruction::MLOAD:
case InternalInstruction::MLOAD:
accessMemory(arg[0], 0x20);
return readMemoryWord(arg[0]);
case Instruction::MSTORE:
case InternalInstruction::MSTORE:
accessMemory(arg[0], 0x20);
writeMemoryWord(arg[0], arg[1]);
return 0;
case Instruction::MSTORE8:
case InternalInstruction::MSTORE8:
accessMemory(arg[0], 1);
m_state.memory[arg[0]] = uint8_t(arg[1] & 0xff);
return 0;
case Instruction::SLOAD:
case InternalInstruction::SLOAD:
return m_state.storage[h256(arg[0])];
case Instruction::SSTORE:
case InternalInstruction::SSTORE:
m_state.storage[h256(arg[0])] = h256(arg[1]);
return 0;
case Instruction::PC:
case InternalInstruction::PC:
return 0x77;
case Instruction::MSIZE:
case InternalInstruction::MSIZE:
return m_state.msize;
case Instruction::GAS:
case InternalInstruction::GAS:
return 0x99;
case Instruction::LOG0:
case InternalInstruction::LOG0:
accessMemory(arg[0], arg[1]);
logTrace(_instruction, arg);
return 0;
case Instruction::LOG1:
case InternalInstruction::LOG1:
accessMemory(arg[0], arg[1]);
logTrace(_instruction, arg);
return 0;
case Instruction::LOG2:
case InternalInstruction::LOG2:
accessMemory(arg[0], arg[1]);
logTrace(_instruction, arg);
return 0;
case Instruction::LOG3:
case InternalInstruction::LOG3:
accessMemory(arg[0], arg[1]);
logTrace(_instruction, arg);
return 0;
case Instruction::LOG4:
case InternalInstruction::LOG4:
accessMemory(arg[0], arg[1]);
logTrace(_instruction, arg);
return 0;
// --------------- calls ---------------
case Instruction::CREATE:
case InternalInstruction::CREATE:
accessMemory(arg[1], arg[2]);
logTrace(_instruction, arg);
return (0xcccccc + arg[1]) & u256("0xffffffffffffffffffffffffffffffffffffffff");
case Instruction::CREATE2:
case InternalInstruction::CREATE2:
accessMemory(arg[1], arg[2]);
logTrace(_instruction, arg);
return (0xdddddd + arg[1]) & u256("0xffffffffffffffffffffffffffffffffffffffff");
case Instruction::CALL:
case Instruction::CALLCODE:
case InternalInstruction::CALL:
case InternalInstruction::CALLCODE:
// TODO assign returndata
accessMemory(arg[3], arg[4]);
accessMemory(arg[5], arg[6]);
logTrace(_instruction, arg);
return arg[0] & 1;
case Instruction::DELEGATECALL:
case Instruction::STATICCALL:
case InternalInstruction::DELEGATECALL:
case InternalInstruction::STATICCALL:
accessMemory(arg[2], arg[3]);
accessMemory(arg[4], arg[5]);
logTrace(_instruction, arg);
return 0;
case Instruction::RETURN:
case InternalInstruction::RETURN:
{
bytes data;
if (accessMemory(arg[0], arg[1]))
@ -341,92 +343,93 @@ u256 EVMInstructionInterpreter::eval(
logTrace(_instruction, arg, data);
BOOST_THROW_EXCEPTION(ExplicitlyTerminated());
}
case Instruction::REVERT:
case InternalInstruction::REVERT:
accessMemory(arg[0], arg[1]);
logTrace(_instruction, arg);
m_state.storage.clear();
m_state.trace.clear();
BOOST_THROW_EXCEPTION(ExplicitlyTerminated());
case Instruction::INVALID:
case InternalInstruction::INVALID:
logTrace(_instruction);
m_state.storage.clear();
m_state.trace.clear();
BOOST_THROW_EXCEPTION(ExplicitlyTerminated());
case Instruction::SELFDESTRUCT:
case InternalInstruction::SELFDESTRUCT:
logTrace(_instruction, arg);
m_state.storage.clear();
m_state.trace.clear();
BOOST_THROW_EXCEPTION(ExplicitlyTerminated());
case Instruction::POP:
case InternalInstruction::POP:
break;
// --------------- invalid in strict assembly ---------------
case Instruction::JUMP:
case Instruction::JUMPI:
case Instruction::JUMPDEST:
case Instruction::PUSH1:
case Instruction::PUSH2:
case Instruction::PUSH3:
case Instruction::PUSH4:
case Instruction::PUSH5:
case Instruction::PUSH6:
case Instruction::PUSH7:
case Instruction::PUSH8:
case Instruction::PUSH9:
case Instruction::PUSH10:
case Instruction::PUSH11:
case Instruction::PUSH12:
case Instruction::PUSH13:
case Instruction::PUSH14:
case Instruction::PUSH15:
case Instruction::PUSH16:
case Instruction::PUSH17:
case Instruction::PUSH18:
case Instruction::PUSH19:
case Instruction::PUSH20:
case Instruction::PUSH21:
case Instruction::PUSH22:
case Instruction::PUSH23:
case Instruction::PUSH24:
case Instruction::PUSH25:
case Instruction::PUSH26:
case Instruction::PUSH27:
case Instruction::PUSH28:
case Instruction::PUSH29:
case Instruction::PUSH30:
case Instruction::PUSH31:
case Instruction::PUSH32:
case Instruction::DUP1:
case Instruction::DUP2:
case Instruction::DUP3:
case Instruction::DUP4:
case Instruction::DUP5:
case Instruction::DUP6:
case Instruction::DUP7:
case Instruction::DUP8:
case Instruction::DUP9:
case Instruction::DUP10:
case Instruction::DUP11:
case Instruction::DUP12:
case Instruction::DUP13:
case Instruction::DUP14:
case Instruction::DUP15:
case Instruction::DUP16:
case Instruction::SWAP1:
case Instruction::SWAP2:
case Instruction::SWAP3:
case Instruction::SWAP4:
case Instruction::SWAP5:
case Instruction::SWAP6:
case Instruction::SWAP7:
case Instruction::SWAP8:
case Instruction::SWAP9:
case Instruction::SWAP10:
case Instruction::SWAP11:
case Instruction::SWAP12:
case Instruction::SWAP13:
case Instruction::SWAP14:
case Instruction::SWAP15:
case Instruction::SWAP16:
case InternalInstruction::JUMP:
case InternalInstruction::JUMPI:
case InternalInstruction::JUMPDEST:
case InternalInstruction::PUSH1:
case InternalInstruction::PUSH2:
case InternalInstruction::PUSH3:
case InternalInstruction::PUSH4:
case InternalInstruction::PUSH5:
case InternalInstruction::PUSH6:
case InternalInstruction::PUSH7:
case InternalInstruction::PUSH8:
case InternalInstruction::PUSH9:
case InternalInstruction::PUSH10:
case InternalInstruction::PUSH11:
case InternalInstruction::PUSH12:
case InternalInstruction::PUSH13:
case InternalInstruction::PUSH14:
case InternalInstruction::PUSH15:
case InternalInstruction::PUSH16:
case InternalInstruction::PUSH17:
case InternalInstruction::PUSH18:
case InternalInstruction::PUSH19:
case InternalInstruction::PUSH20:
case InternalInstruction::PUSH21:
case InternalInstruction::PUSH22:
case InternalInstruction::PUSH23:
case InternalInstruction::PUSH24:
case InternalInstruction::PUSH25:
case InternalInstruction::PUSH26:
case InternalInstruction::PUSH27:
case InternalInstruction::PUSH28:
case InternalInstruction::PUSH29:
case InternalInstruction::PUSH30:
case InternalInstruction::PUSH31:
case InternalInstruction::PUSH32:
case InternalInstruction::DUP1:
case InternalInstruction::DUP2:
case InternalInstruction::DUP3:
case InternalInstruction::DUP4:
case InternalInstruction::DUP5:
case InternalInstruction::DUP6:
case InternalInstruction::DUP7:
case InternalInstruction::DUP8:
case InternalInstruction::DUP9:
case InternalInstruction::DUP10:
case InternalInstruction::DUP11:
case InternalInstruction::DUP12:
case InternalInstruction::DUP13:
case InternalInstruction::DUP14:
case InternalInstruction::DUP15:
case InternalInstruction::DUP16:
case InternalInstruction::SWAP1:
case InternalInstruction::SWAP2:
case InternalInstruction::SWAP3:
case InternalInstruction::SWAP4:
case InternalInstruction::SWAP5:
case InternalInstruction::SWAP6:
case InternalInstruction::SWAP7:
case InternalInstruction::SWAP8:
case InternalInstruction::SWAP9:
case InternalInstruction::SWAP10:
case InternalInstruction::SWAP11:
case InternalInstruction::SWAP12:
case InternalInstruction::SWAP13:
case InternalInstruction::SWAP14:
case InternalInstruction::SWAP15:
case InternalInstruction::SWAP16:
case InternalInstruction::MAX_INTERNAL_INSTRUCTION:
{
yulAssert(false, "");
return 0;
@ -519,7 +522,7 @@ void EVMInstructionInterpreter::writeMemoryWord(u256 const& _offset, u256 const&
void EVMInstructionInterpreter::logTrace(
evmasm::Instruction _instruction,
evmasm::InternalInstruction _instruction,
std::vector<u256> const& _arguments,
bytes const& _data
)

View File

@ -30,7 +30,7 @@
namespace solidity::evmasm
{
enum class Instruction: uint8_t;
enum class InternalInstruction: uint8_t;
}
namespace solidity::yul
@ -71,7 +71,7 @@ public:
m_disableMemoryWriteInstructions(_disableMemWriteTrace)
{}
/// Evaluate instruction
u256 eval(evmasm::Instruction _instruction, std::vector<u256> const& _arguments);
u256 eval(evmasm::InternalInstruction _instruction, std::vector<u256> const& _arguments);
/// Evaluate builtin function
u256 evalBuiltin(
BuiltinFunctionForEVM const& _fun,
@ -95,7 +95,7 @@ private:
void writeMemoryWord(u256 const& _offset, u256 const& _value);
void logTrace(
evmasm::Instruction _instruction,
evmasm::InternalInstruction _instruction,
std::vector<u256> const& _arguments = {},
bytes const& _data = {}
);

View File

@ -180,7 +180,7 @@ u256 EwasmBuiltinInterpreter::evalBuiltin(
return arg.at(0) & uint32_t(-1);
else if (fun == "unreachable")
{
logTrace(evmasm::Instruction::INVALID, {});
logTrace(evmasm::InternalInstruction::INVALID, {});
BOOST_THROW_EXCEPTION(ExplicitlyTerminated());
}
else if (fun == "i64.store")
@ -334,7 +334,7 @@ u256 EwasmBuiltinInterpreter::evalEthBuiltin(string const& _fun, vector<uint64_t
readAddress(arg[1]);
readU128(arg[2]);
accessMemory(arg[3], arg[4]);
logTrace(evmasm::Instruction::CALL, {});
logTrace(evmasm::InternalInstruction::CALL, {});
return arg[0] & 1;
}
else if (_fun == "callDataCopy")
@ -355,21 +355,21 @@ u256 EwasmBuiltinInterpreter::evalEthBuiltin(string const& _fun, vector<uint64_t
readAddress(arg[1]);
readU128(arg[2]);
accessMemory(arg[3], arg[4]);
logTrace(evmasm::Instruction::CALLCODE, {});
logTrace(evmasm::InternalInstruction::CALLCODE, {});
return arg[0] & 1;
}
else if (_fun == "callDelegate")
{
readAddress(arg[1]);
accessMemory(arg[2], arg[3]);
logTrace(evmasm::Instruction::DELEGATECALL, {});
logTrace(evmasm::InternalInstruction::DELEGATECALL, {});
return arg[0] & 1;
}
else if (_fun == "callStatic")
{
readAddress(arg[1]);
accessMemory(arg[2], arg[3]);
logTrace(evmasm::Instruction::STATICCALL, {});
logTrace(evmasm::InternalInstruction::STATICCALL, {});
return arg[0] & 1;
}
else if (_fun == "storageStore")
@ -412,7 +412,7 @@ u256 EwasmBuiltinInterpreter::evalEthBuiltin(string const& _fun, vector<uint64_t
{
readU128(arg[0]);
accessMemory(arg[1], arg[2]);
logTrace(evmasm::Instruction::CREATE, {});
logTrace(evmasm::InternalInstruction::CREATE, {});
writeAddress(arg[3], h160(0xcccccc + arg[1]));
return 1;
}
@ -478,7 +478,7 @@ u256 EwasmBuiltinInterpreter::evalEthBuiltin(string const& _fun, vector<uint64_t
bytes data;
accessMemory(arg[0], arg[1]);
data = readMemory(arg[0], arg[1]);
logTrace(evmasm::Instruction::RETURN, {}, data);
logTrace(evmasm::InternalInstruction::RETURN, {}, data);
BOOST_THROW_EXCEPTION(ExplicitlyTerminated());
}
else if (_fun == "revert")
@ -486,7 +486,7 @@ u256 EwasmBuiltinInterpreter::evalEthBuiltin(string const& _fun, vector<uint64_t
bytes data;
accessMemory(arg[0], arg[1]);
data = readMemory(arg[0], arg[1]);
logTrace(evmasm::Instruction::REVERT, {}, data);
logTrace(evmasm::InternalInstruction::REVERT, {}, data);
BOOST_THROW_EXCEPTION(ExplicitlyTerminated());
}
else if (_fun == "getReturnDataSize")
@ -505,7 +505,7 @@ u256 EwasmBuiltinInterpreter::evalEthBuiltin(string const& _fun, vector<uint64_t
else if (_fun == "selfDestruct")
{
readAddress(arg[0]);
logTrace(evmasm::Instruction::SELFDESTRUCT, {});
logTrace(evmasm::InternalInstruction::SELFDESTRUCT, {});
BOOST_THROW_EXCEPTION(ExplicitlyTerminated());
}
else if (_fun == "getBlockTimestamp")
@ -595,7 +595,7 @@ u256 EwasmBuiltinInterpreter::readU256(uint64_t _offset, size_t _croppedTo)
return value;
}
void EwasmBuiltinInterpreter::logTrace(evmasm::Instruction _instruction, std::vector<u256> const& _arguments, bytes const& _data)
void EwasmBuiltinInterpreter::logTrace(evmasm::InternalInstruction _instruction, std::vector<u256> const& _arguments, bytes const& _data)
{
logTrace(evmasm::instructionInfo(_instruction).name, _arguments, _data);
}

View File

@ -30,7 +30,7 @@
namespace solidity::evmasm
{
enum class Instruction: uint8_t;
enum class InternalInstruction: uint8_t;
}
namespace solidity::yul
@ -127,7 +127,7 @@ private:
util::h256 readBytes32(uint64_t _offset) { accessMemory(_offset, 32); return util::h256(readMemory(_offset, 32)); }
util::h160 readAddress(uint64_t _offset) { accessMemory(_offset, 20); return util::h160(readMemory(_offset, 20)); }
void logTrace(evmasm::Instruction _instruction, std::vector<u256> const& _arguments = {}, bytes const& _data = {});
void logTrace(evmasm::InternalInstruction _instruction, std::vector<u256> const& _arguments = {}, bytes const& _data = {});
/// Appends a log to the trace representing an instruction or similar operation by string,
/// with arguments and auxiliary data (if nonempty).
void logTrace(std::string const& _pseudoInstruction, std::vector<u256> const& _arguments = {}, bytes const& _data = {});