/src/solidity/libevmasm/JumpdestRemover.cpp
Line | Count | Source |
1 | | /* |
2 | | This file is part of solidity. |
3 | | |
4 | | solidity is free software: you can redistribute it and/or modify |
5 | | it under the terms of the GNU General Public License as published by |
6 | | the Free Software Foundation, either version 3 of the License, or |
7 | | (at your option) any later version. |
8 | | |
9 | | solidity is distributed in the hope that it will be useful, |
10 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | | GNU General Public License for more details. |
13 | | |
14 | | You should have received a copy of the GNU General Public License |
15 | | along with solidity. If not, see <http://www.gnu.org/licenses/>. |
16 | | */ |
17 | | // SPDX-License-Identifier: GPL-3.0 |
18 | | /** |
19 | | * @author Alex Beregszaszi |
20 | | * Removes unused JUMPDESTs. |
21 | | */ |
22 | | |
23 | | #include <libevmasm/JumpdestRemover.h> |
24 | | |
25 | | #include <libevmasm/AssemblyItem.h> |
26 | | |
27 | | #include <limits> |
28 | | |
29 | | using namespace solidity; |
30 | | using namespace solidity::util; |
31 | | using namespace solidity::evmasm; |
32 | | |
33 | | bool JumpdestRemover::optimise(std::set<size_t> const& _tagsReferencedFromOutside) |
34 | 173k | { |
35 | 173k | std::set<size_t> references{referencedTags(m_items, SubAssemblyID{})}; |
36 | 173k | references.insert(_tagsReferencedFromOutside.begin(), _tagsReferencedFromOutside.end()); |
37 | | |
38 | 173k | size_t initialSize = m_items.size(); |
39 | | /// Remove tags which are never referenced. |
40 | 173k | auto pend = remove_if( |
41 | 173k | m_items.begin(), |
42 | 173k | m_items.end(), |
43 | 173k | [&](AssemblyItem const& _item) |
44 | 48.1M | { |
45 | 48.1M | if (_item.type() != Tag) |
46 | 43.4M | return false; |
47 | 4.79M | auto asmIdAndTag = _item.splitForeignPushTag(); |
48 | 4.79M | solAssert(asmIdAndTag.first.empty(), "Sub-assembly tag used as label."); |
49 | 4.79M | size_t tag = asmIdAndTag.second; |
50 | 4.79M | return !references.count(tag); |
51 | 4.79M | } |
52 | 173k | ); |
53 | 173k | m_items.erase(pend, m_items.end()); |
54 | 173k | return m_items.size() != initialSize; |
55 | 173k | } |
56 | | |
57 | | std::set<size_t> JumpdestRemover::referencedTags(AssemblyItems const& _items, SubAssemblyID _subId) |
58 | 194k | { |
59 | 194k | std::set<size_t> ret; |
60 | 194k | for (auto const& item: _items) |
61 | 49.3M | if (item.type() == PushTag || item.type() == RelativeJump || item.type() == ConditionalRelativeJump) |
62 | 5.89M | { |
63 | 5.89M | auto subAndTag = item.splitForeignPushTag(); |
64 | 5.89M | if (subAndTag.first == _subId) |
65 | 5.76M | ret.insert(subAndTag.second); |
66 | 5.89M | } |
67 | 194k | return ret; |
68 | 194k | } |