/src/solidity/libsmtutil/Sorts.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 | | #pragma once |
20 | | |
21 | | #include <libsmtutil/Exceptions.h> |
22 | | |
23 | | #include <libsolutil/Common.h> |
24 | | |
25 | | #include <memory> |
26 | | #include <vector> |
27 | | |
28 | | namespace solidity::smtutil |
29 | | { |
30 | | |
31 | | enum class Kind |
32 | | { |
33 | | Int, |
34 | | Bool, |
35 | | BitVector, |
36 | | Function, |
37 | | Array, |
38 | | Sort, |
39 | | Tuple |
40 | | }; |
41 | | |
42 | | struct Sort |
43 | | { |
44 | | Sort(Kind _kind): |
45 | 10.6M | kind(_kind) {} |
46 | 10.6M | virtual ~Sort() = default; |
47 | 1.13M | virtual bool operator==(Sort const& _other) const { return kind == _other.kind; } |
48 | | |
49 | | Kind const kind; |
50 | | }; |
51 | | using SortPointer = std::shared_ptr<Sort>; |
52 | | |
53 | | struct IntSort: public Sort |
54 | | { |
55 | | IntSort(bool _signed): |
56 | | Sort(Kind::Int), |
57 | | isSigned(_signed) |
58 | 24 | {} |
59 | | |
60 | | bool operator==(Sort const& _other) const override |
61 | 567k | { |
62 | 567k | if (!Sort::operator==(_other)) |
63 | 0 | return false; |
64 | | |
65 | 567k | auto otherIntSort = dynamic_cast<IntSort const*>(&_other); |
66 | 567k | smtAssert(otherIntSort); |
67 | 567k | return isSigned == otherIntSort->isSigned; |
68 | 567k | } |
69 | | |
70 | | bool isSigned; |
71 | | }; |
72 | | |
73 | | struct BitVectorSort: public Sort |
74 | | { |
75 | | BitVectorSort(unsigned _size): |
76 | | Sort(Kind::BitVector), |
77 | | size(_size) |
78 | 6.52k | {} |
79 | | |
80 | | bool operator==(Sort const& _other) const override |
81 | 0 | { |
82 | 0 | if (!Sort::operator==(_other)) |
83 | 0 | return false; |
84 | | |
85 | 0 | auto otherBitVectorSort = dynamic_cast<BitVectorSort const*>(&_other); |
86 | 0 | smtAssert(otherBitVectorSort); |
87 | 0 | return size == otherBitVectorSort->size; |
88 | 0 | } |
89 | | |
90 | | unsigned size; |
91 | | }; |
92 | | |
93 | | struct FunctionSort: public Sort |
94 | | { |
95 | | FunctionSort(std::vector<SortPointer> _domain, SortPointer _codomain): |
96 | 394k | Sort(Kind::Function), domain(std::move(_domain)), codomain(std::move(_codomain)) {} |
97 | | bool operator==(Sort const& _other) const override |
98 | 0 | { |
99 | 0 | if (!Sort::operator==(_other)) |
100 | 0 | return false; |
101 | 0 | auto _otherFunction = dynamic_cast<FunctionSort const*>(&_other); |
102 | 0 | smtAssert(_otherFunction, ""); |
103 | 0 | if (domain.size() != _otherFunction->domain.size()) |
104 | 0 | return false; |
105 | 0 | if (!std::equal( |
106 | 0 | domain.begin(), |
107 | 0 | domain.end(), |
108 | 0 | _otherFunction->domain.begin(), |
109 | 0 | [&](SortPointer _a, SortPointer _b) { return *_a == *_b; } |
110 | 0 | )) |
111 | 0 | return false; |
112 | 0 | smtAssert(codomain, ""); |
113 | 0 | smtAssert(_otherFunction->codomain, ""); |
114 | 0 | return *codomain == *_otherFunction->codomain; |
115 | 0 | } |
116 | | |
117 | | std::vector<SortPointer> domain; |
118 | | SortPointer codomain; |
119 | | }; |
120 | | |
121 | | struct ArraySort: public Sort |
122 | | { |
123 | | /// _domain is the sort of the indices |
124 | | /// _range is the sort of the values |
125 | | ArraySort(SortPointer _domain, SortPointer _range): |
126 | 947k | Sort(Kind::Array), domain(std::move(_domain)), range(std::move(_range)) {} |
127 | | bool operator==(Sort const& _other) const override |
128 | 267k | { |
129 | 267k | if (!Sort::operator==(_other)) |
130 | 0 | return false; |
131 | 267k | auto _otherArray = dynamic_cast<ArraySort const*>(&_other); |
132 | 267k | smtAssert(_otherArray, ""); |
133 | 267k | smtAssert(_otherArray->domain, ""); |
134 | 267k | smtAssert(_otherArray->range, ""); |
135 | 267k | smtAssert(domain, ""); |
136 | 267k | smtAssert(range, ""); |
137 | 267k | return *domain == *_otherArray->domain && *range == *_otherArray->range; |
138 | 267k | } |
139 | | |
140 | | SortPointer domain; |
141 | | SortPointer range; |
142 | | }; |
143 | | |
144 | | struct SortSort: public Sort |
145 | | { |
146 | 115k | SortSort(SortPointer _inner): Sort(Kind::Sort), inner(std::move(_inner)) {} |
147 | | bool operator==(Sort const& _other) const override |
148 | 0 | { |
149 | 0 | if (!Sort::operator==(_other)) |
150 | 0 | return false; |
151 | 0 | auto _otherSort = dynamic_cast<SortSort const*>(&_other); |
152 | 0 | smtAssert(_otherSort, ""); |
153 | 0 | smtAssert(_otherSort->inner, ""); |
154 | 0 | smtAssert(inner, ""); |
155 | 0 | return *inner == *_otherSort->inner; |
156 | 0 | } |
157 | | |
158 | | SortPointer inner; |
159 | | }; |
160 | | |
161 | | struct TupleSort: public Sort |
162 | | { |
163 | | TupleSort( |
164 | | std::string _name, |
165 | | std::vector<std::string> _members, |
166 | | std::vector<SortPointer> _components |
167 | | ): |
168 | | Sort(Kind::Tuple), |
169 | | name(std::move(_name)), |
170 | | members(std::move(_members)), |
171 | | components(std::move(_components)) |
172 | 1.02M | { |
173 | 3.14M | for (size_t i = 0; i < members.size(); ++i) |
174 | 2.12M | memberToIndex[members.at(i)] = i; |
175 | 1.02M | } |
176 | | |
177 | | SortPointer memberSort(std::string const& _member) |
178 | 0 | { |
179 | 0 | return components.at(memberToIndex.at(_member)); |
180 | 0 | } |
181 | | |
182 | | bool operator==(Sort const& _other) const override |
183 | 270k | { |
184 | 270k | if (!Sort::operator==(_other)) |
185 | 0 | return false; |
186 | 270k | auto _otherTuple = dynamic_cast<TupleSort const*>(&_other); |
187 | 270k | smtAssert(_otherTuple, ""); |
188 | 270k | if (name != _otherTuple->name) |
189 | 0 | return false; |
190 | 270k | if (members != _otherTuple->members) |
191 | 0 | return false; |
192 | 270k | if (components.size() != _otherTuple->components.size()) |
193 | 0 | return false; |
194 | 270k | if (!std::equal( |
195 | 270k | components.begin(), |
196 | 270k | components.end(), |
197 | 270k | _otherTuple->components.begin(), |
198 | 541k | [&](SortPointer _a, SortPointer _b) { return *_a == *_b; } |
199 | 270k | )) |
200 | 0 | return false; |
201 | 270k | return true; |
202 | 270k | } |
203 | | |
204 | | std::string const name; |
205 | | std::vector<std::string> const members; |
206 | | std::vector<SortPointer> const components; |
207 | | std::map<std::string, size_t> memberToIndex; |
208 | | }; |
209 | | |
210 | | |
211 | | /** Frequently used sorts.*/ |
212 | | struct SortProvider |
213 | | { |
214 | | static std::shared_ptr<Sort> const boolSort; |
215 | | static std::shared_ptr<IntSort> const uintSort; |
216 | | static std::shared_ptr<IntSort> const sintSort; |
217 | | static std::shared_ptr<IntSort> intSort(bool _signed = false); |
218 | | static std::shared_ptr<BitVectorSort> const bitVectorSort; |
219 | | }; |
220 | | |
221 | | } |