Coverage Report

Created: 2022-08-24 06:55

/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
}