P4C
The P4 Compiler
Loading...
Searching...
No Matches
z3_solver.h
1#ifndef BACKENDS_P4TOOLS_COMMON_CORE_Z3_SOLVER_H_
2#define BACKENDS_P4TOOLS_COMMON_CORE_Z3_SOLVER_H_
3
4#include <z3++.h>
5
6#include <cstddef>
7#include <iosfwd>
8#include <optional>
9#include <string>
10#include <vector>
11
12#include "ir/ir.h"
13#include "ir/json_generator.h"
14#include "ir/solver.h"
15#include "lib/cstring.h"
16#include "lib/ordered_map.h"
17#include "lib/rtti.h"
18#include "lib/safe_vector.h"
19
20namespace P4::P4Tools {
21
25using Z3DeclaredVariablesMap = std::vector<ordered_map<unsigned, const IR::SymbolicVariable *>>;
26
28class Z3Solver : public AbstractSolver {
29 friend class Z3Translator;
30 friend class Z3JSON;
31 friend class Z3SolverAccessor;
32
33 public:
34 ~Z3Solver() override = default;
35
36 explicit Z3Solver(bool isIncremental = true,
37 std::optional<std::istream *> inOpt = std::nullopt);
38
39 void comment(cstring comment) override;
40
41 void seed(unsigned seed) override;
42
43 void timeout(unsigned tm) override;
44
45 std::optional<bool> checkSat(const std::vector<const Constraint *> &asserts) override;
46
49 std::optional<bool> checkSat(const z3::expr_vector &asserts);
50
53 std::optional<bool> checkSat();
54
55 [[nodiscard]] const SymbolicMapping &getSymbolicMapping() const override;
56
57 void toJSON(JSONGenerator & /*json*/) const override;
58
59 [[nodiscard]] bool isInIncrementalMode() const override;
60
62 [[nodiscard]] const z3::solver &getZ3Solver() const;
63
65 [[nodiscard]] const z3::context &getZ3Ctx() const;
66
69
72 void reset();
73
75 void push();
76
78 void pop();
79
82 void clearMemory();
83
85 void asrt(const z3::expr &assert);
86
88 void asrt(const Constraint *assertion);
89
90 private:
92 z3::sort toSort(const IR::Type *type);
93
95 [[nodiscard]] z3::context &ctx() const;
96
100 z3::expr declareVar(const IR::SymbolicVariable &var);
101
103 [[nodiscard]] static std::string generateName(const IR::SymbolicVariable &var);
104
106 static const IR::Literal *toLiteral(const z3::expr &e, const IR::Type *type);
107
112 // that is greater than or equal to @asrtIndex.
114 void addZ3Pushes(size_t &chkIndex, size_t asrtIndex);
115
117 static std::optional<bool> interpretSolverResult(z3::check_result result);
118
120 z3::solver z3solver;
121
124 Z3DeclaredVariablesMap declaredVarsById;
125
128
131 bool isIncremental;
132
135 std::vector<size_t> checkpoints;
136
138 z3::expr_vector z3Assertions;
139
141 std::optional<unsigned> seed_;
142
144 std::optional<unsigned> timeout_;
145
146 DECLARE_TYPEINFO(Z3Solver, AbstractSolver);
147};
148
150class Z3Translator : public virtual Inspector {
151 public:
154 explicit Z3Translator(Z3Solver &solver);
155
157 bool preorder(const IR::Node *node) override;
158
160 bool preorder(const IR::Cast *cast) override;
161
163 bool preorder(const IR::Constant *constant) override;
164 bool preorder(const IR::BoolLiteral *boolLiteral) override;
165 bool preorder(const IR::StringLiteral *stringLiteral) override;
166
168 bool preorder(const IR::SymbolicVariable *var) override;
169
170 // Translations for unary operations.
171 bool preorder(const IR::Neg *op) override;
172 bool preorder(const IR::Cmpl *op) override;
173 bool preorder(const IR::LNot *op) override;
174
175 // Translations for binary operations.
176 bool preorder(const IR::Equ *op) override;
177 bool preorder(const IR::Neq *op) override;
178 bool preorder(const IR::Lss *op) override;
179 bool preorder(const IR::Leq *op) override;
180 bool preorder(const IR::Grt *op) override;
181 bool preorder(const IR::Geq *op) override;
182 bool preorder(const IR::Mod *op) override;
183 bool preorder(const IR::Add *op) override;
184 bool preorder(const IR::Sub *op) override;
185 bool preorder(const IR::Mul *op) override;
186 bool preorder(const IR::Div *op) override;
187 bool preorder(const IR::Shl *op) override;
188 bool preorder(const IR::Shr *op) override;
189 bool preorder(const IR::BAnd *op) override;
190 bool preorder(const IR::BOr *op) override;
191 bool preorder(const IR::BXor *op) override;
192 bool preorder(const IR::LAnd *op) override;
193 bool preorder(const IR::LOr *op) override;
194 bool preorder(const IR::Concat *op) override;
195
196 // Translations for ternary operations.
197 bool preorder(const IR::Mux *op) override;
198 bool preorder(const IR::Slice *op) override;
199
201 z3::expr getResult();
202
204 z3::expr translate(const IR::Expression *expression);
205
206 private:
208 using Z3UnaryOp = z3::expr (*)(const z3::expr &);
209
211 using Z3BinaryOp = z3::expr (*)(const z3::expr &, const z3::expr &);
212
214 using Z3TernaryOp = z3::expr (*)(const z3::expr &, const z3::expr &, const z3::expr &);
215
219 bool recurseUnary(const IR::Operation_Unary *unary, Z3UnaryOp f);
220
224 bool recurseBinary(const IR::Operation_Binary *binary, Z3BinaryOp f);
225
229 bool recurseTernary(const IR::Operation_Ternary *ternary, Z3TernaryOp f);
230
237 template <class ShiftType>
238 const ShiftType *rewriteShift(const ShiftType *shift) const;
239
241 z3::expr result;
242
244 std::reference_wrapper<Z3Solver> solver;
245};
246
247} // namespace P4::P4Tools
248
249#endif /* BACKENDS_P4TOOLS_COMMON_CORE_Z3_SOLVER_H_ */
Provides a higher-level interface for an SMT solver.
Definition solver.h:24
Definition node.h:95
Definition visitor.h:400
Definition json_generator.h:36
Definition accessor.h:11
A Z3-based implementation of AbstractSolver. Encapsulates a z3::solver and a z3::context.
Definition z3_solver.h:28
std::optional< bool > checkSat()
Definition z3_solver.cpp:178
bool isInIncrementalMode() const override
Definition z3_solver.cpp:336
void toJSON(JSONGenerator &) const override
Saves solver state to the given JSON generator.
Definition z3_solver.cpp:304
const z3::solver & getZ3Solver() const
Get the actual Z3 solver backing this class.
Definition z3_solver.cpp:330
void pop()
Removes the last solver context.
Definition z3_solver.cpp:108
void asrt(const z3::expr &assert)
Adds a Z3 assertion to the solver context.
Definition z3_solver.cpp:224
void timeout(unsigned tm) override
Sets timeout for solver in milliseconds.
Definition z3_solver.cpp:154
void push()
Pushes new (empty) solver context.
Definition z3_solver.cpp:100
void reset()
Definition z3_solver.cpp:81
const SymbolicMapping & getSymbolicMapping() const override
Definition z3_solver.cpp:237
void seed(unsigned seed) override
Definition z3_solver.cpp:144
void clearMemory()
Definition z3_solver.cpp:88
void comment(cstring comment) override
Definition z3_solver.cpp:138
safe_vector< const Constraint * > getAssertions() const
const z3::context & getZ3Ctx() const
Get the actual Z3 context that this class uses.
Definition z3_solver.cpp:332
Translates P4 expressions into Z3. Any variables encountered are declared to a Z3 instance.
Definition z3_solver.h:150
Z3Translator(Z3Solver &solver)
Definition z3_solver.cpp:368
z3::expr translate(const IR::Expression *expression)
Translate an P4C IR expression and return the Z3 equivalent.
Definition z3_solver.cpp:611
bool preorder(const IR::Node *node) override
Handles unexpected nodes.
Definition z3_solver.cpp:370
z3::expr getResult()
Definition z3_solver.cpp:609
Definition cstring.h:85
Definition safe_vector.h:27
Definition common/compiler/compiler_result.cpp:3
std::vector< ordered_map< unsigned, const IR::SymbolicVariable * > > Z3DeclaredVariablesMap
Definition z3_solver.h:25
IR::Expression Constraint
Represents a constraint that can be shipped to and asserted within a solver.
Definition solver.h:17
absl::btree_map< const IR::SymbolicVariable *, const IR::Expression *, IR::SymbolicVariableLess > SymbolicMapping
This type maps symbolic variables to their value assigned by the solver.
Definition solver.h:20