diff options
author | Alex Beregszaszi <alex@rtfs.hu> | 2017-07-28 06:28:49 +0800 |
---|---|---|
committer | Alex Beregszaszi <alex@rtfs.hu> | 2017-08-25 17:42:36 +0800 |
commit | 70e89a5dac5d2a1c4ec01f6ccbcf660809c81c4c (patch) | |
tree | f3669a9ccf5e009bfd706463f60561d2ad61da09 /libevmasm/JumpdestRemover.cpp | |
parent | de5c702cc690dbfc51d9e7203328d81c6ede13b4 (diff) | |
download | dexon-solidity-70e89a5dac5d2a1c4ec01f6ccbcf660809c81c4c.tar.gz dexon-solidity-70e89a5dac5d2a1c4ec01f6ccbcf660809c81c4c.tar.zst dexon-solidity-70e89a5dac5d2a1c4ec01f6ccbcf660809c81c4c.zip |
Introduce JumpdestRemover optimisation step
Diffstat (limited to 'libevmasm/JumpdestRemover.cpp')
-rw-r--r-- | libevmasm/JumpdestRemover.cpp | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/libevmasm/JumpdestRemover.cpp b/libevmasm/JumpdestRemover.cpp new file mode 100644 index 00000000..b6016798 --- /dev/null +++ b/libevmasm/JumpdestRemover.cpp @@ -0,0 +1,68 @@ +/* + This file is part of solidity. + + solidity 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. + + solidity 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 solidity. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * @author Alex Beregszaszi + * Removes unused JUMPDESTs. + */ + +#include "JumpdestRemover.h" + +#include <libsolidity/interface/Exceptions.h> + +#include <libevmasm/AssemblyItem.h> + +using namespace std; +using namespace dev::eth; +using namespace dev; + + +bool JumpdestRemover::optimise(set<size_t> const& _tagsReferencedFromOutside) +{ + set<size_t> references{referencedTags(m_items, -1)}; + references.insert(_tagsReferencedFromOutside.begin(), _tagsReferencedFromOutside.end()); + + size_t initialSize = m_items.size(); + /// Remove tags which are never referenced. + auto pend = remove_if( + m_items.begin(), + m_items.end(), + [&](AssemblyItem const& _item) + { + if (_item.type() != Tag) + return false; + auto asmIdAndTag = _item.splitForeignPushTag(); + solAssert(asmIdAndTag.first == size_t(-1), "Sub-assembly tag used as label."); + size_t tag = asmIdAndTag.second; + return !references.count(tag); + } + ); + m_items.erase(pend, m_items.end()); + return m_items.size() != initialSize; +} + +set<size_t> JumpdestRemover::referencedTags(AssemblyItems const& _items, size_t _subId) +{ + set<size_t> ret; + for (auto const& item: _items) + if (item.type() == PushTag) + { + auto subAndTag = item.splitForeignPushTag(); + if (subAndTag.first == _subId) + ret.insert(subAndTag.second); + } + return ret; +} |