Coverage Report

Created: 2025-09-04 07:34

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