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)); append(AssemblyItem(std::move(_data), _arguments, _returnVariables));
} }
AssemblyItem appendJump() { auto ret = append(newPushTag()); append(Instruction::JUMP); return ret; } AssemblyItem appendJump() { auto ret = append(newPushTag()); append(InternalInstruction::JUMP); return ret; }
AssemblyItem appendJumpI() { auto ret = append(newPushTag()); append(Instruction::JUMPI); return ret; } AssemblyItem appendJumpI() { auto ret = append(newPushTag()); append(InternalInstruction::JUMPI); return ret; }
AssemblyItem appendJump(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(Instruction::JUMP); 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(Instruction::JUMPI); 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) /// 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. /// 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: case Operation:
_out << " " << instructionInfo(_item.instruction()).name; _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(); _out << "\t" << _item.getJumpTypeAsString();
break; break;
case Push: case Push:

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -221,7 +221,7 @@ public:
/// @returns gas costs for simple instructions with constant gas costs (that do not /// @returns gas costs for simple instructions with constant gas costs (that do not
/// change with EVM versions) /// 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. /// @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 /// 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) if (_items.back().type() != Operation)
return false; return false;
if ( if (
_items.back() != Instruction::JUMP && _items.back() != InternalInstruction::JUMP &&
!SemanticInformation::terminatesControlFlow(_items.back().instruction()) !SemanticInformation::terminatesControlFlow(_items.back().instruction())
) )
return false; return false;
@ -150,13 +150,13 @@ bool Inliner::shouldInlineFullFunctionBody(size_t _tag, ranges::span<AssemblyIte
static AssemblyItems const uninlinedCallSitePattern = { static AssemblyItems const uninlinedCallSitePattern = {
AssemblyItem{PushTag}, AssemblyItem{PushTag},
AssemblyItem{PushTag}, AssemblyItem{PushTag},
AssemblyItem{Instruction::JUMP}, AssemblyItem{InternalInstruction::JUMP},
AssemblyItem{Tag} AssemblyItem{Tag}
}; };
static AssemblyItems const uninlinedFunctionPattern = { static AssemblyItems const uninlinedFunctionPattern = {
AssemblyItem{Tag}, AssemblyItem{Tag},
// Actual function body of size functionBodySize. Handled separately below. // 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. // 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 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(); AssemblyItem blockExit = _block.items.back();
if ( if (
_jump.getJumpType() == AssemblyItem::JumpType::IntoFunction && _jump.getJumpType() == AssemblyItem::JumpType::IntoFunction &&
blockExit == Instruction::JUMP && blockExit == InternalInstruction::JUMP &&
blockExit.getJumpType() == AssemblyItem::JumpType::OutOfFunction && blockExit.getJumpType() == AssemblyItem::JumpType::OutOfFunction &&
shouldInlineFullFunctionBody(_tag, _block.items, _block.pushTagCount) shouldInlineFullFunctionBody(_tag, _block.items, _block.pushTagCount)
) )
@ -223,7 +223,7 @@ optional<AssemblyItem> Inliner::shouldInline(size_t _tag, AssemblyItem const& _j
{ {
static AssemblyItems const jumpPattern = { static AssemblyItems const jumpPattern = {
AssemblyItem{PushTag}, AssemblyItem{PushTag},
AssemblyItem{Instruction::JUMP}, AssemblyItem{InternalInstruction::JUMP},
}; };
if ( if (
GasMeter::dataGas(codeSize(_block.items), m_isCreation, m_evmVersion) <= GasMeter::dataGas(codeSize(_block.items), m_isCreation, m_evmVersion) <=
@ -250,7 +250,7 @@ void Inliner::optimise()
if (next(it) != m_items.end()) if (next(it) != m_items.end())
{ {
AssemblyItem const& nextItem = *next(it); 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 (optional<size_t> tag = getLocalTag(item))
if (auto* inlinableBlock = util::valueOrNullptr(inlinableBlocks, *tag)) 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 // Since AssignImmutable breaks blocks, it should be fine to only consider its changes to the stack, which
// is the same as two POPs. // is the same as two POPs.
// Note that the StoreOperation for POP is generic and _copyItem is ignored. // Note that the StoreOperation for POP is generic and _copyItem is ignored.
feedItem(AssemblyItem(Instruction::POP), _copyItem); feedItem(AssemblyItem(InternalInstruction::POP), _copyItem);
return feedItem(AssemblyItem(Instruction::POP), _copyItem); return feedItem(AssemblyItem(InternalInstruction::POP), _copyItem);
} }
else if (_item.type() == VerbatimBytecode) else if (_item.type() == VerbatimBytecode)
{ {
@ -129,48 +129,48 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool
} }
else else
{ {
Instruction instruction = _item.instruction(); InternalInstruction instruction = _item.instruction();
InstructionInfo info = instructionInfo(instruction); InstructionInfo info = instructionInfo(instruction);
if (SemanticInformation::isDupInstruction(_item)) if (SemanticInformation::isDupInstruction(_item))
setStackElement( setStackElement(
m_stackHeight + 1, m_stackHeight + 1,
stackElement( 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() _item.location()
) )
); );
else if (SemanticInformation::isSwapInstruction(_item)) else if (SemanticInformation::isSwapInstruction(_item))
swapStackElements( swapStackElements(
m_stackHeight, 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() _item.location()
); );
else if (instruction != Instruction::POP) else if (instruction != InternalInstruction::POP)
{ {
vector<Id> arguments(static_cast<size_t>(info.args)); vector<Id> arguments(static_cast<size_t>(info.args));
for (size_t i = 0; i < static_cast<size_t>(info.args); ++i) for (size_t i = 0; i < static_cast<size_t>(info.args); ++i)
arguments[i] = stackElement(m_stackHeight - static_cast<int>(i), _item.location()); arguments[i] = stackElement(m_stackHeight - static_cast<int>(i), _item.location());
switch (_item.instruction()) switch (_item.instruction())
{ {
case Instruction::SSTORE: case InternalInstruction::SSTORE:
op = storeInStorage(arguments[0], arguments[1], _item.location()); op = storeInStorage(arguments[0], arguments[1], _item.location());
break; break;
case Instruction::SLOAD: case InternalInstruction::SLOAD:
setStackElement( setStackElement(
m_stackHeight + static_cast<int>(_item.deposit()), m_stackHeight + static_cast<int>(_item.deposit()),
loadFromStorage(arguments[0], _item.location()) loadFromStorage(arguments[0], _item.location())
); );
break; break;
case Instruction::MSTORE: case InternalInstruction::MSTORE:
op = storeInMemory(arguments[0], arguments[1], _item.location()); op = storeInMemory(arguments[0], arguments[1], _item.location());
break; break;
case Instruction::MLOAD: case InternalInstruction::MLOAD:
setStackElement( setStackElement(
m_stackHeight + static_cast<int>(_item.deposit()), m_stackHeight + static_cast<int>(_item.deposit()),
loadFromMemory(arguments[0], _item.location()) loadFromMemory(arguments[0], _item.location())
); );
break; break;
case Instruction::KECCAK256: case InternalInstruction::KECCAK256:
setStackElement( setStackElement(
m_stackHeight + static_cast<int>(_item.deposit()), m_stackHeight + static_cast<int>(_item.deposit()),
applyKeccak256(arguments.at(0), arguments.at(1), _item.location()) applyKeccak256(arguments.at(0), arguments.at(1), _item.location())
@ -335,7 +335,7 @@ KnownState::StoreOperation KnownState::storeInStorage(
storageContents.insert(storageItem); storageContents.insert(storageItem);
m_storageContent = std::move(storageContents); 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); Id id = m_expressionClasses->find(item, {_slot, _value}, true, m_sequenceNumber);
StoreOperation operation{StoreOperation::Storage, _slot, m_sequenceNumber, id}; StoreOperation operation{StoreOperation::Storage, _slot, m_sequenceNumber, id};
m_storageContent[_slot] = _value; m_storageContent[_slot] = _value;
@ -350,7 +350,7 @@ ExpressionClasses::Id KnownState::loadFromStorage(Id _slot, SourceLocation const
if (m_storageContent.count(_slot)) if (m_storageContent.count(_slot))
return m_storageContent.at(_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); 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); memoryContents.insert(memoryItem);
m_memoryContent = std::move(memoryContents); 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); Id id = m_expressionClasses->find(item, {_slot, _value}, true, m_sequenceNumber);
StoreOperation operation{StoreOperation::Memory, _slot, m_sequenceNumber, id}; StoreOperation operation{StoreOperation::Memory, _slot, m_sequenceNumber, id};
m_memoryContent[_slot] = _value; m_memoryContent[_slot] = _value;
@ -381,7 +381,7 @@ ExpressionClasses::Id KnownState::loadFromMemory(Id _slot, SourceLocation const&
if (m_memoryContent.count(_slot)) if (m_memoryContent.count(_slot))
return m_memoryContent.at(_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); return m_memoryContent[_slot] = m_expressionClasses->find(item, {_slot}, true, m_sequenceNumber);
} }
@ -391,7 +391,7 @@ KnownState::Id KnownState::applyKeccak256(
SourceLocation const& _location 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. // Special logic if length is a short constant, otherwise we cannot tell.
u256 const* l = m_expressionClasses->knownConstant(_length); u256 const* l = m_expressionClasses->knownConstant(_length);
// unknown or too large length // unknown or too large length
@ -402,7 +402,7 @@ KnownState::Id KnownState::applyKeccak256(
for (unsigned i = 0; i < length; i += 32) for (unsigned i = 0; i < length; i += 32)
{ {
Id slot = m_expressionClasses->find( Id slot = m_expressionClasses->find(
AssemblyItem(Instruction::ADD, _location), AssemblyItem(InternalInstruction::ADD, _location),
{_start, m_expressionClasses->find(u256(i))} {_start, m_expressionClasses->find(u256(i))}
); );
arguments.push_back(loadFromMemory(slot, _location)); arguments.push_back(loadFromMemory(slot, _location));

View File

@ -88,7 +88,7 @@ GasMeter::GasConsumption PathGasMeter::handleQueueItem()
bool branchStops = false; bool branchStops = false;
jumpTags.clear(); jumpTags.clear();
AssemblyItem const& item = m_items.at(index); 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 // Do not allow any backwards jump. This is quite restrictive but should work for
// the simplest things. // the simplest things.
@ -96,14 +96,14 @@ GasMeter::GasConsumption PathGasMeter::handleQueueItem()
return GasMeter::GasConsumption::infinite(); return GasMeter::GasConsumption::infinite();
path->visitedJumpdests.insert(index); path->visitedJumpdests.insert(index);
} }
else if (item == AssemblyItem(Instruction::JUMP)) else if (item == AssemblyItem(InternalInstruction::JUMP))
{ {
branchStops = true; branchStops = true;
jumpTags = state->tagsInExpression(state->relativeStackElement(0)); jumpTags = state->tagsInExpression(state->relativeStackElement(0));
if (jumpTags.empty()) // unknown jump destination if (jumpTags.empty()) // unknown jump destination
return GasMeter::GasConsumption::infinite(); return GasMeter::GasConsumption::infinite();
} }
else if (item == AssemblyItem(Instruction::JUMPI)) else if (item == AssemblyItem(InternalInstruction::JUMPI))
{ {
ExpressionClasses::Id condition = state->relativeStackElement(-1); ExpressionClasses::Id condition = state->relativeStackElement(-1);
if (classes.knownNonZero(condition) || !classes.knownZero(condition)) 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>) static bool applySimple(AssemblyItem const& _push, AssemblyItem const& _pop, std::back_insert_iterator<AssemblyItems>)
{ {
auto t = _push.type(); auto t = _push.type();
return _pop == Instruction::POP && ( return _pop == InternalInstruction::POP && (
SemanticInformation::isDupInstruction(_push) || SemanticInformation::isDupInstruction(_push) ||
t == Push || t == PushTag || t == PushSub || t == Push || t == PushTag || t == PushSub ||
t == PushSubSize || t == PushProgramSize || t == PushData || t == PushLibraryAddress t == PushSubSize || t == PushProgramSize || t == PushData || t == PushLibraryAddress
@ -103,13 +103,13 @@ struct OpPop: SimplePeepholeOptimizerMethod<OpPop>
std::back_insert_iterator<AssemblyItems> _out 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) if (instructionInfo(instr).ret == 1 && !instructionInfo(instr).sideEffects)
{ {
for (int j = 0; j < instructionInfo(instr).args; j++) for (int j = 0; j < instructionInfo(instr).args; j++)
*_out = {Instruction::POP, _op.location()}; *_out = {InternalInstruction::POP, _op.location()};
return true; return true;
} }
} }
@ -125,20 +125,20 @@ struct OpStop: SimplePeepholeOptimizerMethod<OpStop>
std::back_insert_iterator<AssemblyItems> _out std::back_insert_iterator<AssemblyItems> _out
) )
{ {
if (_stop == Instruction::STOP) if (_stop == InternalInstruction::STOP)
{ {
if (_op.type() == Operation) if (_op.type() == Operation)
{ {
Instruction instr = _op.instruction(); InternalInstruction instr = _op.instruction();
if (!instructionInfo(instr).sideEffects) if (!instructionInfo(instr).sideEffects)
{ {
*_out = {Instruction::STOP, _op.location()}; *_out = {InternalInstruction::STOP, _op.location()};
return true; return true;
} }
} }
else if (_op.type() == Push) else if (_op.type() == Push)
{ {
*_out = {Instruction::STOP, _op.location()}; *_out = {InternalInstruction::STOP, _op.location()};
return true; return true;
} }
} }
@ -157,7 +157,7 @@ struct OpReturnRevert: SimplePeepholeOptimizerMethod<OpReturnRevert>
) )
{ {
if ( if (
(_returnRevert == Instruction::RETURN || _returnRevert == Instruction::REVERT) && (_returnRevert == InternalInstruction::RETURN || _returnRevert == InternalInstruction::REVERT) &&
_push.type() == Push && _push.type() == Push &&
(_pushOrDup.type() == Push || _pushOrDup == dupInstruction(1)) (_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()) if (_push1.type() == Push && _push2.type() == Push && _push1.data() == _push2.data())
{ {
*_out = _push1; *_out = _push1;
*_out = {Instruction::DUP1, _push2.location()}; *_out = {InternalInstruction::DUP1, _push2.location()};
return true; return true;
} }
else else
@ -204,7 +204,7 @@ struct CommutativeSwap: SimplePeepholeOptimizerMethod<CommutativeSwap>
{ {
// Remove SWAP1 if following instruction is commutative // Remove SWAP1 if following instruction is commutative
if ( if (
_swap == Instruction::SWAP1 && _swap == InternalInstruction::SWAP1 &&
SemanticInformation::isCommutativeOperation(_op) 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 bool applySimple(AssemblyItem const& _swap, AssemblyItem const& _op, std::back_insert_iterator<AssemblyItems> _out)
{ {
static map<Instruction, Instruction> const swappableOps{ static map<InternalInstruction, InternalInstruction> const swappableOps{
{ Instruction::LT, Instruction::GT }, { InternalInstruction::LT, InternalInstruction::GT },
{ Instruction::GT, Instruction::LT }, { InternalInstruction::GT, InternalInstruction::LT },
{ Instruction::SLT, Instruction::SGT }, { InternalInstruction::SLT, InternalInstruction::SGT },
{ Instruction::SGT, Instruction::SLT } { InternalInstruction::SGT, InternalInstruction::SLT }
}; };
if ( if (
_swap == Instruction::SWAP1 && _swap == InternalInstruction::SWAP1 &&
_op.type() == Operation && _op.type() == Operation &&
swappableOps.count(_op.instruction()) swappableOps.count(_op.instruction())
) )
@ -276,10 +276,10 @@ struct IsZeroIsZeroJumpI: SimplePeepholeOptimizerMethod<IsZeroIsZeroJumpI>
) )
{ {
if ( if (
_iszero1 == Instruction::ISZERO && _iszero1 == InternalInstruction::ISZERO &&
_iszero2 == Instruction::ISZERO && _iszero2 == InternalInstruction::ISZERO &&
_pushTag.type() == PushTag && _pushTag.type() == PushTag &&
_jumpi == Instruction::JUMPI _jumpi == InternalInstruction::JUMPI
) )
{ {
*_out = _pushTag; *_out = _pushTag;
@ -302,13 +302,13 @@ struct EqIsZeroJumpI: SimplePeepholeOptimizerMethod<EqIsZeroJumpI>
) )
{ {
if ( if (
_eq == Instruction::EQ && _eq == InternalInstruction::EQ &&
_iszero == Instruction::ISZERO && _iszero == InternalInstruction::ISZERO &&
_pushTag.type() == PushTag && _pushTag.type() == PushTag &&
_jumpi == Instruction::JUMPI _jumpi == InternalInstruction::JUMPI
) )
{ {
*_out = AssemblyItem(Instruction::SUB, _eq.location()); *_out = AssemblyItem(InternalInstruction::SUB, _eq.location());
*_out = _pushTag; *_out = _pushTag;
*_out = _jumpi; *_out = _jumpi;
return true; return true;
@ -332,14 +332,14 @@ struct DoubleJump: SimplePeepholeOptimizerMethod<DoubleJump>
{ {
if ( if (
_pushTag1.type() == PushTag && _pushTag1.type() == PushTag &&
_jumpi == Instruction::JUMPI && _jumpi == InternalInstruction::JUMPI &&
_pushTag2.type() == PushTag && _pushTag2.type() == PushTag &&
_jump == Instruction::JUMP && _jump == InternalInstruction::JUMP &&
_tag1.type() == Tag && _tag1.type() == Tag &&
_pushTag1.data() == _tag1.data() _pushTag1.data() == _tag1.data()
) )
{ {
*_out = AssemblyItem(Instruction::ISZERO, _jumpi.location()); *_out = AssemblyItem(InternalInstruction::ISZERO, _jumpi.location());
*_out = _pushTag2; *_out = _pushTag2;
*_out = _jumpi; *_out = _jumpi;
*_out = _tag1; *_out = _tag1;
@ -361,13 +361,13 @@ struct JumpToNext: SimplePeepholeOptimizerMethod<JumpToNext>
{ {
if ( if (
_pushTag.type() == PushTag && _pushTag.type() == PushTag &&
(_jump == Instruction::JUMP || _jump == Instruction::JUMPI) && (_jump == InternalInstruction::JUMP || _jump == InternalInstruction::JUMPI) &&
_tag.type() == Tag && _tag.type() == Tag &&
_pushTag.data() == _tag.data() _pushTag.data() == _tag.data()
) )
{ {
if (_jump == Instruction::JUMPI) if (_jump == InternalInstruction::JUMPI)
*_out = AssemblyItem(Instruction::POP, _jump.location()); *_out = AssemblyItem(InternalInstruction::POP, _jump.location());
*_out = _tag; *_out = _tag;
return true; return true;
} }
@ -385,7 +385,7 @@ struct TagConjunctions: SimplePeepholeOptimizerMethod<TagConjunctions>
std::back_insert_iterator<AssemblyItems> _out std::back_insert_iterator<AssemblyItems> _out
) )
{ {
if (_and != Instruction::AND) if (_and != InternalInstruction::AND)
return false; return false;
if ( if (
_pushTag.type() == PushTag && _pushTag.type() == PushTag &&
@ -422,8 +422,8 @@ struct TruthyAnd: SimplePeepholeOptimizerMethod<TruthyAnd>
{ {
return ( return (
_push.type() == Push && _push.data() == 0 && _push.type() == Push && _push.data() == 0 &&
_not == Instruction::NOT && _not == InternalInstruction::NOT &&
_and == Instruction::AND _and == InternalInstruction::AND
); );
} }
}; };
@ -438,12 +438,12 @@ struct UnreachableCode
if (it == end) if (it == end)
return false; return false;
if ( if (
it[0] != Instruction::JUMP && it[0] != InternalInstruction::JUMP &&
it[0] != Instruction::RETURN && it[0] != InternalInstruction::RETURN &&
it[0] != Instruction::STOP && it[0] != InternalInstruction::STOP &&
it[0] != Instruction::INVALID && it[0] != InternalInstruction::INVALID &&
it[0] != Instruction::SELFDESTRUCT && it[0] != InternalInstruction::SELFDESTRUCT &&
it[0] != Instruction::REVERT it[0] != InternalInstruction::REVERT
) )
return false; return false;
@ -475,7 +475,7 @@ void applyMethods(OptimiserState& _state, Method, OtherMethods... _other)
size_t numberOfPops(AssemblyItems const& _items) 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: { for (auto instr: {
Instruction::ADDRESS, InternalInstruction::ADDRESS,
Instruction::CALLER, InternalInstruction::CALLER,
Instruction::ORIGIN, InternalInstruction::ORIGIN,
Instruction::COINBASE InternalInstruction::COINBASE
}) })
{ {
assertThrow(Pattern::WordSize > 160, OptimizerException, ""); assertThrow(Pattern::WordSize > 160, OptimizerException, "");
@ -402,11 +402,11 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleListPart6(
std::vector<SimplificationRule<Pattern>> rules; std::vector<SimplificationRule<Pattern>> rules;
// Double negation of opcodes with boolean result // Double negation of opcodes with boolean result
for (auto instr: { for (auto instr: {
Instruction::EQ, InternalInstruction::EQ,
Instruction::LT, InternalInstruction::LT,
Instruction::SLT, InternalInstruction::SLT,
Instruction::GT, InternalInstruction::GT,
Instruction::SGT InternalInstruction::SGT
}) })
{ {
typename Builtins::PatternGeneratorInstance op{instr}; typename Builtins::PatternGeneratorInstance op{instr};
@ -448,12 +448,12 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleListPart7(
std::vector<SimplificationRule<Pattern>> rules; std::vector<SimplificationRule<Pattern>> rules;
// Associative operations // Associative operations
for (auto&& instrAndFunc: std::vector<std::pair<Instruction, std::function<Word(Word, Word)>>>{ for (auto&& instrAndFunc: std::vector<std::pair<InternalInstruction, std::function<Word(Word, Word)>>>{
{Instruction::ADD, std::plus<Word>()}, {InternalInstruction::ADD, std::plus<Word>()},
{Instruction::MUL, std::multiplies<Word>()}, {InternalInstruction::MUL, std::multiplies<Word>()},
{Instruction::AND, std::bit_and<Word>()}, {InternalInstruction::AND, std::bit_and<Word>()},
{Instruction::OR, std::bit_or<Word>()}, {InternalInstruction::OR, std::bit_or<Word>()},
{Instruction::XOR, std::bit_xor<Word>()} {InternalInstruction::XOR, std::bit_xor<Word>()}
}) })
{ {
typename Builtins::PatternGeneratorInstance op{instrAndFunc.first}; 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 // 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}; typename Builtins::PatternGeneratorInstance shiftOp{instr};
auto replacement = [=]() -> Pattern { auto replacement = [=]() -> Pattern {
Word mask = Word mask =
instr == Instruction::SHL ? instr == InternalInstruction::SHL ?
shlWorkaround(A.d(), unsigned(B.d())) : shlWorkaround(A.d(), unsigned(B.d())) :
A.d() >> unsigned(B.d()); A.d() >> unsigned(B.d());
return Builtins::AND(shiftOp(B.d(), X), std::move(mask)); return Builtins::AND(shiftOp(B.d(), X), std::move(mask));
@ -743,8 +743,8 @@ std::vector<SimplificationRule<Pattern>> evmRuleList(
if (_evmVersion.hasSelfBalance()) if (_evmVersion.hasSelfBalance())
rules.push_back({ rules.push_back({
Builtins::BALANCE(Instruction::ADDRESS), Builtins::BALANCE(InternalInstruction::ADDRESS),
[]() -> Pattern { return Instruction::SELFBALANCE; } []() -> Pattern { return InternalInstruction::SELFBALANCE; }
}); });
rules.emplace_back( rules.emplace_back(

View File

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

View File

@ -72,7 +72,7 @@ struct SemanticInformation
/// Order matters. /// Order matters.
/// For external calls, there is just one unknown read and one unknown write operation, /// For external calls, there is just one unknown read and one unknown write operation,
/// event though there might be multiple. /// 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. /// @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. /// @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 isSwapInstruction(AssemblyItem const& _item);
static bool isJumpInstruction(AssemblyItem const& _item); static bool isJumpInstruction(AssemblyItem const& _item);
static bool altersControlFlow(AssemblyItem const& _item); static bool altersControlFlow(AssemblyItem const& _item);
static bool terminatesControlFlow(Instruction _instruction); static bool terminatesControlFlow(InternalInstruction _instruction);
static bool reverts(Instruction _instruction); static bool reverts(InternalInstruction _instruction);
/// @returns false if the value put on the stack by _item depends on anything else than /// @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. /// the information in the current block header, memory, storage or stack.
static bool isDeterministic(AssemblyItem const& _item); static bool isDeterministic(AssemblyItem const& _item);
/// @returns true if the instruction can be moved or copied (together with its arguments) /// @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, /// 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. /// 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) /// 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 /// across control flow branches and instructions as long as these instructions' 'effects' do
/// not influence the 'effects' of the aforementioned expressions. /// 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. /// @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 /// This does not mean that it has to be deterministic or retrieve information from
/// somewhere else than purely the values of its arguments. /// 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. /// @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 /// This does not mean that it has to be deterministic or retrieve information from
/// somewhere else than purely the values of its arguments. /// somewhere else than purely the values of its arguments.
/// If true, the instruction is still allowed to influence the value returned by the /// If true, the instruction is still allowed to influence the value returned by the
/// msize instruction. /// msize instruction.
static bool canBeRemovedIfNoMSize(Instruction _instruction); static bool canBeRemovedIfNoMSize(InternalInstruction _instruction);
static Effect memory(Instruction _instruction); static Effect memory(InternalInstruction _instruction);
static Effect storage(Instruction _instruction); static Effect storage(InternalInstruction _instruction);
static Effect otherState(Instruction _instruction); static Effect otherState(InternalInstruction _instruction);
static bool invalidInPureFunctions(Instruction _instruction); static bool invalidInPureFunctions(InternalInstruction _instruction);
static bool invalidInViewFunctions(Instruction _instruction); static bool invalidInViewFunctions(InternalInstruction _instruction);
}; };
} }

View File

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

View File

@ -58,7 +58,7 @@ SimplificationRule<Pattern> const* Rules::findFirstMatch(
bool Rules::isInitialized() const 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) void Rules::addRules(std::vector<SimplificationRule<Pattern>> const& _rules)
@ -96,7 +96,7 @@ Rules::Rules()
assertThrow(isInitialized(), OptimizerException, "Rule list not properly initialized."); 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_type(Operation),
m_instruction(_instruction), m_instruction(_instruction),
m_arguments(_arguments) m_arguments(_arguments)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -702,7 +702,7 @@ bool AsmAnalyzer::validateInstructions(std::string const& _instructionIdentifier
return false; 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 // We assume that returndatacopy, returndatasize and staticcall are either all available
// or all not available. // or all not available.
@ -712,9 +712,9 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio
// These instructions are disabled in the dialect. // These instructions are disabled in the dialect.
yulAssert( yulAssert(
_instr != evmasm::Instruction::JUMP && _instr != evmasm::InternalInstruction::JUMP &&
_instr != evmasm::Instruction::JUMPI && _instr != evmasm::InternalInstruction::JUMPI &&
_instr != evmasm::Instruction::JUMPDEST, _instr != evmasm::InternalInstruction::JUMPDEST,
""); "");
bool returnValue = true; bool returnValue = true;
@ -733,29 +733,29 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio
returnValue = false; 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); errorForVM(5430_error, "only available for London-compatible");
else if (_instr == evmasm::Instruction::PC) else if (_instr == evmasm::InternalInstruction::PC)
m_errorReporter.error( m_errorReporter.error(
2450_error, 2450_error,
Error::Type::SyntaxError, Error::Type::SyntaxError,

View File

@ -114,7 +114,7 @@ private:
void expectValidType(YulString _type, langutil::SourceLocation const& _location); void expectValidType(YulString _type, langutil::SourceLocation const& _location);
void expectType(YulString _expectedType, YulString _givenType, 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(std::string const& _instrIdentifier, langutil::SourceLocation const& _location);
bool validateInstructions(FunctionCall const& _functionCall); bool validateInstructions(FunctionCall const& _functionCall);

View File

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

View File

@ -48,24 +48,24 @@ struct MiniEVMInterpreter
return std::visit(*this, _expr); 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; vector<u256> args;
for (auto const& arg: _arguments) for (auto const& arg: _arguments)
args.emplace_back(eval(arg)); args.emplace_back(eval(arg));
switch (_instr) switch (_instr)
{ {
case evmasm::Instruction::ADD: case evmasm::InternalInstruction::ADD:
return args.at(0) + args.at(1); return args.at(0) + args.at(1);
case evmasm::Instruction::SUB: case evmasm::InternalInstruction::SUB:
return args.at(0) - args.at(1); return args.at(0) - args.at(1);
case evmasm::Instruction::MUL: case evmasm::InternalInstruction::MUL:
return args.at(0) * args.at(1); return args.at(0) * args.at(1);
case evmasm::Instruction::EXP: case evmasm::InternalInstruction::EXP:
return exp256(args.at(0), args.at(1)); 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))); 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); return ~args.at(0);
default: default:
yulAssert(false, "Invalid operation generated in constant optimizer."); 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)) while (m_unusedStackSlots.count(m_assembly.stackHeight() - 1))
{ {
yulAssert(m_unusedStackSlots.erase(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) if (atTopOfStack)
{ {
m_context->variableStackHeights.erase(&var); m_context->variableStackHeights.erase(&var);
m_assembly.appendInstruction(evmasm::Instruction::POP); m_assembly.appendInstruction(evmasm::InternalInstruction::POP);
} }
else else
m_variablesScheduledForDeletion.insert(&var); m_variablesScheduledForDeletion.insert(&var);
@ -186,7 +186,7 @@ void CodeTransform::operator()(VariableDeclaration const& _varDecl)
m_context->variableStackHeights[&var] = slot; m_context->variableStackHeights[&var] = slot;
if (size_t heightDiff = variableHeightDiff(var, varName, true)) if (size_t heightDiff = variableHeightDiff(var, varName, true))
m_assembly.appendInstruction(evmasm::swapInstruction(static_cast<unsigned>(heightDiff - 1))); m_assembly.appendInstruction(evmasm::swapInstruction(static_cast<unsigned>(heightDiff - 1)));
m_assembly.appendInstruction(evmasm::Instruction::POP); m_assembly.appendInstruction(evmasm::InternalInstruction::POP);
break; break;
} }
if (!foundUnusedSlot) if (!foundUnusedSlot)
@ -197,10 +197,10 @@ void CodeTransform::operator()(VariableDeclaration const& _varDecl)
void CodeTransform::stackError(StackTooDeepError _error, int _targetStackHeight) void CodeTransform::stackError(StackTooDeepError _error, int _targetStackHeight)
{ {
m_assembly.appendInstruction(evmasm::Instruction::INVALID); m_assembly.appendInstruction(evmasm::InternalInstruction::INVALID);
// Correct the stack. // Correct the stack.
while (m_assembly.stackHeight() > _targetStackHeight) while (m_assembly.stackHeight() > _targetStackHeight)
m_assembly.appendInstruction(evmasm::Instruction::POP); m_assembly.appendInstruction(evmasm::InternalInstruction::POP);
while (m_assembly.stackHeight() < _targetStackHeight) while (m_assembly.stackHeight() < _targetStackHeight)
m_assembly.appendConstant(u256(0)); m_assembly.appendConstant(u256(0));
// Store error. // Store error.
@ -303,7 +303,7 @@ void CodeTransform::operator()(If const& _if)
{ {
visitExpression(*_if.condition); visitExpression(*_if.condition);
m_assembly.setSourceLocation(originLocationOf(_if)); m_assembly.setSourceLocation(originLocationOf(_if));
m_assembly.appendInstruction(evmasm::Instruction::ISZERO); m_assembly.appendInstruction(evmasm::InternalInstruction::ISZERO);
AbstractAssembly::LabelID end = m_assembly.newLabelId(); AbstractAssembly::LabelID end = m_assembly.newLabelId();
m_assembly.appendJumpToIf(end); m_assembly.appendJumpToIf(end);
(*this)(_if.body); (*this)(_if.body);
@ -327,7 +327,7 @@ void CodeTransform::operator()(Switch const& _switch)
caseBodies[&c] = bodyLabel; caseBodies[&c] = bodyLabel;
yulAssert(m_assembly.stackHeight() == expressionHeight + 1, ""); yulAssert(m_assembly.stackHeight() == expressionHeight + 1, "");
m_assembly.appendInstruction(evmasm::dupInstruction(2)); m_assembly.appendInstruction(evmasm::dupInstruction(2));
m_assembly.appendInstruction(evmasm::Instruction::EQ); m_assembly.appendInstruction(evmasm::InternalInstruction::EQ);
m_assembly.appendJumpToIf(bodyLabel); m_assembly.appendJumpToIf(bodyLabel);
} }
else else
@ -353,7 +353,7 @@ void CodeTransform::operator()(Switch const& _switch)
m_assembly.setSourceLocation(originLocationOf(_switch)); m_assembly.setSourceLocation(originLocationOf(_switch));
m_assembly.appendLabel(end); m_assembly.appendLabel(end);
m_assembly.appendInstruction(evmasm::Instruction::POP); m_assembly.appendInstruction(evmasm::InternalInstruction::POP);
} }
void CodeTransform::operator()(FunctionDefinition const& _function) 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)) while (!stackLayout.empty() && stackLayout.back() != static_cast<int>(stackLayout.size() - 1))
if (stackLayout.back() < 0) if (stackLayout.back() < 0)
{ {
m_assembly.appendInstruction(evmasm::Instruction::POP); m_assembly.appendInstruction(evmasm::InternalInstruction::POP);
stackLayout.pop_back(); stackLayout.pop_back();
} }
else else
@ -508,7 +508,7 @@ void CodeTransform::operator()(ForLoop const& _forLoop)
visitExpression(*_forLoop.condition); visitExpression(*_forLoop.condition);
m_assembly.setSourceLocation(originLocationOf(_forLoop)); m_assembly.setSourceLocation(originLocationOf(_forLoop));
m_assembly.appendInstruction(evmasm::Instruction::ISZERO); m_assembly.appendInstruction(evmasm::InternalInstruction::ISZERO);
m_assembly.appendJumpToIf(loopEnd); m_assembly.appendJumpToIf(loopEnd);
int const stackHeightBody = m_assembly.stackHeight(); int const stackHeightBody = m_assembly.stackHeight();
@ -533,7 +533,7 @@ int CodeTransform::appendPopUntil(int _targetDepth)
{ {
int const stackDiffAfter = m_assembly.stackHeight() - _targetDepth; int const stackDiffAfter = m_assembly.stackHeight() - _targetDepth;
for (int i = 0; i < stackDiffAfter; ++i) for (int i = 0; i < stackDiffAfter; ++i)
m_assembly.appendInstruction(evmasm::Instruction::POP); m_assembly.appendInstruction(evmasm::InternalInstruction::POP);
return stackDiffAfter; return stackDiffAfter;
} }
@ -733,7 +733,7 @@ void CodeTransform::finalizeBlock(Block const& _block, optional<int> blockStartS
yulAssert(!m_context->variableReferences.count(&var), ""); yulAssert(!m_context->variableReferences.count(&var), "");
} }
else else
m_assembly.appendInstruction(evmasm::Instruction::POP); m_assembly.appendInstruction(evmasm::InternalInstruction::POP);
} }
if (blockStartStackHeight) if (blockStartStackHeight)
@ -758,7 +758,7 @@ void CodeTransform::generateAssignment(Identifier const& _variableName)
Scope::Variable const& _var = std::get<Scope::Variable>(*var); Scope::Variable const& _var = std::get<Scope::Variable>(*var);
if (size_t heightDiff = variableHeightDiff(_var, _variableName.name, true)) if (size_t heightDiff = variableHeightDiff(_var, _variableName.name, true))
m_assembly.appendInstruction(evmasm::swapInstruction(static_cast<unsigned>(heightDiff - 1))); 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); decreaseReference(_variableName.name, _var);
} }
else else

View File

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

View File

@ -50,7 +50,7 @@ struct BuiltinContext
struct BuiltinFunctionForEVM: public BuiltinFunction 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 /// 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 /// assembly. Expects all non-literal arguments of the call to be on stack in reverse order
/// (i.e. right-most argument pushed first). /// (i.e. right-most argument pushed first).
@ -91,7 +91,7 @@ struct EVMDialect: public Dialect
bool providesObjectAccess() const { return m_objectAccess; } bool providesObjectAccess() const { return m_objectAccess; }
static SideEffects sideEffectsOfInstruction(evmasm::Instruction _instruction); static SideEffects sideEffectsOfInstruction(evmasm::InternalInstruction _instruction);
protected: protected:
BuiltinFunctionForEVM const* verbatimFunction(size_t _arguments, size_t _returnVariables) const; 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)); 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)); return combineCosts(GasMeterVisitor::instructionCosts(_instruction, m_dialect, m_isCreation));
} }
@ -64,7 +64,7 @@ pair<bigint, bigint> GasMeterVisitor::costs(
} }
pair<bigint, bigint> GasMeterVisitor::instructionCosts( pair<bigint, bigint> GasMeterVisitor::instructionCosts(
evmasm::Instruction _instruction, evmasm::InternalInstruction _instruction,
EVMDialect const& _dialect, EVMDialect const& _dialect,
bool _isCreation bool _isCreation
) )
@ -88,7 +88,7 @@ void GasMeterVisitor::operator()(FunctionCall const& _funCall)
void GasMeterVisitor::operator()(Literal const& _lit) void GasMeterVisitor::operator()(Literal const& _lit)
{ {
m_runGas += evmasm::GasMeter::runGas(evmasm::Instruction::PUSH1); m_runGas += evmasm::GasMeter::runGas(evmasm::InternalInstruction::PUSH1);
m_dataGas += m_dataGas +=
singleByteDataGas() + singleByteDataGas() +
evmasm::GasMeter::dataGas( evmasm::GasMeter::dataGas(
@ -100,7 +100,7 @@ void GasMeterVisitor::operator()(Literal const& _lit)
void GasMeterVisitor::operator()(Identifier const&) void GasMeterVisitor::operator()(Identifier const&)
{ {
m_runGas += evmasm::GasMeter::runGas(evmasm::Instruction::DUP1); m_runGas += evmasm::GasMeter::runGas(evmasm::InternalInstruction::DUP1);
m_dataGas += singleByteDataGas(); m_dataGas += singleByteDataGas();
} }
@ -112,11 +112,11 @@ bigint GasMeterVisitor::singleByteDataGas() const
return evmasm::GasCosts::createDataGas; 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()); 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). // Assumes that Keccak-256 is computed on a single word (rounded up).
m_runGas += evmasm::GasCosts::keccak256Gas + evmasm::GasCosts::keccak256WordGas; m_runGas += evmasm::GasCosts::keccak256Gas + evmasm::GasCosts::keccak256WordGas;
else else

View File

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

View File

@ -59,7 +59,7 @@ void EthAssemblyAdapter::setStackHeight(int height)
m_assembly.setDeposit(height); m_assembly.setDeposit(height);
} }
void EthAssemblyAdapter::appendInstruction(evmasm::Instruction _instruction) void EthAssemblyAdapter::appendInstruction(evmasm::InternalInstruction _instruction)
{ {
m_assembly.append(_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) void EthAssemblyAdapter::appendJump(int _stackDiffAfter, JumpType _jumpType)
{ {
appendJumpInstruction(evmasm::Instruction::JUMP, _jumpType); appendJumpInstruction(evmasm::InternalInstruction::JUMP, _jumpType);
m_assembly.adjustDeposit(_stackDiffAfter); m_assembly.adjustDeposit(_stackDiffAfter);
} }
@ -114,7 +114,7 @@ void EthAssemblyAdapter::appendJumpTo(LabelID _labelId, int _stackDiffAfter, Jum
void EthAssemblyAdapter::appendJumpToIf(LabelID _labelId, JumpType _jumpType) void EthAssemblyAdapter::appendJumpToIf(LabelID _labelId, JumpType _jumpType)
{ {
appendLabelReference(_labelId); appendLabelReference(_labelId);
appendJumpInstruction(evmasm::Instruction::JUMPI, _jumpType); appendJumpInstruction(evmasm::InternalInstruction::JUMPI, _jumpType);
} }
void EthAssemblyAdapter::appendAssemblySize() void EthAssemblyAdapter::appendAssemblySize()
@ -188,9 +188,9 @@ EthAssemblyAdapter::LabelID EthAssemblyAdapter::assemblyTagToIdentifier(evmasm::
return LabelID(id); 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); evmasm::AssemblyItem jump(_instruction);
switch (_jumpType) switch (_jumpType)
{ {

View File

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

View File

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

View File

@ -51,7 +51,7 @@ public:
void setSourceLocation(langutil::SourceLocation const&) override {} void setSourceLocation(langutil::SourceLocation const&) override {}
int stackHeight() const override { return m_stackHeight; } int stackHeight() const override { return m_stackHeight; }
void setStackHeight(int height) override { m_stackHeight = height; } 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 appendConstant(u256 const& _constant) override;
void appendLabel(LabelID _labelId) override; void appendLabel(LabelID _labelId) override;
void appendLabelReference(LabelID _labelId) override; void appendLabelReference(LabelID _labelId) override;

View File

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

View File

@ -763,7 +763,7 @@ void StackLayoutGenerator::fillInJunk(CFG::BasicBlock const& _block)
opGas += 1000; 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); createStackLayout(_source, _target, swap, dupOrPush, pop);
return opGas; return opGas;
}; };

View File

@ -50,7 +50,7 @@ void ExpressionSimplifier::visit(Expression& _expression)
_expression = match->action().toExpression(debugDataOf(_expression)); _expression = match->action().toExpression(debugDataOf(_expression));
if (auto* functionCall = get_if<FunctionCall>(&_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)) for (auto op: evmasm::SemanticInformation::readWriteOperations(*instruction))
if (op.startParameter && op.lengthParameter) if (op.startParameter && op.lengthParameter)
{ {

View File

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

View File

@ -124,7 +124,7 @@ private:
void visit(Expression const& _expression) override; void visit(Expression const& _expression) override;
private: private:
void addInstructionCost(evmasm::Instruction _instruction); void addInstructionCost(evmasm::InternalInstruction _instruction);
Dialect const& m_dialect; Dialect const& m_dialect;
size_t m_cost = 0; 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); 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 (auto const* dialect = dynamic_cast<EVMDialect const*>(&_dialect))
if (BuiltinFunctionForEVM const* builtin = dialect->builtin(_name)) if (BuiltinFunctionForEVM const* builtin = dialect->builtin(_name))

View File

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

View File

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

View File

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

View File

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

View File

@ -72,10 +72,10 @@ SimplificationRules::Rule const* SimplificationRules::findFirstMatch(
bool SimplificationRules::isInitialized() const 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) SimplificationRules::instructionAndArguments(Dialect const& _dialect, Expression const& _expr)
{ {
if (holds_alternative<FunctionCall>(_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."); 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_kind(PatternKind::Operation),
m_instruction(_instruction), m_instruction(_instruction),
m_arguments(_arguments) m_arguments(_arguments)
@ -229,7 +229,7 @@ bool Pattern::matches(
return true; return true;
} }
evmasm::Instruction Pattern::instruction() const evmasm::InternalInstruction Pattern::instruction() const
{ {
assertThrow(m_kind == PatternKind::Operation, OptimizerException, ""); assertThrow(m_kind == PatternKind::Operation, OptimizerException, "");
return m_instruction; return m_instruction;

View File

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

View File

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

View File

@ -74,12 +74,12 @@ BOOST_AUTO_TEST_CASE(all_assembly_items)
// PushImmutable // PushImmutable
_subAsm.appendImmutable("someImmutable"); _subAsm.appendImmutable("someImmutable");
_subAsm.append(AssemblyItem(PushTag, 0)); _subAsm.append(AssemblyItem(PushTag, 0));
_subAsm.append(Instruction::INVALID); _subAsm.append(InternalInstruction::INVALID);
shared_ptr<Assembly> _subAsmPtr = make_shared<Assembly>(_subAsm); shared_ptr<Assembly> _subAsmPtr = make_shared<Assembly>(_subAsm);
_verbatimAsm.appendVerbatim({0xff,0xff}, 0, 0); _verbatimAsm.appendVerbatim({0xff,0xff}, 0, 0);
_verbatimAsm.appendVerbatim({0x74, 0x65, 0x73, 0x74}, 0, 1); _verbatimAsm.appendVerbatim({0x74, 0x65, 0x73, 0x74}, 0, 1);
_verbatimAsm.append(Instruction::MSTORE); _verbatimAsm.append(InternalInstruction::MSTORE);
shared_ptr<Assembly> _verbatimAsmPtr = make_shared<Assembly>(_verbatimAsm); shared_ptr<Assembly> _verbatimAsmPtr = make_shared<Assembly>(_verbatimAsm);
// Tag // Tag
@ -89,7 +89,7 @@ BOOST_AUTO_TEST_CASE(all_assembly_items)
_assembly.append(u256(1)); _assembly.append(u256(1));
_assembly.append(u256(2)); _assembly.append(u256(2));
// Push // Push
auto keccak256 = AssemblyItem(Instruction::KECCAK256); auto keccak256 = AssemblyItem(InternalInstruction::KECCAK256);
_assembly.m_currentModifierDepth = 1; _assembly.m_currentModifierDepth = 1;
_assembly.append(keccak256); _assembly.append(keccak256);
_assembly.m_currentModifierDepth = 0; _assembly.m_currentModifierDepth = 0;
@ -117,7 +117,7 @@ BOOST_AUTO_TEST_CASE(all_assembly_items)
_assembly.append(u256(2)); _assembly.append(u256(2));
_assembly.appendImmutableAssignment("someImmutable"); _assembly.appendImmutableAssignment("someImmutable");
// Operation // Operation
_assembly.append(Instruction::STOP); _assembly.append(InternalInstruction::STOP);
_assembly.appendToAuxiliaryData(bytes{0x42, 0x66}); _assembly.appendToAuxiliaryData(bytes{0x42, 0x66});
_assembly.appendToAuxiliaryData(bytes{0xee, 0xaa}); _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 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()); 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 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()); 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 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}); 0x12, 0x34, 0x56, 0x78, 0x90});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); 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 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()); 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 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()); 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 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()); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
} }
@ -285,22 +285,22 @@ BOOST_AUTO_TEST_CASE(comparison)
bytes expectation; bytes expectation;
if (solidity::test::CommonOptions::get().optimize) if (solidity::test::CommonOptions::get().optimize)
expectation = { expectation = {
uint8_t(Instruction::PUSH2), 0x11, 0xaa, uint8_t(InternalInstruction::PUSH2), 0x11, 0xaa,
uint8_t(Instruction::PUSH2), 0x10, 0xaa, uint8_t(InternalInstruction::PUSH2), 0x10, 0xaa,
uint8_t(Instruction::LT), uint8_t(Instruction::ISZERO), uint8_t(Instruction::ISZERO), uint8_t(InternalInstruction::LT), uint8_t(InternalInstruction::ISZERO), uint8_t(InternalInstruction::ISZERO),
uint8_t(Instruction::PUSH1), 0x1, uint8_t(InternalInstruction::PUSH1), 0x1,
uint8_t(Instruction::ISZERO), uint8_t(Instruction::ISZERO), uint8_t(InternalInstruction::ISZERO), uint8_t(InternalInstruction::ISZERO),
uint8_t(Instruction::EQ), uint8_t(InternalInstruction::EQ),
uint8_t(Instruction::ISZERO) uint8_t(InternalInstruction::ISZERO)
}; };
else else
expectation = { expectation = {
uint8_t(Instruction::PUSH1), 0x1, uint8_t(Instruction::ISZERO), uint8_t(Instruction::ISZERO), uint8_t(InternalInstruction::PUSH1), 0x1, uint8_t(InternalInstruction::ISZERO), uint8_t(InternalInstruction::ISZERO),
uint8_t(Instruction::PUSH2), 0x11, 0xaa, uint8_t(InternalInstruction::PUSH2), 0x11, 0xaa,
uint8_t(Instruction::PUSH2), 0x10, 0xaa, uint8_t(InternalInstruction::PUSH2), 0x10, 0xaa,
uint8_t(Instruction::LT), uint8_t(Instruction::ISZERO), uint8_t(Instruction::ISZERO), uint8_t(InternalInstruction::LT), uint8_t(InternalInstruction::ISZERO), uint8_t(InternalInstruction::ISZERO),
uint8_t(Instruction::EQ), uint8_t(InternalInstruction::EQ),
uint8_t(Instruction::ISZERO) uint8_t(InternalInstruction::ISZERO)
}; };
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); 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 code = compileFirstExpression(sourceCode);
bytes expectation{ bytes expectation{
uint8_t(Instruction::PUSH1), 0x12, // 8 + 10 uint8_t(InternalInstruction::PUSH1), 0x12, // 8 + 10
uint8_t(Instruction::PUSH1), 0x4, uint8_t(InternalInstruction::PUSH1), 0x4,
uint8_t(Instruction::GT), uint8_t(InternalInstruction::GT),
uint8_t(Instruction::ISZERO), // after this we have 4 <= 8 + 10 uint8_t(InternalInstruction::ISZERO), // after this we have 4 <= 8 + 10
uint8_t(Instruction::DUP1), uint8_t(InternalInstruction::DUP1),
uint8_t(Instruction::PUSH1), 0x11, uint8_t(InternalInstruction::PUSH1), 0x11,
uint8_t(Instruction::JUMPI), // short-circuit if it is true uint8_t(InternalInstruction::JUMPI), // short-circuit if it is true
uint8_t(Instruction::POP), uint8_t(InternalInstruction::POP),
uint8_t(Instruction::PUSH1), 0x2, uint8_t(InternalInstruction::PUSH1), 0x2,
uint8_t(Instruction::PUSH1), 0x9, uint8_t(InternalInstruction::PUSH1), 0x9,
uint8_t(Instruction::EQ), uint8_t(InternalInstruction::EQ),
uint8_t(Instruction::ISZERO), // after this we have 9 != 2 uint8_t(InternalInstruction::ISZERO), // after this we have 9 != 2
uint8_t(Instruction::JUMPDEST), uint8_t(InternalInstruction::JUMPDEST),
uint8_t(Instruction::ISZERO), uint8_t(Instruction::ISZERO), uint8_t(InternalInstruction::ISZERO), uint8_t(InternalInstruction::ISZERO),
uint8_t(Instruction::PUSH1), 0x1, uint8_t(Instruction::ISZERO), uint8_t(Instruction::ISZERO), uint8_t(InternalInstruction::PUSH1), 0x1, uint8_t(InternalInstruction::ISZERO), uint8_t(InternalInstruction::ISZERO),
uint8_t(Instruction::EQ), uint8_t(InternalInstruction::EQ),
uint8_t(Instruction::ISZERO) uint8_t(InternalInstruction::ISZERO)
}; };
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
} }
@ -347,108 +347,108 @@ BOOST_AUTO_TEST_CASE(arithmetic)
bytes panic = bytes panic =
bytes{ bytes{
uint8_t(Instruction::JUMPDEST), uint8_t(InternalInstruction::JUMPDEST),
uint8_t(Instruction::PUSH32) uint8_t(InternalInstruction::PUSH32)
} + } +
util::fromHex("4E487B7100000000000000000000000000000000000000000000000000000000") + util::fromHex("4E487B7100000000000000000000000000000000000000000000000000000000") +
bytes{ bytes{
uint8_t(Instruction::PUSH1), 0x0, uint8_t(InternalInstruction::PUSH1), 0x0,
uint8_t(Instruction::MSTORE), uint8_t(InternalInstruction::MSTORE),
uint8_t(Instruction::PUSH1), 0x12, uint8_t(InternalInstruction::PUSH1), 0x12,
uint8_t(Instruction::PUSH1), 0x4, uint8_t(InternalInstruction::PUSH1), 0x4,
uint8_t(Instruction::MSTORE), uint8_t(InternalInstruction::MSTORE),
uint8_t(Instruction::PUSH1), 0x24, uint8_t(InternalInstruction::PUSH1), 0x24,
uint8_t(Instruction::PUSH1), 0x0, uint8_t(InternalInstruction::PUSH1), 0x0,
uint8_t(Instruction::REVERT), uint8_t(InternalInstruction::REVERT),
uint8_t(Instruction::JUMPDEST), uint8_t(InternalInstruction::JUMPDEST),
uint8_t(Instruction::JUMP), uint8_t(InternalInstruction::JUMP),
uint8_t(Instruction::JUMPDEST) uint8_t(InternalInstruction::JUMPDEST)
}; };
bytes expectation; bytes expectation;
if (solidity::test::CommonOptions::get().optimize) if (solidity::test::CommonOptions::get().optimize)
expectation = bytes{ expectation = bytes{
uint8_t(Instruction::PUSH1), 0x2, uint8_t(InternalInstruction::PUSH1), 0x2,
uint8_t(Instruction::PUSH1), 0x3, uint8_t(InternalInstruction::PUSH1), 0x3,
uint8_t(Instruction::PUSH1), 0x5, uint8_t(InternalInstruction::PUSH1), 0x5,
uint8_t(Instruction::DUP4), uint8_t(InternalInstruction::DUP4),
uint8_t(Instruction::PUSH1), 0x8, uint8_t(InternalInstruction::PUSH1), 0x8,
uint8_t(Instruction::XOR), uint8_t(InternalInstruction::XOR),
uint8_t(Instruction::PUSH1), 0x7, uint8_t(InternalInstruction::PUSH1), 0x7,
uint8_t(Instruction::AND), uint8_t(InternalInstruction::AND),
uint8_t(Instruction::PUSH1), 0x6, uint8_t(InternalInstruction::PUSH1), 0x6,
uint8_t(Instruction::OR), uint8_t(InternalInstruction::OR),
uint8_t(Instruction::SUB), uint8_t(InternalInstruction::SUB),
uint8_t(Instruction::PUSH1), 0x4, uint8_t(InternalInstruction::PUSH1), 0x4,
uint8_t(Instruction::ADD), uint8_t(InternalInstruction::ADD),
uint8_t(Instruction::DUP2), uint8_t(InternalInstruction::DUP2),
uint8_t(Instruction::ISZERO), uint8_t(InternalInstruction::ISZERO),
uint8_t(Instruction::ISZERO), uint8_t(InternalInstruction::ISZERO),
uint8_t(Instruction::PUSH1), 0x20, uint8_t(InternalInstruction::PUSH1), 0x20,
uint8_t(Instruction::JUMPI), uint8_t(InternalInstruction::JUMPI),
uint8_t(Instruction::PUSH1), 0x1f, uint8_t(InternalInstruction::PUSH1), 0x1f,
uint8_t(Instruction::PUSH1), 0x36, uint8_t(InternalInstruction::PUSH1), 0x36,
uint8_t(Instruction::JUMP), uint8_t(InternalInstruction::JUMP),
uint8_t(Instruction::JUMPDEST), uint8_t(InternalInstruction::JUMPDEST),
uint8_t(Instruction::JUMPDEST), uint8_t(InternalInstruction::JUMPDEST),
uint8_t(Instruction::MOD), uint8_t(InternalInstruction::MOD),
uint8_t(Instruction::DUP2), uint8_t(InternalInstruction::DUP2),
uint8_t(Instruction::ISZERO), uint8_t(InternalInstruction::ISZERO),
uint8_t(Instruction::ISZERO), uint8_t(InternalInstruction::ISZERO),
uint8_t(Instruction::PUSH1), 0x2e, uint8_t(InternalInstruction::PUSH1), 0x2e,
uint8_t(Instruction::JUMPI), uint8_t(InternalInstruction::JUMPI),
uint8_t(Instruction::PUSH1), 0x2d, uint8_t(InternalInstruction::PUSH1), 0x2d,
uint8_t(Instruction::PUSH1), 0x36, uint8_t(InternalInstruction::PUSH1), 0x36,
uint8_t(Instruction::JUMP), uint8_t(InternalInstruction::JUMP),
uint8_t(Instruction::JUMPDEST), uint8_t(InternalInstruction::JUMPDEST),
uint8_t(Instruction::JUMPDEST), uint8_t(InternalInstruction::JUMPDEST),
uint8_t(Instruction::DIV), uint8_t(InternalInstruction::DIV),
uint8_t(Instruction::PUSH1), 0x1, uint8_t(InternalInstruction::PUSH1), 0x1,
uint8_t(Instruction::MUL), uint8_t(InternalInstruction::MUL),
uint8_t(Instruction::PUSH1), 0x67, uint8_t(InternalInstruction::PUSH1), 0x67,
uint8_t(Instruction::JUMP) uint8_t(InternalInstruction::JUMP)
} + panic; } + panic;
else else
expectation = bytes{ expectation = bytes{
uint8_t(Instruction::PUSH1), 0x1, uint8_t(InternalInstruction::PUSH1), 0x1,
uint8_t(Instruction::PUSH1), 0x2, uint8_t(InternalInstruction::PUSH1), 0x2,
uint8_t(Instruction::PUSH1), 0x3, uint8_t(InternalInstruction::PUSH1), 0x3,
uint8_t(Instruction::PUSH1), 0x4, uint8_t(InternalInstruction::PUSH1), 0x4,
uint8_t(Instruction::PUSH1), 0x5, uint8_t(InternalInstruction::PUSH1), 0x5,
uint8_t(Instruction::PUSH1), 0x6, uint8_t(InternalInstruction::PUSH1), 0x6,
uint8_t(Instruction::PUSH1), 0x7, uint8_t(InternalInstruction::PUSH1), 0x7,
uint8_t(Instruction::PUSH1), 0x8, uint8_t(InternalInstruction::PUSH1), 0x8,
uint8_t(Instruction::DUP9), uint8_t(InternalInstruction::DUP9),
uint8_t(Instruction::XOR), uint8_t(InternalInstruction::XOR),
uint8_t(Instruction::AND), uint8_t(InternalInstruction::AND),
uint8_t(Instruction::OR), uint8_t(InternalInstruction::OR),
uint8_t(Instruction::SUB), uint8_t(InternalInstruction::SUB),
uint8_t(Instruction::ADD), uint8_t(InternalInstruction::ADD),
uint8_t(Instruction::DUP2), uint8_t(InternalInstruction::DUP2),
uint8_t(Instruction::ISZERO), uint8_t(InternalInstruction::ISZERO),
uint8_t(Instruction::ISZERO), uint8_t(InternalInstruction::ISZERO),
uint8_t(Instruction::PUSH1), 0x22, uint8_t(InternalInstruction::PUSH1), 0x22,
uint8_t(Instruction::JUMPI), uint8_t(InternalInstruction::JUMPI),
uint8_t(Instruction::PUSH1), 0x21, uint8_t(InternalInstruction::PUSH1), 0x21,
uint8_t(Instruction::PUSH1), 0x36, uint8_t(InternalInstruction::PUSH1), 0x36,
uint8_t(Instruction::JUMP), uint8_t(InternalInstruction::JUMP),
uint8_t(Instruction::JUMPDEST), uint8_t(InternalInstruction::JUMPDEST),
uint8_t(Instruction::JUMPDEST), uint8_t(InternalInstruction::JUMPDEST),
uint8_t(Instruction::MOD), uint8_t(InternalInstruction::MOD),
uint8_t(Instruction::DUP2), uint8_t(InternalInstruction::DUP2),
uint8_t(Instruction::ISZERO), uint8_t(InternalInstruction::ISZERO),
uint8_t(Instruction::ISZERO), uint8_t(InternalInstruction::ISZERO),
uint8_t(Instruction::PUSH1), 0x30, uint8_t(InternalInstruction::PUSH1), 0x30,
uint8_t(Instruction::JUMPI), uint8_t(InternalInstruction::JUMPI),
uint8_t(Instruction::PUSH1), 0x2f, uint8_t(InternalInstruction::PUSH1), 0x2f,
uint8_t(Instruction::PUSH1), 0x36, uint8_t(InternalInstruction::PUSH1), 0x36,
uint8_t(Instruction::JUMP), uint8_t(InternalInstruction::JUMP),
uint8_t(Instruction::JUMPDEST), uint8_t(InternalInstruction::JUMPDEST),
uint8_t(Instruction::JUMPDEST), uint8_t(InternalInstruction::JUMPDEST),
uint8_t(Instruction::DIV), uint8_t(InternalInstruction::DIV),
uint8_t(Instruction::MUL), uint8_t(InternalInstruction::MUL),
uint8_t(Instruction::PUSH1), 0x67, uint8_t(InternalInstruction::PUSH1), 0x67,
uint8_t(Instruction::JUMP) uint8_t(InternalInstruction::JUMP)
} + panic; } + panic;
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
@ -466,23 +466,23 @@ BOOST_AUTO_TEST_CASE(unary_operators)
bytes expectation; bytes expectation;
if (solidity::test::CommonOptions::get().optimize) if (solidity::test::CommonOptions::get().optimize)
expectation = { expectation = {
uint8_t(Instruction::DUP1), uint8_t(InternalInstruction::DUP1),
uint8_t(Instruction::PUSH1), 0x0, uint8_t(InternalInstruction::PUSH1), 0x0,
uint8_t(Instruction::SUB), uint8_t(InternalInstruction::SUB),
uint8_t(Instruction::NOT), uint8_t(InternalInstruction::NOT),
uint8_t(Instruction::PUSH1), 0x2, uint8_t(InternalInstruction::PUSH1), 0x2,
uint8_t(Instruction::EQ), uint8_t(InternalInstruction::EQ),
uint8_t(Instruction::ISZERO) uint8_t(InternalInstruction::ISZERO)
}; };
else else
expectation = { expectation = {
uint8_t(Instruction::PUSH1), 0x2, uint8_t(InternalInstruction::PUSH1), 0x2,
uint8_t(Instruction::DUP2), uint8_t(InternalInstruction::DUP2),
uint8_t(Instruction::PUSH1), 0x0, uint8_t(InternalInstruction::PUSH1), 0x0,
uint8_t(Instruction::SUB), uint8_t(InternalInstruction::SUB),
uint8_t(Instruction::NOT), uint8_t(InternalInstruction::NOT),
uint8_t(Instruction::EQ), uint8_t(InternalInstruction::EQ),
uint8_t(Instruction::ISZERO) uint8_t(InternalInstruction::ISZERO)
}; };
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); 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 // Stack: a, x
bytes expectation{ bytes expectation{
uint8_t(Instruction::DUP2), uint8_t(InternalInstruction::DUP2),
uint8_t(Instruction::DUP1), uint8_t(InternalInstruction::DUP1),
uint8_t(Instruction::PUSH1), 0x1, uint8_t(InternalInstruction::PUSH1), 0x1,
uint8_t(Instruction::ADD), uint8_t(InternalInstruction::ADD),
// Stack here: a x a (a+1) // Stack here: a x a (a+1)
uint8_t(Instruction::SWAP3), uint8_t(InternalInstruction::SWAP3),
uint8_t(Instruction::POP), // first ++ uint8_t(InternalInstruction::POP), // first ++
// Stack here: (a+1) x a // Stack here: (a+1) x a
uint8_t(Instruction::DUP3), uint8_t(InternalInstruction::DUP3),
uint8_t(Instruction::PUSH1), 0x1, uint8_t(InternalInstruction::PUSH1), 0x1,
uint8_t(Instruction::ADD), uint8_t(InternalInstruction::ADD),
// Stack here: (a+1) x a (a+2) // Stack here: (a+1) x a (a+2)
uint8_t(Instruction::SWAP3), uint8_t(InternalInstruction::SWAP3),
uint8_t(Instruction::POP), uint8_t(InternalInstruction::POP),
// Stack here: (a+2) x a // Stack here: (a+2) x a
uint8_t(Instruction::DUP3), // second ++ uint8_t(InternalInstruction::DUP3), // second ++
uint8_t(Instruction::XOR), uint8_t(InternalInstruction::XOR),
// Stack here: (a+2) x a^(a+2) // Stack here: (a+2) x a^(a+2)
uint8_t(Instruction::DUP3), uint8_t(InternalInstruction::DUP3),
uint8_t(Instruction::DUP1), uint8_t(InternalInstruction::DUP1),
uint8_t(Instruction::PUSH1), 0x1, uint8_t(InternalInstruction::PUSH1), 0x1,
uint8_t(Instruction::SWAP1), uint8_t(InternalInstruction::SWAP1),
uint8_t(Instruction::SUB), uint8_t(InternalInstruction::SUB),
// Stack here: (a+2) x a^(a+2) (a+2) (a+1) // Stack here: (a+2) x a^(a+2) (a+2) (a+1)
uint8_t(Instruction::SWAP4), uint8_t(InternalInstruction::SWAP4),
uint8_t(Instruction::POP), // first -- uint8_t(InternalInstruction::POP), // first --
uint8_t(Instruction::XOR), uint8_t(InternalInstruction::XOR),
// Stack here: (a+1) x a^(a+2)^(a+2) // Stack here: (a+1) x a^(a+2)^(a+2)
uint8_t(Instruction::DUP3), uint8_t(InternalInstruction::DUP3),
uint8_t(Instruction::PUSH1), 0x1, uint8_t(InternalInstruction::PUSH1), 0x1,
uint8_t(Instruction::SWAP1), uint8_t(InternalInstruction::SWAP1),
uint8_t(Instruction::SUB), uint8_t(InternalInstruction::SUB),
// Stack here: (a+1) x a^(a+2)^(a+2) a // Stack here: (a+1) x a^(a+2)^(a+2) a
uint8_t(Instruction::SWAP3), uint8_t(InternalInstruction::SWAP3),
uint8_t(Instruction::POP), // second ++ uint8_t(InternalInstruction::POP), // second ++
// Stack here: a x a^(a+2)^(a+2) // Stack here: a x a^(a+2)^(a+2)
uint8_t(Instruction::DUP3), // will change uint8_t(InternalInstruction::DUP3), // will change
uint8_t(Instruction::XOR), uint8_t(InternalInstruction::XOR),
uint8_t(Instruction::SWAP1), uint8_t(InternalInstruction::SWAP1),
uint8_t(Instruction::POP), uint8_t(InternalInstruction::POP),
uint8_t(Instruction::DUP1) uint8_t(InternalInstruction::DUP1)
}; };
// Stack here: a x a^(a+2)^(a+2)^a // Stack here: a x a^(a+2)^(a+2)^a
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
@ -557,27 +557,27 @@ BOOST_AUTO_TEST_CASE(assignment)
bytes expectation; bytes expectation;
if (solidity::test::CommonOptions::get().optimize) if (solidity::test::CommonOptions::get().optimize)
expectation = { expectation = {
uint8_t(Instruction::DUP1), uint8_t(InternalInstruction::DUP1),
uint8_t(Instruction::DUP3), uint8_t(InternalInstruction::DUP3),
uint8_t(Instruction::ADD), uint8_t(InternalInstruction::ADD),
uint8_t(Instruction::SWAP2), uint8_t(InternalInstruction::SWAP2),
uint8_t(Instruction::POP), uint8_t(InternalInstruction::POP),
uint8_t(Instruction::DUP2), uint8_t(InternalInstruction::DUP2),
uint8_t(Instruction::PUSH1), 0x2, uint8_t(InternalInstruction::PUSH1), 0x2,
uint8_t(Instruction::MUL) uint8_t(InternalInstruction::MUL)
}; };
else else
expectation = { expectation = {
uint8_t(Instruction::PUSH1), 0x2, uint8_t(InternalInstruction::PUSH1), 0x2,
uint8_t(Instruction::DUP2), uint8_t(InternalInstruction::DUP2),
uint8_t(Instruction::DUP4), uint8_t(InternalInstruction::DUP4),
uint8_t(Instruction::ADD), uint8_t(InternalInstruction::ADD),
// Stack here: a b 2 a+b // Stack here: a b 2 a+b
uint8_t(Instruction::SWAP3), uint8_t(InternalInstruction::SWAP3),
uint8_t(Instruction::POP), uint8_t(InternalInstruction::POP),
uint8_t(Instruction::DUP3), uint8_t(InternalInstruction::DUP3),
// Stack here: a+b b 2 a+b // 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()); 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 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()); 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 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()); 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 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()); 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 code = compileFirstExpression(sourceCode, {}, {});
bytes expectation({uint8_t(Instruction::PUSH1), 0x03, bytes expectation({uint8_t(InternalInstruction::PUSH1), 0x03,
uint8_t(Instruction::BLOCKHASH)}); uint8_t(InternalInstruction::BLOCKHASH)});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); 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 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()); 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()) 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()); 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 /// @returns the number of instructions in the given bytecode, not taking the metadata hash
/// into account. /// 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); bytes realCode = bytecodeSansMetadata(_bytecode);
BOOST_REQUIRE_MESSAGE(!realCode.empty(), "Invalid or missing metadata in bytecode."); BOOST_REQUIRE_MESSAGE(!realCode.empty(), "Invalid or missing metadata in bytecode.");
size_t instructions = 0; size_t instructions = 0;
evmasm::eachInstruction(realCode, [&](Instruction _instr, u256 const&) { evmasm::eachInstruction(realCode, langutil::EVMVersion(), [&](InternalInstruction _instr, u256 const&) {
if (!_which || *_which == _instr) if (!_which || *_which == _instr)
instructions++; instructions++;
}); });
@ -287,8 +287,8 @@ BOOST_AUTO_TEST_CASE(retain_information_in_branches)
bytes optimizedBytecode = compileAndRunWithOptimizer(sourceCode, 0, "c", true); bytes optimizedBytecode = compileAndRunWithOptimizer(sourceCode, 0, "c", true);
size_t numSHA3s = 0; size_t numSHA3s = 0;
eachInstruction(optimizedBytecode, [&](Instruction _instr, u256 const&) { eachInstruction(optimizedBytecode, langutil::EVMVersion(), [&](InternalInstruction _instr, u256 const&) {
if (_instr == Instruction::KECCAK256) if (_instr == InternalInstruction::KECCAK256)
numSHA3s++; numSHA3s++;
}); });
// TEST DISABLED - OPTIMIZER IS NOT EFFECTIVE ON THIS ONE ANYMORE // 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); bytes optimizedBytecode = compileAndRunWithOptimizer(sourceCode, 0, "test", true);
size_t numSHA3s = 0; size_t numSHA3s = 0;
eachInstruction(optimizedBytecode, [&](Instruction _instr, u256 const&) { eachInstruction(optimizedBytecode, langutil::EVMVersion(), [&](InternalInstruction _instr, u256 const&) {
if (_instr == Instruction::KECCAK256) if (_instr == InternalInstruction::KECCAK256)
numSHA3s++; numSHA3s++;
}); });
// TEST DISABLED UNTIL 93693404 IS IMPLEMENTED // TEST DISABLED UNTIL 93693404 IS IMPLEMENTED
@ -635,8 +635,8 @@ BOOST_AUTO_TEST_CASE(optimise_multi_stores)
)"; )";
compileBothVersions(sourceCode); compileBothVersions(sourceCode);
compareVersions("f()"); compareVersions("f()");
BOOST_CHECK_EQUAL(numInstructions(m_nonOptimizedBytecode, Instruction::SSTORE), 8); BOOST_CHECK_EQUAL(numInstructions(m_nonOptimizedBytecode, InternalInstruction::SSTORE), 8);
BOOST_CHECK_EQUAL(numInstructions(m_optimizedBytecode, Instruction::SSTORE), 7); BOOST_CHECK_EQUAL(numInstructions(m_optimizedBytecode, InternalInstruction::SSTORE), 7);
} }
BOOST_AUTO_TEST_CASE(optimise_constant_to_codecopy) BOOST_AUTO_TEST_CASE(optimise_constant_to_codecopy)
@ -672,8 +672,8 @@ BOOST_AUTO_TEST_CASE(optimise_constant_to_codecopy)
compareVersions("h()"); compareVersions("h()");
compareVersions("i()"); compareVersions("i()");
// This is counting in the deployed code. // This is counting in the deployed code.
BOOST_CHECK_EQUAL(numInstructions(m_nonOptimizedBytecode, Instruction::CODECOPY), 0); BOOST_CHECK_EQUAL(numInstructions(m_nonOptimizedBytecode, InternalInstruction::CODECOPY), 0);
BOOST_CHECK_EQUAL(numInstructions(m_optimizedBytecode, Instruction::CODECOPY), 4); BOOST_CHECK_EQUAL(numInstructions(m_optimizedBytecode, InternalInstruction::CODECOPY), 4);
} }
BOOST_AUTO_TEST_CASE(byte_access) BOOST_AUTO_TEST_CASE(byte_access)
@ -722,7 +722,7 @@ BOOST_AUTO_TEST_CASE(avoid_double_cleanup)
)"; )";
compileBothVersions(sourceCode, 0, "C", 50); compileBothVersions(sourceCode, 0, "C", 50);
// Check that there is no double AND instruction in the resulting code // 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() 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>>; using u512 = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<512, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>;
u256 EVMInstructionInterpreter::eval( u256 EVMInstructionInterpreter::eval(
evmasm::Instruction _instruction, evmasm::InternalInstruction _instruction,
vector<u256> const& _arguments vector<u256> const& _arguments
) )
{ {
using namespace solidity::evmasm; using namespace solidity::evmasm;
using evmasm::Instruction; using evmasm::InternalInstruction;
auto info = instructionInfo(_instruction); auto info = instructionInfo(_instruction);
yulAssert(static_cast<size_t>(info.args) == _arguments.size(), ""); yulAssert(static_cast<size_t>(info.args) == _arguments.size(), "");
@ -100,53 +100,53 @@ u256 EVMInstructionInterpreter::eval(
auto const& arg = _arguments; auto const& arg = _arguments;
switch (_instruction) switch (_instruction)
{ {
case Instruction::STOP: case InternalInstruction::STOP:
logTrace(_instruction); logTrace(_instruction);
BOOST_THROW_EXCEPTION(ExplicitlyTerminated()); BOOST_THROW_EXCEPTION(ExplicitlyTerminated());
// --------------- arithmetic --------------- // --------------- arithmetic ---------------
case Instruction::ADD: case InternalInstruction::ADD:
return arg[0] + arg[1]; return arg[0] + arg[1];
case Instruction::MUL: case InternalInstruction::MUL:
return arg[0] * arg[1]; return arg[0] * arg[1];
case Instruction::SUB: case InternalInstruction::SUB:
return arg[0] - arg[1]; return arg[0] - arg[1];
case Instruction::DIV: case InternalInstruction::DIV:
return arg[1] == 0 ? 0 : arg[0] / arg[1]; 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])); 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]; 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])); return arg[1] == 0 ? 0 : s2u(u2s(arg[0]) % u2s(arg[1]));
case Instruction::EXP: case InternalInstruction::EXP:
return exp256(arg[0], arg[1]); return exp256(arg[0], arg[1]);
case Instruction::NOT: case InternalInstruction::NOT:
return ~arg[0]; return ~arg[0];
case Instruction::LT: case InternalInstruction::LT:
return arg[0] < arg[1] ? 1 : 0; return arg[0] < arg[1] ? 1 : 0;
case Instruction::GT: case InternalInstruction::GT:
return arg[0] > arg[1] ? 1 : 0; return arg[0] > arg[1] ? 1 : 0;
case Instruction::SLT: case InternalInstruction::SLT:
return u2s(arg[0]) < u2s(arg[1]) ? 1 : 0; return u2s(arg[0]) < u2s(arg[1]) ? 1 : 0;
case Instruction::SGT: case InternalInstruction::SGT:
return u2s(arg[0]) > u2s(arg[1]) ? 1 : 0; return u2s(arg[0]) > u2s(arg[1]) ? 1 : 0;
case Instruction::EQ: case InternalInstruction::EQ:
return arg[0] == arg[1] ? 1 : 0; return arg[0] == arg[1] ? 1 : 0;
case Instruction::ISZERO: case InternalInstruction::ISZERO:
return arg[0] == 0 ? 1 : 0; return arg[0] == 0 ? 1 : 0;
case Instruction::AND: case InternalInstruction::AND:
return arg[0] & arg[1]; return arg[0] & arg[1];
case Instruction::OR: case InternalInstruction::OR:
return arg[0] | arg[1]; return arg[0] | arg[1];
case Instruction::XOR: case InternalInstruction::XOR:
return arg[0] ^ arg[1]; return arg[0] ^ arg[1];
case Instruction::BYTE: case InternalInstruction::BYTE:
return arg[0] >= 32 ? 0 : (arg[1] >> unsigned(8 * (31 - arg[0]))) & 0xff; 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])); 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])); return arg[0] > 255 ? 0 : (arg[1] >> unsigned(arg[0]));
case Instruction::SAR: case InternalInstruction::SAR:
{ {
static u256 const hibit = u256(1) << 255; static u256 const hibit = u256(1) << 255;
if (arg[0] >= 256) if (arg[0] >= 256)
@ -160,11 +160,11 @@ u256 EVMInstructionInterpreter::eval(
return v; return v;
} }
} }
case Instruction::ADDMOD: case InternalInstruction::ADDMOD:
return arg[2] == 0 ? 0 : u256((u512(arg[0]) + u512(arg[1])) % arg[2]); 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]); return arg[2] == 0 ? 0 : u256((u512(arg[0]) * u512(arg[1])) % arg[2]);
case Instruction::SIGNEXTEND: case InternalInstruction::SIGNEXTEND:
if (arg[0] >= 31) if (arg[0] >= 31)
return arg[1]; return arg[1];
else else
@ -179,7 +179,7 @@ u256 EVMInstructionInterpreter::eval(
return ret; return ret;
} }
// --------------- blockchain stuff --------------- // --------------- blockchain stuff ---------------
case Instruction::KECCAK256: case InternalInstruction::KECCAK256:
{ {
if (!accessMemory(arg[0], arg[1])) if (!accessMemory(arg[0], arg[1]))
return u256("0x1234cafe1234cafe1234cafe") + arg[0]; return u256("0x1234cafe1234cafe1234cafe") + arg[0];
@ -187,26 +187,26 @@ u256 EVMInstructionInterpreter::eval(
uint64_t size = uint64_t(arg[1] & uint64_t(-1)); uint64_t size = uint64_t(arg[1] & uint64_t(-1));
return u256(keccak256(readMemory(offset, size))); return u256(keccak256(readMemory(offset, size)));
} }
case Instruction::ADDRESS: case InternalInstruction::ADDRESS:
return h256(m_state.address, h256::AlignRight); return h256(m_state.address, h256::AlignRight);
case Instruction::BALANCE: case InternalInstruction::BALANCE:
if (arg[0] == h256(m_state.address, h256::AlignRight)) if (arg[0] == h256(m_state.address, h256::AlignRight))
return m_state.selfbalance; return m_state.selfbalance;
else else
return m_state.balance; return m_state.balance;
case Instruction::SELFBALANCE: case InternalInstruction::SELFBALANCE:
return m_state.selfbalance; return m_state.selfbalance;
case Instruction::ORIGIN: case InternalInstruction::ORIGIN:
return h256(m_state.origin, h256::AlignRight); return h256(m_state.origin, h256::AlignRight);
case Instruction::CALLER: case InternalInstruction::CALLER:
return h256(m_state.caller, h256::AlignRight); return h256(m_state.caller, h256::AlignRight);
case Instruction::CALLVALUE: case InternalInstruction::CALLVALUE:
return m_state.callvalue; return m_state.callvalue;
case Instruction::CALLDATALOAD: case InternalInstruction::CALLDATALOAD:
return readZeroExtended(m_state.calldata, arg[0]); return readZeroExtended(m_state.calldata, arg[0]);
case Instruction::CALLDATASIZE: case InternalInstruction::CALLDATASIZE:
return m_state.calldata.size(); return m_state.calldata.size();
case Instruction::CALLDATACOPY: case InternalInstruction::CALLDATACOPY:
logTrace(_instruction, arg); logTrace(_instruction, arg);
if (accessMemory(arg[0], arg[2])) if (accessMemory(arg[0], arg[2]))
copyZeroExtended( copyZeroExtended(
@ -214,9 +214,9 @@ u256 EVMInstructionInterpreter::eval(
size_t(arg[0]), size_t(arg[1]), size_t(arg[2]) size_t(arg[0]), size_t(arg[1]), size_t(arg[2])
); );
return 0; return 0;
case Instruction::CODESIZE: case InternalInstruction::CODESIZE:
return m_state.code.size(); return m_state.code.size();
case Instruction::CODECOPY: case InternalInstruction::CODECOPY:
logTrace(_instruction, arg); logTrace(_instruction, arg);
if (accessMemory(arg[0], arg[2])) if (accessMemory(arg[0], arg[2]))
copyZeroExtended( copyZeroExtended(
@ -224,17 +224,17 @@ u256 EVMInstructionInterpreter::eval(
size_t(arg[0]), size_t(arg[1]), size_t(arg[2]) size_t(arg[0]), size_t(arg[1]), size_t(arg[2])
); );
return 0; return 0;
case Instruction::GASPRICE: case InternalInstruction::GASPRICE:
return m_state.gasprice; return m_state.gasprice;
case Instruction::CHAINID: case InternalInstruction::CHAINID:
return m_state.chainid; return m_state.chainid;
case Instruction::BASEFEE: case InternalInstruction::BASEFEE:
return m_state.basefee; return m_state.basefee;
case Instruction::EXTCODESIZE: case InternalInstruction::EXTCODESIZE:
return u256(keccak256(h256(arg[0]))) & 0xffffff; return u256(keccak256(h256(arg[0]))) & 0xffffff;
case Instruction::EXTCODEHASH: case InternalInstruction::EXTCODEHASH:
return u256(keccak256(h256(arg[0] + 1))); return u256(keccak256(h256(arg[0] + 1)));
case Instruction::EXTCODECOPY: case InternalInstruction::EXTCODECOPY:
logTrace(_instruction, arg); logTrace(_instruction, arg);
if (accessMemory(arg[1], arg[3])) if (accessMemory(arg[1], arg[3]))
// TODO this way extcodecopy and codecopy do the same thing. // 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]) size_t(arg[1]), size_t(arg[2]), size_t(arg[3])
); );
return 0; return 0;
case Instruction::RETURNDATASIZE: case InternalInstruction::RETURNDATASIZE:
return m_state.returndata.size(); return m_state.returndata.size();
case Instruction::RETURNDATACOPY: case InternalInstruction::RETURNDATACOPY:
logTrace(_instruction, arg); logTrace(_instruction, arg);
if (accessMemory(arg[0], arg[2])) if (accessMemory(arg[0], arg[2]))
copyZeroExtended( copyZeroExtended(
@ -253,87 +253,89 @@ u256 EVMInstructionInterpreter::eval(
size_t(arg[0]), size_t(arg[1]), size_t(arg[2]) size_t(arg[0]), size_t(arg[1]), size_t(arg[2])
); );
return 0; return 0;
case Instruction::BLOCKHASH: case InternalInstruction::BLOCKHASH:
if (arg[0] >= m_state.blockNumber || arg[0] + 256 < m_state.blockNumber) if (arg[0] >= m_state.blockNumber || arg[0] + 256 < m_state.blockNumber)
return 0; return 0;
else else
return 0xaaaaaaaa + (arg[0] - m_state.blockNumber - 256); return 0xaaaaaaaa + (arg[0] - m_state.blockNumber - 256);
case Instruction::COINBASE: case InternalInstruction::COINBASE:
return h256(m_state.coinbase, h256::AlignRight); return h256(m_state.coinbase, h256::AlignRight);
case Instruction::TIMESTAMP: case InternalInstruction::TIMESTAMP:
return m_state.timestamp; return m_state.timestamp;
case Instruction::NUMBER: case InternalInstruction::NUMBER:
return m_state.blockNumber; return m_state.blockNumber;
case Instruction::DIFFICULTY: case InternalInstruction::DIFFICULTY:
// TODO should be properly implemented
case InternalInstruction::PREVRANDAO:
return m_state.difficulty; return m_state.difficulty;
case Instruction::GASLIMIT: case InternalInstruction::GASLIMIT:
return m_state.gaslimit; return m_state.gaslimit;
// --------------- memory / storage / logs --------------- // --------------- memory / storage / logs ---------------
case Instruction::MLOAD: case InternalInstruction::MLOAD:
accessMemory(arg[0], 0x20); accessMemory(arg[0], 0x20);
return readMemoryWord(arg[0]); return readMemoryWord(arg[0]);
case Instruction::MSTORE: case InternalInstruction::MSTORE:
accessMemory(arg[0], 0x20); accessMemory(arg[0], 0x20);
writeMemoryWord(arg[0], arg[1]); writeMemoryWord(arg[0], arg[1]);
return 0; return 0;
case Instruction::MSTORE8: case InternalInstruction::MSTORE8:
accessMemory(arg[0], 1); accessMemory(arg[0], 1);
m_state.memory[arg[0]] = uint8_t(arg[1] & 0xff); m_state.memory[arg[0]] = uint8_t(arg[1] & 0xff);
return 0; return 0;
case Instruction::SLOAD: case InternalInstruction::SLOAD:
return m_state.storage[h256(arg[0])]; return m_state.storage[h256(arg[0])];
case Instruction::SSTORE: case InternalInstruction::SSTORE:
m_state.storage[h256(arg[0])] = h256(arg[1]); m_state.storage[h256(arg[0])] = h256(arg[1]);
return 0; return 0;
case Instruction::PC: case InternalInstruction::PC:
return 0x77; return 0x77;
case Instruction::MSIZE: case InternalInstruction::MSIZE:
return m_state.msize; return m_state.msize;
case Instruction::GAS: case InternalInstruction::GAS:
return 0x99; return 0x99;
case Instruction::LOG0: case InternalInstruction::LOG0:
accessMemory(arg[0], arg[1]); accessMemory(arg[0], arg[1]);
logTrace(_instruction, arg); logTrace(_instruction, arg);
return 0; return 0;
case Instruction::LOG1: case InternalInstruction::LOG1:
accessMemory(arg[0], arg[1]); accessMemory(arg[0], arg[1]);
logTrace(_instruction, arg); logTrace(_instruction, arg);
return 0; return 0;
case Instruction::LOG2: case InternalInstruction::LOG2:
accessMemory(arg[0], arg[1]); accessMemory(arg[0], arg[1]);
logTrace(_instruction, arg); logTrace(_instruction, arg);
return 0; return 0;
case Instruction::LOG3: case InternalInstruction::LOG3:
accessMemory(arg[0], arg[1]); accessMemory(arg[0], arg[1]);
logTrace(_instruction, arg); logTrace(_instruction, arg);
return 0; return 0;
case Instruction::LOG4: case InternalInstruction::LOG4:
accessMemory(arg[0], arg[1]); accessMemory(arg[0], arg[1]);
logTrace(_instruction, arg); logTrace(_instruction, arg);
return 0; return 0;
// --------------- calls --------------- // --------------- calls ---------------
case Instruction::CREATE: case InternalInstruction::CREATE:
accessMemory(arg[1], arg[2]); accessMemory(arg[1], arg[2]);
logTrace(_instruction, arg); logTrace(_instruction, arg);
return (0xcccccc + arg[1]) & u256("0xffffffffffffffffffffffffffffffffffffffff"); return (0xcccccc + arg[1]) & u256("0xffffffffffffffffffffffffffffffffffffffff");
case Instruction::CREATE2: case InternalInstruction::CREATE2:
accessMemory(arg[1], arg[2]); accessMemory(arg[1], arg[2]);
logTrace(_instruction, arg); logTrace(_instruction, arg);
return (0xdddddd + arg[1]) & u256("0xffffffffffffffffffffffffffffffffffffffff"); return (0xdddddd + arg[1]) & u256("0xffffffffffffffffffffffffffffffffffffffff");
case Instruction::CALL: case InternalInstruction::CALL:
case Instruction::CALLCODE: case InternalInstruction::CALLCODE:
// TODO assign returndata // TODO assign returndata
accessMemory(arg[3], arg[4]); accessMemory(arg[3], arg[4]);
accessMemory(arg[5], arg[6]); accessMemory(arg[5], arg[6]);
logTrace(_instruction, arg); logTrace(_instruction, arg);
return arg[0] & 1; return arg[0] & 1;
case Instruction::DELEGATECALL: case InternalInstruction::DELEGATECALL:
case Instruction::STATICCALL: case InternalInstruction::STATICCALL:
accessMemory(arg[2], arg[3]); accessMemory(arg[2], arg[3]);
accessMemory(arg[4], arg[5]); accessMemory(arg[4], arg[5]);
logTrace(_instruction, arg); logTrace(_instruction, arg);
return 0; return 0;
case Instruction::RETURN: case InternalInstruction::RETURN:
{ {
bytes data; bytes data;
if (accessMemory(arg[0], arg[1])) if (accessMemory(arg[0], arg[1]))
@ -341,92 +343,93 @@ u256 EVMInstructionInterpreter::eval(
logTrace(_instruction, arg, data); logTrace(_instruction, arg, data);
BOOST_THROW_EXCEPTION(ExplicitlyTerminated()); BOOST_THROW_EXCEPTION(ExplicitlyTerminated());
} }
case Instruction::REVERT: case InternalInstruction::REVERT:
accessMemory(arg[0], arg[1]); accessMemory(arg[0], arg[1]);
logTrace(_instruction, arg); logTrace(_instruction, arg);
m_state.storage.clear(); m_state.storage.clear();
m_state.trace.clear(); m_state.trace.clear();
BOOST_THROW_EXCEPTION(ExplicitlyTerminated()); BOOST_THROW_EXCEPTION(ExplicitlyTerminated());
case Instruction::INVALID: case InternalInstruction::INVALID:
logTrace(_instruction); logTrace(_instruction);
m_state.storage.clear(); m_state.storage.clear();
m_state.trace.clear(); m_state.trace.clear();
BOOST_THROW_EXCEPTION(ExplicitlyTerminated()); BOOST_THROW_EXCEPTION(ExplicitlyTerminated());
case Instruction::SELFDESTRUCT: case InternalInstruction::SELFDESTRUCT:
logTrace(_instruction, arg); logTrace(_instruction, arg);
m_state.storage.clear(); m_state.storage.clear();
m_state.trace.clear(); m_state.trace.clear();
BOOST_THROW_EXCEPTION(ExplicitlyTerminated()); BOOST_THROW_EXCEPTION(ExplicitlyTerminated());
case Instruction::POP: case InternalInstruction::POP:
break; break;
// --------------- invalid in strict assembly --------------- // --------------- invalid in strict assembly ---------------
case Instruction::JUMP: case InternalInstruction::JUMP:
case Instruction::JUMPI: case InternalInstruction::JUMPI:
case Instruction::JUMPDEST: case InternalInstruction::JUMPDEST:
case Instruction::PUSH1: case InternalInstruction::PUSH1:
case Instruction::PUSH2: case InternalInstruction::PUSH2:
case Instruction::PUSH3: case InternalInstruction::PUSH3:
case Instruction::PUSH4: case InternalInstruction::PUSH4:
case Instruction::PUSH5: case InternalInstruction::PUSH5:
case Instruction::PUSH6: case InternalInstruction::PUSH6:
case Instruction::PUSH7: case InternalInstruction::PUSH7:
case Instruction::PUSH8: case InternalInstruction::PUSH8:
case Instruction::PUSH9: case InternalInstruction::PUSH9:
case Instruction::PUSH10: case InternalInstruction::PUSH10:
case Instruction::PUSH11: case InternalInstruction::PUSH11:
case Instruction::PUSH12: case InternalInstruction::PUSH12:
case Instruction::PUSH13: case InternalInstruction::PUSH13:
case Instruction::PUSH14: case InternalInstruction::PUSH14:
case Instruction::PUSH15: case InternalInstruction::PUSH15:
case Instruction::PUSH16: case InternalInstruction::PUSH16:
case Instruction::PUSH17: case InternalInstruction::PUSH17:
case Instruction::PUSH18: case InternalInstruction::PUSH18:
case Instruction::PUSH19: case InternalInstruction::PUSH19:
case Instruction::PUSH20: case InternalInstruction::PUSH20:
case Instruction::PUSH21: case InternalInstruction::PUSH21:
case Instruction::PUSH22: case InternalInstruction::PUSH22:
case Instruction::PUSH23: case InternalInstruction::PUSH23:
case Instruction::PUSH24: case InternalInstruction::PUSH24:
case Instruction::PUSH25: case InternalInstruction::PUSH25:
case Instruction::PUSH26: case InternalInstruction::PUSH26:
case Instruction::PUSH27: case InternalInstruction::PUSH27:
case Instruction::PUSH28: case InternalInstruction::PUSH28:
case Instruction::PUSH29: case InternalInstruction::PUSH29:
case Instruction::PUSH30: case InternalInstruction::PUSH30:
case Instruction::PUSH31: case InternalInstruction::PUSH31:
case Instruction::PUSH32: case InternalInstruction::PUSH32:
case Instruction::DUP1: case InternalInstruction::DUP1:
case Instruction::DUP2: case InternalInstruction::DUP2:
case Instruction::DUP3: case InternalInstruction::DUP3:
case Instruction::DUP4: case InternalInstruction::DUP4:
case Instruction::DUP5: case InternalInstruction::DUP5:
case Instruction::DUP6: case InternalInstruction::DUP6:
case Instruction::DUP7: case InternalInstruction::DUP7:
case Instruction::DUP8: case InternalInstruction::DUP8:
case Instruction::DUP9: case InternalInstruction::DUP9:
case Instruction::DUP10: case InternalInstruction::DUP10:
case Instruction::DUP11: case InternalInstruction::DUP11:
case Instruction::DUP12: case InternalInstruction::DUP12:
case Instruction::DUP13: case InternalInstruction::DUP13:
case Instruction::DUP14: case InternalInstruction::DUP14:
case Instruction::DUP15: case InternalInstruction::DUP15:
case Instruction::DUP16: case InternalInstruction::DUP16:
case Instruction::SWAP1: case InternalInstruction::SWAP1:
case Instruction::SWAP2: case InternalInstruction::SWAP2:
case Instruction::SWAP3: case InternalInstruction::SWAP3:
case Instruction::SWAP4: case InternalInstruction::SWAP4:
case Instruction::SWAP5: case InternalInstruction::SWAP5:
case Instruction::SWAP6: case InternalInstruction::SWAP6:
case Instruction::SWAP7: case InternalInstruction::SWAP7:
case Instruction::SWAP8: case InternalInstruction::SWAP8:
case Instruction::SWAP9: case InternalInstruction::SWAP9:
case Instruction::SWAP10: case InternalInstruction::SWAP10:
case Instruction::SWAP11: case InternalInstruction::SWAP11:
case Instruction::SWAP12: case InternalInstruction::SWAP12:
case Instruction::SWAP13: case InternalInstruction::SWAP13:
case Instruction::SWAP14: case InternalInstruction::SWAP14:
case Instruction::SWAP15: case InternalInstruction::SWAP15:
case Instruction::SWAP16: case InternalInstruction::SWAP16:
case InternalInstruction::MAX_INTERNAL_INSTRUCTION:
{ {
yulAssert(false, ""); yulAssert(false, "");
return 0; return 0;
@ -519,7 +522,7 @@ void EVMInstructionInterpreter::writeMemoryWord(u256 const& _offset, u256 const&
void EVMInstructionInterpreter::logTrace( void EVMInstructionInterpreter::logTrace(
evmasm::Instruction _instruction, evmasm::InternalInstruction _instruction,
std::vector<u256> const& _arguments, std::vector<u256> const& _arguments,
bytes const& _data bytes const& _data
) )

View File

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

View File

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

View File

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