diff options
Diffstat (limited to 'libevmasm')
| -rw-r--r-- | libevmasm/Assembly.cpp | 19 | ||||
| -rw-r--r-- | libevmasm/Assembly.h | 11 | ||||
| -rw-r--r-- | libevmasm/AssemblyItem.h | 8 | ||||
| -rw-r--r-- | libevmasm/ConstantOptimiser.cpp | 5 | ||||
| -rw-r--r-- | libevmasm/PeepholeOptimiser.cpp | 23 |
5 files changed, 46 insertions, 20 deletions
diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index ea061a30..92a4c2a4 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 && i != errorTag())) + if (i.type() == Tag || i.type() == PushTag) i.setData(i.data() + m_usedTags); else if (i.type() == PushSub || i.type() == PushSubSize) i.setData(i.data() + m_subs.size()); @@ -72,13 +72,6 @@ void Assembly::append(Assembly const& _a, int _deposit) } } -string Assembly::out() const -{ - stringstream ret; - stream(ret); - return ret.str(); -} - unsigned Assembly::bytesRequired(unsigned subTagSize) const { for (unsigned tagSize = subTagSize; true; ++tagSize) @@ -216,6 +209,9 @@ ostream& Assembly::streamAsm(ostream& _out, string const& _prefix, StringMap con } } + if (m_auxiliaryData.size() > 0) + _out << endl << _prefix << "auxdata: 0x" << toHex(m_auxiliaryData) << endl; + return _out; } @@ -315,8 +311,13 @@ Json::Value Assembly::streamAsmJson(ostream& _out, StringMap const& _sourceCodes data[hexStr.str()] = m_subs[i]->stream(_out, "", _sourceCodes, true); } root[".data"] = data; - _out << root; } + + if (m_auxiliaryData.size() > 0) + root[".auxdata"] = toHex(m_auxiliaryData); + + _out << root; + return root; } diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 528c9e74..13d82e1a 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -69,7 +69,13 @@ public: 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); } + + /// Adds a subroutine to the code (in the data section) and pushes its size (via a tag) + /// on the stack. @returns the pushsub assembly item. + AssemblyItem appendSubroutine(AssemblyPointer const& _assembly) { auto sub = newSub(_assembly); append(newPushSubSize(size_t(sub.data()))); return sub; } + void pushSubroutineSize(size_t _subRoutine) { append(newPushSubSize(_subRoutine)); } + /// Pushes the offset of the subroutine. + void pushSubroutineOffset(size_t _subRoutine) { append(AssemblyItem(PushSub, _subRoutine)); } /// Appends @a _data literally to the very end of the bytecode. void appendAuxiliaryDataToEnd(bytes const& _data) { m_auxiliaryData += _data; } @@ -85,10 +91,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(solidity::Instruction::POP); } - void injectStart(AssemblyItem const& _i); - std::string out() const; int deposit() const { return m_deposit; } void adjustDeposit(int _adjustment) { m_deposit += _adjustment; if (asserts(m_deposit >= 0)) BOOST_THROW_EXCEPTION(InvalidDeposit()); } void setDeposit(int _deposit) { m_deposit = _deposit; if (asserts(m_deposit >= 0)) BOOST_THROW_EXCEPTION(InvalidDeposit()); } diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index 464368fb..d38db927 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -148,6 +148,14 @@ private: using AssemblyItems = std::vector<AssemblyItem>; +inline size_t bytesRequired(AssemblyItems const& _items, size_t _addressLength) +{ + size_t size = 0; + for (AssemblyItem const& item: _items) + size += item.bytesRequired(_addressLength); + return size; +} + std::ostream& operator<<(std::ostream& _out, AssemblyItem const& _item); inline std::ostream& operator<<(std::ostream& _out, AssemblyItems const& _items) { diff --git a/libevmasm/ConstantOptimiser.cpp b/libevmasm/ConstantOptimiser.cpp index 0c093ebf..2ecbfa7f 100644 --- a/libevmasm/ConstantOptimiser.cpp +++ b/libevmasm/ConstantOptimiser.cpp @@ -99,10 +99,7 @@ bigint ConstantOptimisationMethod::dataGas(bytes const& _data) const size_t ConstantOptimisationMethod::bytesRequired(AssemblyItems const& _items) { - size_t size = 0; - for (AssemblyItem const& item: _items) - size += item.bytesRequired(3); // assume 3 byte addresses - return size; + return eth::bytesRequired(_items, 3); // assume 3 byte addresses } void ConstantOptimisationMethod::replaceConstants( diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index 6c92d76b..e94a8ba4 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -136,6 +136,21 @@ struct DoubleSwap: SimplePeepholeOptimizerMethod<DoubleSwap, 2> } }; +struct DoublePush: SimplePeepholeOptimizerMethod<DoublePush, 2> +{ + static bool applySimple(AssemblyItem const& _push1, AssemblyItem const& _push2, std::back_insert_iterator<AssemblyItems> _out) + { + if (_push1.type() == Push && _push2.type() == Push && _push1.data() == _push2.data()) + { + *_out = _push1; + *_out = {Instruction::DUP1, _push2.location()}; + return true; + } + else + return false; + } +}; + struct JumpToNext: SimplePeepholeOptimizerMethod<JumpToNext, 3> { static size_t applySimple( @@ -235,13 +250,15 @@ bool PeepholeOptimiser::optimise() { OptimiserState state {m_items, 0, std::back_inserter(m_optimisedItems)}; while (state.i < m_items.size()) - applyMethods(state, PushPop(), OpPop(), DoubleSwap(), JumpToNext(), UnreachableCode(), TagConjunctions(), Identity()); - if (m_optimisedItems.size() < m_items.size()) + applyMethods(state, PushPop(), OpPop(), DoublePush(), DoubleSwap(), JumpToNext(), UnreachableCode(), TagConjunctions(), Identity()); + if (m_optimisedItems.size() < m_items.size() || ( + m_optimisedItems.size() == m_items.size() && + eth::bytesRequired(m_optimisedItems, 3) < eth::bytesRequired(m_items, 3) + )) { m_items = std::move(m_optimisedItems); return true; } else return false; - } |
