diff options
author | chriseth <chris@ethereum.org> | 2017-02-01 01:29:51 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-02-01 01:29:51 +0800 |
commit | 364da425d3116a4b85863df39a1864340861d71e (patch) | |
tree | 521a52c3f8182cd6a054f148bd649c8b6b0e2af9 /libevmasm | |
parent | 60cc1668517f56ce6ca8225555472e7a27eab8b0 (diff) | |
parent | 7b18c9df1dfa0076566bfa1e4a3bc5e5ba9c8594 (diff) | |
download | dexon-solidity-364da425d3116a4b85863df39a1864340861d71e.tar dexon-solidity-364da425d3116a4b85863df39a1864340861d71e.tar.gz dexon-solidity-364da425d3116a4b85863df39a1864340861d71e.tar.bz2 dexon-solidity-364da425d3116a4b85863df39a1864340861d71e.tar.lz dexon-solidity-364da425d3116a4b85863df39a1864340861d71e.tar.xz dexon-solidity-364da425d3116a4b85863df39a1864340861d71e.tar.zst dexon-solidity-364da425d3116a4b85863df39a1864340861d71e.zip |
Merge pull request #1622 from ethereum/develop
Solidity version 0.4.9
Diffstat (limited to 'libevmasm')
-rw-r--r-- | libevmasm/Assembly.cpp | 96 | ||||
-rw-r--r-- | libevmasm/Assembly.h | 1 | ||||
-rw-r--r-- | libevmasm/AssemblyItem.cpp | 12 | ||||
-rw-r--r-- | libevmasm/AssemblyItem.h | 4 | ||||
-rw-r--r-- | libevmasm/GasMeter.cpp | 16 | ||||
-rw-r--r-- | libevmasm/Instruction.cpp | 264 | ||||
-rw-r--r-- | libevmasm/Instruction.h | 24 | ||||
-rw-r--r-- | libevmasm/LinkerObject.cpp | 29 | ||||
-rw-r--r-- | libevmasm/LinkerObject.h | 6 | ||||
-rw-r--r-- | libevmasm/PeepholeOptimiser.cpp | 1 | ||||
-rw-r--r-- | libevmasm/SemanticInformation.cpp | 1 |
11 files changed, 280 insertions, 174 deletions
diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 845abfd4..b7859c1f 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -40,7 +40,7 @@ void Assembly::append(Assembly const& _a) auto newDeposit = m_deposit + _a.deposit(); for (AssemblyItem i: _a.m_items) { - if (i.type() == Tag || i.type() == PushTag) + if (i.type() == Tag || (i.type() == PushTag && i != errorTag())) i.setData(i.data() + m_usedTags); else if (i.type() == PushSub || i.type() == PushSubSize) i.setData(i.data() + m_subs.size()); @@ -94,7 +94,10 @@ unsigned Assembly::bytesRequired(unsigned subTagSize) const } } -string Assembly::locationFromSources(StringMap const& _sourceCodes, SourceLocation const& _location) const +namespace +{ + +string locationFromSources(StringMap const& _sourceCodes, SourceLocation const& _location) { if (_location.isEmpty() || _sourceCodes.empty() || _location.start >= _location.end || _location.start < 0) return ""; @@ -115,27 +118,92 @@ string Assembly::locationFromSources(StringMap const& _sourceCodes, SourceLocati return cut; } -ostream& Assembly::streamAsm(ostream& _out, string const& _prefix, StringMap const& _sourceCodes) const +class Functionalizer { - for (size_t i = 0; i < m_items.size(); ++i) +public: + Functionalizer (ostream& _out, string const& _prefix, StringMap const& _sourceCodes): + m_out(_out), m_prefix(_prefix), m_sourceCodes(_sourceCodes) + {} + + void feed(AssemblyItem const& _item) { - AssemblyItem const& item = m_items[i]; - if (!item.location().isEmpty() && (i == 0 || m_items[i - 1].location() != item.location())) + if (!_item.location().isEmpty() && _item.location() != m_location) { - _out << _prefix << " /*"; - if (item.location().sourceName) - _out << " \"" + *item.location().sourceName + "\""; - if (!item.location().isEmpty()) - _out << ":" << to_string(item.location().start) + ":" + to_string(item.location().end); - _out << " */" << endl; + flush(); + printLocation(); + m_location = _item.location(); } - _out << _prefix << (item.type() == Tag ? "" : " ") << item.toAssemblyText() << endl; + if (!( + _item.canBeFunctional() && + _item.returnValues() <= 1 && + _item.arguments() <= int(m_pending.size()) + )) + { + flush(); + m_out << m_prefix << (_item.type() == Tag ? "" : " ") << _item.toAssemblyText() << endl; + return; + } + string expression = _item.toAssemblyText(); + if (_item.arguments() > 0) + { + expression += "("; + for (int i = 0; i < _item.arguments(); ++i) + { + expression += m_pending.back(); + m_pending.pop_back(); + if (i + 1 < _item.arguments()) + expression += ", "; + } + expression += ")"; + } + + m_pending.push_back(expression); + if (_item.returnValues() != 1) + flush(); + } + + void flush() + { + for (string const& expression: m_pending) + m_out << m_prefix << " " << expression << endl; + m_pending.clear(); + } + + void printLocation() + { + if (!m_location.sourceName && m_location.isEmpty()) + return; + m_out << m_prefix << " /*"; + if (m_location.sourceName) + m_out << " \"" + *m_location.sourceName + "\""; + if (!m_location.isEmpty()) + m_out << ":" << to_string(m_location.start) + ":" + to_string(m_location.end); + m_out << " " << locationFromSources(m_sourceCodes, m_location); + m_out << " */" << endl; } +private: + strings m_pending; + SourceLocation m_location; + + ostream& m_out; + string const& m_prefix; + StringMap const& m_sourceCodes; +}; + +} + +ostream& Assembly::streamAsm(ostream& _out, string const& _prefix, StringMap const& _sourceCodes) const +{ + Functionalizer f(_out, _prefix, _sourceCodes); + + for (auto const& i: m_items) + f.feed(i); + f.flush(); + if (!m_data.empty() || !m_subs.empty()) { _out << _prefix << "stop" << endl; - Json::Value data; for (auto const& i: m_data) assertThrow(u256(i.first) < m_subs.size(), AssemblyException, "Data not yet implemented."); diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 9e7f9f7b..528c9e74 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -118,7 +118,6 @@ protected: /// returns the replaced tags. std::map<u256, u256> optimiseInternal(bool _enable, bool _isCreation, size_t _runs); - std::string locationFromSources(StringMap const& _sourceCodes, SourceLocation const& _location) const; void donePath() { if (m_totalDeposit != INT_MAX && m_totalDeposit != m_deposit) BOOST_THROW_EXCEPTION(InvalidDeposit()); } unsigned bytesRequired(unsigned subTagSize) const; diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index 6c7d5425..26d9fded 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -76,12 +76,20 @@ unsigned AssemblyItem::bytesRequired(unsigned _addressLength) const BOOST_THROW_EXCEPTION(InvalidOpcode()); } -int AssemblyItem::deposit() const +int AssemblyItem::arguments() const +{ + if (type() == Operation) + return instructionInfo(instruction()).args; + else + return 0; +} + +int AssemblyItem::returnValues() const { switch (m_type) { case Operation: - return instructionInfo(instruction()).ret - instructionInfo(instruction()).args; + return instructionInfo(instruction()).ret; case Push: case PushString: case PushTag: diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index 002b3c87..464368fb 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -116,7 +116,9 @@ public: /// @returns an upper bound for the number of bytes required by this item, assuming that /// the value of a jump tag takes @a _addressLength bytes. unsigned bytesRequired(unsigned _addressLength) const; - int deposit() const; + int arguments() const; + int returnValues() const; + int deposit() const { return returnValues() - arguments(); } /// @returns true if the assembly item can be used in a functional context. bool canBeFunctional() const; diff --git a/libevmasm/GasMeter.cpp b/libevmasm/GasMeter.cpp index 21db3565..462c09dd 100644 --- a/libevmasm/GasMeter.cpp +++ b/libevmasm/GasMeter.cpp @@ -223,14 +223,14 @@ unsigned GasMeter::runGas(Instruction _instruction) switch (instructionInfo(_instruction).gasPriceTier) { - case 0: return GasCosts::tier0Gas; - case 1: return GasCosts::tier1Gas; - case 2: return GasCosts::tier2Gas; - case 3: return GasCosts::tier3Gas; - case 4: return GasCosts::tier4Gas; - case 5: return GasCosts::tier5Gas; - case 6: return GasCosts::tier6Gas; - case 7: return GasCosts::tier7Gas; + case Tier::Zero: return GasCosts::tier0Gas; + case Tier::Base: return GasCosts::tier1Gas; + case Tier::VeryLow: return GasCosts::tier2Gas; + case Tier::Low: return GasCosts::tier3Gas; + case Tier::Mid: return GasCosts::tier4Gas; + case Tier::High: return GasCosts::tier5Gas; + case Tier::Ext: return GasCosts::tier6Gas; + case Tier::Special: return GasCosts::tier7Gas; default: break; } assertThrow(false, OptimizerException, "Invalid gas tier."); diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index 5244a91f..b0f063da 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -159,141 +159,143 @@ const std::map<std::string, Instruction> dev::solidity::c_instructions = { "CALLCODE", Instruction::CALLCODE }, { "RETURN", Instruction::RETURN }, { "DELEGATECALL", Instruction::DELEGATECALL }, + { "INVALID", Instruction::INVALID }, { "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 } } + { Instruction::STOP, { "STOP", 0, 0, 0, true, Tier::Zero } }, + { Instruction::ADD, { "ADD", 0, 2, 1, false, Tier::VeryLow } }, + { Instruction::SUB, { "SUB", 0, 2, 1, false, Tier::VeryLow } }, + { Instruction::MUL, { "MUL", 0, 2, 1, false, Tier::Low } }, + { Instruction::DIV, { "DIV", 0, 2, 1, false, Tier::Low } }, + { Instruction::SDIV, { "SDIV", 0, 2, 1, false, Tier::Low } }, + { Instruction::MOD, { "MOD", 0, 2, 1, false, Tier::Low } }, + { Instruction::SMOD, { "SMOD", 0, 2, 1, false, Tier::Low } }, + { Instruction::EXP, { "EXP", 0, 2, 1, false, Tier::Special } }, + { Instruction::NOT, { "NOT", 0, 1, 1, false, Tier::VeryLow } }, + { Instruction::LT, { "LT", 0, 2, 1, false, Tier::VeryLow } }, + { Instruction::GT, { "GT", 0, 2, 1, false, Tier::VeryLow } }, + { Instruction::SLT, { "SLT", 0, 2, 1, false, Tier::VeryLow } }, + { Instruction::SGT, { "SGT", 0, 2, 1, false, Tier::VeryLow } }, + { Instruction::EQ, { "EQ", 0, 2, 1, false, Tier::VeryLow } }, + { Instruction::ISZERO, { "ISZERO", 0, 1, 1, false, Tier::VeryLow } }, + { Instruction::AND, { "AND", 0, 2, 1, false, Tier::VeryLow } }, + { Instruction::OR, { "OR", 0, 2, 1, false, Tier::VeryLow } }, + { Instruction::XOR, { "XOR", 0, 2, 1, false, Tier::VeryLow } }, + { Instruction::BYTE, { "BYTE", 0, 2, 1, false, Tier::VeryLow } }, + { Instruction::ADDMOD, { "ADDMOD", 0, 3, 1, false, Tier::Mid } }, + { Instruction::MULMOD, { "MULMOD", 0, 3, 1, false, Tier::Mid } }, + { Instruction::SIGNEXTEND, { "SIGNEXTEND", 0, 2, 1, false, Tier::Low } }, + { Instruction::SHA3, { "SHA3", 0, 2, 1, false, Tier::Special } }, + { Instruction::ADDRESS, { "ADDRESS", 0, 0, 1, false, Tier::Base } }, + { Instruction::BALANCE, { "BALANCE", 0, 1, 1, false, Tier::Ext } }, + { Instruction::ORIGIN, { "ORIGIN", 0, 0, 1, false, Tier::Base } }, + { Instruction::CALLER, { "CALLER", 0, 0, 1, false, Tier::Base } }, + { Instruction::CALLVALUE, { "CALLVALUE", 0, 0, 1, false, Tier::Base } }, + { Instruction::CALLDATALOAD,{ "CALLDATALOAD", 0, 1, 1, false, Tier::VeryLow } }, + { Instruction::CALLDATASIZE,{ "CALLDATASIZE", 0, 0, 1, false, Tier::Base } }, + { Instruction::CALLDATACOPY,{ "CALLDATACOPY", 0, 3, 0, true, Tier::VeryLow } }, + { Instruction::CODESIZE, { "CODESIZE", 0, 0, 1, false, Tier::Base } }, + { Instruction::CODECOPY, { "CODECOPY", 0, 3, 0, true, Tier::VeryLow } }, + { Instruction::GASPRICE, { "GASPRICE", 0, 0, 1, false, Tier::Base } }, + { Instruction::EXTCODESIZE, { "EXTCODESIZE", 0, 1, 1, false, Tier::Ext } }, + { Instruction::EXTCODECOPY, { "EXTCODECOPY", 0, 4, 0, true, Tier::Ext } }, + { Instruction::BLOCKHASH, { "BLOCKHASH", 0, 1, 1, false, Tier::Ext } }, + { Instruction::COINBASE, { "COINBASE", 0, 0, 1, false, Tier::Base } }, + { Instruction::TIMESTAMP, { "TIMESTAMP", 0, 0, 1, false, Tier::Base } }, + { Instruction::NUMBER, { "NUMBER", 0, 0, 1, false, Tier::Base } }, + { Instruction::DIFFICULTY, { "DIFFICULTY", 0, 0, 1, false, Tier::Base } }, + { Instruction::GASLIMIT, { "GASLIMIT", 0, 0, 1, false, Tier::Base } }, + { Instruction::POP, { "POP", 0, 1, 0, false, Tier::Base } }, + { Instruction::MLOAD, { "MLOAD", 0, 1, 1, false, Tier::VeryLow } }, + { Instruction::MSTORE, { "MSTORE", 0, 2, 0, true, Tier::VeryLow } }, + { Instruction::MSTORE8, { "MSTORE8", 0, 2, 0, true, Tier::VeryLow } }, + { Instruction::SLOAD, { "SLOAD", 0, 1, 1, false, Tier::Special } }, + { Instruction::SSTORE, { "SSTORE", 0, 2, 0, true, Tier::Special } }, + { Instruction::JUMP, { "JUMP", 0, 1, 0, true, Tier::Mid } }, + { Instruction::JUMPI, { "JUMPI", 0, 2, 0, true, Tier::High } }, + { Instruction::PC, { "PC", 0, 0, 1, false, Tier::Base } }, + { Instruction::MSIZE, { "MSIZE", 0, 0, 1, false, Tier::Base } }, + { Instruction::GAS, { "GAS", 0, 0, 1, false, Tier::Base } }, + { Instruction::JUMPDEST, { "JUMPDEST", 0, 0, 0, true, Tier::Special } }, + { Instruction::PUSH1, { "PUSH1", 1, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH2, { "PUSH2", 2, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH3, { "PUSH3", 3, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH4, { "PUSH4", 4, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH5, { "PUSH5", 5, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH6, { "PUSH6", 6, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH7, { "PUSH7", 7, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH8, { "PUSH8", 8, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH9, { "PUSH9", 9, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH10, { "PUSH10", 10, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH11, { "PUSH11", 11, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH12, { "PUSH12", 12, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH13, { "PUSH13", 13, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH14, { "PUSH14", 14, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH15, { "PUSH15", 15, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH16, { "PUSH16", 16, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH17, { "PUSH17", 17, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH18, { "PUSH18", 18, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH19, { "PUSH19", 19, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH20, { "PUSH20", 20, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH21, { "PUSH21", 21, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH22, { "PUSH22", 22, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH23, { "PUSH23", 23, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH24, { "PUSH24", 24, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH25, { "PUSH25", 25, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH26, { "PUSH26", 26, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH27, { "PUSH27", 27, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH28, { "PUSH28", 28, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH29, { "PUSH29", 29, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH30, { "PUSH30", 30, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH31, { "PUSH31", 31, 0, 1, false, Tier::VeryLow } }, + { Instruction::PUSH32, { "PUSH32", 32, 0, 1, false, Tier::VeryLow } }, + { Instruction::DUP1, { "DUP1", 0, 1, 2, false, Tier::VeryLow } }, + { Instruction::DUP2, { "DUP2", 0, 2, 3, false, Tier::VeryLow } }, + { Instruction::DUP3, { "DUP3", 0, 3, 4, false, Tier::VeryLow } }, + { Instruction::DUP4, { "DUP4", 0, 4, 5, false, Tier::VeryLow } }, + { Instruction::DUP5, { "DUP5", 0, 5, 6, false, Tier::VeryLow } }, + { Instruction::DUP6, { "DUP6", 0, 6, 7, false, Tier::VeryLow } }, + { Instruction::DUP7, { "DUP7", 0, 7, 8, false, Tier::VeryLow } }, + { Instruction::DUP8, { "DUP8", 0, 8, 9, false, Tier::VeryLow } }, + { Instruction::DUP9, { "DUP9", 0, 9, 10, false, Tier::VeryLow } }, + { Instruction::DUP10, { "DUP10", 0, 10, 11, false, Tier::VeryLow } }, + { Instruction::DUP11, { "DUP11", 0, 11, 12, false, Tier::VeryLow } }, + { Instruction::DUP12, { "DUP12", 0, 12, 13, false, Tier::VeryLow } }, + { Instruction::DUP13, { "DUP13", 0, 13, 14, false, Tier::VeryLow } }, + { Instruction::DUP14, { "DUP14", 0, 14, 15, false, Tier::VeryLow } }, + { Instruction::DUP15, { "DUP15", 0, 15, 16, false, Tier::VeryLow } }, + { Instruction::DUP16, { "DUP16", 0, 16, 17, false, Tier::VeryLow } }, + { Instruction::SWAP1, { "SWAP1", 0, 2, 2, false, Tier::VeryLow } }, + { Instruction::SWAP2, { "SWAP2", 0, 3, 3, false, Tier::VeryLow } }, + { Instruction::SWAP3, { "SWAP3", 0, 4, 4, false, Tier::VeryLow } }, + { Instruction::SWAP4, { "SWAP4", 0, 5, 5, false, Tier::VeryLow } }, + { Instruction::SWAP5, { "SWAP5", 0, 6, 6, false, Tier::VeryLow } }, + { Instruction::SWAP6, { "SWAP6", 0, 7, 7, false, Tier::VeryLow } }, + { Instruction::SWAP7, { "SWAP7", 0, 8, 8, false, Tier::VeryLow } }, + { Instruction::SWAP8, { "SWAP8", 0, 9, 9, false, Tier::VeryLow } }, + { Instruction::SWAP9, { "SWAP9", 0, 10, 10, false, Tier::VeryLow } }, + { Instruction::SWAP10, { "SWAP10", 0, 11, 11, false, Tier::VeryLow } }, + { Instruction::SWAP11, { "SWAP11", 0, 12, 12, false, Tier::VeryLow } }, + { Instruction::SWAP12, { "SWAP12", 0, 13, 13, false, Tier::VeryLow } }, + { Instruction::SWAP13, { "SWAP13", 0, 14, 14, false, Tier::VeryLow } }, + { Instruction::SWAP14, { "SWAP14", 0, 15, 15, false, Tier::VeryLow } }, + { Instruction::SWAP15, { "SWAP15", 0, 16, 16, false, Tier::VeryLow } }, + { Instruction::SWAP16, { "SWAP16", 0, 17, 17, false, Tier::VeryLow } }, + { Instruction::LOG0, { "LOG0", 0, 2, 0, true, Tier::Special } }, + { Instruction::LOG1, { "LOG1", 0, 3, 0, true, Tier::Special } }, + { Instruction::LOG2, { "LOG2", 0, 4, 0, true, Tier::Special } }, + { Instruction::LOG3, { "LOG3", 0, 5, 0, true, Tier::Special } }, + { Instruction::LOG4, { "LOG4", 0, 6, 0, true, Tier::Special } }, + { Instruction::CREATE, { "CREATE", 0, 3, 1, true, Tier::Special } }, + { Instruction::CALL, { "CALL", 0, 7, 1, true, Tier::Special } }, + { Instruction::CALLCODE, { "CALLCODE", 0, 7, 1, true, Tier::Special } }, + { Instruction::RETURN, { "RETURN", 0, 2, 0, true, Tier::Zero } }, + { Instruction::DELEGATECALL,{ "DELEGATECALL", 0, 6, 1, true, Tier::Special } }, + { Instruction::INVALID, { "INVALID", 0, 0, 0, true, Tier::Zero } }, + { Instruction::SUICIDE, { "SUICIDE", 0, 1, 0, true, Tier::Zero } } }; void dev::solidity::eachInstruction( @@ -343,7 +345,7 @@ InstructionInfo dev::solidity::instructionInfo(Instruction _inst) } catch (...) { - return InstructionInfo({"<INVALID_INSTRUCTION: " + toString((unsigned)_inst) + ">", 0, 0, 0, false, InvalidTier}); + return InstructionInfo({"<INVALID_INSTRUCTION: " + toString((unsigned)_inst) + ">", 0, 0, 0, false, Tier::Invalid}); } } diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index c7fad1c5..a8a72234 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -176,6 +176,8 @@ enum class Instruction: uint8_t 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 + + INVALID = 0xfe, ///< invalid instruction for expressing runtime errors (e.g., division-by-zero) SUICIDE = 0xff ///< halt execution and register account for later deletion }; @@ -225,17 +227,17 @@ inline Instruction logInstruction(unsigned _number) return Instruction(unsigned(Instruction::LOG0) + _number); } -enum Tier +enum class Tier : unsigned { - 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. + Zero = 0, // 0, Zero + Base, // 2, Quick + VeryLow, // 3, Fastest + Low, // 5, Fast + Mid, // 8, Mid + High, // 10, Slow + Ext, // 20, Ext + Special, // multiparam or otherwise special + Invalid // Invalid. }; /// Information structure for a particular instruction. @@ -246,7 +248,7 @@ struct InstructionInfo 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. + Tier gasPriceTier; ///< Tier for gas pricing. }; /// Information on all the instructions. diff --git a/libevmasm/LinkerObject.cpp b/libevmasm/LinkerObject.cpp index 93e4067c..06607089 100644 --- a/libevmasm/LinkerObject.cpp +++ b/libevmasm/LinkerObject.cpp @@ -37,13 +37,10 @@ void LinkerObject::link(map<string, h160> const& _libraryAddresses) { std::map<size_t, std::string> remainingRefs; for (auto const& linkRef: linkReferences) - { - auto it = _libraryAddresses.find(linkRef.second); - if (it == _libraryAddresses.end()) - remainingRefs.insert(linkRef); + if (h160 const* address = matchLibrary(linkRef.second, _libraryAddresses)) + address->ref().copyTo(ref(bytecode).cropped(linkRef.first, 20)); else - it->second.ref().copyTo(ref(bytecode).cropped(linkRef.first, 20)); - } + remainingRefs.insert(linkRef); linkReferences.swap(remainingRefs); } @@ -60,3 +57,23 @@ string LinkerObject::toHex() const } return hex; } + +h160 const* +LinkerObject::matchLibrary( + string const& _linkRefName, + map<string, h160> const& _libraryAddresses +) +{ + auto it = _libraryAddresses.find(_linkRefName); + if (it != _libraryAddresses.end()) + return &it->second; + // If the user did not supply a fully qualified library name, + // try to match only the simple libary name + size_t colon = _linkRefName.find(':'); + if (colon == string::npos) + return nullptr; + it = _libraryAddresses.find(_linkRefName.substr(colon + 1)); + if (it != _libraryAddresses.end()) + return &it->second; + return nullptr; +} diff --git a/libevmasm/LinkerObject.h b/libevmasm/LinkerObject.h index d3ec3e97..152487b4 100644 --- a/libevmasm/LinkerObject.h +++ b/libevmasm/LinkerObject.h @@ -49,6 +49,12 @@ struct LinkerObject /// @returns a hex representation of the bytecode of the given object, replacing unlinked /// addresses by placeholders. std::string toHex() const; + +private: + static h160 const* matchLibrary( + std::string const& _linkRefName, + std::map<std::string, h160> const& _libraryAddresses + ); }; } diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index 923ffa67..528ce1c4 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -199,6 +199,7 @@ struct UnreachableCode it[0] != Instruction::JUMP && it[0] != Instruction::RETURN && it[0] != Instruction::STOP && + it[0] != Instruction::INVALID && it[0] != Instruction::SUICIDE ) return false; diff --git a/libevmasm/SemanticInformation.cpp b/libevmasm/SemanticInformation.cpp index 23a00d95..d3ce4735 100644 --- a/libevmasm/SemanticInformation.cpp +++ b/libevmasm/SemanticInformation.cpp @@ -118,6 +118,7 @@ bool SemanticInformation::altersControlFlow(AssemblyItem const& _item) case Instruction::RETURN: case Instruction::SUICIDE: case Instruction::STOP: + case Instruction::INVALID: return true; default: return false; |