diff options
31 files changed, 1348 insertions, 724 deletions
diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 28328277..d48fa99c 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -26,7 +26,7 @@ #include <libdevcore/Common.h> #include <libdevcore/Assertions.h> #include <libdevcore/SHA3.h> -#include <libevmcore/Instruction.h> +#include <libevmasm/Instruction.h> #include <libevmasm/SourceLocation.h> #include <libevmasm/AssemblyItem.h> #include <libevmasm/LinkerObject.h> @@ -69,10 +69,10 @@ public: void appendProgramSize() { append(AssemblyItem(PushProgramSize)); } void appendLibraryAddress(std::string const& _identifier) { append(newPushLibraryAddress(_identifier)); } - AssemblyItem appendJump() { auto ret = append(newPushTag()); append(Instruction::JUMP); return ret; } - AssemblyItem appendJumpI() { auto ret = append(newPushTag()); append(Instruction::JUMPI); return ret; } - AssemblyItem appendJump(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(Instruction::JUMP); return ret; } - AssemblyItem appendJumpI(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(Instruction::JUMPI); return ret; } + AssemblyItem appendJump() { auto ret = append(newPushTag()); append(solidity::Instruction::JUMP); return ret; } + AssemblyItem appendJumpI() { auto ret = append(newPushTag()); append(solidity::Instruction::JUMPI); return ret; } + AssemblyItem appendJump(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(solidity::Instruction::JUMP); return ret; } + AssemblyItem appendJumpI(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(solidity::Instruction::JUMPI); return ret; } AssemblyItem errorTag() { return AssemblyItem(PushTag, 0); } template <class T> Assembly& operator<<(T const& _d) { append(_d); return *this; } @@ -86,7 +86,7 @@ public: void ignored() { m_baseDeposit = m_deposit; } void endIgnored() { m_deposit = m_baseDeposit; m_baseDeposit = 0; } - void popTo(int _deposit) { while (m_deposit > _deposit) append(Instruction::POP); } + void popTo(int _deposit) { while (m_deposit > _deposit) append(solidity::Instruction::POP); } void injectStart(AssemblyItem const& _i); std::string out() const; diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index d7051064..599ded85 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -94,7 +94,7 @@ ostream& dev::eth::operator<<(ostream& _out, AssemblyItem const& _item) { case Operation: _out << " " << instructionInfo(_item.instruction()).name; - if (_item.instruction() == eth::Instruction::JUMP || _item.instruction() == eth::Instruction::JUMPI) + if (_item.instruction() == solidity::Instruction::JUMP || _item.instruction() == solidity::Instruction::JUMPI) _out << "\t" << _item.getJumpTypeAsString(); break; case Push: diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index 795b5a8a..1c3d9789 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -25,9 +25,10 @@ #include <sstream> #include <libdevcore/Common.h> #include <libdevcore/Assertions.h> -#include <libevmcore/Instruction.h> +#include <libevmasm/Instruction.h> #include <libevmasm/SourceLocation.h> #include "Exceptions.h" +using namespace dev::solidity; namespace dev { @@ -57,7 +58,7 @@ public: AssemblyItem(u256 _push, SourceLocation const& _location = SourceLocation()): AssemblyItem(Push, _push, _location) { } - AssemblyItem(Instruction _i, SourceLocation const& _location = SourceLocation()): + AssemblyItem(solidity::Instruction _i, SourceLocation const& _location = SourceLocation()): AssemblyItem(Operation, byte(_i), _location) { } AssemblyItem(AssemblyItemType _type, u256 _data = 0, SourceLocation const& _location = SourceLocation()): m_type(_type), diff --git a/libevmasm/BlockDeduplicator.cpp b/libevmasm/BlockDeduplicator.cpp index d930ea22..3bb7a797 100644 --- a/libevmasm/BlockDeduplicator.cpp +++ b/libevmasm/BlockDeduplicator.cpp @@ -106,7 +106,7 @@ BlockDeduplicator::BlockIterator& BlockDeduplicator::BlockIterator::operator++() { if (it == end) return *this; - if (SemanticInformation::altersControlFlow(*it) && *it != AssemblyItem(eth::Instruction::JUMPI)) + if (SemanticInformation::altersControlFlow(*it) && *it != AssemblyItem(Instruction::JUMPI)) it = end; else { diff --git a/libevmasm/CMakeLists.txt b/libevmasm/CMakeLists.txt index 424644ca..c753fbe3 100644 --- a/libevmasm/CMakeLists.txt +++ b/libevmasm/CMakeLists.txt @@ -8,7 +8,7 @@ file(GLOB HEADERS "*.h") include_directories(BEFORE ..) add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) -eth_use(${EXECUTABLE} REQUIRED Eth::evmcore) +eth_use(${EXECUTABLE} REQUIRED Dev::devcore Eth::ethcore) install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libevmasm/GasMeter.cpp b/libevmasm/GasMeter.cpp index 93583169..40a67bb1 100644 --- a/libevmasm/GasMeter.cpp +++ b/libevmasm/GasMeter.cpp @@ -84,13 +84,13 @@ GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item) break; case Instruction::MLOAD: case Instruction::MSTORE: - gas += memoryGas(classes.find(eth::Instruction::ADD, { + gas += memoryGas(classes.find(Instruction::ADD, { m_state->relativeStackElement(0), classes.find(AssemblyItem(32)) })); break; case Instruction::MSTORE8: - gas += memoryGas(classes.find(eth::Instruction::ADD, { + gas += memoryGas(classes.find(Instruction::ADD, { m_state->relativeStackElement(0), classes.find(AssemblyItem(1)) })); @@ -198,7 +198,7 @@ GasMeter::GasConsumption GasMeter::memoryGas(int _stackPosOffset, int _stackPosS if (classes.knownZero(m_state->relativeStackElement(_stackPosSize))) return GasConsumption(0); else - return memoryGas(classes.find(eth::Instruction::ADD, { + return memoryGas(classes.find(Instruction::ADD, { m_state->relativeStackElement(_stackPosOffset), m_state->relativeStackElement(_stackPosSize) })); diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp new file mode 100644 index 00000000..da765c41 --- /dev/null +++ b/libevmasm/Instruction.cpp @@ -0,0 +1,354 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. +*/ +/** @file Instruction.cpp + * @author Gav Wood <i@gavwood.com> + * @date 2014 + */ + +#include "./Instruction.h" + +#include <functional> +#include <libdevcore/Common.h> +#include <libdevcore/CommonIO.h> +#include <libdevcore/Log.h> +using namespace std; +using namespace dev; +using namespace dev::solidity; + +const std::map<std::string, Instruction> dev::solidity::c_instructions = +{ + { "STOP", Instruction::STOP }, + { "ADD", Instruction::ADD }, + { "SUB", Instruction::SUB }, + { "MUL", Instruction::MUL }, + { "DIV", Instruction::DIV }, + { "SDIV", Instruction::SDIV }, + { "MOD", Instruction::MOD }, + { "SMOD", Instruction::SMOD }, + { "EXP", Instruction::EXP }, + { "BNOT", Instruction::NOT }, + { "LT", Instruction::LT }, + { "GT", Instruction::GT }, + { "SLT", Instruction::SLT }, + { "SGT", Instruction::SGT }, + { "EQ", Instruction::EQ }, + { "NOT", Instruction::ISZERO }, + { "AND", Instruction::AND }, + { "OR", Instruction::OR }, + { "XOR", Instruction::XOR }, + { "BYTE", Instruction::BYTE }, + { "ADDMOD", Instruction::ADDMOD }, + { "MULMOD", Instruction::MULMOD }, + { "SIGNEXTEND", Instruction::SIGNEXTEND }, + { "SHA3", Instruction::SHA3 }, + { "ADDRESS", Instruction::ADDRESS }, + { "BALANCE", Instruction::BALANCE }, + { "ORIGIN", Instruction::ORIGIN }, + { "CALLER", Instruction::CALLER }, + { "CALLVALUE", Instruction::CALLVALUE }, + { "CALLDATALOAD", Instruction::CALLDATALOAD }, + { "CALLDATASIZE", Instruction::CALLDATASIZE }, + { "CALLDATACOPY", Instruction::CALLDATACOPY }, + { "CODESIZE", Instruction::CODESIZE }, + { "CODECOPY", Instruction::CODECOPY }, + { "GASPRICE", Instruction::GASPRICE }, + { "EXTCODESIZE", Instruction::EXTCODESIZE }, + { "EXTCODECOPY", Instruction::EXTCODECOPY }, + { "BLOCKHASH", Instruction::BLOCKHASH }, + { "COINBASE", Instruction::COINBASE }, + { "TIMESTAMP", Instruction::TIMESTAMP }, + { "NUMBER", Instruction::NUMBER }, + { "DIFFICULTY", Instruction::DIFFICULTY }, + { "GASLIMIT", Instruction::GASLIMIT }, + { "POP", Instruction::POP }, + { "MLOAD", Instruction::MLOAD }, + { "MSTORE", Instruction::MSTORE }, + { "MSTORE8", Instruction::MSTORE8 }, + { "SLOAD", Instruction::SLOAD }, + { "SSTORE", Instruction::SSTORE }, + { "JUMP", Instruction::JUMP }, + { "JUMPI", Instruction::JUMPI }, + { "PC", Instruction::PC }, + { "MSIZE", Instruction::MSIZE }, + { "GAS", Instruction::GAS }, + { "JUMPDEST", Instruction::JUMPDEST }, + { "PUSH1", Instruction::PUSH1 }, + { "PUSH2", Instruction::PUSH2 }, + { "PUSH3", Instruction::PUSH3 }, + { "PUSH4", Instruction::PUSH4 }, + { "PUSH5", Instruction::PUSH5 }, + { "PUSH6", Instruction::PUSH6 }, + { "PUSH7", Instruction::PUSH7 }, + { "PUSH8", Instruction::PUSH8 }, + { "PUSH9", Instruction::PUSH9 }, + { "PUSH10", Instruction::PUSH10 }, + { "PUSH11", Instruction::PUSH11 }, + { "PUSH12", Instruction::PUSH12 }, + { "PUSH13", Instruction::PUSH13 }, + { "PUSH14", Instruction::PUSH14 }, + { "PUSH15", Instruction::PUSH15 }, + { "PUSH16", Instruction::PUSH16 }, + { "PUSH17", Instruction::PUSH17 }, + { "PUSH18", Instruction::PUSH18 }, + { "PUSH19", Instruction::PUSH19 }, + { "PUSH20", Instruction::PUSH20 }, + { "PUSH21", Instruction::PUSH21 }, + { "PUSH22", Instruction::PUSH22 }, + { "PUSH23", Instruction::PUSH23 }, + { "PUSH24", Instruction::PUSH24 }, + { "PUSH25", Instruction::PUSH25 }, + { "PUSH26", Instruction::PUSH26 }, + { "PUSH27", Instruction::PUSH27 }, + { "PUSH28", Instruction::PUSH28 }, + { "PUSH29", Instruction::PUSH29 }, + { "PUSH30", Instruction::PUSH30 }, + { "PUSH31", Instruction::PUSH31 }, + { "PUSH32", Instruction::PUSH32 }, + { "DUP1", Instruction::DUP1 }, + { "DUP2", Instruction::DUP2 }, + { "DUP3", Instruction::DUP3 }, + { "DUP4", Instruction::DUP4 }, + { "DUP5", Instruction::DUP5 }, + { "DUP6", Instruction::DUP6 }, + { "DUP7", Instruction::DUP7 }, + { "DUP8", Instruction::DUP8 }, + { "DUP9", Instruction::DUP9 }, + { "DUP10", Instruction::DUP10 }, + { "DUP11", Instruction::DUP11 }, + { "DUP12", Instruction::DUP12 }, + { "DUP13", Instruction::DUP13 }, + { "DUP14", Instruction::DUP14 }, + { "DUP15", Instruction::DUP15 }, + { "DUP16", Instruction::DUP16 }, + { "SWAP1", Instruction::SWAP1 }, + { "SWAP2", Instruction::SWAP2 }, + { "SWAP3", Instruction::SWAP3 }, + { "SWAP4", Instruction::SWAP4 }, + { "SWAP5", Instruction::SWAP5 }, + { "SWAP6", Instruction::SWAP6 }, + { "SWAP7", Instruction::SWAP7 }, + { "SWAP8", Instruction::SWAP8 }, + { "SWAP9", Instruction::SWAP9 }, + { "SWAP10", Instruction::SWAP10 }, + { "SWAP11", Instruction::SWAP11 }, + { "SWAP12", Instruction::SWAP12 }, + { "SWAP13", Instruction::SWAP13 }, + { "SWAP14", Instruction::SWAP14 }, + { "SWAP15", Instruction::SWAP15 }, + { "SWAP16", Instruction::SWAP16 }, + { "LOG0", Instruction::LOG0 }, + { "LOG1", Instruction::LOG1 }, + { "LOG2", Instruction::LOG2 }, + { "LOG3", Instruction::LOG3 }, + { "LOG4", Instruction::LOG4 }, + { "CREATE", Instruction::CREATE }, + { "CALL", Instruction::CALL }, + { "CALLCODE", Instruction::CALLCODE }, + { "RETURN", Instruction::RETURN }, + { "DELEGATECALL", Instruction::DELEGATECALL }, + { "SUICIDE", Instruction::SUICIDE } +}; + +static const std::map<Instruction, InstructionInfo> c_instructionInfo = +{ // Add, Args, Ret, SideEffects, GasPriceTier + { Instruction::STOP, { "STOP", 0, 0, 0, true, ZeroTier } }, + { Instruction::ADD, { "ADD", 0, 2, 1, false, VeryLowTier } }, + { Instruction::SUB, { "SUB", 0, 2, 1, false, VeryLowTier } }, + { Instruction::MUL, { "MUL", 0, 2, 1, false, LowTier } }, + { Instruction::DIV, { "DIV", 0, 2, 1, false, LowTier } }, + { Instruction::SDIV, { "SDIV", 0, 2, 1, false, LowTier } }, + { Instruction::MOD, { "MOD", 0, 2, 1, false, LowTier } }, + { Instruction::SMOD, { "SMOD", 0, 2, 1, false, LowTier } }, + { Instruction::EXP, { "EXP", 0, 2, 1, false, SpecialTier } }, + { Instruction::NOT, { "NOT", 0, 1, 1, false, VeryLowTier } }, + { Instruction::LT, { "LT", 0, 2, 1, false, VeryLowTier } }, + { Instruction::GT, { "GT", 0, 2, 1, false, VeryLowTier } }, + { Instruction::SLT, { "SLT", 0, 2, 1, false, VeryLowTier } }, + { Instruction::SGT, { "SGT", 0, 2, 1, false, VeryLowTier } }, + { Instruction::EQ, { "EQ", 0, 2, 1, false, VeryLowTier } }, + { Instruction::ISZERO, { "ISZERO", 0, 1, 1, false, VeryLowTier } }, + { Instruction::AND, { "AND", 0, 2, 1, false, VeryLowTier } }, + { Instruction::OR, { "OR", 0, 2, 1, false, VeryLowTier } }, + { Instruction::XOR, { "XOR", 0, 2, 1, false, VeryLowTier } }, + { Instruction::BYTE, { "BYTE", 0, 2, 1, false, VeryLowTier } }, + { Instruction::ADDMOD, { "ADDMOD", 0, 3, 1, false, MidTier } }, + { Instruction::MULMOD, { "MULMOD", 0, 3, 1, false, MidTier } }, + { Instruction::SIGNEXTEND, { "SIGNEXTEND", 0, 2, 1, false, LowTier } }, + { Instruction::SHA3, { "SHA3", 0, 2, 1, false, SpecialTier } }, + { Instruction::ADDRESS, { "ADDRESS", 0, 0, 1, false, BaseTier } }, + { Instruction::BALANCE, { "BALANCE", 0, 1, 1, false, ExtTier } }, + { Instruction::ORIGIN, { "ORIGIN", 0, 0, 1, false, BaseTier } }, + { Instruction::CALLER, { "CALLER", 0, 0, 1, false, BaseTier } }, + { Instruction::CALLVALUE, { "CALLVALUE", 0, 0, 1, false, BaseTier } }, + { Instruction::CALLDATALOAD,{ "CALLDATALOAD", 0, 1, 1, false, VeryLowTier } }, + { Instruction::CALLDATASIZE,{ "CALLDATASIZE", 0, 0, 1, false, BaseTier } }, + { Instruction::CALLDATACOPY,{ "CALLDATACOPY", 0, 3, 0, true, VeryLowTier } }, + { Instruction::CODESIZE, { "CODESIZE", 0, 0, 1, false, BaseTier } }, + { Instruction::CODECOPY, { "CODECOPY", 0, 3, 0, true, VeryLowTier } }, + { Instruction::GASPRICE, { "GASPRICE", 0, 0, 1, false, BaseTier } }, + { Instruction::EXTCODESIZE, { "EXTCODESIZE", 0, 1, 1, false, ExtTier } }, + { Instruction::EXTCODECOPY, { "EXTCODECOPY", 0, 4, 0, true, ExtTier } }, + { Instruction::BLOCKHASH, { "BLOCKHASH", 0, 1, 1, false, ExtTier } }, + { Instruction::COINBASE, { "COINBASE", 0, 0, 1, false, BaseTier } }, + { Instruction::TIMESTAMP, { "TIMESTAMP", 0, 0, 1, false, BaseTier } }, + { Instruction::NUMBER, { "NUMBER", 0, 0, 1, false, BaseTier } }, + { Instruction::DIFFICULTY, { "DIFFICULTY", 0, 0, 1, false, BaseTier } }, + { Instruction::GASLIMIT, { "GASLIMIT", 0, 0, 1, false, BaseTier } }, + { Instruction::POP, { "POP", 0, 1, 0, false, BaseTier } }, + { Instruction::MLOAD, { "MLOAD", 0, 1, 1, false, VeryLowTier } }, + { Instruction::MSTORE, { "MSTORE", 0, 2, 0, true, VeryLowTier } }, + { Instruction::MSTORE8, { "MSTORE8", 0, 2, 0, true, VeryLowTier } }, + { Instruction::SLOAD, { "SLOAD", 0, 1, 1, false, SpecialTier } }, + { Instruction::SSTORE, { "SSTORE", 0, 2, 0, true, SpecialTier } }, + { Instruction::JUMP, { "JUMP", 0, 1, 0, true, MidTier } }, + { Instruction::JUMPI, { "JUMPI", 0, 2, 0, true, HighTier } }, + { Instruction::PC, { "PC", 0, 0, 1, false, BaseTier } }, + { Instruction::MSIZE, { "MSIZE", 0, 0, 1, false, BaseTier } }, + { Instruction::GAS, { "GAS", 0, 0, 1, false, BaseTier } }, + { Instruction::JUMPDEST, { "JUMPDEST", 0, 0, 0, true, SpecialTier } }, + { Instruction::PUSH1, { "PUSH1", 1, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH2, { "PUSH2", 2, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH3, { "PUSH3", 3, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH4, { "PUSH4", 4, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH5, { "PUSH5", 5, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH6, { "PUSH6", 6, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH7, { "PUSH7", 7, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH8, { "PUSH8", 8, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH9, { "PUSH9", 9, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH10, { "PUSH10", 10, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH11, { "PUSH11", 11, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH12, { "PUSH12", 12, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH13, { "PUSH13", 13, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH14, { "PUSH14", 14, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH15, { "PUSH15", 15, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH16, { "PUSH16", 16, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH17, { "PUSH17", 17, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH18, { "PUSH18", 18, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH19, { "PUSH19", 19, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH20, { "PUSH20", 20, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH21, { "PUSH21", 21, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH22, { "PUSH22", 22, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH23, { "PUSH23", 23, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH24, { "PUSH24", 24, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH25, { "PUSH25", 25, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH26, { "PUSH26", 26, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH27, { "PUSH27", 27, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH28, { "PUSH28", 28, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH29, { "PUSH29", 29, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH30, { "PUSH30", 30, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH31, { "PUSH31", 31, 0, 1, false, VeryLowTier } }, + { Instruction::PUSH32, { "PUSH32", 32, 0, 1, false, VeryLowTier } }, + { Instruction::DUP1, { "DUP1", 0, 1, 2, false, VeryLowTier } }, + { Instruction::DUP2, { "DUP2", 0, 2, 3, false, VeryLowTier } }, + { Instruction::DUP3, { "DUP3", 0, 3, 4, false, VeryLowTier } }, + { Instruction::DUP4, { "DUP4", 0, 4, 5, false, VeryLowTier } }, + { Instruction::DUP5, { "DUP5", 0, 5, 6, false, VeryLowTier } }, + { Instruction::DUP6, { "DUP6", 0, 6, 7, false, VeryLowTier } }, + { Instruction::DUP7, { "DUP7", 0, 7, 8, false, VeryLowTier } }, + { Instruction::DUP8, { "DUP8", 0, 8, 9, false, VeryLowTier } }, + { Instruction::DUP9, { "DUP9", 0, 9, 10, false, VeryLowTier } }, + { Instruction::DUP10, { "DUP10", 0, 10, 11, false, VeryLowTier } }, + { Instruction::DUP11, { "DUP11", 0, 11, 12, false, VeryLowTier } }, + { Instruction::DUP12, { "DUP12", 0, 12, 13, false, VeryLowTier } }, + { Instruction::DUP13, { "DUP13", 0, 13, 14, false, VeryLowTier } }, + { Instruction::DUP14, { "DUP14", 0, 14, 15, false, VeryLowTier } }, + { Instruction::DUP15, { "DUP15", 0, 15, 16, false, VeryLowTier } }, + { Instruction::DUP16, { "DUP16", 0, 16, 17, false, VeryLowTier } }, + { Instruction::SWAP1, { "SWAP1", 0, 2, 2, false, VeryLowTier } }, + { Instruction::SWAP2, { "SWAP2", 0, 3, 3, false, VeryLowTier } }, + { Instruction::SWAP3, { "SWAP3", 0, 4, 4, false, VeryLowTier } }, + { Instruction::SWAP4, { "SWAP4", 0, 5, 5, false, VeryLowTier } }, + { Instruction::SWAP5, { "SWAP5", 0, 6, 6, false, VeryLowTier } }, + { Instruction::SWAP6, { "SWAP6", 0, 7, 7, false, VeryLowTier } }, + { Instruction::SWAP7, { "SWAP7", 0, 8, 8, false, VeryLowTier } }, + { Instruction::SWAP8, { "SWAP8", 0, 9, 9, false, VeryLowTier } }, + { Instruction::SWAP9, { "SWAP9", 0, 10, 10, false, VeryLowTier } }, + { Instruction::SWAP10, { "SWAP10", 0, 11, 11, false, VeryLowTier } }, + { Instruction::SWAP11, { "SWAP11", 0, 12, 12, false, VeryLowTier } }, + { Instruction::SWAP12, { "SWAP12", 0, 13, 13, false, VeryLowTier } }, + { Instruction::SWAP13, { "SWAP13", 0, 14, 14, false, VeryLowTier } }, + { Instruction::SWAP14, { "SWAP14", 0, 15, 15, false, VeryLowTier } }, + { Instruction::SWAP15, { "SWAP15", 0, 16, 16, false, VeryLowTier } }, + { Instruction::SWAP16, { "SWAP16", 0, 17, 17, false, VeryLowTier } }, + { Instruction::LOG0, { "LOG0", 0, 2, 0, true, SpecialTier } }, + { Instruction::LOG1, { "LOG1", 0, 3, 0, true, SpecialTier } }, + { Instruction::LOG2, { "LOG2", 0, 4, 0, true, SpecialTier } }, + { Instruction::LOG3, { "LOG3", 0, 5, 0, true, SpecialTier } }, + { Instruction::LOG4, { "LOG4", 0, 6, 0, true, SpecialTier } }, + { Instruction::CREATE, { "CREATE", 0, 3, 1, true, SpecialTier } }, + { Instruction::CALL, { "CALL", 0, 7, 1, true, SpecialTier } }, + { Instruction::CALLCODE, { "CALLCODE", 0, 7, 1, true, SpecialTier } }, + { Instruction::RETURN, { "RETURN", 0, 2, 0, true, ZeroTier } }, + { Instruction::DELEGATECALL,{ "DELEGATECALL", 0, 6, 1, true, SpecialTier } }, + { Instruction::SUICIDE, { "SUICIDE", 0, 1, 0, true, ZeroTier } } +}; + +void dev::solidity::eachInstruction( + bytes const& _mem, + function<void(Instruction,u256 const&)> const& _onInstruction +) +{ + for (auto it = _mem.begin(); it < _mem.end(); ++it) + { + Instruction instr = Instruction(*it); + size_t additional = 0; + if (isValidInstruction(instr)) + additional = instructionInfo(instr).additional; + u256 data; + for (size_t i = 0; i < additional; ++i) + { + data <<= 8; + if (++it < _mem.end()) + data |= *it; + } + _onInstruction(instr, data); + } +} + +string dev::solidity::disassemble(bytes const& _mem) +{ + stringstream ret; + eachInstruction(_mem, [&](Instruction _instr, u256 const& _data) { + if (!isValidInstruction(_instr)) + ret << "0x" << hex << int(_instr) << " "; + else + { + InstructionInfo info = instructionInfo(_instr); + ret << info.name << " "; + if (info.additional) + ret << "0x" << hex << _data << " "; + } + }); + return ret.str(); +} + +InstructionInfo dev::solidity::instructionInfo(Instruction _inst) +{ + try + { + return c_instructionInfo.at(_inst); + } + catch (...) + { + return InstructionInfo({"<INVALID_INSTRUCTION: " + toString((unsigned)_inst) + ">", 0, 0, 0, false, InvalidTier}); + } +} + +bool dev::solidity::isValidInstruction(Instruction _inst) +{ + return !!c_instructionInfo.count(_inst); +} diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h new file mode 100644 index 00000000..0b06a677 --- /dev/null +++ b/libevmasm/Instruction.h @@ -0,0 +1,268 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. +*/ +/** @file Instruction.h + * @author Gav Wood <i@gavwood.com> + * @date 2014 + */ + +#pragma once + +#include <functional> +#include <libdevcore/Common.h> +#include <libdevcore/Assertions.h> +#include "Exceptions.h" + +namespace dev +{ +namespace solidity +{ + +DEV_SIMPLE_EXCEPTION(InvalidDeposit); +DEV_SIMPLE_EXCEPTION(InvalidOpcode); + +/// Virtual machine bytecode instruction. +enum class Instruction: uint8_t +{ + STOP = 0x00, ///< halts execution + ADD, ///< addition operation + MUL, ///< mulitplication operation + SUB, ///< subtraction operation + DIV, ///< integer division operation + SDIV, ///< signed integer division operation + MOD, ///< modulo remainder operation + SMOD, ///< signed modulo remainder operation + ADDMOD, ///< unsigned modular addition + MULMOD, ///< unsigned modular multiplication + EXP, ///< exponential operation + SIGNEXTEND, ///< extend length of signed integer + + LT = 0x10, ///< less-than comparision + GT, ///< greater-than comparision + SLT, ///< signed less-than comparision + SGT, ///< signed greater-than comparision + EQ, ///< equality comparision + ISZERO, ///< simple not operator + AND, ///< bitwise AND operation + OR, ///< bitwise OR operation + XOR, ///< bitwise XOR operation + NOT, ///< bitwise NOT opertation + BYTE, ///< retrieve single byte from word + + SHA3 = 0x20, ///< compute SHA3-256 hash + + ADDRESS = 0x30, ///< get address of currently executing account + BALANCE, ///< get balance of the given account + ORIGIN, ///< get execution origination address + CALLER, ///< get caller address + CALLVALUE, ///< get deposited value by the instruction/transaction responsible for this execution + CALLDATALOAD, ///< get input data of current environment + CALLDATASIZE, ///< get size of input data in current environment + CALLDATACOPY, ///< copy input data in current environment to memory + CODESIZE, ///< get size of code running in current environment + CODECOPY, ///< copy code running in current environment to memory + GASPRICE, ///< get price of gas in current environment + EXTCODESIZE, ///< get external code size (from another contract) + EXTCODECOPY, ///< copy external code (from another contract) + + BLOCKHASH = 0x40, ///< get hash of most recent complete block + COINBASE, ///< get the block's coinbase address + TIMESTAMP, ///< get the block's timestamp + NUMBER, ///< get the block's number + DIFFICULTY, ///< get the block's difficulty + GASLIMIT, ///< get the block's gas limit + + POP = 0x50, ///< remove item from stack + MLOAD, ///< load word from memory + MSTORE, ///< save word to memory + MSTORE8, ///< save byte to memory + SLOAD, ///< load word from storage + SSTORE, ///< save word to storage + JUMP, ///< alter the program counter + JUMPI, ///< conditionally alter the program counter + PC, ///< get the program counter + MSIZE, ///< get the size of active memory + GAS, ///< get the amount of available gas + JUMPDEST, ///< set a potential jump destination + + PUSH1 = 0x60, ///< place 1 byte item on stack + PUSH2, ///< place 2 byte item on stack + PUSH3, ///< place 3 byte item on stack + PUSH4, ///< place 4 byte item on stack + PUSH5, ///< place 5 byte item on stack + PUSH6, ///< place 6 byte item on stack + PUSH7, ///< place 7 byte item on stack + PUSH8, ///< place 8 byte item on stack + PUSH9, ///< place 9 byte item on stack + PUSH10, ///< place 10 byte item on stack + PUSH11, ///< place 11 byte item on stack + PUSH12, ///< place 12 byte item on stack + PUSH13, ///< place 13 byte item on stack + PUSH14, ///< place 14 byte item on stack + PUSH15, ///< place 15 byte item on stack + PUSH16, ///< place 16 byte item on stack + PUSH17, ///< place 17 byte item on stack + PUSH18, ///< place 18 byte item on stack + PUSH19, ///< place 19 byte item on stack + PUSH20, ///< place 20 byte item on stack + PUSH21, ///< place 21 byte item on stack + PUSH22, ///< place 22 byte item on stack + PUSH23, ///< place 23 byte item on stack + PUSH24, ///< place 24 byte item on stack + PUSH25, ///< place 25 byte item on stack + PUSH26, ///< place 26 byte item on stack + PUSH27, ///< place 27 byte item on stack + PUSH28, ///< place 28 byte item on stack + PUSH29, ///< place 29 byte item on stack + PUSH30, ///< place 30 byte item on stack + PUSH31, ///< place 31 byte item on stack + PUSH32, ///< place 32 byte item on stack + + DUP1 = 0x80, ///< copies the highest item in the stack to the top of the stack + DUP2, ///< copies the second highest item in the stack to the top of the stack + DUP3, ///< copies the third highest item in the stack to the top of the stack + DUP4, ///< copies the 4th highest item in the stack to the top of the stack + DUP5, ///< copies the 5th highest item in the stack to the top of the stack + DUP6, ///< copies the 6th highest item in the stack to the top of the stack + DUP7, ///< copies the 7th highest item in the stack to the top of the stack + DUP8, ///< copies the 8th highest item in the stack to the top of the stack + DUP9, ///< copies the 9th highest item in the stack to the top of the stack + DUP10, ///< copies the 10th highest item in the stack to the top of the stack + DUP11, ///< copies the 11th highest item in the stack to the top of the stack + DUP12, ///< copies the 12th highest item in the stack to the top of the stack + DUP13, ///< copies the 13th highest item in the stack to the top of the stack + DUP14, ///< copies the 14th highest item in the stack to the top of the stack + DUP15, ///< copies the 15th highest item in the stack to the top of the stack + DUP16, ///< copies the 16th highest item in the stack to the top of the stack + + SWAP1 = 0x90, ///< swaps the highest and second highest value on the stack + SWAP2, ///< swaps the highest and third highest value on the stack + SWAP3, ///< swaps the highest and 4th highest value on the stack + SWAP4, ///< swaps the highest and 5th highest value on the stack + SWAP5, ///< swaps the highest and 6th highest value on the stack + SWAP6, ///< swaps the highest and 7th highest value on the stack + SWAP7, ///< swaps the highest and 8th highest value on the stack + SWAP8, ///< swaps the highest and 9th highest value on the stack + SWAP9, ///< swaps the highest and 10th highest value on the stack + SWAP10, ///< swaps the highest and 11th highest value on the stack + SWAP11, ///< swaps the highest and 12th highest value on the stack + SWAP12, ///< swaps the highest and 13th highest value on the stack + SWAP13, ///< swaps the highest and 14th highest value on the stack + SWAP14, ///< swaps the highest and 15th highest value on the stack + SWAP15, ///< swaps the highest and 16th highest value on the stack + SWAP16, ///< swaps the highest and 17th highest value on the stack + + LOG0 = 0xa0, ///< Makes a log entry; no topics. + LOG1, ///< Makes a log entry; 1 topic. + LOG2, ///< Makes a log entry; 2 topics. + LOG3, ///< Makes a log entry; 3 topics. + LOG4, ///< Makes a log entry; 4 topics. + + CREATE = 0xf0, ///< create a new account with associated code + CALL, ///< message-call into an account + CALLCODE, ///< message-call with another account's code only + RETURN, ///< halt execution returning output data + DELEGATECALL, ///< like CALLCODE but keeps caller's value and sender + SUICIDE = 0xff ///< halt execution and register account for later deletion +}; + +/// @returns the number of PUSH Instruction _inst +inline unsigned getPushNumber(Instruction _inst) +{ + return (byte)_inst - unsigned(Instruction::PUSH1) + 1; +} + +/// @returns the number of DUP Instruction _inst +inline unsigned getDupNumber(Instruction _inst) +{ + return (byte)_inst - unsigned(Instruction::DUP1) + 1; +} + +/// @returns the number of SWAP Instruction _inst +inline unsigned getSwapNumber(Instruction _inst) +{ + return (byte)_inst - unsigned(Instruction::SWAP1) + 1; +} + +/// @returns the PUSH<_number> instruction +inline Instruction pushInstruction(unsigned _number) +{ + assertThrow(1 <= _number && _number <= 32, InvalidOpcode, "Invalid PUSH instruction requested."); + return Instruction(unsigned(Instruction::PUSH1) + _number - 1); +} + +/// @returns the DUP<_number> instruction +inline Instruction dupInstruction(unsigned _number) +{ + assertThrow(1 <= _number && _number <= 16, InvalidOpcode, "Invalid DUP instruction requested."); + return Instruction(unsigned(Instruction::DUP1) + _number - 1); +} + +/// @returns the SWAP<_number> instruction +inline Instruction swapInstruction(unsigned _number) +{ + assertThrow(1 <= _number && _number <= 16, InvalidOpcode, "Invalid SWAP instruction requested."); + return Instruction(unsigned(Instruction::SWAP1) + _number - 1); +} + +/// @returns the LOG<_number> instruction +inline Instruction logInstruction(unsigned _number) +{ + assertThrow(_number <= 4, InvalidOpcode, "Invalid LOG instruction requested."); + return Instruction(unsigned(Instruction::LOG0) + _number); +} + +enum Tier +{ + ZeroTier = 0, // 0, Zero + BaseTier, // 2, Quick + VeryLowTier, // 3, Fastest + LowTier, // 5, Fast + MidTier, // 8, Mid + HighTier, // 10, Slow + ExtTier, // 20, Ext + SpecialTier, // multiparam or otherwise special + InvalidTier // Invalid. +}; + +/// Information structure for a particular instruction. +struct InstructionInfo +{ + std::string name; ///< The name of the instruction. + int additional; ///< Additional items required in memory for this instructions (only for PUSH). + int args; ///< Number of items required on the stack for this instruction (and, for the purposes of ret, the number taken from the stack). + int ret; ///< Number of items placed (back) on the stack by this instruction, assuming args items were removed. + bool sideEffects; ///< false if the only effect on the execution environment (apart from gas usage) is a change to a topmost segment of the stack + int gasPriceTier; ///< Tier for gas pricing. +}; + +/// Information on all the instructions. +InstructionInfo instructionInfo(Instruction _inst); + +/// check whether instructions exists +bool isValidInstruction(Instruction _inst); + +/// Convert from string mnemonic to Instruction type. +extern const std::map<std::string, Instruction> c_instructions; + +/// Iterate through EVM code and call a function on each instruction. +void eachInstruction(bytes const& _mem, std::function<void(Instruction,u256 const&)> const& _onInstruction); + +/// Convert from EVM code to simple EVM assembly language. +std::string disassemble(bytes const& _mem); + +} +} diff --git a/libevmasm/PathGasMeter.cpp b/libevmasm/PathGasMeter.cpp index 8f7314f8..2113008b 100644 --- a/libevmasm/PathGasMeter.cpp +++ b/libevmasm/PathGasMeter.cpp @@ -76,7 +76,7 @@ GasMeter::GasConsumption PathGasMeter::handleQueueItem() bool branchStops = false; jumpTags.clear(); AssemblyItem const& item = m_items.at(index); - if (item.type() == Tag || item == AssemblyItem(eth::Instruction::JUMPDEST)) + if (item.type() == Tag || item == AssemblyItem(Instruction::JUMPDEST)) { // Do not allow any backwards jump. This is quite restrictive but should work for // the simplest things. @@ -84,14 +84,14 @@ GasMeter::GasConsumption PathGasMeter::handleQueueItem() return GasMeter::GasConsumption::infinite(); path->visitedJumpdests.insert(index); } - else if (item == AssemblyItem(eth::Instruction::JUMP)) + else if (item == AssemblyItem(Instruction::JUMP)) { branchStops = true; jumpTags = state->tagsInExpression(state->relativeStackElement(0)); if (jumpTags.empty()) // unknown jump destination return GasMeter::GasConsumption::infinite(); } - else if (item == AssemblyItem(eth::Instruction::JUMPI)) + else if (item == AssemblyItem(Instruction::JUMPI)) { ExpressionClasses::Id condition = state->relativeStackElement(-1); if (classes.knownNonZero(condition) || !classes.knownZero(condition)) diff --git a/libevmasm/SemanticInformation.h b/libevmasm/SemanticInformation.h index 094f4591..0eda5ed5 100644 --- a/libevmasm/SemanticInformation.h +++ b/libevmasm/SemanticInformation.h @@ -23,7 +23,7 @@ #pragma once -#include <libevmcore/Instruction.h> +#include <libevmasm/Instruction.h> namespace dev { @@ -50,9 +50,9 @@ struct SemanticInformation /// the information in the current block header, memory, storage or stack. static bool isDeterministic(AssemblyItem const& _item); /// @returns true if the given instruction modifies memory. - static bool invalidatesMemory(Instruction _instruction); + static bool invalidatesMemory(solidity::Instruction _instruction); /// @returns true if the given instruction modifies storage (even indirectly). - static bool invalidatesStorage(Instruction _instruction); + static bool invalidatesStorage(solidity::Instruction _instruction); }; } diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp index 64680d5a..7998a5b5 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -30,7 +30,7 @@ #pragma GCC diagnostic pop #include <libdevcore/Log.h> #include <libdevcore/CommonIO.h> -#include <libevmcore/Instruction.h> +#include <libevmasm/Instruction.h> #include "CompilerState.h" #include "Parser.h" using namespace std; diff --git a/liblll/CodeFragment.h b/liblll/CodeFragment.h index 03f812b6..e0d48ab7 100644 --- a/liblll/CodeFragment.h +++ b/liblll/CodeFragment.h @@ -22,7 +22,7 @@ #pragma once #include <libdevcore/Common.h> -#include <libevmcore/Instruction.h> +#include <libevmasm/Instruction.h> #include <libevmasm/Assembly.h> #include "Exceptions.h" diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index c63b6b5a..bc342b58 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -595,7 +595,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) if (!varDecl->isLocalVariable()) return false; // only local variables are inline-assemlby lvalues for (unsigned i = 0; i < declaration->type()->sizeOnStack(); ++i) - _assembly.append(eth::Instruction::POP); // remove value just to verify the stack height + _assembly.append(Instruction::POP); // remove value just to verify the stack height } else return false; diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 7bb2529a..bf275869 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -28,7 +28,7 @@ #include <memory> #include <boost/noncopyable.hpp> #include <libevmasm/SourceLocation.h> -#include <libevmcore/Instruction.h> +#include <libevmasm/Instruction.h> #include <libsolidity/interface/Utils.h> #include <libsolidity/ast/ASTForward.h> #include <libsolidity/parsing/Token.h> diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index f1acce31..8e568be5 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -21,7 +21,7 @@ */ #include <libsolidity/codegen/ArrayUtils.h> -#include <libevmcore/Instruction.h> +#include <libevmasm/Instruction.h> #include <libsolidity/codegen/CompilerContext.h> #include <libsolidity/codegen/CompilerUtils.h> #include <libsolidity/ast/Types.h> @@ -56,7 +56,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons // stack: source_ref [source_length] target_ref // store target_ref for (unsigned i = _sourceType.sizeOnStack(); i > 0; --i) - m_context << eth::swapInstruction(i); + m_context << swapInstruction(i); // stack: target_ref source_ref [source_length] // stack: target_ref source_ref [source_length] // retrieve source length @@ -65,12 +65,12 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons if (_sourceType.location() == DataLocation::Memory && _sourceType.isDynamicallySized()) { // increment source pointer to point to data - m_context << eth::Instruction::SWAP1 << u256(0x20); - m_context << eth::Instruction::ADD << eth::Instruction::SWAP1; + m_context << Instruction::SWAP1 << u256(0x20); + m_context << Instruction::ADD << Instruction::SWAP1; } // stack: target_ref source_ref source_length - m_context << eth::Instruction::DUP3; + m_context << Instruction::DUP3; // stack: target_ref source_ref source_length target_ref retrieveLength(_targetType); // stack: target_ref source_ref source_length target_ref target_length @@ -78,28 +78,28 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons // store new target length if (!_targetType.isByteArray()) // Otherwise, length will be stored below. - m_context << eth::Instruction::DUP3 << eth::Instruction::DUP3 << eth::Instruction::SSTORE; + m_context << Instruction::DUP3 << Instruction::DUP3 << Instruction::SSTORE; if (sourceBaseType->category() == Type::Category::Mapping) { solAssert(targetBaseType->category() == Type::Category::Mapping, ""); solAssert(_sourceType.location() == DataLocation::Storage, ""); // nothing to copy m_context - << eth::Instruction::POP << eth::Instruction::POP - << eth::Instruction::POP << eth::Instruction::POP; + << Instruction::POP << Instruction::POP + << Instruction::POP << Instruction::POP; return; } // stack: target_ref source_ref source_length target_ref target_length // compute hashes (data positions) - m_context << eth::Instruction::SWAP1; + m_context << Instruction::SWAP1; if (_targetType.isDynamicallySized()) CompilerUtils(m_context).computeHashStatic(); // stack: target_ref source_ref source_length target_length target_data_pos - m_context << eth::Instruction::SWAP1; + m_context << Instruction::SWAP1; convertLengthToSize(_targetType); - m_context << eth::Instruction::DUP2 << eth::Instruction::ADD; + m_context << Instruction::DUP2 << Instruction::ADD; // stack: target_ref source_ref source_length target_data_pos target_data_end - m_context << eth::Instruction::SWAP3; + m_context << Instruction::SWAP3; // stack: target_ref target_data_end source_length target_data_pos source_ref eth::AssemblyItem copyLoopEndWithoutByteOffset = m_context.newTag(); @@ -108,47 +108,47 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons if (_targetType.isByteArray()) { // stack: target_ref target_data_end source_length target_data_pos source_ref - m_context << eth::Instruction::DUP3 << u256(31) << eth::Instruction::LT; + m_context << Instruction::DUP3 << u256(31) << Instruction::LT; eth::AssemblyItem longByteArray = m_context.appendConditionalJump(); // store the short byte array solAssert(_sourceType.isByteArray(), ""); if (_sourceType.location() == DataLocation::Storage) { // just copy the slot, it contains length and data - m_context << eth::Instruction::DUP1 << eth::Instruction::SLOAD; - m_context << eth::Instruction::DUP6 << eth::Instruction::SSTORE; + m_context << Instruction::DUP1 << Instruction::SLOAD; + m_context << Instruction::DUP6 << Instruction::SSTORE; } else { - m_context << eth::Instruction::DUP1; + m_context << Instruction::DUP1; CompilerUtils(m_context).loadFromMemoryDynamic(*sourceBaseType, fromCalldata, true, false); // stack: target_ref target_data_end source_length target_data_pos source_ref value // clear the lower-order byte - which will hold the length - m_context << u256(0xff) << eth::Instruction::NOT << eth::Instruction::AND; + m_context << u256(0xff) << Instruction::NOT << Instruction::AND; // fetch the length and shift it left by one - m_context << eth::Instruction::DUP4 << eth::Instruction::DUP1 << eth::Instruction::ADD; + m_context << Instruction::DUP4 << Instruction::DUP1 << Instruction::ADD; // combine value and length and store them - m_context << eth::Instruction::OR << eth::Instruction::DUP6 << eth::Instruction::SSTORE; + m_context << Instruction::OR << Instruction::DUP6 << Instruction::SSTORE; } // end of special case, jump right into cleaning target data area m_context.appendJumpTo(copyLoopEndWithoutByteOffset); m_context << longByteArray; // Store length (2*length+1) - m_context << eth::Instruction::DUP3 << eth::Instruction::DUP1 << eth::Instruction::ADD; - m_context << u256(1) << eth::Instruction::ADD; - m_context << eth::Instruction::DUP6 << eth::Instruction::SSTORE; + m_context << Instruction::DUP3 << Instruction::DUP1 << Instruction::ADD; + m_context << u256(1) << Instruction::ADD; + m_context << Instruction::DUP6 << Instruction::SSTORE; } // skip copying if source length is zero - m_context << eth::Instruction::DUP3 << eth::Instruction::ISZERO; + m_context << Instruction::DUP3 << Instruction::ISZERO; m_context.appendConditionalJumpTo(copyLoopEndWithoutByteOffset); if (_sourceType.location() == DataLocation::Storage && _sourceType.isDynamicallySized()) CompilerUtils(m_context).computeHashStatic(); // stack: target_ref target_data_end source_length target_data_pos source_data_pos - m_context << eth::Instruction::SWAP2; + m_context << Instruction::SWAP2; convertLengthToSize(_sourceType); - m_context << eth::Instruction::DUP3 << eth::Instruction::ADD; + m_context << Instruction::DUP3 << Instruction::ADD; // stack: target_ref target_data_end source_data_pos target_data_pos source_data_end if (haveByteOffsetTarget) m_context << u256(0); @@ -159,8 +159,8 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons m_context << copyLoopStart; // check for loop condition m_context - << eth::dupInstruction(3 + byteOffsetSize) << eth::dupInstruction(2 + byteOffsetSize) - << eth::Instruction::GT << eth::Instruction::ISZERO; + << dupInstruction(3 + byteOffsetSize) << dupInstruction(2 + byteOffsetSize) + << Instruction::GT << Instruction::ISZERO; eth::AssemblyItem copyLoopEnd = m_context.appendConditionalJump(); // stack: target_ref target_data_end source_data_pos target_data_pos source_data_end [target_byte_offset] [source_byte_offset] // copy @@ -168,19 +168,19 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons { solAssert(byteOffsetSize == 0, "Byte offset for array as base type."); auto const& sourceBaseArrayType = dynamic_cast<ArrayType const&>(*sourceBaseType); - m_context << eth::Instruction::DUP3; + m_context << Instruction::DUP3; if (sourceBaseArrayType.location() == DataLocation::Memory) - m_context << eth::Instruction::MLOAD; - m_context << eth::Instruction::DUP3; + m_context << Instruction::MLOAD; + m_context << Instruction::DUP3; copyArrayToStorage(dynamic_cast<ArrayType const&>(*targetBaseType), sourceBaseArrayType); - m_context << eth::Instruction::POP; + m_context << Instruction::POP; } else if (directCopy) { solAssert(byteOffsetSize == 0, "Byte offset for direct copy."); m_context - << eth::Instruction::DUP3 << eth::Instruction::SLOAD - << eth::Instruction::DUP3 << eth::Instruction::SSTORE; + << Instruction::DUP3 << Instruction::SLOAD + << Instruction::DUP3 << Instruction::SSTORE; } else { @@ -188,11 +188,11 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons // We might copy too much if there is padding at the last element, but this way end // checking is easier. // stack: target_ref target_data_end source_data_pos target_data_pos source_data_end [target_byte_offset] [source_byte_offset] - m_context << eth::dupInstruction(3 + byteOffsetSize); + m_context << dupInstruction(3 + byteOffsetSize); if (_sourceType.location() == DataLocation::Storage) { if (haveByteOffsetSource) - m_context << eth::Instruction::DUP2; + m_context << Instruction::DUP2; else m_context << u256(0); StorageItem(m_context, *sourceBaseType).retrieveValue(SourceLocation(), true); @@ -207,9 +207,9 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons "Stack too deep, try removing local variables." ); // fetch target storage reference - m_context << eth::dupInstruction(2 + byteOffsetSize + sourceBaseType->sizeOnStack()); + m_context << dupInstruction(2 + byteOffsetSize + sourceBaseType->sizeOnStack()); if (haveByteOffsetTarget) - m_context << eth::dupInstruction(1 + byteOffsetSize + sourceBaseType->sizeOnStack()); + m_context << dupInstruction(1 + byteOffsetSize + sourceBaseType->sizeOnStack()); else m_context << u256(0); StorageItem(m_context, *targetBaseType).storeValue(*sourceBaseType, SourceLocation(), true); @@ -220,7 +220,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons incrementByteOffset(sourceBaseType->storageBytes(), 1, haveByteOffsetTarget ? 5 : 4); else { - m_context << eth::swapInstruction(2 + byteOffsetSize); + m_context << swapInstruction(2 + byteOffsetSize); if (sourceIsStorage) m_context << sourceBaseType->storageSize(); else if (_sourceType.location() == DataLocation::Memory) @@ -228,44 +228,44 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons else m_context << sourceBaseType->calldataEncodedSize(true); m_context - << eth::Instruction::ADD - << eth::swapInstruction(2 + byteOffsetSize); + << Instruction::ADD + << swapInstruction(2 + byteOffsetSize); } // increment target if (haveByteOffsetTarget) incrementByteOffset(targetBaseType->storageBytes(), byteOffsetSize, byteOffsetSize + 2); else m_context - << eth::swapInstruction(1 + byteOffsetSize) + << swapInstruction(1 + byteOffsetSize) << targetBaseType->storageSize() - << eth::Instruction::ADD - << eth::swapInstruction(1 + byteOffsetSize); + << Instruction::ADD + << swapInstruction(1 + byteOffsetSize); m_context.appendJumpTo(copyLoopStart); m_context << copyLoopEnd; if (haveByteOffsetTarget) { // 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] - m_context << eth::dupInstruction(byteOffsetSize) << eth::Instruction::ISZERO; + m_context << dupInstruction(byteOffsetSize) << Instruction::ISZERO; eth::AssemblyItem copyCleanupLoopEnd = m_context.appendConditionalJump(); - m_context << eth::dupInstruction(2 + byteOffsetSize) << eth::dupInstruction(1 + byteOffsetSize); + m_context << dupInstruction(2 + byteOffsetSize) << dupInstruction(1 + byteOffsetSize); StorageItem(m_context, *targetBaseType).setToZero(SourceLocation(), true); incrementByteOffset(targetBaseType->storageBytes(), byteOffsetSize, byteOffsetSize + 2); m_context.appendJumpTo(copyLoopEnd); m_context << copyCleanupLoopEnd; - m_context << eth::Instruction::POP; // might pop the source, but then target is popped next + m_context << Instruction::POP; // might pop the source, but then target is popped next } if (haveByteOffsetSource) - m_context << eth::Instruction::POP; + m_context << Instruction::POP; m_context << copyLoopEndWithoutByteOffset; // zero-out leftovers in target // stack: target_ref target_data_end source_data_pos target_data_pos_updated source_data_end - m_context << eth::Instruction::POP << eth::Instruction::SWAP1 << eth::Instruction::POP; + m_context << Instruction::POP << Instruction::SWAP1 << Instruction::POP; // stack: target_ref target_data_end target_data_pos_updated clearStorageLoop(*targetBaseType); - m_context << eth::Instruction::POP; + m_context << Instruction::POP; } void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWordBoundaries) const @@ -285,13 +285,13 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord if (!_sourceType.isDynamicallySized()) m_context << _sourceType.length(); if (baseSize > 1) - m_context << u256(baseSize) << eth::Instruction::MUL; + m_context << u256(baseSize) << Instruction::MUL; // stack: target source_offset source_len - m_context << eth::Instruction::DUP1 << eth::Instruction::DUP3 << eth::Instruction::DUP5; + m_context << Instruction::DUP1 << Instruction::DUP3 << Instruction::DUP5; // stack: target source_offset source_len source_len source_offset target - m_context << eth::Instruction::CALLDATACOPY; - m_context << eth::Instruction::DUP3 << eth::Instruction::ADD; - m_context << eth::Instruction::SWAP2 << eth::Instruction::POP << eth::Instruction::POP; + m_context << Instruction::CALLDATACOPY; + m_context << Instruction::DUP3 << Instruction::ADD; + m_context << Instruction::SWAP2 << Instruction::POP << Instruction::POP; } else if (_sourceType.location() == DataLocation::Memory) { @@ -300,25 +300,25 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord if (!_sourceType.baseType()->isValueType()) { // copy using a loop - m_context << u256(0) << eth::Instruction::SWAP3; + m_context << u256(0) << Instruction::SWAP3; // stack: counter source length target auto repeat = m_context.newTag(); m_context << repeat; - m_context << eth::Instruction::DUP2 << eth::Instruction::DUP5; - m_context << eth::Instruction::LT << eth::Instruction::ISZERO; + m_context << Instruction::DUP2 << Instruction::DUP5; + m_context << Instruction::LT << Instruction::ISZERO; auto loopEnd = m_context.appendConditionalJump(); - m_context << eth::Instruction::DUP3 << eth::Instruction::DUP5; + m_context << Instruction::DUP3 << Instruction::DUP5; accessIndex(_sourceType, false); MemoryItem(m_context, *_sourceType.baseType(), true).retrieveValue(SourceLocation(), true); if (auto baseArray = dynamic_cast<ArrayType const*>(_sourceType.baseType().get())) copyArrayToMemory(*baseArray, _padToWordBoundaries); else utils.storeInMemoryDynamic(*_sourceType.baseType()); - m_context << eth::Instruction::SWAP3 << u256(1) << eth::Instruction::ADD; - m_context << eth::Instruction::SWAP3; + m_context << Instruction::SWAP3 << u256(1) << Instruction::ADD; + m_context << Instruction::SWAP3; m_context.appendJumpTo(repeat); m_context << loopEnd; - m_context << eth::Instruction::SWAP3; + m_context << Instruction::SWAP3; utils.popStackSlots(3); // stack: updated_target_pos return; @@ -328,18 +328,18 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord if (_sourceType.isDynamicallySized()) { // change pointer to data part - m_context << eth::Instruction::SWAP1 << u256(32) << eth::Instruction::ADD; - m_context << eth::Instruction::SWAP1; + m_context << Instruction::SWAP1 << u256(32) << Instruction::ADD; + m_context << Instruction::SWAP1; } // convert length to size if (baseSize > 1) - m_context << u256(baseSize) << eth::Instruction::MUL; + m_context << u256(baseSize) << Instruction::MUL; // stack: <target> <source> <size> //@TODO do not use ::CALL if less than 32 bytes? - m_context << eth::Instruction::DUP1 << eth::Instruction::DUP4 << eth::Instruction::DUP4; + m_context << Instruction::DUP1 << Instruction::DUP4 << Instruction::DUP4; utils.memoryCopy(); - m_context << eth::Instruction::SWAP1 << eth::Instruction::POP; + m_context << Instruction::SWAP1 << Instruction::POP; // stack: <target> <size> bool paddingNeeded = false; @@ -350,43 +350,43 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord if (paddingNeeded) { // stack: <target> <size> - m_context << eth::Instruction::SWAP1 << eth::Instruction::DUP2 << eth::Instruction::ADD; + m_context << Instruction::SWAP1 << Instruction::DUP2 << Instruction::ADD; // stack: <length> <target + size> - m_context << eth::Instruction::SWAP1 << u256(31) << eth::Instruction::AND; + m_context << Instruction::SWAP1 << u256(31) << Instruction::AND; // stack: <target + size> <remainder = size % 32> eth::AssemblyItem skip = m_context.newTag(); if (_sourceType.isDynamicallySized()) { - m_context << eth::Instruction::DUP1 << eth::Instruction::ISZERO; + m_context << Instruction::DUP1 << Instruction::ISZERO; m_context.appendConditionalJumpTo(skip); } // round off, load from there. // stack <target + size> <remainder = size % 32> - m_context << eth::Instruction::DUP1 << eth::Instruction::DUP3; - m_context << eth::Instruction::SUB; + m_context << Instruction::DUP1 << Instruction::DUP3; + m_context << Instruction::SUB; // stack: target+size remainder <target + size - remainder> - m_context << eth::Instruction::DUP1 << eth::Instruction::MLOAD; + m_context << Instruction::DUP1 << Instruction::MLOAD; // Now we AND it with ~(2**(8 * (32 - remainder)) - 1) m_context << u256(1); - m_context << eth::Instruction::DUP4 << u256(32) << eth::Instruction::SUB; + m_context << Instruction::DUP4 << u256(32) << Instruction::SUB; // stack: ...<v> 1 <32 - remainder> - m_context << u256(0x100) << eth::Instruction::EXP << eth::Instruction::SUB; - m_context << eth::Instruction::NOT << eth::Instruction::AND; + m_context << u256(0x100) << Instruction::EXP << Instruction::SUB; + m_context << Instruction::NOT << Instruction::AND; // stack: target+size remainder target+size-remainder <v & ...> - m_context << eth::Instruction::DUP2 << eth::Instruction::MSTORE; + m_context << Instruction::DUP2 << Instruction::MSTORE; // stack: target+size remainder target+size-remainder - m_context << u256(32) << eth::Instruction::ADD; + m_context << u256(32) << Instruction::ADD; // stack: target+size remainder <new_padded_end> - m_context << eth::Instruction::SWAP2 << eth::Instruction::POP; + m_context << Instruction::SWAP2 << Instruction::POP; if (_sourceType.isDynamicallySized()) m_context << skip.tag(); // stack <target + "size"> <remainder = size % 32> - m_context << eth::Instruction::POP; + m_context << Instruction::POP; } else // stack: <target> <size> - m_context << eth::Instruction::ADD; + m_context << Instruction::ADD; } else { @@ -398,48 +398,48 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord retrieveLength(_sourceType); // stack here: memory_offset storage_offset length // jump to end if length is zero - m_context << eth::Instruction::DUP1 << eth::Instruction::ISZERO; + m_context << Instruction::DUP1 << Instruction::ISZERO; eth::AssemblyItem loopEnd = m_context.appendConditionalJump(); // Special case for tightly-stored byte arrays if (_sourceType.isByteArray()) { // stack here: memory_offset storage_offset length - m_context << eth::Instruction::DUP1 << u256(31) << eth::Instruction::LT; + m_context << Instruction::DUP1 << u256(31) << Instruction::LT; eth::AssemblyItem longByteArray = m_context.appendConditionalJump(); // store the short byte array (discard lower-order byte) - m_context << u256(0x100) << eth::Instruction::DUP1; - m_context << eth::Instruction::DUP4 << eth::Instruction::SLOAD; - m_context << eth::Instruction::DIV << eth::Instruction::MUL; - m_context << eth::Instruction::DUP4 << eth::Instruction::MSTORE; + m_context << u256(0x100) << Instruction::DUP1; + m_context << Instruction::DUP4 << Instruction::SLOAD; + m_context << Instruction::DIV << Instruction::MUL; + m_context << Instruction::DUP4 << Instruction::MSTORE; // stack here: memory_offset storage_offset length // add 32 or length to memory offset - m_context << eth::Instruction::SWAP2; + m_context << Instruction::SWAP2; if (_padToWordBoundaries) m_context << u256(32); else - m_context << eth::Instruction::DUP3; - m_context << eth::Instruction::ADD; - m_context << eth::Instruction::SWAP2; + m_context << Instruction::DUP3; + m_context << Instruction::ADD; + m_context << Instruction::SWAP2; m_context.appendJumpTo(loopEnd); m_context << longByteArray; } // compute memory end offset if (baseSize > 1) // convert length to memory size - m_context << u256(baseSize) << eth::Instruction::MUL; - m_context << eth::Instruction::DUP3 << eth::Instruction::ADD << eth::Instruction::SWAP2; + m_context << u256(baseSize) << Instruction::MUL; + m_context << Instruction::DUP3 << Instruction::ADD << Instruction::SWAP2; if (_sourceType.isDynamicallySized()) { // actual array data is stored at SHA3(storage_offset) - m_context << eth::Instruction::SWAP1; + m_context << Instruction::SWAP1; utils.computeHashStatic(); - m_context << eth::Instruction::SWAP1; + m_context << Instruction::SWAP1; } // stack here: memory_end_offset storage_data_offset memory_offset bool haveByteOffset = !_sourceType.isByteArray() && storageBytes <= 16; if (haveByteOffset) - m_context << u256(0) << eth::Instruction::SWAP1; + m_context << u256(0) << Instruction::SWAP1; // stack here: memory_end_offset storage_data_offset [storage_byte_offset] memory_offset eth::AssemblyItem loopStart = m_context.newTag(); m_context << loopStart; @@ -447,20 +447,20 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord if (_sourceType.isByteArray()) { // Packed both in storage and memory. - m_context << eth::Instruction::DUP2 << eth::Instruction::SLOAD; - m_context << eth::Instruction::DUP2 << eth::Instruction::MSTORE; + m_context << Instruction::DUP2 << Instruction::SLOAD; + m_context << Instruction::DUP2 << Instruction::MSTORE; // increment storage_data_offset by 1 - m_context << eth::Instruction::SWAP1 << u256(1) << eth::Instruction::ADD; + m_context << Instruction::SWAP1 << u256(1) << Instruction::ADD; // increment memory offset by 32 - m_context << eth::Instruction::SWAP1 << u256(32) << eth::Instruction::ADD; + m_context << Instruction::SWAP1 << u256(32) << Instruction::ADD; } else { // stack here: memory_end_offset storage_data_offset [storage_byte_offset] memory_offset if (haveByteOffset) - m_context << eth::Instruction::DUP3 << eth::Instruction::DUP3; + m_context << Instruction::DUP3 << Instruction::DUP3; else - m_context << eth::Instruction::DUP2 << u256(0); + m_context << Instruction::DUP2 << u256(0); StorageItem(m_context, *_sourceType.baseType()).retrieveValue(SourceLocation(), true); if (auto baseArray = dynamic_cast<ArrayType const*>(_sourceType.baseType().get())) copyArrayToMemory(*baseArray, _padToWordBoundaries); @@ -471,29 +471,29 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord incrementByteOffset(storageBytes, 2, 3); else { - m_context << eth::Instruction::SWAP1; - m_context << storageSize << eth::Instruction::ADD; - m_context << eth::Instruction::SWAP1; + m_context << Instruction::SWAP1; + m_context << storageSize << Instruction::ADD; + m_context << Instruction::SWAP1; } } // check for loop condition - m_context << eth::Instruction::DUP1 << eth::dupInstruction(haveByteOffset ? 5 : 4); - m_context << eth::Instruction::GT; + m_context << Instruction::DUP1 << dupInstruction(haveByteOffset ? 5 : 4); + m_context << Instruction::GT; m_context.appendConditionalJumpTo(loopStart); // stack here: memory_end_offset storage_data_offset [storage_byte_offset] memory_offset if (haveByteOffset) - m_context << eth::Instruction::SWAP1 << eth::Instruction::POP; + m_context << Instruction::SWAP1 << Instruction::POP; if (_padToWordBoundaries && baseSize % 32 != 0) { // memory_end_offset - start is the actual length (we want to compute the ceil of). // memory_offset - start is its next multiple of 32, but it might be off by 32. // so we compute: memory_end_offset += (memory_offset - memory_end_offest) & 31 - m_context << eth::Instruction::DUP3 << eth::Instruction::SWAP1 << eth::Instruction::SUB; - m_context << u256(31) << eth::Instruction::AND; - m_context << eth::Instruction::DUP3 << eth::Instruction::ADD; - m_context << eth::Instruction::SWAP2; + m_context << Instruction::DUP3 << Instruction::SWAP1 << Instruction::SUB; + m_context << u256(31) << Instruction::AND; + m_context << Instruction::DUP3 << Instruction::ADD; + m_context << Instruction::SWAP2; } - m_context << loopEnd << eth::Instruction::POP << eth::Instruction::POP; + m_context << loopEnd << Instruction::POP << Instruction::POP; } } @@ -509,20 +509,20 @@ void ArrayUtils::clearArray(ArrayType const& _type) const if (_type.baseType()->isValueType()) solAssert(_type.baseType()->storageSize() <= 1, "Invalid size for value type."); - m_context << eth::Instruction::POP; // remove byte offset + m_context << Instruction::POP; // remove byte offset if (_type.isDynamicallySized()) clearDynamicArray(_type); else if (_type.length() == 0 || _type.baseType()->category() == Type::Category::Mapping) - m_context << eth::Instruction::POP; + m_context << Instruction::POP; else if (_type.baseType()->isValueType() && _type.storageSize() <= 5) { // unroll loop for small arrays @todo choose a good value // Note that we loop over storage slots here, not elements. for (unsigned i = 1; i < _type.storageSize(); ++i) m_context - << u256(0) << eth::Instruction::DUP2 << eth::Instruction::SSTORE - << u256(1) << eth::Instruction::ADD; - m_context << u256(0) << eth::Instruction::SWAP1 << eth::Instruction::SSTORE; + << u256(0) << Instruction::DUP2 << Instruction::SSTORE + << u256(1) << Instruction::ADD; + m_context << u256(0) << Instruction::SWAP1 << Instruction::SSTORE; } else if (!_type.baseType()->isValueType() && _type.length() <= 4) { @@ -533,22 +533,22 @@ void ArrayUtils::clearArray(ArrayType const& _type) const m_context << u256(0); StorageItem(m_context, *_type.baseType()).setToZero(SourceLocation(), false); m_context - << eth::Instruction::POP - << u256(_type.baseType()->storageSize()) << eth::Instruction::ADD; + << Instruction::POP + << u256(_type.baseType()->storageSize()) << Instruction::ADD; } m_context << u256(0); StorageItem(m_context, *_type.baseType()).setToZero(SourceLocation(), true); } else { - m_context << eth::Instruction::DUP1 << _type.length(); + m_context << Instruction::DUP1 << _type.length(); convertLengthToSize(_type); - m_context << eth::Instruction::ADD << eth::Instruction::SWAP1; + m_context << Instruction::ADD << Instruction::SWAP1; if (_type.baseType()->storageBytes() < 32) clearStorageLoop(IntegerType(256)); else clearStorageLoop(*_type.baseType()); - m_context << eth::Instruction::POP; + m_context << Instruction::POP; } solAssert(m_context.stackHeight() == stackHeightStart - 2, ""); } @@ -561,15 +561,15 @@ void ArrayUtils::clearDynamicArray(ArrayType const& _type) const // fetch length retrieveLength(_type); // set length to zero - m_context << u256(0) << eth::Instruction::DUP3 << eth::Instruction::SSTORE; + m_context << u256(0) << Instruction::DUP3 << Instruction::SSTORE; // Special case: short byte arrays are stored togeher with their length eth::AssemblyItem endTag = m_context.newTag(); if (_type.isByteArray()) { // stack: ref old_length - m_context << eth::Instruction::DUP1 << u256(31) << eth::Instruction::LT; + m_context << Instruction::DUP1 << u256(31) << Instruction::LT; eth::AssemblyItem longByteArray = m_context.appendConditionalJump(); - m_context << eth::Instruction::POP; + m_context << Instruction::POP; m_context.appendJumpTo(endTag); m_context.adjustStackOffset(1); // needed because of jump m_context << longByteArray; @@ -577,11 +577,11 @@ void ArrayUtils::clearDynamicArray(ArrayType const& _type) const // stack: ref old_length convertLengthToSize(_type); // compute data positions - m_context << eth::Instruction::SWAP1; + m_context << Instruction::SWAP1; CompilerUtils(m_context).computeHashStatic(); // stack: len data_pos - m_context << eth::Instruction::SWAP1 << eth::Instruction::DUP2 << eth::Instruction::ADD - << eth::Instruction::SWAP1; + m_context << Instruction::SWAP1 << Instruction::DUP2 << Instruction::ADD + << Instruction::SWAP1; // stack: data_pos_end data_pos if (_type.isByteArray() || _type.baseType()->storageBytes() < 32) clearStorageLoop(IntegerType(256)); @@ -589,7 +589,7 @@ void ArrayUtils::clearDynamicArray(ArrayType const& _type) const clearStorageLoop(*_type.baseType()); // cleanup m_context << endTag; - m_context << eth::Instruction::POP; + m_context << Instruction::POP; } void ArrayUtils::resizeDynamicArray(ArrayType const& _type) const @@ -614,13 +614,13 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _type) const eth::AssemblyItem regularPath = m_context.newTag(); // We start by a large case-distinction about the old and new length of the byte array. - m_context << eth::Instruction::DUP3 << eth::Instruction::SLOAD; + m_context << Instruction::DUP3 << Instruction::SLOAD; // stack: ref new_length current_length ref_value solAssert(m_context.stackHeight() - stackHeightStart == 4 - 2, "3"); - m_context << eth::Instruction::DUP2 << u256(31) << eth::Instruction::LT; + m_context << Instruction::DUP2 << u256(31) << Instruction::LT; eth::AssemblyItem currentIsLong = m_context.appendConditionalJump(); - m_context << eth::Instruction::DUP3 << u256(31) << eth::Instruction::LT; + m_context << Instruction::DUP3 << u256(31) << Instruction::LT; eth::AssemblyItem newIsLong = m_context.appendConditionalJump(); // Here: short -> short @@ -628,17 +628,17 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _type) const // Compute 1 << (256 - 8 * new_size) eth::AssemblyItem shortToShort = m_context.newTag(); m_context << shortToShort; - m_context << eth::Instruction::DUP3 << u256(8) << eth::Instruction::MUL; - m_context << u256(0x100) << eth::Instruction::SUB; - m_context << u256(2) << eth::Instruction::EXP; + m_context << Instruction::DUP3 << u256(8) << Instruction::MUL; + m_context << u256(0x100) << Instruction::SUB; + m_context << u256(2) << Instruction::EXP; // Divide and multiply by that value, clearing bits. - m_context << eth::Instruction::DUP1 << eth::Instruction::SWAP2; - m_context << eth::Instruction::DIV << eth::Instruction::MUL; + m_context << Instruction::DUP1 << Instruction::SWAP2; + m_context << Instruction::DIV << Instruction::MUL; // Insert 2*length. - m_context << eth::Instruction::DUP3 << eth::Instruction::DUP1 << eth::Instruction::ADD; - m_context << eth::Instruction::OR; + m_context << Instruction::DUP3 << Instruction::DUP1 << Instruction::ADD; + m_context << Instruction::OR; // Store. - m_context << eth::Instruction::DUP4 << eth::Instruction::SSTORE; + m_context << Instruction::DUP4 << Instruction::SSTORE; solAssert(m_context.stackHeight() - stackHeightStart == 3 - 2, "3"); m_context.appendJumpTo(resizeEnd); @@ -649,24 +649,24 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _type) const // stack: ref new_length current_length ref_value solAssert(m_context.stackHeight() - stackHeightStart == 4 - 2, "3"); // Zero out lower-order byte. - m_context << u256(0xff) << eth::Instruction::NOT << eth::Instruction::AND; + m_context << u256(0xff) << Instruction::NOT << Instruction::AND; // Store at data location. - m_context << eth::Instruction::DUP4; + m_context << Instruction::DUP4; CompilerUtils(m_context).computeHashStatic(); - m_context << eth::Instruction::SSTORE; + m_context << Instruction::SSTORE; // stack: ref new_length current_length // Store new length: Compule 2*length + 1 and store it. - m_context << eth::Instruction::DUP2 << eth::Instruction::DUP1 << eth::Instruction::ADD; - m_context << u256(1) << eth::Instruction::ADD; + m_context << Instruction::DUP2 << Instruction::DUP1 << Instruction::ADD; + m_context << u256(1) << Instruction::ADD; // stack: ref new_length current_length 2*new_length+1 - m_context << eth::Instruction::DUP4 << eth::Instruction::SSTORE; + m_context << Instruction::DUP4 << Instruction::SSTORE; solAssert(m_context.stackHeight() - stackHeightStart == 3 - 2, "3"); m_context.appendJumpTo(resizeEnd); m_context.adjustStackOffset(1); // we have to do that because of the jumps m_context << currentIsLong; - m_context << eth::Instruction::DUP3 << u256(31) << eth::Instruction::LT; + m_context << Instruction::DUP3 << u256(31) << Instruction::LT; m_context.appendConditionalJumpTo(regularPath); // Here: long -> short @@ -675,51 +675,51 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _type) const // stack: ref new_length current_length ref_value solAssert(m_context.stackHeight() - stackHeightStart == 4 - 2, "3"); - m_context << eth::Instruction::POP << eth::Instruction::DUP3; + m_context << Instruction::POP << Instruction::DUP3; CompilerUtils(m_context).computeHashStatic(); - m_context << eth::Instruction::DUP1 << eth::Instruction::SLOAD << eth::Instruction::SWAP1; + m_context << Instruction::DUP1 << Instruction::SLOAD << Instruction::SWAP1; // stack: ref new_length current_length first_word data_location - m_context << eth::Instruction::DUP3; + m_context << Instruction::DUP3; convertLengthToSize(_type); - m_context << eth::Instruction::DUP2 << eth::Instruction::ADD << eth::Instruction::SWAP1; + m_context << Instruction::DUP2 << Instruction::ADD << Instruction::SWAP1; // stack: ref new_length current_length first_word data_location_end data_location clearStorageLoop(IntegerType(256)); - m_context << eth::Instruction::POP; + m_context << Instruction::POP; // stack: ref new_length current_length first_word solAssert(m_context.stackHeight() - stackHeightStart == 4 - 2, "3"); m_context.appendJumpTo(shortToShort); m_context << regularPath; // stack: ref new_length current_length ref_value - m_context << eth::Instruction::POP; + m_context << Instruction::POP; } // Change of length for a regular array (i.e. length at location, data at sha3(location)). // stack: ref new_length old_length // store new length - m_context << eth::Instruction::DUP2; + m_context << Instruction::DUP2; if (_type.isByteArray()) // For a "long" byte array, store length as 2*length+1 - m_context << eth::Instruction::DUP1 << eth::Instruction::ADD << u256(1) << eth::Instruction::ADD; - m_context<< eth::Instruction::DUP4 << eth::Instruction::SSTORE; + m_context << Instruction::DUP1 << Instruction::ADD << u256(1) << Instruction::ADD; + m_context<< Instruction::DUP4 << Instruction::SSTORE; // skip if size is not reduced - m_context << eth::Instruction::DUP2 << eth::Instruction::DUP2 - << eth::Instruction::ISZERO << eth::Instruction::GT; + m_context << Instruction::DUP2 << Instruction::DUP2 + << Instruction::ISZERO << Instruction::GT; m_context.appendConditionalJumpTo(resizeEnd); // size reduced, clear the end of the array // stack: ref new_length old_length convertLengthToSize(_type); - m_context << eth::Instruction::DUP2; + m_context << Instruction::DUP2; convertLengthToSize(_type); // stack: ref new_length old_size new_size // compute data positions - m_context << eth::Instruction::DUP4; + m_context << Instruction::DUP4; CompilerUtils(m_context).computeHashStatic(); // stack: ref new_length old_size new_size data_pos - m_context << eth::Instruction::SWAP2 << eth::Instruction::DUP3 << eth::Instruction::ADD; + m_context << Instruction::SWAP2 << Instruction::DUP3 << Instruction::ADD; // stack: ref new_length data_pos new_size delete_end - m_context << eth::Instruction::SWAP2 << eth::Instruction::ADD; + m_context << Instruction::SWAP2 << Instruction::ADD; // stack: ref new_length delete_end delete_start if (_type.isByteArray() || _type.baseType()->storageBytes() < 32) clearStorageLoop(IntegerType(256)); @@ -728,7 +728,7 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _type) const m_context << resizeEnd; // cleanup - m_context << eth::Instruction::POP << eth::Instruction::POP << eth::Instruction::POP; + m_context << Instruction::POP << Instruction::POP << Instruction::POP; solAssert(m_context.stackHeight() == stackHeightStart - 2, ""); } @@ -737,35 +737,35 @@ void ArrayUtils::clearStorageLoop(Type const& _type) const unsigned stackHeightStart = m_context.stackHeight(); if (_type.category() == Type::Category::Mapping) { - m_context << eth::Instruction::POP; + m_context << Instruction::POP; return; } // stack: end_pos pos // jump to and return from the loop to allow for duplicate code removal eth::AssemblyItem returnTag = m_context.pushNewTag(); - m_context << eth::Instruction::SWAP2 << eth::Instruction::SWAP1; + m_context << Instruction::SWAP2 << Instruction::SWAP1; // stack: <return tag> end_pos pos eth::AssemblyItem loopStart = m_context.appendJumpToNew(); m_context << loopStart; // check for loop condition - m_context << eth::Instruction::DUP1 << eth::Instruction::DUP3 - << eth::Instruction::GT << eth::Instruction::ISZERO; + m_context << Instruction::DUP1 << Instruction::DUP3 + << Instruction::GT << Instruction::ISZERO; eth::AssemblyItem zeroLoopEnd = m_context.newTag(); m_context.appendConditionalJumpTo(zeroLoopEnd); // delete m_context << u256(0); StorageItem(m_context, _type).setToZero(SourceLocation(), false); - m_context << eth::Instruction::POP; + m_context << Instruction::POP; // increment - m_context << u256(1) << eth::Instruction::ADD; + m_context << u256(1) << Instruction::ADD; m_context.appendJumpTo(loopStart); // cleanup m_context << zeroLoopEnd; - m_context << eth::Instruction::POP << eth::Instruction::SWAP1; + m_context << Instruction::POP << Instruction::SWAP1; // "return" - m_context << eth::Instruction::JUMP; + m_context << Instruction::JUMP; m_context << returnTag; solAssert(m_context.stackHeight() == stackHeightStart - 1, ""); @@ -779,17 +779,17 @@ void ArrayUtils::convertLengthToSize(ArrayType const& _arrayType, bool _pad) con { unsigned baseBytes = _arrayType.baseType()->storageBytes(); if (baseBytes == 0) - m_context << eth::Instruction::POP << u256(1); + m_context << Instruction::POP << u256(1); else if (baseBytes <= 16) { unsigned itemsPerSlot = 32 / baseBytes; m_context - << u256(itemsPerSlot - 1) << eth::Instruction::ADD - << u256(itemsPerSlot) << eth::Instruction::SWAP1 << eth::Instruction::DIV; + << u256(itemsPerSlot - 1) << Instruction::ADD + << u256(itemsPerSlot) << Instruction::SWAP1 << Instruction::DIV; } } else - m_context << _arrayType.baseType()->storageSize() << eth::Instruction::MUL; + m_context << _arrayType.baseType()->storageSize() << Instruction::MUL; } else { @@ -799,12 +799,12 @@ void ArrayUtils::convertLengthToSize(ArrayType const& _arrayType, bool _pad) con m_context << _arrayType.baseType()->memoryHeadSize(); else m_context << _arrayType.baseType()->calldataEncodedSize(); - m_context << eth::Instruction::MUL; + m_context << Instruction::MUL; } else if (_pad) - m_context << u256(31) << eth::Instruction::ADD - << u256(32) << eth::Instruction::DUP1 - << eth::Instruction::SWAP2 << eth::Instruction::DIV << eth::Instruction::MUL; + m_context << u256(31) << Instruction::ADD + << u256(32) << Instruction::DUP1 + << Instruction::SWAP2 << Instruction::DIV << Instruction::MUL; } } @@ -814,27 +814,27 @@ void ArrayUtils::retrieveLength(ArrayType const& _arrayType, unsigned _stackDept m_context << _arrayType.length(); else { - m_context << eth::dupInstruction(1 + _stackDepth); + m_context << dupInstruction(1 + _stackDepth); switch (_arrayType.location()) { case DataLocation::CallData: // length is stored on the stack break; case DataLocation::Memory: - m_context << eth::Instruction::MLOAD; + m_context << Instruction::MLOAD; break; case DataLocation::Storage: - m_context << eth::Instruction::SLOAD; + m_context << Instruction::SLOAD; if (_arrayType.isByteArray()) { // Retrieve length both for in-place strings and off-place strings: // Computes (x & (0x100 * (ISZERO (x & 1)) - 1)) / 2 // i.e. for short strings (x & 1 == 0) it does (x & 0xff) / 2 and for long strings it // computes (x & (-1)) / 2, which is equivalent to just x / 2. - m_context << u256(1) << eth::Instruction::DUP2 << u256(1) << eth::Instruction::AND; - m_context << eth::Instruction::ISZERO << u256(0x100) << eth::Instruction::MUL; - m_context << eth::Instruction::SUB << eth::Instruction::AND; - m_context << u256(2) << eth::Instruction::SWAP1 << eth::Instruction::DIV; + m_context << u256(1) << Instruction::DUP2 << u256(1) << Instruction::AND; + m_context << Instruction::ISZERO << u256(0x100) << Instruction::MUL; + m_context << Instruction::SUB << Instruction::AND; + m_context << u256(2) << Instruction::SWAP1 << Instruction::DIV; } break; } @@ -852,34 +852,34 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck) c ArrayUtils::retrieveLength(_arrayType, 1); // Stack: ref [length] index length // check out-of-bounds access - m_context << eth::Instruction::DUP2 << eth::Instruction::LT << eth::Instruction::ISZERO; + m_context << Instruction::DUP2 << Instruction::LT << Instruction::ISZERO; // out-of-bounds access throws exception m_context.appendConditionalJumpTo(m_context.errorTag()); } if (location == DataLocation::CallData && _arrayType.isDynamicallySized()) // remove length if present - m_context << eth::Instruction::SWAP1 << eth::Instruction::POP; + m_context << Instruction::SWAP1 << Instruction::POP; // stack: <base_ref> <index> - m_context << eth::Instruction::SWAP1; + m_context << Instruction::SWAP1; // stack: <index> <base_ref> switch (location) { case DataLocation::Memory: if (_arrayType.isDynamicallySized()) - m_context << u256(32) << eth::Instruction::ADD; + m_context << u256(32) << Instruction::ADD; // fall-through case DataLocation::CallData: if (!_arrayType.isByteArray()) { - m_context << eth::Instruction::SWAP1; + m_context << Instruction::SWAP1; if (location == DataLocation::CallData) m_context << _arrayType.baseType()->calldataEncodedSize(); else m_context << u256(_arrayType.memoryHeadSize()); - m_context << eth::Instruction::MUL; + m_context << Instruction::MUL; } - m_context << eth::Instruction::ADD; + m_context << Instruction::ADD; break; case DataLocation::Storage: { @@ -887,16 +887,16 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck) c if (_arrayType.isByteArray()) { // Special case of short byte arrays. - m_context << eth::Instruction::SWAP1; - m_context << eth::Instruction::DUP2 << eth::Instruction::SLOAD; - m_context << u256(1) << eth::Instruction::AND << eth::Instruction::ISZERO; + m_context << Instruction::SWAP1; + m_context << Instruction::DUP2 << Instruction::SLOAD; + m_context << u256(1) << Instruction::AND << Instruction::ISZERO; // No action needed for short byte arrays. m_context.appendConditionalJumpTo(endTag); - m_context << eth::Instruction::SWAP1; + m_context << Instruction::SWAP1; } if (_arrayType.isDynamicallySized()) CompilerUtils(m_context).computeHashStatic(); - m_context << eth::Instruction::SWAP1; + m_context << Instruction::SWAP1; if (_arrayType.baseType()->storageBytes() <= 16) { // stack: <data_ref> <index> @@ -905,22 +905,22 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck) c unsigned byteSize = _arrayType.baseType()->storageBytes(); solAssert(byteSize != 0, ""); unsigned itemsPerSlot = 32 / byteSize; - m_context << u256(itemsPerSlot) << eth::Instruction::SWAP2; + m_context << u256(itemsPerSlot) << Instruction::SWAP2; // stack: itemsPerSlot index data_ref m_context - << eth::Instruction::DUP3 << eth::Instruction::DUP3 - << eth::Instruction::DIV << eth::Instruction::ADD + << Instruction::DUP3 << Instruction::DUP3 + << Instruction::DIV << Instruction::ADD // stack: itemsPerSlot index (data_ref + index / itemsPerSlot) - << eth::Instruction::SWAP2 << eth::Instruction::SWAP1 - << eth::Instruction::MOD; + << Instruction::SWAP2 << Instruction::SWAP1 + << Instruction::MOD; if (byteSize != 1) - m_context << u256(byteSize) << eth::Instruction::MUL; + m_context << u256(byteSize) << Instruction::MUL; } else { if (_arrayType.baseType()->storageSize() != 1) - m_context << _arrayType.baseType()->storageSize() << eth::Instruction::MUL; - m_context << eth::Instruction::ADD << u256(0); + m_context << _arrayType.baseType()->storageSize() << Instruction::MUL; + m_context << Instruction::ADD << u256(0); } m_context << endTag; break; @@ -942,27 +942,27 @@ void ArrayUtils::incrementByteOffset(unsigned _byteSize, unsigned _byteOffsetPos // byteOffset = 0; // } if (_byteOffsetPosition > 1) - m_context << eth::swapInstruction(_byteOffsetPosition - 1); - m_context << u256(_byteSize) << eth::Instruction::ADD; + m_context << swapInstruction(_byteOffsetPosition - 1); + m_context << u256(_byteSize) << Instruction::ADD; if (_byteOffsetPosition > 1) - m_context << eth::swapInstruction(_byteOffsetPosition - 1); + m_context << swapInstruction(_byteOffsetPosition - 1); // compute, X := (byteOffset + byteSize - 1) / 32, should be 1 iff byteOffset + bytesize > 32 m_context - << u256(32) << eth::dupInstruction(1 + _byteOffsetPosition) << u256(_byteSize - 1) - << eth::Instruction::ADD << eth::Instruction::DIV; + << u256(32) << dupInstruction(1 + _byteOffsetPosition) << u256(_byteSize - 1) + << Instruction::ADD << Instruction::DIV; // increment storage offset if X == 1 (just add X to it) // stack: X m_context - << eth::swapInstruction(_storageOffsetPosition) << eth::dupInstruction(_storageOffsetPosition + 1) - << eth::Instruction::ADD << eth::swapInstruction(_storageOffsetPosition); + << swapInstruction(_storageOffsetPosition) << dupInstruction(_storageOffsetPosition + 1) + << Instruction::ADD << swapInstruction(_storageOffsetPosition); // stack: X // set source_byte_offset to zero if X == 1 (using source_byte_offset *= 1 - X) - m_context << u256(1) << eth::Instruction::SUB; + m_context << u256(1) << Instruction::SUB; // stack: 1 - X if (_byteOffsetPosition == 1) - m_context << eth::Instruction::MUL; + m_context << Instruction::MUL; else m_context - << eth::dupInstruction(_byteOffsetPosition + 1) << eth::Instruction::MUL - << eth::swapInstruction(_byteOffsetPosition) << eth::Instruction::POP; + << dupInstruction(_byteOffsetPosition + 1) << Instruction::MUL + << swapInstruction(_byteOffsetPosition) << Instruction::POP; } diff --git a/libsolidity/codegen/Compiler.cpp b/libsolidity/codegen/Compiler.cpp index 69e23359..8b718fca 100644 --- a/libsolidity/codegen/Compiler.cpp +++ b/libsolidity/codegen/Compiler.cpp @@ -23,7 +23,7 @@ #include <libsolidity/codegen/Compiler.h> #include <algorithm> #include <boost/range/adaptor/reversed.hpp> -#include <libevmcore/Instruction.h> +#include <libevmasm/Instruction.h> #include <libethcore/ChainOperationParams.h> #include <libevmasm/Assembly.h> #include <libsolidity/inlineasm/AsmCodeGen.h> @@ -92,8 +92,8 @@ void Compiler::compileClone( m_runtimeSub = size_t(runtimeSub.data()); // stack contains sub size - m_context << eth::Instruction::DUP1 << runtimeSub << u256(0) << eth::Instruction::CODECOPY; - m_context << u256(0) << eth::Instruction::RETURN; + m_context << Instruction::DUP1 << runtimeSub << u256(0) << Instruction::CODECOPY; + m_context << u256(0) << Instruction::RETURN; appendFunctionsWithoutCode(); @@ -164,8 +164,8 @@ void Compiler::packIntoContractCreator(ContractDefinition const& _contract, Comp m_runtimeSub = size_t(runtimeSub.data()); // stack contains sub size - m_context << eth::Instruction::DUP1 << runtimeSub << u256(0) << eth::Instruction::CODECOPY; - m_context << u256(0) << eth::Instruction::RETURN; + m_context << Instruction::DUP1 << runtimeSub << u256(0) << Instruction::CODECOPY; + m_context << u256(0) << Instruction::RETURN; // note that we have to include the functions again because of absolute jump labels appendFunctionsWithoutCode(); @@ -208,15 +208,15 @@ void Compiler::appendConstructor(FunctionDefinition const& _constructor) // argument size is dynamic, use CODESIZE to determine it m_context.appendProgramSize(); // program itself // CODESIZE is program plus manually added arguments - m_context << eth::Instruction::CODESIZE << eth::Instruction::SUB; + m_context << Instruction::CODESIZE << Instruction::SUB; } else m_context << u256(argumentSize); // stack: <memptr> <argument size> - m_context << eth::Instruction::DUP1; + m_context << Instruction::DUP1; m_context.appendProgramSize(); - m_context << eth::Instruction::DUP4 << eth::Instruction::CODECOPY; - m_context << eth::Instruction::DUP2 << eth::Instruction::ADD; + m_context << Instruction::DUP4 << Instruction::CODECOPY; + m_context << Instruction::DUP2 << Instruction::ADD; CompilerUtils(m_context).storeFreeMemoryPointer(); // stack: <memptr> appendCalldataUnpacker(FunctionType(_constructor).parameterTypes(), true); @@ -235,7 +235,7 @@ void Compiler::appendFunctionSelector(ContractDefinition const& _contract) // ether with constant gas if (interfaceFunctions.size() > 5 || fallback) { - m_context << eth::Instruction::CALLDATASIZE << eth::Instruction::ISZERO; + m_context << Instruction::CALLDATASIZE << Instruction::ISZERO; m_context.appendConditionalJumpTo(notFound); } @@ -247,7 +247,7 @@ void Compiler::appendFunctionSelector(ContractDefinition const& _contract) for (auto const& it: interfaceFunctions) { callDataUnpackerEntryPoints.insert(std::make_pair(it.first, m_context.newTag())); - m_context << eth::dupInstruction(1) << u256(FixedHash<4>::Arith(it.first)) << eth::Instruction::EQ; + m_context << dupInstruction(1) << u256(FixedHash<4>::Arith(it.first)) << Instruction::EQ; m_context.appendConditionalJumpTo(callDataUnpackerEntryPoints.at(it.first)); } m_context.appendJumpTo(notFound); @@ -264,7 +264,7 @@ void Compiler::appendFunctionSelector(ContractDefinition const& _contract) // Reject invalid library calls and ether sent to a library. m_context.appendJumpTo(m_context.errorTag()); else - m_context << eth::Instruction::STOP; // function not found + m_context << Instruction::STOP; // function not found for (auto const& it: interfaceFunctions) { @@ -288,7 +288,7 @@ void Compiler::appendCalldataUnpacker(TypePointers const& _typeParameters, bool //@todo this does not yet support nested dynamic arrays // Retain the offset pointer as base_offset, the point from which the data offsets are computed. - m_context << eth::Instruction::DUP1; + m_context << Instruction::DUP1; for (TypePointer const& parameterType: _typeParameters) { // stack: v1 v2 ... v(k-1) base_offset current_offset @@ -309,15 +309,15 @@ void Compiler::appendCalldataUnpacker(TypePointers const& _typeParameters, bool if (arrayType.isDynamicallySized()) { // compute data pointer - m_context << eth::Instruction::DUP1 << eth::Instruction::MLOAD; - m_context << eth::Instruction::DUP3 << eth::Instruction::ADD; - m_context << eth::Instruction::SWAP2 << eth::Instruction::SWAP1; - m_context << u256(0x20) << eth::Instruction::ADD; + m_context << Instruction::DUP1 << Instruction::MLOAD; + m_context << Instruction::DUP3 << Instruction::ADD; + m_context << Instruction::SWAP2 << Instruction::SWAP1; + m_context << u256(0x20) << Instruction::ADD; } else { - m_context << eth::Instruction::DUP1; - m_context << u256(arrayType.calldataEncodedSize(true)) << eth::Instruction::ADD; + m_context << Instruction::DUP1; + m_context << u256(arrayType.calldataEncodedSize(true)) << Instruction::ADD; } } else @@ -329,19 +329,19 @@ void Compiler::appendCalldataUnpacker(TypePointers const& _typeParameters, bool // put on stack: data_pointer length CompilerUtils(m_context).loadFromMemoryDynamic(IntegerType(256), !_fromMemory); // stack: base_offset data_offset next_pointer - m_context << eth::Instruction::SWAP1 << eth::Instruction::DUP3 << eth::Instruction::ADD; + m_context << Instruction::SWAP1 << Instruction::DUP3 << Instruction::ADD; // stack: base_offset next_pointer data_pointer // retrieve length CompilerUtils(m_context).loadFromMemoryDynamic(IntegerType(256), !_fromMemory, true); // stack: base_offset next_pointer length data_pointer - m_context << eth::Instruction::SWAP2; + m_context << Instruction::SWAP2; // stack: base_offset data_pointer length next_pointer } else { // leave the pointer on the stack - m_context << eth::Instruction::DUP1; - m_context << u256(calldataType->calldataEncodedSize()) << eth::Instruction::ADD; + m_context << Instruction::DUP1; + m_context << u256(calldataType->calldataEncodedSize()) << Instruction::ADD; } if (arrayType.location() == DataLocation::Memory) { @@ -355,7 +355,7 @@ void Compiler::appendCalldataUnpacker(TypePointers const& _typeParameters, bool } // move base_offset up CompilerUtils(m_context).moveToStackTop(1 + arrayType.sizeOnStack()); - m_context << eth::Instruction::SWAP1; + m_context << Instruction::SWAP1; } } else @@ -363,18 +363,18 @@ void Compiler::appendCalldataUnpacker(TypePointers const& _typeParameters, bool solAssert(!type->isDynamicallySized(), "Unknown dynamically sized type: " + type->toString()); CompilerUtils(m_context).loadFromMemoryDynamic(*type, !_fromMemory, true); CompilerUtils(m_context).moveToStackTop(1 + type->sizeOnStack()); - m_context << eth::Instruction::SWAP1; + m_context << Instruction::SWAP1; } // stack: v1 v2 ... v(k-1) v(k) base_offset mem_offset } - m_context << eth::Instruction::POP << eth::Instruction::POP; + m_context << Instruction::POP << Instruction::POP; } void Compiler::appendReturnValuePacker(TypePointers const& _typeParameters, bool _isLibrary) { CompilerUtils utils(m_context); if (_typeParameters.empty()) - m_context << eth::Instruction::STOP; + m_context << Instruction::STOP; else { utils.fetchFreeMemoryPointer(); @@ -382,7 +382,7 @@ void Compiler::appendReturnValuePacker(TypePointers const& _typeParameters, bool // its data to add the needed parts and we avoid a memory copy. utils.encodeToMemory(_typeParameters, _typeParameters, true, false, _isLibrary); utils.toSizeAfterFreeMemoryPointer(); - m_context << eth::Instruction::RETURN; + m_context << Instruction::RETURN; } } @@ -476,12 +476,12 @@ bool Compiler::visit(FunctionDefinition const& _function) while (stackLayout.back() != int(stackLayout.size() - 1)) if (stackLayout.back() < 0) { - m_context << eth::Instruction::POP; + m_context << Instruction::POP; stackLayout.pop_back(); } else { - m_context << eth::swapInstruction(stackLayout.size() - stackLayout.back() - 1); + m_context << swapInstruction(stackLayout.size() - stackLayout.back() - 1); swap(stackLayout[stackLayout.back()], stackLayout.back()); } //@todo assert that everything is in place now @@ -532,7 +532,7 @@ bool Compiler::visit(InlineAssembly const& _inlineAssembly) errinfo_comment("Stack too deep, try removing local variables.") ); for (unsigned i = 0; i < variable->type()->sizeOnStack(); ++i) - _assembly.append(eth::dupInstruction(stackDiff)); + _assembly.append(dupInstruction(stackDiff)); } else { @@ -572,8 +572,8 @@ bool Compiler::visit(InlineAssembly const& _inlineAssembly) errinfo_comment("Stack too deep, try removing local variables.") ); for (unsigned i = 0; i < size; ++i) { - _assembly.append(eth::swapInstruction(stackDiff)); - _assembly.append(eth::Instruction::POP); + _assembly.append(swapInstruction(stackDiff)); + _assembly.append(Instruction::POP); } } return true; @@ -588,7 +588,7 @@ bool Compiler::visit(IfStatement const& _ifStatement) StackHeightChecker checker(m_context); CompilerContext::LocationSetter locationSetter(m_context, _ifStatement); compileExpression(_ifStatement.condition()); - m_context << eth::Instruction::ISZERO; + m_context << Instruction::ISZERO; eth::AssemblyItem falseTag = m_context.appendConditionalJump(); eth::AssemblyItem endTag = falseTag; _ifStatement.trueStatement().accept(*this); @@ -615,7 +615,7 @@ bool Compiler::visit(WhileStatement const& _whileStatement) m_context << loopStart; compileExpression(_whileStatement.condition()); - m_context << eth::Instruction::ISZERO; + m_context << Instruction::ISZERO; m_context.appendConditionalJumpTo(loopEnd); _whileStatement.body().accept(*this); @@ -649,7 +649,7 @@ bool Compiler::visit(ForStatement const& _forStatement) if (_forStatement.condition()) { compileExpression(*_forStatement.condition()); - m_context << eth::Instruction::ISZERO; + m_context << Instruction::ISZERO; m_context.appendConditionalJumpTo(loopEnd); } @@ -710,7 +710,7 @@ bool Compiler::visit(Return const& _return) CompilerUtils(m_context).moveToStackVariable(*retVariable); } for (unsigned i = 0; i < m_stackCleanupForReturn; ++i) - m_context << eth::Instruction::POP; + m_context << Instruction::POP; m_context.appendJumpTo(m_returnTag); m_context.adjustStackOffset(m_stackCleanupForReturn); return false; @@ -831,7 +831,7 @@ void Compiler::appendModifierOrFunctionCode() modifier.body().accept(*this); for (unsigned i = 0; i < c_stackSurplus; ++i) - m_context << eth::Instruction::POP; + m_context << Instruction::POP; m_stackCleanupForReturn -= c_stackSurplus; } } @@ -855,20 +855,20 @@ eth::Assembly Compiler::cloneRuntime() { eth::EVMSchedule schedule; eth::Assembly a; - a << eth::Instruction::CALLDATASIZE; - a << u256(0) << eth::Instruction::DUP1 << eth::Instruction::CALLDATACOPY; + a << Instruction::CALLDATASIZE; + a << u256(0) << Instruction::DUP1 << Instruction::CALLDATACOPY; //@todo adjust for larger return values, make this dynamic. - a << u256(0x20) << u256(0) << eth::Instruction::CALLDATASIZE; + a << u256(0x20) << u256(0) << Instruction::CALLDATASIZE; a << u256(0); // this is the address which has to be substituted by the linker. //@todo implement as special "marker" AssemblyItem. a << u256("0xcafecafecafecafecafecafecafecafecafecafe"); - a << u256(schedule.callGas + 10) << eth::Instruction::GAS << eth::Instruction::SUB; - a << eth::Instruction::DELEGATECALL; + a << u256(schedule.callGas + 10) << Instruction::GAS << Instruction::SUB; + a << Instruction::DELEGATECALL; //Propagate error condition (if DELEGATECALL pushes 0 on stack). - a << eth::Instruction::ISZERO; + a << Instruction::ISZERO; a.appendJumpI(a.errorTag()); //@todo adjust for larger return values, make this dynamic. - a << u256(0x20) << u256(0) << eth::Instruction::RETURN; + a << u256(0x20) << u256(0) << Instruction::RETURN; return a; } diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 9e2405cc..7810288e 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -166,7 +166,7 @@ pair<u256, unsigned> CompilerContext::storageLocationOfVariable(const Declaratio CompilerContext& CompilerContext::appendJump(eth::AssemblyItem::JumpType _jumpType) { - eth::AssemblyItem item(eth::Instruction::JUMP); + eth::AssemblyItem item(Instruction::JUMP); item.setJumpType(_jumpType); return *this << item; } @@ -182,7 +182,7 @@ void CompilerContext::resetVisitedNodes(ASTNode const* _node) void CompilerContext::injectVersionStampIntoSub(size_t _subIndex) { eth::Assembly& sub = m_asm.sub(_subIndex); - sub.injectStart(eth::Instruction::POP); + sub.injectStart(Instruction::POP); sub.injectStart(fromBigEndian<u256>(binaryVersion())); } diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index bd8fc295..9368dbcf 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -25,7 +25,7 @@ #include <ostream> #include <stack> #include <utility> -#include <libevmcore/Instruction.h> +#include <libevmasm/Instruction.h> #include <libevmasm/Assembly.h> #include <libsolidity/ast/ASTForward.h> #include <libsolidity/ast/Types.h> @@ -126,7 +126,7 @@ public: /// Append elements to the current instruction list and adjust @a m_stackOffset. CompilerContext& operator<<(eth::AssemblyItem const& _item) { m_asm.append(_item); return *this; } - CompilerContext& operator<<(eth::Instruction _instruction) { m_asm.append(_instruction); return *this; } + CompilerContext& operator<<(Instruction _instruction) { m_asm.append(_instruction); return *this; } CompilerContext& operator<<(u256 const& _value) { m_asm.append(_value); return *this; } CompilerContext& operator<<(bytes const& _data) { m_asm.append(_data); return *this; } diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index bd0857f6..36ed480e 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -22,7 +22,7 @@ #include <libsolidity/codegen/CompilerUtils.h> #include <libsolidity/ast/AST.h> -#include <libevmcore/Instruction.h> +#include <libevmasm/Instruction.h> #include <libsolidity/codegen/ArrayUtils.h> #include <libsolidity/codegen/LValue.h> @@ -45,26 +45,26 @@ void CompilerUtils::initialiseFreeMemoryPointer() void CompilerUtils::fetchFreeMemoryPointer() { - m_context << u256(freeMemoryPointer) << eth::Instruction::MLOAD; + m_context << u256(freeMemoryPointer) << Instruction::MLOAD; } void CompilerUtils::storeFreeMemoryPointer() { - m_context << u256(freeMemoryPointer) << eth::Instruction::MSTORE; + m_context << u256(freeMemoryPointer) << Instruction::MSTORE; } void CompilerUtils::allocateMemory() { fetchFreeMemoryPointer(); - m_context << eth::Instruction::SWAP1 << eth::Instruction::DUP2 << eth::Instruction::ADD; + m_context << Instruction::SWAP1 << Instruction::DUP2 << Instruction::ADD; storeFreeMemoryPointer(); } void CompilerUtils::toSizeAfterFreeMemoryPointer() { fetchFreeMemoryPointer(); - m_context << eth::Instruction::DUP1 << eth::Instruction::SWAP2 << eth::Instruction::SUB; - m_context << eth::Instruction::SWAP1; + m_context << Instruction::DUP1 << Instruction::SWAP2 << Instruction::SUB; + m_context << Instruction::SWAP1; } unsigned CompilerUtils::loadFromMemory( @@ -87,7 +87,7 @@ void CompilerUtils::loadFromMemoryDynamic( ) { if (_keepUpdatedMemoryOffset) - m_context << eth::Instruction::DUP1; + m_context << Instruction::DUP1; if (auto arrayType = dynamic_cast<ArrayType const*>(&_type)) { @@ -95,7 +95,7 @@ void CompilerUtils::loadFromMemoryDynamic( solAssert(!_fromCalldata, ""); solAssert(_padToWordBoundaries, ""); if (_keepUpdatedMemoryOffset) - m_context << arrayType->memorySize() << eth::Instruction::ADD; + m_context << arrayType->memorySize() << Instruction::ADD; } else { @@ -104,7 +104,7 @@ void CompilerUtils::loadFromMemoryDynamic( { // update memory counter moveToStackTop(_type.sizeOnStack()); - m_context << u256(numBytes) << eth::Instruction::ADD; + m_context << u256(numBytes) << Instruction::ADD; } } } @@ -113,7 +113,7 @@ void CompilerUtils::storeInMemory(unsigned _offset) { unsigned numBytes = prepareMemoryStore(IntegerType(256), true); if (numBytes > 0) - m_context << u256(_offset) << eth::Instruction::MSTORE; + m_context << u256(_offset) << Instruction::MSTORE; } void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBoundaries) @@ -125,13 +125,13 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound } else if (auto str = dynamic_cast<StringLiteralType const*>(&_type)) { - m_context << eth::Instruction::DUP1; + m_context << Instruction::DUP1; storeStringData(bytesConstRef(str->value())); if (_padToWordBoundaries) m_context << u256(((str->value().size() + 31) / 32) * 32); else m_context << u256(str->value().size()); - m_context << eth::Instruction::ADD; + m_context << Instruction::ADD; } else { @@ -142,8 +142,8 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound _type.sizeOnStack() == 1, "Memory store of types with stack size != 1 not implemented." ); - m_context << eth::Instruction::DUP2 << eth::Instruction::MSTORE; - m_context << u256(numBytes) << eth::Instruction::ADD; + m_context << Instruction::DUP2 << Instruction::MSTORE; + m_context << u256(numBytes) << Instruction::ADD; } } } @@ -168,7 +168,7 @@ void CompilerUtils::encodeToMemory( // of the ith dynamic parameter, which is filled once the dynamic parts are processed. // store memory start pointer - m_context << eth::Instruction::DUP1; + m_context << Instruction::DUP1; unsigned argSize = CompilerUtils::sizeOnStack(_givenTypes); unsigned stackPos = 0; // advances through the argument values @@ -180,7 +180,7 @@ void CompilerUtils::encodeToMemory( if (targetType->isDynamicallySized() && !_copyDynamicDataInPlace) { // leave end_of_mem as dyn head pointer - m_context << eth::Instruction::DUP1 << u256(32) << eth::Instruction::ADD; + m_context << Instruction::DUP1 << u256(32) << Instruction::ADD; dynPointers++; } else @@ -222,10 +222,10 @@ void CompilerUtils::encodeToMemory( if (targetType->isDynamicallySized() && !_copyDynamicDataInPlace) { // copy tail pointer (=mem_end - mem_start) to memory - m_context << eth::dupInstruction(2 + dynPointers) << eth::Instruction::DUP2; - m_context << eth::Instruction::SUB; - m_context << eth::dupInstruction(2 + dynPointers - thisDynPointer); - m_context << eth::Instruction::MSTORE; + m_context << dupInstruction(2 + dynPointers) << Instruction::DUP2; + m_context << Instruction::SUB; + m_context << dupInstruction(2 + dynPointers - thisDynPointer); + m_context << Instruction::MSTORE; // stack: ... <end_of_mem> if (_givenTypes[i]->category() == Type::Category::StringLiteral) { @@ -243,13 +243,13 @@ void CompilerUtils::encodeToMemory( copyToStackTop(argSize - stackPos + dynPointers + 2, arrayType.sizeOnStack()); // stack: ... <end_of_mem> <value...> // copy length to memory - m_context << eth::dupInstruction(1 + arrayType.sizeOnStack()); + m_context << dupInstruction(1 + arrayType.sizeOnStack()); ArrayUtils(m_context).retrieveLength(arrayType, 1); // stack: ... <end_of_mem> <value...> <end_of_mem'> <length> storeInMemoryDynamic(IntegerType(256), true); // stack: ... <end_of_mem> <value...> <end_of_mem''> // copy the new memory pointer - m_context << eth::swapInstruction(arrayType.sizeOnStack() + 1) << eth::Instruction::POP; + m_context << swapInstruction(arrayType.sizeOnStack() + 1) << Instruction::POP; // stack: ... <end_of_mem''> <value...> // copy data part ArrayUtils(m_context).copyArrayToMemory(arrayType, _padToWordBoundaries); @@ -262,7 +262,7 @@ void CompilerUtils::encodeToMemory( } // remove unneeded stack elements (and retain memory pointer) - m_context << eth::swapInstruction(argSize + dynPointers + 1); + m_context << swapInstruction(argSize + dynPointers + 1); popStackSlots(argSize + dynPointers + 1); } @@ -272,11 +272,11 @@ void CompilerUtils::zeroInitialiseMemoryArray(ArrayType const& _type) m_context << repeat; pushZeroValue(*_type.baseType()); storeInMemoryDynamic(*_type.baseType()); - m_context << eth::Instruction::SWAP1 << u256(1) << eth::Instruction::SWAP1; - m_context << eth::Instruction::SUB << eth::Instruction::SWAP1; - m_context << eth::Instruction::DUP2; + m_context << Instruction::SWAP1 << u256(1) << Instruction::SWAP1; + m_context << Instruction::SUB << Instruction::SWAP1; + m_context << Instruction::DUP2; m_context.appendConditionalJumpTo(repeat); - m_context << eth::Instruction::SWAP1 << eth::Instruction::POP; + m_context << Instruction::SWAP1 << Instruction::POP; } void CompilerUtils::memoryCopy() @@ -284,16 +284,16 @@ void CompilerUtils::memoryCopy() // Stack here: size target source // stack for call: outsize target size source value contract gas //@TODO do not use ::CALL if less than 32 bytes? - m_context << eth::Instruction::DUP3 << eth::Instruction::SWAP1; + m_context << Instruction::DUP3 << Instruction::SWAP1; m_context << u256(0) << u256(identityContractAddress); // compute gas costs - m_context << u256(32) << eth::Instruction::DUP5 << u256(31) << eth::Instruction::ADD; + m_context << u256(32) << Instruction::DUP5 << u256(31) << Instruction::ADD; static unsigned c_identityGas = 3; static unsigned c_identityWordGas = 15; - m_context << eth::Instruction::DIV << u256(c_identityWordGas) << eth::Instruction::MUL; - m_context << u256(c_identityGas) << eth::Instruction::ADD; - m_context << eth::Instruction::CALL; - m_context << eth::Instruction::POP; // ignore return value + m_context << Instruction::DIV << u256(c_identityWordGas) << Instruction::MUL; + m_context << u256(c_identityGas) << Instruction::ADD; + m_context << Instruction::CALL; + m_context << Instruction::POP; // ignore return value } void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded) @@ -317,7 +317,7 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp // conversion from bytes to integer. no need to clean the high bit // only to shift right because of opposite alignment IntegerType const& targetIntegerType = dynamic_cast<IntegerType const&>(_targetType); - m_context << (u256(1) << (256 - typeOnStack.numBytes() * 8)) << eth::Instruction::SWAP1 << eth::Instruction::DIV; + m_context << (u256(1) << (256 - typeOnStack.numBytes() * 8)) << Instruction::SWAP1 << Instruction::DIV; if (targetIntegerType.numBits() < typeOnStack.numBytes() * 8) convertType(IntegerType(typeOnStack.numBytes() * 8), _targetType, _cleanupNeeded); } @@ -329,12 +329,12 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp if (targetType.numBytes() < typeOnStack.numBytes()) { if (targetType.numBytes() == 0) - m_context << eth::Instruction::DUP1 << eth::Instruction::XOR; + m_context << Instruction::DUP1 << Instruction::XOR; else { m_context << (u256(1) << (256 - targetType.numBytes() * 8)); - m_context << eth::Instruction::DUP1 << eth::Instruction::SWAP2; - m_context << eth::Instruction::DIV << eth::Instruction::MUL; + m_context << Instruction::DUP1 << Instruction::SWAP2; + m_context << Instruction::DIV << Instruction::MUL; } } } @@ -356,7 +356,7 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp if (auto typeOnStack = dynamic_cast<IntegerType const*>(&_typeOnStack)) if (targetBytesType.numBytes() * 8 > typeOnStack->numBits()) cleanHigherOrderBits(*typeOnStack); - m_context << (u256(1) << (256 - targetBytesType.numBytes() * 8)) << eth::Instruction::MUL; + m_context << (u256(1) << (256 - targetBytesType.numBytes() * 8)) << Instruction::MUL; } else if (targetTypeCategory == Type::Category::Enum) // just clean @@ -406,7 +406,7 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp m_context << storageSize; allocateMemory(); // stack: mempos - m_context << eth::Instruction::DUP1 << u256(data.size()); + m_context << Instruction::DUP1 << u256(data.size()); storeInMemoryDynamic(IntegerType(256)); // stack: mempos datapos storeStringData(data); @@ -445,18 +445,18 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp // allocate memory // stack: <source ref> (variably sized) <length> - m_context << eth::Instruction::DUP1; + m_context << Instruction::DUP1; ArrayUtils(m_context).convertLengthToSize(targetType, true); // stack: <source ref> (variably sized) <length> <size> if (targetType.isDynamicallySized()) - m_context << u256(0x20) << eth::Instruction::ADD; + m_context << u256(0x20) << Instruction::ADD; allocateMemory(); // stack: <source ref> (variably sized) <length> <mem start> - m_context << eth::Instruction::DUP1; + m_context << Instruction::DUP1; moveIntoStack(2 + stackSize); if (targetType.isDynamicallySized()) { - m_context << eth::Instruction::DUP2; + m_context << Instruction::DUP2; storeInMemoryDynamic(IntegerType(256)); } // stack: <mem start> <source ref> (variably sized) <length> <mem data pos> @@ -468,12 +468,12 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp } else { - m_context << u256(0) << eth::Instruction::SWAP1; + m_context << u256(0) << Instruction::SWAP1; // stack: <mem start> <source ref> (variably sized) <length> <counter> <mem data pos> auto repeat = m_context.newTag(); m_context << repeat; - m_context << eth::Instruction::DUP3 << eth::Instruction::DUP3; - m_context << eth::Instruction::LT << eth::Instruction::ISZERO; + m_context << Instruction::DUP3 << Instruction::DUP3; + m_context << Instruction::LT << Instruction::ISZERO; auto loopEnd = m_context.appendConditionalJump(); copyToStackTop(3 + stackSize, stackSize); copyToStackTop(2 + stackSize, 1); @@ -482,11 +482,11 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp StorageItem(m_context, *typeOnStack.baseType()).retrieveValue(SourceLocation(), true); convertType(*typeOnStack.baseType(), *targetType.baseType(), _cleanupNeeded); storeInMemoryDynamic(*targetType.baseType(), true); - m_context << eth::Instruction::SWAP1 << u256(1) << eth::Instruction::ADD; - m_context << eth::Instruction::SWAP1; + m_context << Instruction::SWAP1 << u256(1) << Instruction::ADD; + m_context << Instruction::SWAP1; m_context.appendJumpTo(repeat); m_context << loopEnd; - m_context << eth::Instruction::POP; + m_context << Instruction::POP; } // stack: <mem start> <source ref> (variably sized) <length> <mem data pos updated> popStackSlots(2 + stackSize); @@ -540,14 +540,14 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp // stack: <source ref> m_context << typeOnStack.memorySize(); allocateMemory(); - m_context << eth::Instruction::SWAP1 << eth::Instruction::DUP2; + m_context << Instruction::SWAP1 << Instruction::DUP2; // stack: <memory ptr> <source ref> <memory ptr> for (auto const& member: typeOnStack.members(nullptr)) { if (!member.type->canLiveOutsideStorage()) continue; pair<u256, unsigned> const& offsets = typeOnStack.storageOffsetsOfMember(member.name); - m_context << offsets.first << eth::Instruction::DUP3 << eth::Instruction::ADD; + m_context << offsets.first << Instruction::DUP3 << Instruction::ADD; m_context << u256(offsets.second); StorageItem(m_context, *member.type).retrieveValue(SourceLocation(), true); TypePointer targetMemberType = targetType.memberType(member.name); @@ -555,7 +555,7 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp convertType(*member.type, *targetMemberType, true); storeInMemoryDynamic(*targetMemberType, true); } - m_context << eth::Instruction::POP << eth::Instruction::POP; + m_context << Instruction::POP << Instruction::POP; } break; case DataLocation::CallData: @@ -602,13 +602,13 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp // Move it back into its place. for (unsigned j = 0; j < min(sourceSize, targetSize); ++j) m_context << - eth::swapInstruction(depth + targetSize - sourceSize) << - eth::Instruction::POP; + swapInstruction(depth + targetSize - sourceSize) << + Instruction::POP; // Value shrank for (unsigned j = targetSize; j < sourceSize; ++j) { moveToStackTop(depth - 1, 1); - m_context << eth::Instruction::POP; + m_context << Instruction::POP; } // Value grew if (targetSize > sourceSize) @@ -639,7 +639,7 @@ void CompilerUtils::pushZeroValue(Type const& _type) m_context << u256(max(32u, _type.calldataEncodedSize())); allocateMemory(); - m_context << eth::Instruction::DUP1; + m_context << Instruction::DUP1; if (auto structType = dynamic_cast<StructType const*>(&_type)) for (auto const& member: structType->members(nullptr)) @@ -657,7 +657,7 @@ void CompilerUtils::pushZeroValue(Type const& _type) } else if (arrayType->length() > 0) { - m_context << arrayType->length() << eth::Instruction::SWAP1; + m_context << arrayType->length() << Instruction::SWAP1; // stack: items_to_do memory_pos zeroInitialiseMemoryArray(*arrayType); // stack: updated_memory_pos @@ -667,7 +667,7 @@ void CompilerUtils::pushZeroValue(Type const& _type) solAssert(false, "Requested initialisation for unknown type: " + _type.toString()); // remove the updated memory pointer - m_context << eth::Instruction::POP; + m_context << Instruction::POP; } void CompilerUtils::moveToStackVariable(VariableDeclaration const& _variable) @@ -683,14 +683,14 @@ void CompilerUtils::moveToStackVariable(VariableDeclaration const& _variable) errinfo_comment("Stack too deep, try removing local variables.") ); for (unsigned i = 0; i < size; ++i) - m_context << eth::swapInstruction(stackPosition - size + 1) << eth::Instruction::POP; + m_context << swapInstruction(stackPosition - size + 1) << Instruction::POP; } void CompilerUtils::copyToStackTop(unsigned _stackDepth, unsigned _itemSize) { solAssert(_stackDepth <= 16, "Stack too deep, try removing local variables."); for (unsigned i = 0; i < _itemSize; ++i) - m_context << eth::dupInstruction(_stackDepth); + m_context << dupInstruction(_stackDepth); } void CompilerUtils::moveToStackTop(unsigned _stackDepth, unsigned _itemSize) @@ -712,14 +712,14 @@ void CompilerUtils::rotateStackUp(unsigned _items) { solAssert(_items - 1 <= 16, "Stack too deep, try removing local variables."); for (unsigned i = 1; i < _items; ++i) - m_context << eth::swapInstruction(_items - i); + m_context << swapInstruction(_items - i); } void CompilerUtils::rotateStackDown(unsigned _items) { solAssert(_items - 1 <= 16, "Stack too deep, try removing local variables."); for (unsigned i = 1; i < _items; ++i) - m_context << eth::swapInstruction(i); + m_context << swapInstruction(i); } void CompilerUtils::popStackElement(Type const& _type) @@ -730,7 +730,7 @@ void CompilerUtils::popStackElement(Type const& _type) void CompilerUtils::popStackSlots(size_t _amount) { for (size_t i = 0; i < _amount; ++i) - m_context << eth::Instruction::POP; + m_context << Instruction::POP; } unsigned CompilerUtils::sizeOnStack(vector<shared_ptr<Type const>> const& _variableTypes) @@ -744,7 +744,7 @@ unsigned CompilerUtils::sizeOnStack(vector<shared_ptr<Type const>> const& _varia void CompilerUtils::computeHashStatic() { storeInMemory(0); - m_context << u256(32) << u256(0) << eth::Instruction::SHA3; + m_context << u256(32) << u256(0) << Instruction::SHA3; } void CompilerUtils::storeStringData(bytesConstRef _data) @@ -758,14 +758,14 @@ void CompilerUtils::storeStringData(bytesConstRef _data) m_context << h256::Arith(h256(_data.cropped(i), h256::AlignLeft)); storeInMemoryDynamic(IntegerType(256)); } - m_context << eth::Instruction::POP; + m_context << Instruction::POP; } else { // stack: mempos mempos_data m_context.appendData(_data.toBytes()); - m_context << u256(_data.size()) << eth::Instruction::SWAP2; - m_context << eth::Instruction::CODECOPY; + m_context << u256(_data.size()) << Instruction::SWAP2; + m_context << Instruction::CODECOPY; } } @@ -774,18 +774,18 @@ unsigned CompilerUtils::loadFromMemoryHelper(Type const& _type, bool _fromCallda unsigned numBytes = _type.calldataEncodedSize(_padToWordBoundaries); bool leftAligned = _type.category() == Type::Category::FixedBytes; if (numBytes == 0) - m_context << eth::Instruction::POP << u256(0); + m_context << Instruction::POP << u256(0); else { solAssert(numBytes <= 32, "Static memory load of more than 32 bytes requested."); - m_context << (_fromCalldata ? eth::Instruction::CALLDATALOAD : eth::Instruction::MLOAD); + m_context << (_fromCalldata ? Instruction::CALLDATALOAD : Instruction::MLOAD); if (numBytes != 32) { // add leading or trailing zeros by dividing/multiplying depending on alignment u256 shiftFactor = u256(1) << ((32 - numBytes) * 8); - m_context << shiftFactor << eth::Instruction::SWAP1 << eth::Instruction::DIV; + m_context << shiftFactor << Instruction::SWAP1 << Instruction::DIV; if (leftAligned) - m_context << shiftFactor << eth::Instruction::MUL; + m_context << shiftFactor << Instruction::MUL; } } @@ -797,9 +797,9 @@ void CompilerUtils::cleanHigherOrderBits(IntegerType const& _typeOnStack) if (_typeOnStack.numBits() == 256) return; else if (_typeOnStack.isSigned()) - m_context << u256(_typeOnStack.numBits() / 8 - 1) << eth::Instruction::SIGNEXTEND; + m_context << u256(_typeOnStack.numBits() / 8 - 1) << Instruction::SIGNEXTEND; else - m_context << ((u256(1) << _typeOnStack.numBits()) - 1) << eth::Instruction::AND; + m_context << ((u256(1) << _typeOnStack.numBits()) - 1) << Instruction::AND; } unsigned CompilerUtils::prepareMemoryStore(Type const& _type, bool _padToWordBoundaries) const @@ -807,13 +807,13 @@ unsigned CompilerUtils::prepareMemoryStore(Type const& _type, bool _padToWordBou unsigned numBytes = _type.calldataEncodedSize(_padToWordBoundaries); bool leftAligned = _type.category() == Type::Category::FixedBytes; if (numBytes == 0) - m_context << eth::Instruction::POP; + m_context << Instruction::POP; else { solAssert(numBytes <= 32, "Memory store of more than 32 bytes requested."); if (numBytes != 32 && !leftAligned && !_padToWordBoundaries) // shift the value accordingly before storing - m_context << (u256(1) << ((32 - numBytes) * 8)) << eth::Instruction::MUL; + m_context << (u256(1) << ((32 - numBytes) * 8)) << Instruction::MUL; } return numBytes; } diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index a17ec2f6..ed36fb24 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -75,7 +75,7 @@ void ExpressionCompiler::appendConstStateVariableAccessor(VariableDeclaration co utils().convertType(*_varDecl.value()->annotation().type, *_varDecl.annotation().type); // append return - m_context << eth::dupInstruction(_varDecl.annotation().type->sizeOnStack() + 1); + m_context << dupInstruction(_varDecl.annotation().type->sizeOnStack() + 1); m_context.appendJump(eth::AssemblyItem::JumpType::OutOfFunction); } @@ -103,13 +103,13 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& "Accessors for mapping with dynamically-sized keys not yet implemented." ); // pop offset - m_context << eth::Instruction::POP; + m_context << Instruction::POP; // move storage offset to memory. utils().storeInMemory(32); // move key to memory. utils().copyToStackTop(paramTypes.size() - i, 1); utils().storeInMemory(0); - m_context << u256(64) << u256(0) << eth::Instruction::SHA3; + m_context << u256(64) << u256(0) << Instruction::SHA3; // push offset m_context << u256(0); returnType = mappingType->valueType(); @@ -117,7 +117,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& else if (auto arrayType = dynamic_cast<ArrayType const*>(returnType.get())) { // pop offset - m_context << eth::Instruction::POP; + m_context << Instruction::POP; utils().copyToStackTop(paramTypes.size() - i + 1, 1); ArrayUtils(m_context).accessIndex(*arrayType); returnType = arrayType->baseType(); @@ -127,12 +127,12 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& } // remove index arguments. if (paramTypes.size() == 1) - m_context << eth::Instruction::SWAP2 << eth::Instruction::POP << eth::Instruction::SWAP1; + m_context << Instruction::SWAP2 << Instruction::POP << Instruction::SWAP1; else if (paramTypes.size() >= 2) { - m_context << eth::swapInstruction(paramTypes.size()); - m_context << eth::Instruction::POP; - m_context << eth::swapInstruction(paramTypes.size()); + m_context << swapInstruction(paramTypes.size()); + m_context << Instruction::POP; + m_context << swapInstruction(paramTypes.size()); utils().popStackSlots(paramTypes.size() - 1); } unsigned retSizeOnStack = 0; @@ -141,7 +141,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& if (StructType const* structType = dynamic_cast<StructType const*>(returnType.get())) { // remove offset - m_context << eth::Instruction::POP; + m_context << Instruction::POP; auto const& names = accessorType.returnParameterNames(); // struct for (size_t i = 0; i < names.size(); ++i) @@ -152,7 +152,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& if (!arrayType->isByteArray()) continue; pair<u256, unsigned> const& offsets = structType->storageOffsetsOfMember(names[i]); - m_context << eth::Instruction::DUP1 << u256(offsets.first) << eth::Instruction::ADD << u256(offsets.second); + m_context << Instruction::DUP1 << u256(offsets.first) << Instruction::ADD << u256(offsets.second); TypePointer memberType = structType->memberType(names[i]); StorageItem(m_context, *memberType).retrieveValue(SourceLocation(), true); utils().convertType(*memberType, *returnTypes[i]); @@ -160,7 +160,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& retSizeOnStack += returnTypes[i]->sizeOnStack(); } // remove slot - m_context << eth::Instruction::POP; + m_context << Instruction::POP; } else { @@ -172,7 +172,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& } solAssert(retSizeOnStack == utils().sizeOnStack(returnTypes), ""); solAssert(retSizeOnStack <= 15, "Stack is too deep."); - m_context << eth::dupInstruction(retSizeOnStack + 1); + m_context << dupInstruction(retSizeOnStack + 1); m_context.appendJump(eth::AssemblyItem::JumpType::OutOfFunction); } @@ -226,7 +226,7 @@ bool ExpressionCompiler::visit(Assignment const& _assignment) solAssert(itemSize + lvalueSize <= 16, "Stack too deep, try removing local variables."); // value [lvalue_ref] updated_value for (unsigned i = 0; i < itemSize; ++i) - m_context << eth::swapInstruction(itemSize + lvalueSize) << eth::Instruction::POP; + m_context << swapInstruction(itemSize + lvalueSize) << Instruction::POP; } } m_currentLValue->storeValue(*type, _assignment.location()); @@ -243,7 +243,7 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple) solAssert(!arrayType.isDynamicallySized(), "Cannot create dynamically sized inline array."); m_context << max(u256(32u), arrayType.memorySize()); utils().allocateMemory(); - m_context << eth::Instruction::DUP1; + m_context << Instruction::DUP1; for (auto const& component: _tuple.components()) { @@ -252,7 +252,7 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple) utils().storeInMemoryDynamic(*arrayType.baseType(), true); } - m_context << eth::Instruction::POP; + m_context << Instruction::POP; } else { @@ -298,13 +298,13 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation) switch (_unaryOperation.getOperator()) { case Token::Not: // ! - m_context << eth::Instruction::ISZERO; + m_context << Instruction::ISZERO; break; case Token::BitNot: // ~ - m_context << eth::Instruction::NOT; + m_context << Instruction::NOT; break; case Token::After: // after - m_context << eth::Instruction::TIMESTAMP << eth::Instruction::ADD; + m_context << Instruction::TIMESTAMP << Instruction::ADD; break; case Token::Delete: // delete solAssert(!!m_currentLValue, "LValue not retrieved."); @@ -319,20 +319,20 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation) { // store value for later solAssert(_unaryOperation.annotation().type->sizeOnStack() == 1, "Stack size != 1 not implemented."); - m_context << eth::Instruction::DUP1; + m_context << Instruction::DUP1; if (m_currentLValue->sizeOnStack() > 0) for (unsigned i = 1 + m_currentLValue->sizeOnStack(); i > 0; --i) - m_context << eth::swapInstruction(i); + m_context << swapInstruction(i); } m_context << u256(1); if (_unaryOperation.getOperator() == Token::Inc) - m_context << eth::Instruction::ADD; + m_context << Instruction::ADD; else - m_context << eth::Instruction::SWAP1 << eth::Instruction::SUB; + m_context << Instruction::SWAP1 << Instruction::SUB; // Stack for prefix: [ref...] (*ref)+-1 // Stack for postfix: *ref [ref...] (*ref)+-1 for (unsigned i = m_currentLValue->sizeOnStack(); i > 0; --i) - m_context << eth::swapInstruction(i); + m_context << swapInstruction(i); m_currentLValue->storeValue( *_unaryOperation.annotation().type, _unaryOperation.location(), !_unaryOperation.isPrefixOperation()); @@ -342,7 +342,7 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation) // unary add, so basically no-op break; case Token::Sub: // - - m_context << u256(0) << eth::Instruction::SUB; + m_context << u256(0) << Instruction::SUB; break; default: BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid unary operator: " + @@ -452,7 +452,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) m_context << max(u256(32u), structType.memorySize()); utils().allocateMemory(); - m_context << eth::Instruction::DUP1; + m_context << Instruction::DUP1; for (unsigned i = 0; i < arguments.size(); ++i) { @@ -460,7 +460,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) utils().convertType(*arguments[i]->annotation().type, *functionType->parameterTypes()[i]); utils().storeInMemoryDynamic(*functionType->parameterTypes()[i]); } - m_context << eth::Instruction::POP; + m_context << Instruction::POP; } else { @@ -518,21 +518,21 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) utils().fetchFreeMemoryPointer(); // pushes size eth::AssemblyItem subroutine = m_context.addSubroutine(assembly); - m_context << eth::Instruction::DUP1 << subroutine; - m_context << eth::Instruction::DUP4 << eth::Instruction::CODECOPY; + m_context << Instruction::DUP1 << subroutine; + m_context << Instruction::DUP4 << Instruction::CODECOPY; - m_context << eth::Instruction::ADD; + m_context << Instruction::ADD; utils().encodeToMemory(argumentTypes, function.parameterTypes()); // now on stack: memory_end_ptr // need: size, offset, endowment utils().toSizeAfterFreeMemoryPointer(); if (function.valueSet()) - m_context << eth::dupInstruction(3); + m_context << dupInstruction(3); else m_context << u256(0); - m_context << eth::Instruction::CREATE; + m_context << Instruction::CREATE; if (function.valueSet()) - m_context << eth::swapInstruction(1) << eth::Instruction::POP; + m_context << swapInstruction(1) << Instruction::POP; break; } case Location::SetGas: @@ -546,9 +546,9 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) // Its values of gasSet and valueSet is equal to the original function's though. unsigned stackDepth = (function.gasSet() ? 1 : 0) + (function.valueSet() ? 1 : 0); if (stackDepth > 0) - m_context << eth::swapInstruction(stackDepth); + m_context << swapInstruction(stackDepth); if (function.gasSet()) - m_context << eth::Instruction::POP; + m_context << Instruction::POP; break; } case Location::SetValue: @@ -557,7 +557,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) // Note that function is not the original function, but the ".value" function. // Its values of gasSet and valueSet is equal to the original function's though. if (function.valueSet()) - m_context << eth::Instruction::POP; + m_context << Instruction::POP; arguments.front()->accept(*this); break; case Location::Send: @@ -586,7 +586,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) case Location::Selfdestruct: arguments.front()->accept(*this); utils().convertType(*arguments.front()->annotation().type, *function.parameterTypes().front(), true); - m_context << eth::Instruction::SUICIDE; + m_context << Instruction::SUICIDE; break; case Location::SHA3: { @@ -599,7 +599,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) utils().fetchFreeMemoryPointer(); utils().encodeToMemory(argumentTypes, TypePointers(), function.padArguments(), true); utils().toSizeAfterFreeMemoryPointer(); - m_context << eth::Instruction::SHA3; + m_context << Instruction::SHA3; break; } case Location::Log0: @@ -622,7 +622,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) false, true); utils().toSizeAfterFreeMemoryPointer(); - m_context << eth::logInstruction(logNumber); + m_context << logInstruction(logNumber); break; } case Location::Event: @@ -646,7 +646,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) true ); utils().toSizeAfterFreeMemoryPointer(); - m_context << eth::Instruction::SHA3; + m_context << Instruction::SHA3; } else utils().convertType( @@ -676,14 +676,14 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) utils().encodeToMemory(nonIndexedArgTypes, nonIndexedParamTypes); // need: topic1 ... topicn memsize memstart utils().toSizeAfterFreeMemoryPointer(); - m_context << eth::logInstruction(numIndexed); + m_context << logInstruction(numIndexed); break; } case Location::BlockHash: { arguments[0]->accept(*this); utils().convertType(*arguments[0]->annotation().type, *function.parameterTypes()[0], true); - m_context << eth::Instruction::BLOCKHASH; + m_context << Instruction::BLOCKHASH; break; } case Location::AddMod: @@ -695,9 +695,9 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) utils().convertType(*arguments[2 - i]->annotation().type, IntegerType(256)); } if (function.location() == Location::AddMod) - m_context << eth::Instruction::ADDMOD; + m_context << Instruction::ADDMOD; else - m_context << eth::Instruction::MULMOD; + m_context << Instruction::MULMOD; break; } case Location::ECRecover: @@ -710,7 +710,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) {Location::RIPEMD160, 3}}; m_context << contractAddresses.find(function.location())->second; for (unsigned i = function.sizeOnStack(); i > 0; --i) - m_context << eth::swapInstruction(i); + m_context << swapInstruction(i); appendExternalFunctionCall(function, arguments); break; } @@ -727,13 +727,13 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) make_shared<ArrayType>(DataLocation::Storage); // get the current length ArrayUtils(m_context).retrieveLength(*arrayType); - m_context << eth::Instruction::DUP1; + m_context << Instruction::DUP1; // stack: ArrayReference currentLength currentLength - m_context << u256(1) << eth::Instruction::ADD; + m_context << u256(1) << Instruction::ADD; // stack: ArrayReference currentLength newLength - m_context << eth::Instruction::DUP3 << eth::Instruction::DUP2; + m_context << Instruction::DUP3 << Instruction::DUP2; ArrayUtils(m_context).resizeDynamicArray(*arrayType); - m_context << eth::Instruction::SWAP2 << eth::Instruction::SWAP1; + m_context << Instruction::SWAP2 << Instruction::SWAP1; // stack: newLength ArrayReference oldLength ArrayUtils(m_context).accessIndex(*arrayType, false); @@ -766,36 +766,36 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) // Stack: requested_length // Allocate at max(MSIZE, freeMemoryPointer) utils().fetchFreeMemoryPointer(); - m_context << eth::Instruction::DUP1 << eth::Instruction::MSIZE; - m_context << eth::Instruction::LT; + m_context << Instruction::DUP1 << Instruction::MSIZE; + m_context << Instruction::LT; auto initialise = m_context.appendConditionalJump(); // Free memory pointer does not point to empty memory, use MSIZE. - m_context << eth::Instruction::POP; - m_context << eth::Instruction::MSIZE; + m_context << Instruction::POP; + m_context << Instruction::MSIZE; m_context << initialise; // Stack: requested_length memptr - m_context << eth::Instruction::SWAP1; + m_context << Instruction::SWAP1; // Stack: memptr requested_length // store length - m_context << eth::Instruction::DUP1 << eth::Instruction::DUP3 << eth::Instruction::MSTORE; + m_context << Instruction::DUP1 << Instruction::DUP3 << Instruction::MSTORE; // Stack: memptr requested_length // update free memory pointer - m_context << eth::Instruction::DUP1 << arrayType.baseType()->memoryHeadSize(); - m_context << eth::Instruction::MUL << u256(32) << eth::Instruction::ADD; - m_context << eth::Instruction::DUP3 << eth::Instruction::ADD; + m_context << Instruction::DUP1 << arrayType.baseType()->memoryHeadSize(); + m_context << Instruction::MUL << u256(32) << Instruction::ADD; + m_context << Instruction::DUP3 << Instruction::ADD; utils().storeFreeMemoryPointer(); // Stack: memptr requested_length // We only have to initialise if the base type is a not a value type. if (dynamic_cast<ReferenceType const*>(arrayType.baseType().get())) { - m_context << eth::Instruction::DUP2 << u256(32) << eth::Instruction::ADD; + m_context << Instruction::DUP2 << u256(32) << Instruction::ADD; utils().zeroInitialiseMemoryArray(arrayType); - m_context << eth::Instruction::POP; + m_context << Instruction::POP; } else - m_context << eth::Instruction::POP; + m_context << Instruction::POP; break; } default: @@ -876,7 +876,7 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) IntegerType(0, IntegerType::Modifier::Address), true ); - m_context << eth::Instruction::BALANCE; + m_context << Instruction::BALANCE; } else if ((set<string>{"send", "call", "callcode", "delegatecall"}).count(member)) utils().convertType( @@ -894,30 +894,30 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) case Type::Category::Magic: // we can ignore the kind of magic and only look at the name of the member if (member == "coinbase") - m_context << eth::Instruction::COINBASE; + m_context << Instruction::COINBASE; else if (member == "timestamp") - m_context << eth::Instruction::TIMESTAMP; + m_context << Instruction::TIMESTAMP; else if (member == "difficulty") - m_context << eth::Instruction::DIFFICULTY; + m_context << Instruction::DIFFICULTY; else if (member == "number") - m_context << eth::Instruction::NUMBER; + m_context << Instruction::NUMBER; else if (member == "gaslimit") - m_context << eth::Instruction::GASLIMIT; + m_context << Instruction::GASLIMIT; else if (member == "sender") - m_context << eth::Instruction::CALLER; + m_context << Instruction::CALLER; else if (member == "value") - m_context << eth::Instruction::CALLVALUE; + m_context << Instruction::CALLVALUE; else if (member == "origin") - m_context << eth::Instruction::ORIGIN; + m_context << Instruction::ORIGIN; else if (member == "gas") - m_context << eth::Instruction::GAS; + m_context << Instruction::GAS; else if (member == "gasprice") - m_context << eth::Instruction::GASPRICE; + m_context << Instruction::GASPRICE; else if (member == "data") - m_context << u256(0) << eth::Instruction::CALLDATASIZE; + m_context << u256(0) << Instruction::CALLDATASIZE; else if (member == "sig") - m_context << u256(0) << eth::Instruction::CALLDATALOAD - << (u256(0xffffffff) << (256 - 32)) << eth::Instruction::AND; + m_context << u256(0) << Instruction::CALLDATALOAD + << (u256(0xffffffff) << (256 - 32)) << Instruction::AND; else BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown magic member.")); break; @@ -929,13 +929,13 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) case DataLocation::Storage: { pair<u256, unsigned> const& offsets = type.storageOffsetsOfMember(member); - m_context << offsets.first << eth::Instruction::ADD << u256(offsets.second); + m_context << offsets.first << Instruction::ADD << u256(offsets.second); setLValueToStorageItem(_memberAccess); break; } case DataLocation::Memory: { - m_context << type.memoryOffsetOfMember(member) << eth::Instruction::ADD; + m_context << type.memoryOffsetOfMember(member) << Instruction::ADD; setLValue<MemoryItem>(_memberAccess, *_memberAccess.annotation().type); break; } @@ -986,13 +986,13 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) switch (type.location()) { case DataLocation::CallData: - m_context << eth::Instruction::SWAP1 << eth::Instruction::POP; + m_context << Instruction::SWAP1 << Instruction::POP; break; case DataLocation::Storage: setLValue<StorageArrayLength>(_memberAccess, type); break; case DataLocation::Memory: - m_context << eth::Instruction::MLOAD; + m_context << Instruction::MLOAD; break; } } @@ -1046,7 +1046,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) false, true ); - m_context << eth::Instruction::SWAP1; + m_context << Instruction::SWAP1; utils().storeInMemoryDynamic(IntegerType(256)); utils().toSizeAfterFreeMemoryPointer(); } @@ -1054,12 +1054,12 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) { m_context << u256(0); // memory position appendExpressionCopyToMemory(*keyType, *_indexAccess.indexExpression()); - m_context << eth::Instruction::SWAP1; + m_context << Instruction::SWAP1; solAssert(CompilerUtils::freeMemoryPointer >= 0x40, ""); utils().storeInMemoryDynamic(IntegerType(256)); m_context << u256(0); } - m_context << eth::Instruction::SHA3; + m_context << Instruction::SHA3; m_context << u256(0); setLValueToStorageItem(_indexAccess); } @@ -1109,12 +1109,12 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) // stack layout: <value> <index> // check out-of-bounds access m_context << u256(fixedBytesType.numBytes()); - m_context << eth::Instruction::DUP2 << eth::Instruction::LT << eth::Instruction::ISZERO; + m_context << Instruction::DUP2 << Instruction::LT << Instruction::ISZERO; // out-of-bounds access throws exception m_context.appendConditionalJumpTo(m_context.errorTag()); - m_context << eth::Instruction::BYTE; - m_context << (u256(1) << (256 - 8)) << eth::Instruction::MUL; + m_context << Instruction::BYTE; + m_context << (u256(1) << (256 - 8)) << Instruction::MUL; } else if (baseType.category() == Type::Category::TypeType) { @@ -1139,11 +1139,11 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier) case Type::Category::Contract: // "this" or "super" if (!dynamic_cast<ContractType const&>(*magicVar->type()).isSuper()) - m_context << eth::Instruction::ADDRESS; + m_context << Instruction::ADDRESS; break; case Type::Category::Integer: // "now" - m_context << eth::Instruction::TIMESTAMP; + m_context << Instruction::TIMESTAMP; break; default: break; @@ -1208,11 +1208,11 @@ void ExpressionCompiler::appendAndOrOperatorCode(BinaryOperation const& _binaryO solAssert(c_op == Token::Or || c_op == Token::And, ""); _binaryOperation.leftExpression().accept(*this); - m_context << eth::Instruction::DUP1; + m_context << Instruction::DUP1; if (c_op == Token::And) - m_context << eth::Instruction::ISZERO; + m_context << Instruction::ISZERO; eth::AssemblyItem endLabel = m_context.appendConditionalJump(); - m_context << eth::Instruction::POP; + m_context << Instruction::POP; _binaryOperation.rightExpression().accept(*this); m_context << endLabel; } @@ -1221,9 +1221,9 @@ void ExpressionCompiler::appendCompareOperatorCode(Token::Value _operator, Type { if (_operator == Token::Equal || _operator == Token::NotEqual) { - m_context << eth::Instruction::EQ; + m_context << Instruction::EQ; if (_operator == Token::NotEqual) - m_context << eth::Instruction::ISZERO; + m_context << Instruction::ISZERO; } else { @@ -1235,19 +1235,19 @@ void ExpressionCompiler::appendCompareOperatorCode(Token::Value _operator, Type { case Token::GreaterThanOrEqual: m_context << - (isSigned ? eth::Instruction::SLT : eth::Instruction::LT) << - eth::Instruction::ISZERO; + (isSigned ? Instruction::SLT : Instruction::LT) << + Instruction::ISZERO; break; case Token::LessThanOrEqual: m_context << - (isSigned ? eth::Instruction::SGT : eth::Instruction::GT) << - eth::Instruction::ISZERO; + (isSigned ? Instruction::SGT : Instruction::GT) << + Instruction::ISZERO; break; case Token::GreaterThan: - m_context << (isSigned ? eth::Instruction::SGT : eth::Instruction::GT); + m_context << (isSigned ? Instruction::SGT : Instruction::GT); break; case Token::LessThan: - m_context << (isSigned ? eth::Instruction::SLT : eth::Instruction::LT); + m_context << (isSigned ? Instruction::SLT : Instruction::LT); break; default: BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown comparison operator.")); @@ -1275,22 +1275,22 @@ void ExpressionCompiler::appendArithmeticOperatorCode(Token::Value _operator, Ty switch (_operator) { case Token::Add: - m_context << eth::Instruction::ADD; + m_context << Instruction::ADD; break; case Token::Sub: - m_context << eth::Instruction::SUB; + m_context << Instruction::SUB; break; case Token::Mul: - m_context << eth::Instruction::MUL; + m_context << Instruction::MUL; break; case Token::Div: - m_context << (c_isSigned ? eth::Instruction::SDIV : eth::Instruction::DIV); + m_context << (c_isSigned ? Instruction::SDIV : Instruction::DIV); break; case Token::Mod: - m_context << (c_isSigned ? eth::Instruction::SMOD : eth::Instruction::MOD); + m_context << (c_isSigned ? Instruction::SMOD : Instruction::MOD); break; case Token::Exp: - m_context << eth::Instruction::EXP; + m_context << Instruction::EXP; break; default: BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown arithmetic operator.")); @@ -1302,13 +1302,13 @@ void ExpressionCompiler::appendBitOperatorCode(Token::Value _operator) switch (_operator) { case Token::BitOr: - m_context << eth::Instruction::OR; + m_context << Instruction::OR; break; case Token::BitAnd: - m_context << eth::Instruction::AND; + m_context << Instruction::AND; break; case Token::BitXor: - m_context << eth::Instruction::XOR; + m_context << Instruction::XOR; break; default: BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown bit operator.")); @@ -1392,7 +1392,7 @@ void ExpressionCompiler::appendExternalFunctionCall( true ); for (unsigned i = 0; i < gasValueSize; ++i) - m_context << eth::swapInstruction(gasValueSize - i); + m_context << swapInstruction(gasValueSize - i); gasStackPos++; valueStackPos++; } @@ -1411,7 +1411,7 @@ void ExpressionCompiler::appendExternalFunctionCall( utils().fetchFreeMemoryPointer(); if (!_functionType.isBareCall() || manualFunctionId) { - m_context << eth::dupInstruction(2 + gasValueSize + CompilerUtils::sizeOnStack(argumentTypes)); + m_context << dupInstruction(2 + gasValueSize + CompilerUtils::sizeOnStack(argumentTypes)); utils().storeInMemoryDynamic(IntegerType(8 * CompilerUtils::dataStartOffset), false); } // If the function takes arbitrary parameters, copy dynamic length data in place. @@ -1437,21 +1437,21 @@ void ExpressionCompiler::appendExternalFunctionCall( // put on stack: <size of output> <memory pos of output> <size of input> <memory pos of input> m_context << u256(retSize); utils().fetchFreeMemoryPointer(); - m_context << eth::Instruction::DUP1 << eth::Instruction::DUP4 << eth::Instruction::SUB; - m_context << eth::Instruction::DUP2; + m_context << Instruction::DUP1 << Instruction::DUP4 << Instruction::SUB; + m_context << Instruction::DUP2; // CALL arguments: outSize, outOff, inSize, inOff (already present up to here) // [value,] addr, gas (stack top) if (isDelegateCall) solAssert(!_functionType.valueSet(), "Value set for delegatecall"); else if (_functionType.valueSet()) - m_context << eth::dupInstruction(m_context.baseToCurrentStackOffset(valueStackPos)); + m_context << dupInstruction(m_context.baseToCurrentStackOffset(valueStackPos)); else m_context << u256(0); - m_context << eth::dupInstruction(m_context.baseToCurrentStackOffset(contractStackPos)); + m_context << dupInstruction(m_context.baseToCurrentStackOffset(contractStackPos)); if (_functionType.gasSet()) - m_context << eth::dupInstruction(m_context.baseToCurrentStackOffset(gasStackPos)); + m_context << dupInstruction(m_context.baseToCurrentStackOffset(gasStackPos)); else { eth::EVMSchedule schedule; @@ -1464,15 +1464,15 @@ void ExpressionCompiler::appendExternalFunctionCall( gasNeededByCaller += schedule.callNewAccountGas; // we never know m_context << gasNeededByCaller << - eth::Instruction::GAS << - eth::Instruction::SUB; + Instruction::GAS << + Instruction::SUB; } if (isDelegateCall) - m_context << eth::Instruction::DELEGATECALL; + m_context << Instruction::DELEGATECALL; else if (isCallCode) - m_context << eth::Instruction::CALLCODE; + m_context << Instruction::CALLCODE; else - m_context << eth::Instruction::CALL; + m_context << Instruction::CALL; unsigned remainsSize = 2 + // contract address, input_memory_end @@ -1481,11 +1481,11 @@ void ExpressionCompiler::appendExternalFunctionCall( (!_functionType.isBareCall() || manualFunctionId); if (returnSuccessCondition) - m_context << eth::swapInstruction(remainsSize); + m_context << swapInstruction(remainsSize); else { //Propagate error condition (if CALL pushes 0 on stack). - m_context << eth::Instruction::ISZERO; + m_context << Instruction::ISZERO; m_context.appendConditionalJumpTo(m_context.errorTag()); } @@ -1515,7 +1515,7 @@ void ExpressionCompiler::appendExternalFunctionCall( if (memoryNeeded) utils().storeFreeMemoryPointer(); else - m_context << eth::Instruction::POP; + m_context << Instruction::POP; } } diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index fdef6937..fcadd2ff 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -21,7 +21,7 @@ */ #include <libsolidity/codegen/LValue.h> -#include <libevmcore/Instruction.h> +#include <libevmasm/Instruction.h> #include <libsolidity/ast/Types.h> #include <libsolidity/ast/AST.h> #include <libsolidity/codegen/CompilerUtils.h> @@ -49,7 +49,7 @@ void StackVariable::retrieveValue(SourceLocation const& _location, bool) const ); solAssert(stackPos + 1 >= m_size, "Size and stack pos mismatch."); for (unsigned i = 0; i < m_size; ++i) - m_context << eth::dupInstruction(stackPos + 1); + m_context << dupInstruction(stackPos + 1); } void StackVariable::storeValue(Type const&, SourceLocation const& _location, bool _move) const @@ -63,7 +63,7 @@ void StackVariable::storeValue(Type const&, SourceLocation const& _location, boo ); else if (stackDiff > 0) for (unsigned i = 0; i < m_size; ++i) - m_context << eth::swapInstruction(stackDiff) << eth::Instruction::POP; + m_context << swapInstruction(stackDiff) << Instruction::POP; if (!_move) retrieveValue(_location); } @@ -85,11 +85,11 @@ void MemoryItem::retrieveValue(SourceLocation const&, bool _remove) const if (m_dataType->isValueType()) { if (!_remove) - m_context << eth::Instruction::DUP1; + m_context << Instruction::DUP1; CompilerUtils(m_context).loadFromMemoryDynamic(*m_dataType, false, m_padded, false); } else - m_context << eth::Instruction::MLOAD; + m_context << Instruction::MLOAD; } void MemoryItem::storeValue(Type const& _sourceType, SourceLocation const&, bool _move) const @@ -109,13 +109,13 @@ void MemoryItem::storeValue(Type const& _sourceType, SourceLocation const&, bool { solAssert(m_dataType->calldataEncodedSize(false) == 1, "Invalid non-padded type."); if (m_dataType->category() == Type::Category::FixedBytes) - m_context << u256(0) << eth::Instruction::BYTE; - m_context << eth::Instruction::SWAP1 << eth::Instruction::MSTORE8; + m_context << u256(0) << Instruction::BYTE; + m_context << Instruction::SWAP1 << Instruction::MSTORE8; } else { utils.storeInMemoryDynamic(*m_dataType, m_padded); - m_context << eth::Instruction::POP; + m_context << Instruction::POP; } } else @@ -124,10 +124,10 @@ void MemoryItem::storeValue(Type const& _sourceType, SourceLocation const&, bool solAssert(m_dataType->sizeOnStack() == 1, ""); if (!_move) - m_context << eth::Instruction::DUP2 << eth::Instruction::SWAP1; + m_context << Instruction::DUP2 << Instruction::SWAP1; // stack: [value] value lvalue // only store the reference - m_context << eth::Instruction::MSTORE; + m_context << Instruction::MSTORE; } } @@ -135,10 +135,10 @@ void MemoryItem::setToZero(SourceLocation const&, bool _removeReference) const { CompilerUtils utils(m_context); if (!_removeReference) - m_context << eth::Instruction::DUP1; + m_context << Instruction::DUP1; utils.pushZeroValue(*m_dataType); utils.storeInMemoryDynamic(*m_dataType, m_padded); - m_context << eth::Instruction::POP; + m_context << Instruction::POP; } StorageItem::StorageItem(CompilerContext& _compilerContext, VariableDeclaration const& _declaration): @@ -165,29 +165,29 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const { solAssert(m_dataType->sizeOnStack() == 1, "Invalid storage ref size."); if (_remove) - m_context << eth::Instruction::POP; // remove byte offset + m_context << Instruction::POP; // remove byte offset else - m_context << eth::Instruction::DUP2; + m_context << Instruction::DUP2; return; } if (!_remove) CompilerUtils(m_context).copyToStackTop(sizeOnStack(), sizeOnStack()); if (m_dataType->storageBytes() == 32) - m_context << eth::Instruction::POP << eth::Instruction::SLOAD; + m_context << Instruction::POP << Instruction::SLOAD; else { m_context - << eth::Instruction::SWAP1 << eth::Instruction::SLOAD << eth::Instruction::SWAP1 - << u256(0x100) << eth::Instruction::EXP << eth::Instruction::SWAP1 << eth::Instruction::DIV; + << Instruction::SWAP1 << Instruction::SLOAD << Instruction::SWAP1 + << u256(0x100) << Instruction::EXP << Instruction::SWAP1 << Instruction::DIV; if (m_dataType->category() == Type::Category::FixedBytes) - m_context << (u256(0x1) << (256 - 8 * m_dataType->storageBytes())) << eth::Instruction::MUL; + m_context << (u256(0x1) << (256 - 8 * m_dataType->storageBytes())) << Instruction::MUL; else if ( m_dataType->category() == Type::Category::Integer && dynamic_cast<IntegerType const&>(*m_dataType).isSigned() ) - m_context << u256(m_dataType->storageBytes() - 1) << eth::Instruction::SIGNEXTEND; + m_context << u256(m_dataType->storageBytes() - 1) << Instruction::SIGNEXTEND; else - m_context << ((u256(0x1) << (8 * m_dataType->storageBytes())) - 1) << eth::Instruction::AND; + m_context << ((u256(0x1) << (8 * m_dataType->storageBytes())) - 1) << Instruction::AND; } } @@ -202,32 +202,32 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc if (m_dataType->storageBytes() == 32) { // offset should be zero - m_context << eth::Instruction::POP; + m_context << Instruction::POP; if (!_move) - m_context << eth::Instruction::DUP2 << eth::Instruction::SWAP1; - m_context << eth::Instruction::SSTORE; + m_context << Instruction::DUP2 << Instruction::SWAP1; + m_context << Instruction::SSTORE; } else { // OR the value into the other values in the storage slot - m_context << u256(0x100) << eth::Instruction::EXP; + m_context << u256(0x100) << Instruction::EXP; // stack: value storage_ref multiplier // fetch old value - m_context << eth::Instruction::DUP2 << eth::Instruction::SLOAD; + m_context << Instruction::DUP2 << Instruction::SLOAD; // stack: value storege_ref multiplier old_full_value // clear bytes in old value m_context - << eth::Instruction::DUP2 << ((u256(1) << (8 * m_dataType->storageBytes())) - 1) - << eth::Instruction::MUL; - m_context << eth::Instruction::NOT << eth::Instruction::AND; + << Instruction::DUP2 << ((u256(1) << (8 * m_dataType->storageBytes())) - 1) + << Instruction::MUL; + m_context << Instruction::NOT << Instruction::AND; // stack: value storage_ref multiplier cleared_value m_context - << eth::Instruction::SWAP1 << eth::Instruction::DUP4; + << Instruction::SWAP1 << Instruction::DUP4; // stack: value storage_ref cleared_value multiplier value if (m_dataType->category() == Type::Category::FixedBytes) m_context << (u256(0x1) << (256 - 8 * dynamic_cast<FixedBytesType const&>(*m_dataType).numBytes())) - << eth::Instruction::SWAP1 << eth::Instruction::DIV; + << Instruction::SWAP1 << Instruction::DIV; else if ( m_dataType->category() == Type::Category::Integer && dynamic_cast<IntegerType const&>(*m_dataType).isSigned() @@ -235,15 +235,15 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc // remove the higher order bits m_context << (u256(1) << (8 * (32 - m_dataType->storageBytes()))) - << eth::Instruction::SWAP1 - << eth::Instruction::DUP2 - << eth::Instruction::MUL - << eth::Instruction::DIV; - m_context << eth::Instruction::MUL << eth::Instruction::OR; + << Instruction::SWAP1 + << Instruction::DUP2 + << Instruction::MUL + << Instruction::DIV; + m_context << Instruction::MUL << Instruction::OR; // stack: value storage_ref updated_value - m_context << eth::Instruction::SWAP1 << eth::Instruction::SSTORE; + m_context << Instruction::SWAP1 << Instruction::SSTORE; if (_move) - m_context << eth::Instruction::POP; + m_context << Instruction::POP; } } else @@ -253,19 +253,19 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc "Wrong type conversation for assignment."); if (m_dataType->category() == Type::Category::Array) { - m_context << eth::Instruction::POP; // remove byte offset + m_context << Instruction::POP; // remove byte offset ArrayUtils(m_context).copyArrayToStorage( dynamic_cast<ArrayType const&>(*m_dataType), dynamic_cast<ArrayType const&>(_sourceType) ); if (_move) - m_context << eth::Instruction::POP; + m_context << Instruction::POP; } else if (m_dataType->category() == Type::Category::Struct) { // stack layout: source_ref target_ref target_offset // note that we have structs, so offset should be zero and are ignored - m_context << eth::Instruction::POP; + m_context << Instruction::POP; auto const& structType = dynamic_cast<StructType const&>(*m_dataType); auto const& sourceType = dynamic_cast<StructType const&>(_sourceType); solAssert( @@ -284,7 +284,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc { // stack layout: source_ref target_ref pair<u256, unsigned> const& offsets = sourceType.storageOffsetsOfMember(member.name); - m_context << offsets.first << eth::Instruction::DUP3 << eth::Instruction::ADD; + m_context << offsets.first << Instruction::DUP3 << Instruction::ADD; m_context << u256(offsets.second); // stack: source_ref target_ref source_member_ref source_member_off StorageItem(m_context, *sourceMemberType).retrieveValue(_location, true); @@ -296,13 +296,13 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc // stack layout: source_ref target_ref TypePointer sourceMemberType = sourceType.memberType(member.name); m_context << sourceType.memoryOffsetOfMember(member.name); - m_context << eth::Instruction::DUP3 << eth::Instruction::ADD; + m_context << Instruction::DUP3 << Instruction::ADD; MemoryItem(m_context, *sourceMemberType).retrieveValue(_location, true); // stack layout: source_ref target_ref source_value... } unsigned stackSize = sourceMemberType->sizeOnStack(); pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member.name); - m_context << eth::dupInstruction(1 + stackSize) << offsets.first << eth::Instruction::ADD; + m_context << dupInstruction(1 + stackSize) << offsets.first << Instruction::ADD; m_context << u256(offsets.second); // stack: source_ref target_ref target_off source_value... target_member_ref target_member_byte_off StorageItem(m_context, *memberType).storeValue(*sourceMemberType, _location, true); @@ -312,7 +312,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc if (_move) utils.popStackSlots(2); else - m_context << eth::Instruction::SWAP1 << eth::Instruction::POP; + m_context << Instruction::SWAP1 << Instruction::POP; } else BOOST_THROW_EXCEPTION( @@ -344,12 +344,12 @@ void StorageItem::setToZero(SourceLocation const&, bool _removeReference) const continue; pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member.name); m_context - << offsets.first << eth::Instruction::DUP3 << eth::Instruction::ADD + << offsets.first << Instruction::DUP3 << Instruction::ADD << u256(offsets.second); StorageItem(m_context, *memberType).setToZero(); } if (_removeReference) - m_context << eth::Instruction::POP << eth::Instruction::POP; + m_context << Instruction::POP << Instruction::POP; } else { @@ -360,23 +360,23 @@ void StorageItem::setToZero(SourceLocation const&, bool _removeReference) const { // offset should be zero m_context - << eth::Instruction::POP << u256(0) - << eth::Instruction::SWAP1 << eth::Instruction::SSTORE; + << Instruction::POP << u256(0) + << Instruction::SWAP1 << Instruction::SSTORE; } else { - m_context << u256(0x100) << eth::Instruction::EXP; + m_context << u256(0x100) << Instruction::EXP; // stack: storage_ref multiplier // fetch old value - m_context << eth::Instruction::DUP2 << eth::Instruction::SLOAD; + m_context << Instruction::DUP2 << Instruction::SLOAD; // stack: storege_ref multiplier old_full_value // clear bytes in old value m_context - << eth::Instruction::SWAP1 << ((u256(1) << (8 * m_dataType->storageBytes())) - 1) - << eth::Instruction::MUL; - m_context << eth::Instruction::NOT << eth::Instruction::AND; + << Instruction::SWAP1 << ((u256(1) << (8 * m_dataType->storageBytes())) - 1) + << Instruction::MUL; + m_context << Instruction::NOT << Instruction::AND; // stack: storage_ref cleared_value - m_context << eth::Instruction::SWAP1 << eth::Instruction::SSTORE; + m_context << Instruction::SWAP1 << Instruction::SSTORE; } } } @@ -393,48 +393,48 @@ void StorageByteArrayElement::retrieveValue(SourceLocation const&, bool _remove) { // stack: ref byte_number if (_remove) - m_context << eth::Instruction::SWAP1 << eth::Instruction::SLOAD - << eth::Instruction::SWAP1 << eth::Instruction::BYTE; + m_context << Instruction::SWAP1 << Instruction::SLOAD + << Instruction::SWAP1 << Instruction::BYTE; else - m_context << eth::Instruction::DUP2 << eth::Instruction::SLOAD - << eth::Instruction::DUP2 << eth::Instruction::BYTE; - m_context << (u256(1) << (256 - 8)) << eth::Instruction::MUL; + m_context << Instruction::DUP2 << Instruction::SLOAD + << Instruction::DUP2 << Instruction::BYTE; + m_context << (u256(1) << (256 - 8)) << Instruction::MUL; } void StorageByteArrayElement::storeValue(Type const&, SourceLocation const&, bool _move) const { // stack: value ref byte_number - m_context << u256(31) << eth::Instruction::SUB << u256(0x100) << eth::Instruction::EXP; + m_context << u256(31) << Instruction::SUB << u256(0x100) << Instruction::EXP; // stack: value ref (1<<(8*(31-byte_number))) - m_context << eth::Instruction::DUP2 << eth::Instruction::SLOAD; + m_context << Instruction::DUP2 << Instruction::SLOAD; // stack: value ref (1<<(8*(31-byte_number))) old_full_value // clear byte in old value - m_context << eth::Instruction::DUP2 << u256(0xff) << eth::Instruction::MUL - << eth::Instruction::NOT << eth::Instruction::AND; + m_context << Instruction::DUP2 << u256(0xff) << Instruction::MUL + << Instruction::NOT << Instruction::AND; // stack: value ref (1<<(32-byte_number)) old_full_value_with_cleared_byte - m_context << eth::Instruction::SWAP1; - m_context << (u256(1) << (256 - 8)) << eth::Instruction::DUP5 << eth::Instruction::DIV - << eth::Instruction::MUL << eth::Instruction::OR; + m_context << Instruction::SWAP1; + m_context << (u256(1) << (256 - 8)) << Instruction::DUP5 << Instruction::DIV + << Instruction::MUL << Instruction::OR; // stack: value ref new_full_value - m_context << eth::Instruction::SWAP1 << eth::Instruction::SSTORE; + m_context << Instruction::SWAP1 << Instruction::SSTORE; if (_move) - m_context << eth::Instruction::POP; + m_context << Instruction::POP; } void StorageByteArrayElement::setToZero(SourceLocation const&, bool _removeReference) const { // stack: ref byte_number if (!_removeReference) - m_context << eth::Instruction::DUP2 << eth::Instruction::DUP2; - m_context << u256(31) << eth::Instruction::SUB << u256(0x100) << eth::Instruction::EXP; + m_context << Instruction::DUP2 << Instruction::DUP2; + m_context << u256(31) << Instruction::SUB << u256(0x100) << Instruction::EXP; // stack: ref (1<<(8*(31-byte_number))) - m_context << eth::Instruction::DUP2 << eth::Instruction::SLOAD; + m_context << Instruction::DUP2 << Instruction::SLOAD; // stack: ref (1<<(8*(31-byte_number))) old_full_value // clear byte in old value - m_context << eth::Instruction::SWAP1 << u256(0xff) << eth::Instruction::MUL; - m_context << eth::Instruction::NOT << eth::Instruction::AND; + m_context << Instruction::SWAP1 << u256(0xff) << Instruction::MUL; + m_context << Instruction::NOT << Instruction::AND; // stack: ref old_full_value_with_cleared_byte - m_context << eth::Instruction::SWAP1 << eth::Instruction::SSTORE; + m_context << Instruction::SWAP1 << Instruction::SSTORE; } StorageArrayLength::StorageArrayLength(CompilerContext& _compilerContext, const ArrayType& _arrayType): @@ -448,22 +448,22 @@ void StorageArrayLength::retrieveValue(SourceLocation const&, bool _remove) cons { ArrayUtils(m_context).retrieveLength(m_arrayType); if (_remove) - m_context << eth::Instruction::SWAP1 << eth::Instruction::POP; + m_context << Instruction::SWAP1 << Instruction::POP; } void StorageArrayLength::storeValue(Type const&, SourceLocation const&, bool _move) const { if (_move) - m_context << eth::Instruction::SWAP1; + m_context << Instruction::SWAP1; else - m_context << eth::Instruction::DUP2; + m_context << Instruction::DUP2; ArrayUtils(m_context).resizeDynamicArray(m_arrayType); } void StorageArrayLength::setToZero(SourceLocation const&, bool _removeReference) const { if (!_removeReference) - m_context << eth::Instruction::DUP1; + m_context << Instruction::DUP1; ArrayUtils(m_context).clearDynamicArray(m_arrayType); } diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp index 89e95bc1..5fa04087 100644 --- a/libsolidity/inlineasm/AsmCodeGen.cpp +++ b/libsolidity/inlineasm/AsmCodeGen.cpp @@ -25,6 +25,7 @@ #include <functional> #include <libevmasm/Assembly.h> #include <libevmasm/SourceLocation.h> +#include <libevmasm/Instruction.h> #include <libsolidity/inlineasm/AsmParser.h> #include <libsolidity/inlineasm/AsmData.h> @@ -116,7 +117,7 @@ public: m_identifierAccess = [](assembly::Identifier const&, eth::Assembly&, CodeGenerator::IdentifierContext) { return false; }; } - void operator()(Instruction const& _instruction) + void operator()(dev::solidity::assembly::Instruction const& _instruction) { m_state.assembly.append(_instruction.instruction); } @@ -145,7 +146,7 @@ public: "Variable inaccessible, too deep inside stack (" + boost::lexical_cast<string>(heightDiff) + ")" ); else - m_state.assembly.append(eth::dupInstruction(heightDiff)); + m_state.assembly.append(solidity::dupInstruction(heightDiff)); return; } else if (eth::AssemblyItem const* label = m_state.findLabel(_identifier.name)) @@ -196,7 +197,7 @@ public: //@TODO check height before and after while (m_state.variables.size() > numVariables) { - m_state.assembly.append(eth::Instruction::POP); + m_state.assembly.append(solidity::Instruction::POP); m_state.variables.pop_back(); } } @@ -215,8 +216,8 @@ private: ); else { - m_state.assembly.append(eth::swapInstruction(heightDiff)); - m_state.assembly.append(eth::Instruction::POP); + m_state.assembly.append(solidity::swapInstruction(heightDiff)); + m_state.assembly.append(solidity::Instruction::POP); } return; } diff --git a/libsolidity/inlineasm/AsmData.h b/libsolidity/inlineasm/AsmData.h index 0361a4c2..42f0ae31 100644 --- a/libsolidity/inlineasm/AsmData.h +++ b/libsolidity/inlineasm/AsmData.h @@ -23,7 +23,7 @@ #pragma once #include <boost/variant.hpp> -#include <libevmcore/Instruction.h> +#include <libevmasm/Instruction.h> namespace dev { @@ -35,7 +35,7 @@ namespace assembly /// What follows are the AST nodes for assembly. /// Direct EVM instruction (except PUSHi and JUMPDEST) -struct Instruction { eth::Instruction instruction; }; +struct Instruction { solidity::Instruction instruction; }; /// Literal number or string (up to 32 bytes) struct Literal { bool isNumber; std::string value; }; /// External / internal identifier or label reference diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp index 3f794351..33c8efa0 100644 --- a/libsolidity/inlineasm/AsmParser.cpp +++ b/libsolidity/inlineasm/AsmParser.cpp @@ -23,7 +23,6 @@ #include <libsolidity/inlineasm/AsmParser.h> #include <ctype.h> #include <algorithm> -#include <libevmcore/Instruction.h> #include <libsolidity/parsing/Scanner.h> using namespace std; @@ -122,17 +121,17 @@ assembly::Statement Parser::parseExpression() assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher) { // Allowed instructions, lowercase names. - static map<string, eth::Instruction> s_instructions; + static map<string, dev::solidity::Instruction> s_instructions; if (s_instructions.empty()) - for (auto const& instruction: eth::c_instructions) + for (auto const& instruction: solidity::c_instructions) { if ( - instruction.second == eth::Instruction::JUMPDEST || - (eth::Instruction::PUSH1 <= instruction.second && instruction.second <= eth::Instruction::PUSH32) + instruction.second == solidity::Instruction::JUMPDEST || + (solidity::Instruction::PUSH1 <= instruction.second && instruction.second <= solidity::Instruction::PUSH32) ) continue; string name = instruction.first; - if (instruction.second == eth::Instruction::SUICIDE) + if (instruction.second == solidity::Instruction::SUICIDE) name = "selfdestruct"; transform(name.begin(), name.end(), name.begin(), [](unsigned char _c) { return tolower(_c); }); s_instructions[name] = instruction.second; @@ -156,10 +155,10 @@ assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher) // first search the set of instructions. if (s_instructions.count(literal)) { - eth::Instruction const& instr = s_instructions[literal]; + dev::solidity::Instruction const& instr = s_instructions[literal]; if (_onlySinglePusher) { - eth::InstructionInfo info = eth::instructionInfo(instr); + InstructionInfo info = dev::solidity::instructionInfo(instr); if (info.ret != 1) fatalParserError("Instruction " + info.name + " not allowed in this context."); } @@ -204,11 +203,11 @@ FunctionalInstruction Parser::parseFunctionalInstruction(assembly::Statement con { if (_instruction.type() != typeid(Instruction)) fatalParserError("Assembly instruction required in front of \"(\")"); - eth::Instruction instr = boost::get<Instruction>(_instruction).instruction; - eth::InstructionInfo instrInfo = eth::instructionInfo(instr); - if (eth::Instruction::DUP1 <= instr && instr <= eth::Instruction::DUP16) + solidity::Instruction instr = boost::get<solidity::assembly::Instruction>(_instruction).instruction; + InstructionInfo instrInfo = instructionInfo(instr); + if (solidity::Instruction::DUP1 <= instr && instr <= solidity::Instruction::DUP16) fatalParserError("DUPi instructions not allowed for functional notation"); - if (eth::Instruction::SWAP1 <= instr && instr <= eth::Instruction::SWAP16) + if (solidity::Instruction::SWAP1 <= instr && instr <= solidity::Instruction::SWAP16) fatalParserError("SWAPi instructions not allowed for functional notation"); expectToken(Token::LParen); diff --git a/libsolidity/interface/GasEstimator.cpp b/libsolidity/interface/GasEstimator.cpp index d460ba76..99ed75bc 100644 --- a/libsolidity/interface/GasEstimator.cpp +++ b/libsolidity/interface/GasEstimator.cpp @@ -137,8 +137,8 @@ GasEstimator::GasConsumption GasEstimator::functionalEstimation( using Id = ExpressionClasses::Id; using Ids = vector<Id>; Id hashValue = classes.find(u256(FixedHash<4>::Arith(FixedHash<4>(dev::sha3(_signature))))); - Id calldata = classes.find(eth::Instruction::CALLDATALOAD, Ids{classes.find(u256(0))}); - classes.forceEqual(hashValue, eth::Instruction::DIV, Ids{ + Id calldata = classes.find(Instruction::CALLDATALOAD, Ids{classes.find(u256(0))}); + classes.forceEqual(hashValue, Instruction::DIV, Ids{ calldata, classes.find(u256(1) << (8 * 28)) }); @@ -165,7 +165,7 @@ GasEstimator::GasConsumption GasEstimator::functionalEstimation( AssemblyItem invalidTag(PushTag, u256(-0x10)); state->feedItem(invalidTag, true); if (parametersSize > 0) - state->feedItem(eth::swapInstruction(parametersSize)); + state->feedItem(swapInstruction(parametersSize)); return PathGasMeter(_items).estimateMax(_offset, state); } diff --git a/lllc/CMakeLists.txt b/lllc/CMakeLists.txt index 989b8cbf..a897e663 100644 --- a/lllc/CMakeLists.txt +++ b/lllc/CMakeLists.txt @@ -6,7 +6,7 @@ file(GLOB HEADERS "*.h") include_directories(BEFORE ..) add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) -eth_use(${EXECUTABLE} REQUIRED Solidity::lll Dev::buildinfo) +eth_use(${EXECUTABLE} REQUIRED Solidity::lll Dev::buildinfo Solidity::evmasm) install( TARGETS ${EXECUTABLE} DESTINATION bin ) diff --git a/lllc/main.cpp b/lllc/main.cpp index 5f3078c2..2c3b6a64 100644 --- a/lllc/main.cpp +++ b/lllc/main.cpp @@ -25,10 +25,11 @@ #include <liblll/Compiler.h> #include <libdevcore/CommonIO.h> #include <libdevcore/CommonData.h> -#include <libevmcore/Instruction.h> +#include <libevmasm/Instruction.h> #include "ethereum/BuildInfo.h" using namespace std; using namespace dev; +using namespace dev::solidity; using namespace dev::eth; void help() diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index a302e024..d82a2442 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -34,7 +34,7 @@ #include <libdevcore/Common.h> #include <libdevcore/CommonData.h> #include <libdevcore/CommonIO.h> -#include <libevmcore/Instruction.h> +#include <libevmasm/Instruction.h> #include <libsolidity/interface/Version.h> #include <libsolidity/parsing/Scanner.h> #include <libsolidity/parsing/Parser.h> @@ -161,11 +161,11 @@ void CommandLineInterface::handleBinary(string const& _contract) void CommandLineInterface::handleOpcode(string const& _contract) { if (m_args.count("output-dir")) - createFile(_contract + ".opcode", eth::disassemble(m_compiler->object(_contract).bytecode)); + createFile(_contract + ".opcode", solidity::disassemble(m_compiler->object(_contract).bytecode)); else { cout << "Opcodes: " << endl; - cout << eth::disassemble(m_compiler->object(_contract).bytecode); + cout << solidity::disassemble(m_compiler->object(_contract).bytecode); cout << endl; } } @@ -674,7 +674,7 @@ void CommandLineInterface::handleCombinedJSON() if (requests.count("clone-bin")) contractData["clone-bin"] = m_compiler->cloneObject(contractName).toHex(); if (requests.count("opcodes")) - contractData["opcodes"] = eth::disassemble(m_compiler->object(contractName).bytecode); + contractData["opcodes"] = solidity::disassemble(m_compiler->object(contractName).bytecode); if (requests.count("asm")) { ostringstream unused; diff --git a/solc/jsonCompiler.cpp b/solc/jsonCompiler.cpp index c6b40fdc..1c20d695 100644 --- a/solc/jsonCompiler.cpp +++ b/solc/jsonCompiler.cpp @@ -27,7 +27,7 @@ #include <libdevcore/Common.h> #include <libdevcore/CommonData.h> #include <libdevcore/CommonIO.h> -#include <libevmcore/Instruction.h> +#include <libevmasm/Instruction.h> #include <libsolidity/parsing/Scanner.h> #include <libsolidity/parsing/Parser.h> #include <libsolidity/ast/ASTPrinter.h> @@ -206,7 +206,7 @@ string compile(StringMap const& _sources, bool _optimize, CStyleReadFileCallback contractData["interface"] = compiler.interface(contractName); contractData["bytecode"] = compiler.object(contractName).toHex(); contractData["runtimeBytecode"] = compiler.runtimeObject(contractName).toHex(); - contractData["opcodes"] = eth::disassemble(compiler.object(contractName).bytecode); + contractData["opcodes"] = solidity::disassemble(compiler.object(contractName).bytecode); contractData["functionHashes"] = functionHashes(compiler.contractDefinition(contractName)); contractData["gasEstimates"] = estimateGas(compiler, contractName); ostringstream unused; diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index 0e814e56..a201604b 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -174,7 +174,7 @@ BOOST_AUTO_TEST_CASE(literal_true) "}\n"; bytes code = compileFirstExpression(sourceCode); - bytes expectation({byte(eth::Instruction::PUSH1), 0x1}); + bytes expectation({byte(Instruction::PUSH1), 0x1}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -185,7 +185,7 @@ BOOST_AUTO_TEST_CASE(literal_false) "}\n"; bytes code = compileFirstExpression(sourceCode); - bytes expectation({byte(eth::Instruction::PUSH1), 0x0}); + bytes expectation({byte(Instruction::PUSH1), 0x0}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -196,7 +196,7 @@ BOOST_AUTO_TEST_CASE(int_literal) "}\n"; bytes code = compileFirstExpression(sourceCode); - bytes expectation({byte(eth::Instruction::PUSH10), 0x12, 0x34, 0x56, 0x78, 0x90, + bytes expectation({byte(Instruction::PUSH10), 0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -212,7 +212,7 @@ BOOST_AUTO_TEST_CASE(int_with_wei_ether_subdenomination) })"; bytes code = compileFirstExpression(sourceCode); - bytes expectation({byte(eth::Instruction::PUSH1), 0x1}); + bytes expectation({byte(Instruction::PUSH1), 0x1}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -227,7 +227,7 @@ BOOST_AUTO_TEST_CASE(int_with_szabo_ether_subdenomination) })"; bytes code = compileFirstExpression(sourceCode); - bytes expectation({byte(eth::Instruction::PUSH5), 0xe8, 0xd4, 0xa5, 0x10, 0x00}); + bytes expectation({byte(Instruction::PUSH5), 0xe8, 0xd4, 0xa5, 0x10, 0x00}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -242,7 +242,7 @@ BOOST_AUTO_TEST_CASE(int_with_finney_ether_subdenomination) })"; bytes code = compileFirstExpression(sourceCode); - bytes expectation({byte(eth::Instruction::PUSH7), 0x3, 0x8d, 0x7e, 0xa4, 0xc6, 0x80, 0x00}); + bytes expectation({byte(Instruction::PUSH7), 0x3, 0x8d, 0x7e, 0xa4, 0xc6, 0x80, 0x00}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -257,7 +257,7 @@ BOOST_AUTO_TEST_CASE(int_with_ether_ether_subdenomination) })"; bytes code = compileFirstExpression(sourceCode); - bytes expectation({byte(eth::Instruction::PUSH8), 0xd, 0xe0, 0xb6, 0xb3, 0xa7, 0x64, 0x00, 0x00}); + bytes expectation({byte(Instruction::PUSH8), 0xd, 0xe0, 0xb6, 0xb3, 0xa7, 0x64, 0x00, 0x00}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -268,12 +268,12 @@ BOOST_AUTO_TEST_CASE(comparison) "}\n"; bytes code = compileFirstExpression(sourceCode); - bytes expectation({byte(eth::Instruction::PUSH1), 0x1, - byte(eth::Instruction::PUSH2), 0x11, 0xaa, - byte(eth::Instruction::PUSH2), 0x10, 0xaa, - byte(eth::Instruction::LT), - byte(eth::Instruction::EQ), - byte(eth::Instruction::ISZERO)}); + bytes expectation({byte(Instruction::PUSH1), 0x1, + byte(Instruction::PUSH2), 0x11, 0xaa, + byte(Instruction::PUSH2), 0x10, 0xaa, + byte(Instruction::LT), + byte(Instruction::EQ), + byte(Instruction::ISZERO)}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -284,22 +284,22 @@ BOOST_AUTO_TEST_CASE(short_circuiting) "}\n"; bytes code = compileFirstExpression(sourceCode); - bytes expectation({byte(eth::Instruction::PUSH1), 0x12, // 8 + 10 - byte(eth::Instruction::PUSH1), 0x4, - byte(eth::Instruction::GT), - byte(eth::Instruction::ISZERO), // after this we have 4 <= 8 + 10 - byte(eth::Instruction::DUP1), - byte(eth::Instruction::PUSH1), 0x11, - byte(eth::Instruction::JUMPI), // short-circuit if it is true - byte(eth::Instruction::POP), - byte(eth::Instruction::PUSH1), 0x2, - byte(eth::Instruction::PUSH1), 0x9, - byte(eth::Instruction::EQ), - byte(eth::Instruction::ISZERO), // after this we have 9 != 2 - byte(eth::Instruction::JUMPDEST), - byte(eth::Instruction::PUSH1), 0x1, - byte(eth::Instruction::EQ), - byte(eth::Instruction::ISZERO)}); + bytes expectation({byte(Instruction::PUSH1), 0x12, // 8 + 10 + byte(Instruction::PUSH1), 0x4, + byte(Instruction::GT), + byte(Instruction::ISZERO), // after this we have 4 <= 8 + 10 + byte(Instruction::DUP1), + byte(Instruction::PUSH1), 0x11, + byte(Instruction::JUMPI), // short-circuit if it is true + byte(Instruction::POP), + byte(Instruction::PUSH1), 0x2, + byte(Instruction::PUSH1), 0x9, + byte(Instruction::EQ), + byte(Instruction::ISZERO), // after this we have 9 != 2 + byte(Instruction::JUMPDEST), + byte(Instruction::PUSH1), 0x1, + byte(Instruction::EQ), + byte(Instruction::ISZERO)}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -309,23 +309,23 @@ BOOST_AUTO_TEST_CASE(arithmetics) " function f(uint y) { var x = ((((((((y ^ 8) & 7) | 6) - 5) + 4) % 3) / 2) * 1); }" "}\n"; bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}, {"test", "f", "x"}}); - bytes expectation({byte(eth::Instruction::PUSH1), 0x1, - byte(eth::Instruction::PUSH1), 0x2, - byte(eth::Instruction::PUSH1), 0x3, - byte(eth::Instruction::PUSH1), 0x4, - byte(eth::Instruction::PUSH1), 0x5, - byte(eth::Instruction::PUSH1), 0x6, - byte(eth::Instruction::PUSH1), 0x7, - byte(eth::Instruction::PUSH1), 0x8, - byte(eth::Instruction::DUP10), - byte(eth::Instruction::XOR), - byte(eth::Instruction::AND), - byte(eth::Instruction::OR), - byte(eth::Instruction::SUB), - byte(eth::Instruction::ADD), - byte(eth::Instruction::MOD), - byte(eth::Instruction::DIV), - byte(eth::Instruction::MUL)}); + bytes expectation({byte(Instruction::PUSH1), 0x1, + byte(Instruction::PUSH1), 0x2, + byte(Instruction::PUSH1), 0x3, + byte(Instruction::PUSH1), 0x4, + byte(Instruction::PUSH1), 0x5, + byte(Instruction::PUSH1), 0x6, + byte(Instruction::PUSH1), 0x7, + byte(Instruction::PUSH1), 0x8, + byte(Instruction::DUP10), + byte(Instruction::XOR), + byte(Instruction::AND), + byte(Instruction::OR), + byte(Instruction::SUB), + byte(Instruction::ADD), + byte(Instruction::MOD), + byte(Instruction::DIV), + byte(Instruction::MUL)}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -336,13 +336,13 @@ BOOST_AUTO_TEST_CASE(unary_operators) "}\n"; bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}, {"test", "f", "x"}}); - bytes expectation({byte(eth::Instruction::PUSH1), 0x2, - byte(eth::Instruction::DUP3), - byte(eth::Instruction::PUSH1), 0x0, - byte(eth::Instruction::SUB), - byte(eth::Instruction::NOT), - byte(eth::Instruction::EQ), - byte(eth::Instruction::ISZERO)}); + bytes expectation({byte(Instruction::PUSH1), 0x2, + byte(Instruction::DUP3), + byte(Instruction::PUSH1), 0x0, + byte(Instruction::SUB), + byte(Instruction::NOT), + byte(Instruction::EQ), + byte(Instruction::ISZERO)}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -354,44 +354,44 @@ BOOST_AUTO_TEST_CASE(unary_inc_dec) bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "a"}, {"test", "f", "x"}}); // Stack: a, x - bytes expectation({byte(eth::Instruction::DUP2), - byte(eth::Instruction::DUP1), - byte(eth::Instruction::PUSH1), 0x1, - byte(eth::Instruction::ADD), + bytes expectation({byte(Instruction::DUP2), + byte(Instruction::DUP1), + byte(Instruction::PUSH1), 0x1, + byte(Instruction::ADD), // Stack here: a x a (a+1) - byte(eth::Instruction::SWAP3), - byte(eth::Instruction::POP), // first ++ + byte(Instruction::SWAP3), + byte(Instruction::POP), // first ++ // Stack here: (a+1) x a - byte(eth::Instruction::DUP3), - byte(eth::Instruction::PUSH1), 0x1, - byte(eth::Instruction::ADD), + byte(Instruction::DUP3), + byte(Instruction::PUSH1), 0x1, + byte(Instruction::ADD), // Stack here: (a+1) x a (a+2) - byte(eth::Instruction::SWAP3), - byte(eth::Instruction::POP), + byte(Instruction::SWAP3), + byte(Instruction::POP), // Stack here: (a+2) x a - byte(eth::Instruction::DUP3), // second ++ - byte(eth::Instruction::XOR), + byte(Instruction::DUP3), // second ++ + byte(Instruction::XOR), // Stack here: (a+2) x a^(a+2) - byte(eth::Instruction::DUP3), - byte(eth::Instruction::DUP1), - byte(eth::Instruction::PUSH1), 0x1, - byte(eth::Instruction::SWAP1), - byte(eth::Instruction::SUB), + byte(Instruction::DUP3), + byte(Instruction::DUP1), + byte(Instruction::PUSH1), 0x1, + byte(Instruction::SWAP1), + byte(Instruction::SUB), // Stack here: (a+2) x a^(a+2) (a+2) (a+1) - byte(eth::Instruction::SWAP4), - byte(eth::Instruction::POP), // first -- - byte(eth::Instruction::XOR), + byte(Instruction::SWAP4), + byte(Instruction::POP), // first -- + byte(Instruction::XOR), // Stack here: (a+1) x a^(a+2)^(a+2) - byte(eth::Instruction::DUP3), - byte(eth::Instruction::PUSH1), 0x1, - byte(eth::Instruction::SWAP1), - byte(eth::Instruction::SUB), + byte(Instruction::DUP3), + byte(Instruction::PUSH1), 0x1, + byte(Instruction::SWAP1), + byte(Instruction::SUB), // Stack here: (a+1) x a^(a+2)^(a+2) a - byte(eth::Instruction::SWAP3), - byte(eth::Instruction::POP), // second ++ + byte(Instruction::SWAP3), + byte(Instruction::POP), // second ++ // Stack here: a x a^(a+2)^(a+2) - byte(eth::Instruction::DUP3), // will change - byte(eth::Instruction::XOR)}); + byte(Instruction::DUP3), // will change + byte(Instruction::XOR)}); // Stack here: a x a^(a+2)^(a+2)^a BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -404,16 +404,16 @@ BOOST_AUTO_TEST_CASE(assignment) bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "a"}, {"test", "f", "b"}}); // Stack: a, b - bytes expectation({byte(eth::Instruction::PUSH1), 0x2, - byte(eth::Instruction::DUP2), - byte(eth::Instruction::DUP4), - byte(eth::Instruction::ADD), + bytes expectation({byte(Instruction::PUSH1), 0x2, + byte(Instruction::DUP2), + byte(Instruction::DUP4), + byte(Instruction::ADD), // Stack here: a b 2 a+b - byte(eth::Instruction::SWAP3), - byte(eth::Instruction::POP), - byte(eth::Instruction::DUP3), + byte(Instruction::SWAP3), + byte(Instruction::POP), + byte(Instruction::DUP3), // Stack here: a+b b 2 a+b - byte(eth::Instruction::MUL)}); + byte(Instruction::MUL)}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -427,26 +427,26 @@ BOOST_AUTO_TEST_CASE(function_call) {{"test", "f", "a"}, {"test", "f", "b"}}); // Stack: a, b - bytes expectation({byte(eth::Instruction::PUSH1), 0x02, - byte(eth::Instruction::PUSH1), 0x0c, - byte(eth::Instruction::PUSH1), 0x01, - byte(eth::Instruction::DUP5), - byte(eth::Instruction::ADD), + bytes expectation({byte(Instruction::PUSH1), 0x02, + byte(Instruction::PUSH1), 0x0c, + byte(Instruction::PUSH1), 0x01, + byte(Instruction::DUP5), + byte(Instruction::ADD), // Stack here: a b 2 <ret label> (a+1) - byte(eth::Instruction::DUP4), - byte(eth::Instruction::PUSH1), 0x13, - byte(eth::Instruction::JUMP), - byte(eth::Instruction::JUMPDEST), + byte(Instruction::DUP4), + byte(Instruction::PUSH1), 0x13, + byte(Instruction::JUMP), + byte(Instruction::JUMPDEST), // Stack here: a b 2 g(a+1, b) - byte(eth::Instruction::MUL), + byte(Instruction::MUL), // Stack here: a b g(a+1, b)*2 - byte(eth::Instruction::DUP3), - byte(eth::Instruction::ADD), + byte(Instruction::DUP3), + byte(Instruction::ADD), // Stack here: a b a+g(a+1, b)*2 - byte(eth::Instruction::SWAP2), - byte(eth::Instruction::POP), - byte(eth::Instruction::DUP2), - byte(eth::Instruction::JUMPDEST)}); + byte(Instruction::SWAP2), + byte(Instruction::POP), + byte(Instruction::DUP2), + byte(Instruction::JUMPDEST)}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -457,7 +457,7 @@ BOOST_AUTO_TEST_CASE(negative_literals_8bits) "}\n"; bytes code = compileFirstExpression(sourceCode); - bytes expectation(bytes({byte(eth::Instruction::PUSH32)}) + bytes(31, 0xff) + bytes(1, 0x80)); + bytes expectation(bytes({byte(Instruction::PUSH32)}) + bytes(31, 0xff) + bytes(1, 0x80)); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -468,7 +468,7 @@ BOOST_AUTO_TEST_CASE(negative_literals_16bits) "}\n"; bytes code = compileFirstExpression(sourceCode); - bytes expectation(bytes({byte(eth::Instruction::PUSH32)}) + bytes(30, 0xff) + bytes{0xf5, 0x43}); + bytes expectation(bytes({byte(Instruction::PUSH32)}) + bytes(30, 0xff) + bytes{0xf5, 0x43}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -481,7 +481,7 @@ BOOST_AUTO_TEST_CASE(intermediately_overflowing_literals) "}\n"; bytes code = compileFirstExpression(sourceCode); - bytes expectation(bytes({byte(eth::Instruction::PUSH1), 0xbf})); + bytes expectation(bytes({byte(Instruction::PUSH1), 0xbf})); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -495,8 +495,8 @@ BOOST_AUTO_TEST_CASE(blockhash) bytes code = compileFirstExpression(sourceCode, {}, {}, {make_shared<MagicVariableDeclaration>("block", make_shared<MagicType>(MagicType::Kind::Block))}); - bytes expectation({byte(eth::Instruction::PUSH1), 0x03, - byte(eth::Instruction::BLOCKHASH)}); + bytes expectation({byte(Instruction::PUSH1), 0x03, + byte(Instruction::BLOCKHASH)}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index 6aa90973..d48c7648 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -58,11 +58,11 @@ public: m_optimize = true; bytes optimizedBytecode = compileAndRun(_sourceCode, _value, _contractName); size_t nonOptimizedSize = 0; - eth::eachInstruction(nonOptimizedBytecode, [&](Instruction, u256 const&) { + solidity::eachInstruction(nonOptimizedBytecode, [&](Instruction, u256 const&) { nonOptimizedSize++; }); size_t optimizedSize = 0; - eth::eachInstruction(optimizedBytecode, [&](Instruction, u256 const&) { + solidity::eachInstruction(optimizedBytecode, [&](Instruction, u256 const&) { optimizedSize++; }); BOOST_CHECK_MESSAGE( @@ -308,8 +308,8 @@ BOOST_AUTO_TEST_CASE(retain_information_in_branches) m_optimize = true; bytes optimizedBytecode = compileAndRun(sourceCode, 0, "c"); size_t numSHA3s = 0; - eth::eachInstruction(optimizedBytecode, [&](Instruction _instr, u256 const&) { - if (_instr == eth::Instruction::SHA3) + eachInstruction(optimizedBytecode, [&](Instruction _instr, u256 const&) { + if (_instr == Instruction::SHA3) numSHA3s++; }); BOOST_CHECK_EQUAL(1, numSHA3s); @@ -351,8 +351,8 @@ BOOST_AUTO_TEST_CASE(store_tags_as_unions) m_optimize = true; bytes optimizedBytecode = compileAndRun(sourceCode, 0, "test"); size_t numSHA3s = 0; - eth::eachInstruction(optimizedBytecode, [&](Instruction _instr, u256 const&) { - if (_instr == eth::Instruction::SHA3) + eachInstruction(optimizedBytecode, [&](Instruction _instr, u256 const&) { + if (_instr == Instruction::SHA3) numSHA3s++; }); // TEST DISABLED UNTIL 93693404 IS IMPLEMENTED @@ -1071,16 +1071,16 @@ BOOST_AUTO_TEST_CASE(block_deduplicator) AssemblyItem(PushTag, 1), AssemblyItem(PushTag, 3), u256(6), - eth::Instruction::SWAP3, - eth::Instruction::JUMP, + Instruction::SWAP3, + Instruction::JUMP, AssemblyItem(Tag, 1), u256(6), - eth::Instruction::SWAP3, - eth::Instruction::JUMP, + Instruction::SWAP3, + Instruction::JUMP, AssemblyItem(Tag, 2), u256(6), - eth::Instruction::SWAP3, - eth::Instruction::JUMP, + Instruction::SWAP3, + Instruction::JUMP, AssemblyItem(Tag, 3) }; BlockDeduplicator dedup(input); @@ -1097,23 +1097,23 @@ BOOST_AUTO_TEST_CASE(block_deduplicator_loops) { AssemblyItems input{ u256(0), - eth::Instruction::SLOAD, + Instruction::SLOAD, AssemblyItem(PushTag, 1), AssemblyItem(PushTag, 2), - eth::Instruction::JUMPI, - eth::Instruction::JUMP, + Instruction::JUMPI, + Instruction::JUMP, AssemblyItem(Tag, 1), u256(5), u256(6), - eth::Instruction::SSTORE, + Instruction::SSTORE, AssemblyItem(PushTag, 1), - eth::Instruction::JUMP, + Instruction::JUMP, AssemblyItem(Tag, 2), u256(5), u256(6), - eth::Instruction::SSTORE, + Instruction::SSTORE, AssemblyItem(PushTag, 2), - eth::Instruction::JUMP, + Instruction::JUMP, }; BlockDeduplicator dedup(input); dedup.deduplicate(); |