Coverage Report

Created: 2025-09-04 07:34

/src/solidity/libevmasm/ExpressionClasses.h
Line
Count
Source (jump to first uncovered line)
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
 * @file ExpressionClasses.h
20
 * @author Christian <c@ethdev.com>
21
 * @date 2015
22
 * Container for equivalence classes of expressions for use in common subexpression elimination.
23
 */
24
25
#pragma once
26
27
#include <libevmasm/AssemblyItem.h>
28
29
#include <libsolutil/Common.h>
30
31
#include <memory>
32
#include <unordered_set>
33
#include <vector>
34
35
namespace solidity::langutil
36
{
37
struct SourceLocation;
38
}
39
40
namespace solidity::evmasm
41
{
42
43
class Pattern;
44
struct ExpressionTemplate;
45
46
/**
47
 * Collection of classes of equivalent expressions that can also determine the class of an expression.
48
 * Identifiers are contiguously assigned to new classes starting from zero.
49
 */
50
class ExpressionClasses
51
{
52
public:
53
  using Id = unsigned;
54
  using Ids = std::vector<Id>;
55
56
  struct Expression
57
  {
58
    Id id;
59
    AssemblyItem const* item = nullptr;
60
    Ids arguments;
61
    /// Storage modification sequence, only used for storage and memory operations.
62
    unsigned sequenceNumber = 0;
63
    /// Behaves as if this was a tuple of (item->type(), item->data(), arguments, sequenceNumber).
64
    bool operator==(Expression const& _other) const;
65
66
    struct ExpressionHash
67
    {
68
      std::size_t operator()(Expression const& _expression) const;
69
    };
70
  };
71
72
73
  /// Retrieves the id of the expression equivalence class resulting from the given item applied to the
74
  /// given classes, might also create a new one.
75
  /// @param _copyItem if true, copies the assembly item to an internal storage instead of just
76
  /// keeping a pointer.
77
  /// The @a _sequenceNumber indicates the current storage or memory access sequence.
78
  Id find(
79
    AssemblyItem const& _item,
80
    Ids const& _arguments = {},
81
    bool _copyItem = true,
82
    unsigned _sequenceNumber = 0
83
  );
84
  /// @returns the canonical representative of an expression class.
85
98.5M
  Expression const& representative(Id _id) const { return m_representatives.at(_id); }
86
  /// @returns the number of classes.
87
0
  size_t size() const { return m_representatives.size(); }
88
89
  /// Forces the given @a _item with @a _arguments to the class @a _id. This can be used to
90
  /// add prior knowledge e.g. about CALLDATA, but has to be used with caution. Will not work as
91
  /// expected if @a _item applied to @a _arguments already exists.
92
  void forceEqual(Id _id, AssemblyItem const& _item, Ids const& _arguments, bool _copyItem = true);
93
94
  /// @returns the id of a new class which is different to all other classes.
95
  Id newClass(langutil::DebugData::ConstPtr _debugData);
96
97
  /// @returns true if the values of the given classes are known to be different (on every input).
98
  /// @note that this function might still return false for some different inputs.
99
  bool knownToBeDifferent(Id _a, Id _b);
100
  /// Similar to @a knownToBeDifferent but require that abs(_a - b) >= 32.
101
  bool knownToBeDifferentBy32(Id _a, Id _b);
102
  /// @returns true if the value of the given class is known to be zero.
103
  /// @note that this is not the negation of knownNonZero
104
  bool knownZero(Id _c);
105
  /// @returns true if the value of the given class is known to be nonzero.
106
  /// @note that this is not the negation of knownZero
107
  bool knownNonZero(Id _c);
108
  /// @returns a pointer to the value if the given class is known to be a constant,
109
  /// and a nullptr otherwise.
110
  u256 const* knownConstant(Id _c);
111
112
  /// Stores a copy of the given AssemblyItem and returns a pointer to the copy that is valid for
113
  /// the lifetime of the ExpressionClasses object.
114
  AssemblyItem const* storeItem(AssemblyItem const& _item);
115
116
  std::string fullDAGToString(Id _id) const;
117
118
private:
119
  /// Tries to simplify the given expression.
120
  /// @returns its class if it possible or Id(-1) otherwise.
121
  Id tryToSimplify(Expression const& _expr);
122
123
  /// Rebuilds an expression from a (matched) pattern.
124
  Id rebuildExpression(ExpressionTemplate const& _template);
125
126
  std::vector<std::pair<Pattern, std::function<Pattern()>>> createRules() const;
127
128
  /// Expression equivalence class representatives - we only store one item of an equivalence.
129
  std::vector<Expression> m_representatives;
130
  /// All expression ever encountered.
131
  std::unordered_set<Expression, Expression::ExpressionHash> m_expressions;
132
  std::vector<std::shared_ptr<AssemblyItem>> m_spareAssemblyItems;
133
};
134
135
}