libTriton version 1.0 build 1592
Loading...
Searching...
No Matches
tritonToBitwuzla.cpp
Go to the documentation of this file.
1
2/*
3** Copyright (C) - Triton
4**
5** This program is under the terms of the Apache License 2.0.
6*/
7
8#include <vector>
9
10#include <triton/coreUtils.hpp>
11#include <triton/cpuSize.hpp>
12#include <triton/exceptions.hpp>
16
17
18
19namespace triton {
20 namespace ast {
21
23 : isEval(eval) {
24 }
25
26
28 this->translatedNodes.clear();
29 this->variables.clear();
30 this->symbols.clear();
31 }
32
33
34 const std::unordered_map<BitwuzlaTerm, triton::engines::symbolic::SharedSymbolicVariable>& TritonToBitwuzla::getVariables(void) const {
35 return this->variables;
36 }
37
38
39 const std::map<size_t, BitwuzlaSort>& TritonToBitwuzla::getBitvectorSorts(void) const {
40 return this->bvSorts;
41 }
42
43
44 BitwuzlaTerm TritonToBitwuzla::convert(const SharedAbstractNode& node, Bitwuzla* bzla) {
45 auto nodes = childrenExtraction(node, true /* unroll*/, true /* revert */);
46
47 for (auto&& n : nodes) {
48 this->translatedNodes[n] = translate(n, bzla);
49 }
50
51 return this->translatedNodes.at(node);
52 }
53
54
55 BitwuzlaTerm TritonToBitwuzla::translate(const SharedAbstractNode& node, Bitwuzla* bzla) {
56 if (node == nullptr)
57 throw triton::exceptions::AstLifting("TritonToBitwuzla::translate(): node cannot be null.");
58
59 std::vector<BitwuzlaTerm> children;
60 for (auto&& n : node->getChildren()) {
61 children.emplace_back(this->translatedNodes.at(n));
62 }
63
64 BitwuzlaTermManager* tm = bitwuzla_get_term_mgr(bzla);
65 switch (node->getType()) {
66
67 case ARRAY_NODE: {
68 auto size = triton::ast::getInteger<triton::uint32>(node->getChildren()[0]);
69 auto isort = bitwuzla_mk_bv_sort(tm, size); // index sort
70 auto vsort = bitwuzla_mk_bv_sort(tm, 8); // value sort
71 auto asort = bitwuzla_mk_array_sort(tm, isort, vsort); // array sort
72 auto value = bitwuzla_mk_bv_value_uint64(tm, vsort, 0); // const value
73 return bitwuzla_mk_const_array(tm, asort, value);
74 }
75
76 case BSWAP_NODE: {
77 auto bvsize = node->getBitvectorSize();
78 auto bvsort = bitwuzla_mk_bv_sort(tm, bvsize);
79 auto retval = bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_AND, children[0], bitwuzla_mk_bv_value_uint64(tm, bvsort, 0xff));
80 for (triton::uint32 index = 8 ; index != bvsize ; index += triton::bitsize::byte) {
81 retval = bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_SHL, retval, bitwuzla_mk_bv_value_uint64(tm, bvsort, 8));
82 retval = bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_OR, retval,
83 bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_AND,
84 bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_SHR, children[0], bitwuzla_mk_bv_value_uint64(tm, bvsort, index)),
85 bitwuzla_mk_bv_value_uint64(tm, bvsort, 0xff)
86 )
87 );
88 }
89 return retval;
90 }
91
92 case BVADD_NODE:
93 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_ADD, children[0], children[1]);
94
95 case BVAND_NODE:
96 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_AND, children[0], children[1]);
97
98 case BVASHR_NODE:
99 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_ASHR, children[0], children[1]);
100
101 case BVLSHR_NODE:
102 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_SHR, children[0], children[1]);
103
104 case BVMUL_NODE:
105 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_MUL, children[0], children[1]);
106
107 case BVNAND_NODE:
108 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_NAND, children[0], children[1]);
109
110 case BVNEG_NODE:
111 return bitwuzla_mk_term1(tm, BITWUZLA_KIND_BV_NEG, children[0]);
112
113 case BVNOR_NODE:
114 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_NOR, children[0], children[1]);
115
116 case BVNOT_NODE:
117 return bitwuzla_mk_term1(tm, BITWUZLA_KIND_BV_NOT, children[0]);
118
119 case BVOR_NODE:
120 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_OR, children[0], children[1]);
121
122 case BVROL_NODE: {
123 auto childNodes = node->getChildren();
124 auto idx = triton::ast::getInteger<triton::usize>(childNodes[1]);
125 return bitwuzla_mk_term1_indexed1(tm, BITWUZLA_KIND_BV_ROLI, children[0], idx);
126 }
127
128 case BVROR_NODE: {
129 auto childNodes = node->getChildren();
130 auto idx = triton::ast::getInteger<triton::usize>(childNodes[1]);
131 return bitwuzla_mk_term1_indexed1(tm, BITWUZLA_KIND_BV_RORI, children[0], idx);
132 }
133
134 case BVSDIV_NODE:
135 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_SDIV, children[0], children[1]);
136
137 case BVSGE_NODE:
138 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_SGE, children[0], children[1]);
139
140 case BVSGT_NODE:
141 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_SGT, children[0], children[1]);
142
143 case BVSHL_NODE:
144 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_SHL, children[0], children[1]);
145
146 case BVSLE_NODE:
147 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_SLE, children[0], children[1]);
148
149 case BVSLT_NODE:
150 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_SLT, children[0], children[1]);
151
152 case BVSMOD_NODE:
153 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_SMOD, children[0], children[1]);
154
155 case BVSREM_NODE:
156 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_SREM, children[0], children[1]);
157
158 case BVSUB_NODE:
159 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_SUB, children[0], children[1]);
160
161 case BVUDIV_NODE:
162 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_UDIV, children[0], children[1]);
163
164 case BVUGE_NODE:
165 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_UGE, children[0], children[1]);
166
167 case BVUGT_NODE:
168 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_UGT, children[0], children[1]);
169
170 case BVULE_NODE:
171 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_ULE, children[0], children[1]);
172
173 case BVULT_NODE:
174 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_ULT, children[0], children[1]);
175
176 case BVUREM_NODE:
177 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_UREM, children[0], children[1]);
178
179 case BVXNOR_NODE:
180 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_XNOR, children[0], children[1]);
181
182 case BVXOR_NODE:
183 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_BV_XOR, children[0], children[1]);
184
185 case BV_NODE: {
186 auto childNodes = node->getChildren();
187 auto bv_size = triton::ast::getInteger<triton::usize>(childNodes[1]);
188 auto sort = this->bvSorts.find(bv_size);
189 if (sort == this->bvSorts.end()) {
190 sort = this->bvSorts.insert({bv_size, bitwuzla_mk_bv_sort(tm, bv_size)}).first;
191 }
192
193 // Handle bitvector value as integer if it small enough.
194 if (bv_size <= sizeof(uint64_t) * 8) {
195 auto bv_value = triton::ast::getInteger<triton::uint64>(childNodes[0]);
196 return bitwuzla_mk_bv_value_uint64(tm, sort->second, bv_value);
197 }
198
199 auto bv_value = triton::ast::getInteger<std::string>(childNodes[0]);
200 return bitwuzla_mk_bv_value(tm, sort->second, bv_value.c_str(), 10);
201 }
202
203 case CONCAT_NODE:
204 return bitwuzla_mk_term(tm, BITWUZLA_KIND_BV_CONCAT, children.size(), children.data());
205
206 case DISTINCT_NODE:
207 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_DISTINCT, children[0], children[1]);
208
209 case EQUAL_NODE:
210 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_EQUAL, children[0], children[1]);
211
212 case EXTRACT_NODE: {
213 auto childNodes = node->getChildren();
214 auto high = triton::ast::getInteger<triton::usize>(childNodes[0]);
215 auto low = triton::ast::getInteger<triton::usize>(childNodes[1]);
216 return bitwuzla_mk_term1_indexed2(tm, BITWUZLA_KIND_BV_EXTRACT, children[2], high, low);
217 }
218
219 case FORALL_NODE:
220 throw triton::exceptions::AstLifting("TritonToBitwuzla::translate(): FORALL node can't be converted due to a Bitwuzla issue (see #1062).");
221
222 case IFF_NODE:
223 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_IFF, children[0], children[1]);
224
225 case INTEGER_NODE:
226 return (BitwuzlaTerm) 0;
227
228 case ITE_NODE:
229 return bitwuzla_mk_term3(tm, BITWUZLA_KIND_ITE, children[0], children[1], children[2]);
230
231 case LAND_NODE:
232 return bitwuzla_mk_term(tm, BITWUZLA_KIND_AND, children.size(), children.data());
233
234 case LET_NODE: {
235 auto childNodes = node->getChildren();
236 symbols[reinterpret_cast<triton::ast::StringNode*>(childNodes[0].get())->getString()] = childNodes[1];
237 return children[2];
238 }
239
240 case LNOT_NODE:
241 return bitwuzla_mk_term1(tm, BITWUZLA_KIND_NOT, children[0]);
242
243 case LOR_NODE:
244 return bitwuzla_mk_term(tm, BITWUZLA_KIND_OR, children.size(), children.data());
245
246 case LXOR_NODE:
247 return bitwuzla_mk_term(tm, BITWUZLA_KIND_XOR, children.size(), children.data());
248
249 case REFERENCE_NODE: {
250 auto ref = reinterpret_cast<ReferenceNode*>(node.get())->getSymbolicExpression()->getAst();
251 return this->translatedNodes.at(ref);
252 }
253
254 case SELECT_NODE:
255 return bitwuzla_mk_term2(tm, BITWUZLA_KIND_ARRAY_SELECT, children[0], children[1]);
256
257 case STORE_NODE:
258 return bitwuzla_mk_term3(tm, BITWUZLA_KIND_ARRAY_STORE, children[0], children[1], children[2]);
259
260 case STRING_NODE: {
261 std::string value = reinterpret_cast<triton::ast::StringNode*>(node.get())->getString();
262
263 auto it = symbols.find(value);
264 if (it == symbols.end())
265 throw triton::exceptions::AstLifting("TritonToBitwuzla::translate(): [STRING_NODE] Symbols not found.");
266
267 return this->translatedNodes.at(it->second);
268 }
269
270 case SX_NODE: {
271 auto childNodes = node->getChildren();
272 auto ext = triton::ast::getInteger<triton::usize>(childNodes[0]);
273 return bitwuzla_mk_term1_indexed1(tm, BITWUZLA_KIND_BV_SIGN_EXTEND, children[1], ext);
274 }
275
276 case VARIABLE_NODE: {
277 const auto& symVar = reinterpret_cast<VariableNode*>(node.get())->getSymbolicVariable();
278 auto size = symVar->getSize();
279 auto sort = this->bvSorts.find(size);
280 if (sort == this->bvSorts.end()) {
281 sort = this->bvSorts.insert({size, bitwuzla_mk_bv_sort(tm, size)}).first;
282 }
283
284 // If the conversion is used to evaluate a node, we concretize symbolic variables.
285 if (this->isEval) {
286 triton::uint512 value = reinterpret_cast<triton::ast::VariableNode*>(node.get())->evaluate();
287 if (size <= sizeof(uint64_t) * 8) {
288 return bitwuzla_mk_bv_value_uint64(tm, sort->second, static_cast<uint64_t>(value));
289 }
290 return bitwuzla_mk_bv_value(tm, sort->second, triton::utils::toString(value).c_str(), 10);
291 }
292
293 auto n = (BitwuzlaTerm) 0;
294 /* If we already translated the node, return that. */
295 for (auto it = variables.begin(); it != variables.end(); ++it) {
296 if (it->second == symVar) {
297 n = it->first;
298 break;
299 }
300 }
301
302 if (n == 0) {
303 n = bitwuzla_mk_const(tm, sort->second, symVar->getName().c_str());
304 variables[n] = symVar;
305 }
306
307 return n;
308 }
309
310 case ZX_NODE: {
311 auto childNodes = node->getChildren();
312 auto ext = triton::ast::getInteger<triton::usize>(childNodes[0]);
313 return bitwuzla_mk_term1_indexed1(tm, BITWUZLA_KIND_BV_ZERO_EXTEND,children[1], ext);
314 }
315
316 default:
317 throw triton::exceptions::AstLifting("TritonToBitwuzla::translate(): Invalid kind of node.");
318 }
319 }
320
321 }; /* ast namespace */
322}; /* triton namespace */
String node.
Definition ast.hpp:852
TRITON_EXPORT BitwuzlaTerm convert(const SharedAbstractNode &node, Bitwuzla *bzla)
Converts to Bitwuzla's AST.
TRITON_EXPORT const std::map< size_t, BitwuzlaSort > & getBitvectorSorts(void) const
Returns bitvector sorts.
TRITON_EXPORT ~TritonToBitwuzla()
Destructor.
TRITON_EXPORT const std::unordered_map< BitwuzlaTerm, triton::engines::symbolic::SharedSymbolicVariable > & getVariables(void) const
Returns symbolic variables and its assosiated Bitwuzla terms to process the solver model.
TRITON_EXPORT TritonToBitwuzla(bool eval=false)
Constructor.
Variable node.
Definition ast.hpp:878
The exception class used by all AST lifting (e.g z3 <-> triton).
std::vector< SharedAbstractNode > childrenExtraction(const SharedAbstractNode &node, bool unroll, bool revert)
Returns node and all its children of an AST sorted topologically. If unroll is true,...
Definition ast.cpp:3700
std::shared_ptr< triton::ast::AbstractNode > SharedAbstractNode
Shared Abstract Node.
Definition ast.hpp:59
constexpr triton::uint32 byte
byte size in bit
Definition cpuSize.hpp:60
std::uint32_t uint32
unisgned 32-bits
std::string toString(const T &obj)
Converts an object to a string.
Definition coreUtils.hpp:38
The Triton namespace.