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#include <z3.h>
6
7#include <cstddef>
8#include <iosfwd>
9#include <optional>
10#include <string>
11#include <vector>
12
13#include "ir/ir.h"
14#include "ir/json_generator.h"
15#include "ir/solver.h"
16#include "lib/cstring.h"
17#include "lib/ordered_map.h"
18#include "lib/rtti.h"
19#include "lib/safe_vector.h"
20
21namespace P4::P4Tools {
22
26using Z3DeclaredVariablesMap = std::vector<ordered_map<unsigned, const IR::SymbolicVariable *>>;
27
29class Z3Solver : public AbstractSolver {
30 friend class Z3Translator;
31 friend class Z3JSON;
32 friend class Z3SolverAccessor;
33
34 public:
35 ~Z3Solver() override = default;
36
37 explicit Z3Solver(bool isIncremental = true,
38 std::optional<std::istream *> inOpt = std::nullopt);
39
40 void comment(cstring comment) override;
41
42 void seed(unsigned seed) override;
43
44 void timeout(unsigned tm) override;
45
46 std::optional<bool> checkSat(const std::vector<const Constraint *> &asserts) override;
47
50 std::optional<bool> checkSat(const z3::expr_vector &asserts);
51
54 std::optional<bool> checkSat();
55
56 [[nodiscard]] const SymbolicMapping &getSymbolicMapping() const override;
57
58 void toJSON(JSONGenerator & /*json*/) const override;
59
60 [[nodiscard]] bool isInIncrementalMode() const override;
61
63 [[nodiscard]] const z3::solver &getZ3Solver() const;
64
66 [[nodiscard]] const z3::context &getZ3Ctx() const;
67
70
73 void reset();
74
76 void push();
77
79 void pop();
80
83 void clearMemory();
84
86 void asrt(const z3::expr &assert);
87
89 void asrt(const Constraint *assertion);
90
91 private:
93 z3::sort toSort(const IR::Type *type);
94
96 [[nodiscard]] z3::context &ctx() const;
97
101 z3::expr declareVar(const IR::SymbolicVariable &var);
102
104 [[nodiscard]] static std::string generateName(const IR::SymbolicVariable &var);
105
107 static const IR::Literal *toLiteral(const z3::expr &e, const IR::Type *type);
108
113 // that is greater than or equal to @asrtIndex.
115 void addZ3Pushes(size_t &chkIndex, size_t asrtIndex);
116
118 static std::optional<bool> interpretSolverResult(z3::check_result result);
119
121 z3::solver z3solver;
122
125 Z3DeclaredVariablesMap declaredVarsById;
126
129
132 bool isIncremental;
133
136 std::vector<size_t> checkpoints;
137
139 z3::expr_vector z3Assertions;
140
142 std::optional<unsigned> seed_;
143
145 std::optional<unsigned> timeout_;
146
147 DECLARE_TYPEINFO(Z3Solver, AbstractSolver);
148};
149
151class Z3Translator : public virtual Inspector {
152 public:
155 explicit Z3Translator(Z3Solver &solver);
156
158 bool preorder(const IR::Node *node) override;
159
161 bool preorder(const IR::Cast *cast) override;
162
164 bool preorder(const IR::Constant *constant) override;
165 bool preorder(const IR::BoolLiteral *boolLiteral) override;
166 bool preorder(const IR::StringLiteral *stringLiteral) override;
167
169 bool preorder(const IR::SymbolicVariable *var) override;
170
171 // Translations for unary operations.
172 bool preorder(const IR::Neg *op) override;
173 bool preorder(const IR::Cmpl *op) override;
174 bool preorder(const IR::LNot *op) override;
175
176 // Translations for binary operations.
177 bool preorder(const IR::Equ *op) override;
178 bool preorder(const IR::Neq *op) override;
179 bool preorder(const IR::Lss *op) override;
180 bool preorder(const IR::Leq *op) override;
181 bool preorder(const IR::Grt *op) override;
182 bool preorder(const IR::Geq *op) override;
183 bool preorder(const IR::Mod *op) override;
184 bool preorder(const IR::Add *op) override;
185 bool preorder(const IR::Sub *op) override;
186 bool preorder(const IR::Mul *op) override;
187 bool preorder(const IR::Div *op) override;
188 bool preorder(const IR::Shl *op) override;
189 bool preorder(const IR::Shr *op) override;
190 bool preorder(const IR::BAnd *op) override;
191 bool preorder(const IR::BOr *op) override;
192 bool preorder(const IR::BXor *op) override;
193 bool preorder(const IR::LAnd *op) override;
194 bool preorder(const IR::LOr *op) override;
195 bool preorder(const IR::Concat *op) override;
196
197 // Translations for ternary operations.
198 bool preorder(const IR::Mux *op) override;
199 bool preorder(const IR::Slice *op) override;
200
202 z3::expr getResult();
203
205 z3::expr translate(const IR::Expression *expression);
206
207 private:
209 using Z3UnaryOp = z3::expr (*)(const z3::expr &);
210
212 using Z3BinaryOp = z3::expr (*)(const z3::expr &, const z3::expr &);
213
215 using Z3TernaryOp = z3::expr (*)(const z3::expr &, const z3::expr &, const z3::expr &);
216
220 bool recurseUnary(const IR::Operation_Unary *unary, Z3UnaryOp f);
221
225 bool recurseBinary(const IR::Operation_Binary *binary, Z3BinaryOp f);
226
230 bool recurseTernary(const IR::Operation_Ternary *ternary, Z3TernaryOp f);
231
238 template <class ShiftType>
239 const ShiftType *rewriteShift(const ShiftType *shift) const;
240
242 z3::expr result;
243
245 std::reference_wrapper<Z3Solver> solver;
246};
247
248} // namespace P4::P4Tools
249
250#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:29
std::optional< bool > checkSat()
Definition z3_solver.cpp:175
bool isInIncrementalMode() const override
Definition z3_solver.cpp:333
void toJSON(JSONGenerator &) const override
Saves solver state to the given JSON generator.
Definition z3_solver.cpp:301
const z3::solver & getZ3Solver() const
Get the actual Z3 solver backing this class.
Definition z3_solver.cpp:327
void pop()
Removes the last solver context.
Definition z3_solver.cpp:105
void asrt(const z3::expr &assert)
Adds a Z3 assertion to the solver context.
Definition z3_solver.cpp:221
void timeout(unsigned tm) override
Sets timeout for solver in milliseconds.
Definition z3_solver.cpp:151
void push()
Pushes new (empty) solver context.
Definition z3_solver.cpp:97
void reset()
Definition z3_solver.cpp:78
const SymbolicMapping & getSymbolicMapping() const override
Definition z3_solver.cpp:234
void seed(unsigned seed) override
Definition z3_solver.cpp:141
void clearMemory()
Definition z3_solver.cpp:85
void comment(cstring comment) override
Definition z3_solver.cpp:135
safe_vector< const Constraint * > getAssertions() const
const z3::context & getZ3Ctx() const
Get the actual Z3 context that this class uses.
Definition z3_solver.cpp:329
Translates P4 expressions into Z3. Any variables encountered are declared to a Z3 instance.
Definition z3_solver.h:151
Z3Translator(Z3Solver &solver)
Definition z3_solver.cpp:365
z3::expr translate(const IR::Expression *expression)
Translate an P4C IR expression and return the Z3 equivalent.
Definition z3_solver.cpp:608
bool preorder(const IR::Node *node) override
Handles unexpected nodes.
Definition z3_solver.cpp:367
z3::expr getResult()
Definition z3_solver.cpp:606
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:26
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
Definition phv/solver/action_constraint_solver.cpp:33