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