/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 std; |
30 | | using namespace solidity; |
31 | | using namespace solidity::util; |
32 | | using namespace solidity::evmasm; |
33 | | |
34 | | bool JumpdestRemover::optimise(set<size_t> const& _tagsReferencedFromOutside) |
35 | 27.3k | { |
36 | 27.3k | set<size_t> references{referencedTags(m_items, numeric_limits<size_t>::max())}; |
37 | 27.3k | references.insert(_tagsReferencedFromOutside.begin(), _tagsReferencedFromOutside.end()); |
38 | | |
39 | 27.3k | size_t initialSize = m_items.size(); |
40 | | /// Remove tags which are never referenced. |
41 | 27.3k | auto pend = remove_if( |
42 | 27.3k | m_items.begin(), |
43 | 27.3k | m_items.end(), |
44 | 27.3k | [&](AssemblyItem const& _item) |
45 | 322M | { |
46 | 322M | if (_item.type() != Tag) |
47 | 290M | return false; |
48 | 31.8M | auto asmIdAndTag = _item.splitForeignPushTag(); |
49 | 31.8M | assertThrow(asmIdAndTag.first == numeric_limits<size_t>::max(), OptimizerException, "Sub-assembly tag used as label."); |
50 | 31.8M | size_t tag = asmIdAndTag.second; |
51 | 31.8M | return !references.count(tag); |
52 | 31.8M | } |
53 | 27.3k | ); |
54 | 27.3k | m_items.erase(pend, m_items.end()); |
55 | 27.3k | return m_items.size() != initialSize; |
56 | 27.3k | } |
57 | | |
58 | | set<size_t> JumpdestRemover::referencedTags(AssemblyItems const& _items, size_t _subId) |
59 | 31.8k | { |
60 | 31.8k | set<size_t> ret; |
61 | 31.8k | for (auto const& item: _items) |
62 | 322M | if (item.type() == PushTag) |
63 | 45.5M | { |
64 | 45.5M | auto subAndTag = item.splitForeignPushTag(); |
65 | 45.5M | if (subAndTag.first == _subId) |
66 | 45.5M | ret.insert(subAndTag.second); |
67 | 45.5M | } |
68 | 31.8k | return ret; |
69 | 31.8k | } |