P4C
The P4 Compiler
Loading...
Searching...
No Matches
z3_solver.h
1/*
2 * SPDX-FileCopyrightText: 2022 The P4 Language Consortium
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7#ifndef BACKENDS_P4TOOLS_COMMON_CORE_Z3_SOLVER_H_
8#define BACKENDS_P4TOOLS_COMMON_CORE_Z3_SOLVER_H_
9
10#include <z3++.h>
11#include <z3.h>
12
13#include <cstddef>
14#include <iosfwd>
15#include <optional>
16#include <string>
17#include <vector>
18
19#include "ir/ir.h"
20#include "ir/json_generator.h"
21#include "ir/solver.h"
22#include "lib/cstring.h"
23#include "lib/ordered_map.h"
24#include "lib/rtti.h"
25#include "lib/safe_vector.h"
26
27namespace P4::P4Tools {
28
32using Z3DeclaredVariablesMap = std::vector<ordered_map<unsigned, const IR::SymbolicVariable *>>;
33
35class Z3Solver : public AbstractSolver {
36 friend class Z3Translator;
37 friend class Z3JSON;
38 friend class Z3SolverAccessor;
39
40 public:
41 ~Z3Solver() override = default;
42
43 explicit Z3Solver(bool isIncremental = true,
44 std::optional<std::istream *> inOpt = std::nullopt);
45
46 void comment(cstring comment) override;
47
48 void seed(unsigned seed) override;
49
50 void timeout(unsigned tm) override;
51
52 std::optional<bool> checkSat(const std::vector<const Constraint *> &asserts) override;
53
56 std::optional<bool> checkSat(const z3::expr_vector &asserts);
57
60 std::optional<bool> checkSat();
61
62 [[nodiscard]] const SymbolicMapping &getSymbolicMapping() const override;
63
64 void toJSON(JSONGenerator & /*json*/) const override;
65
66 [[nodiscard]] bool isInIncrementalMode() const override;
67
69 [[nodiscard]] const z3::solver &getZ3Solver() const;
70
72 [[nodiscard]] const z3::context &getZ3Ctx() const;
73
76
79 void reset();
80
82 void push();
83
85 void pop();
86
89 void clearMemory();
90
92 void asrt(const z3::expr &assert);
93
95 void asrt(const Constraint *assertion);
96
97 private:
99 z3::sort toSort(const IR::Type *type);
100
102 [[nodiscard]] z3::context &ctx() const;
103
107 z3::expr declareVar(const IR::SymbolicVariable &var);
108
110 [[nodiscard]] static std::string generateName(const IR::SymbolicVariable &var);
111
113 static const IR::Literal *toLiteral(const z3::expr &e, const IR::Type *type);
114
119 // that is greater than or equal to @asrtIndex.
121 void addZ3Pushes(size_t &chkIndex, size_t asrtIndex);
122
124 static std::optional<bool> interpretSolverResult(z3::check_result result);
125
127 z3::solver z3solver;
128
131 Z3DeclaredVariablesMap declaredVarsById;
132
135
138 bool isIncremental;
139
142 std::vector<size_t> checkpoints;
143
145 z3::expr_vector z3Assertions;
146
148 std::optional<unsigned> seed_;
149
151 std::optional<unsigned> timeout_;
152
153 DECLARE_TYPEINFO(Z3Solver, AbstractSolver);
154};
155
157class Z3Translator : public virtual Inspector {
158 public:
161 explicit Z3Translator(Z3Solver &solver);
162
164 bool preorder(const IR::Node *node) override;
165
167 bool preorder(const IR::Cast *cast) override;
168
170 bool preorder(const IR::Constant *constant) override;
171 bool preorder(const IR::BoolLiteral *boolLiteral) override;
172 bool preorder(const IR::StringLiteral *stringLiteral) override;
173
175 bool preorder(const IR::SymbolicVariable *var) override;
176
177 // Translations for unary operations.
178 bool preorder(const IR::Neg *op) override;
179 bool preorder(const IR::Cmpl *op) override;
180 bool preorder(const IR::LNot *op) override;
181
182 // Translations for binary operations.
183 bool preorder(const IR::Equ *op) override;
184 bool preorder(const IR::Neq *op) override;
185 bool preorder(const IR::Lss *op) override;
186 bool preorder(const IR::Leq *op) override;
187 bool preorder(const IR::Grt *op) override;
188 bool preorder(const IR::Geq *op) override;
189 bool preorder(const IR::Mod *op) override;
190 bool preorder(const IR::Add *op) override;
191 bool preorder(const IR::Sub *op) override;
192 bool preorder(const IR::Mul *op) override;
193 bool preorder(const IR::Div *op) override;
194 bool preorder(const IR::Shl *op) override;
195 bool preorder(const IR::Shr *op) override;
196 bool preorder(const IR::BAnd *op) override;
197 bool preorder(const IR::BOr *op) override;
198 bool preorder(const IR::BXor *op) override;
199 bool preorder(const IR::LAnd *op) override;
200 bool preorder(const IR::LOr *op) override;
201 bool preorder(const IR::Concat *op) override;
202
203 // Translations for ternary operations.
204 bool preorder(const IR::Mux *op) override;
205 bool preorder(const IR::Slice *op) override;
206
208 z3::expr getResult();
209
211 z3::expr translate(const IR::Expression *expression);
212
213 private:
215 using Z3UnaryOp = z3::expr (*)(const z3::expr &);
216
218 using Z3BinaryOp = z3::expr (*)(const z3::expr &, const z3::expr &);
219
221 using Z3TernaryOp = z3::expr (*)(const z3::expr &, const z3::expr &, const z3::expr &);
222
226 bool recurseUnary(const IR::Operation_Unary *unary, Z3UnaryOp f);
227
231 bool recurseBinary(const IR::Operation_Binary *binary, Z3BinaryOp f);
232
236 bool recurseTernary(const IR::Operation_Ternary *ternary, Z3TernaryOp f);
237
244 template <class ShiftType>
245 const ShiftType *rewriteShift(const ShiftType *shift) const;
246
248 z3::expr result;
249
251 std::reference_wrapper<Z3Solver> solver;
252};
253
254} // namespace P4::P4Tools
255
256#endif /* BACKENDS_P4TOOLS_COMMON_CORE_Z3_SOLVER_H_ */
Provides a higher-level interface for an SMT solver.
Definition solver.h:30
Definition node.h:53
Definition json_generator.h:30
A Z3-based implementation of AbstractSolver. Encapsulates a z3::solver and a z3::context.
Definition z3_solver.h:35
std::optional< bool > checkSat()
Definition z3_solver.cpp:179
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:305
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:109
void asrt(const z3::expr &assert)
Adds a Z3 assertion to the solver context.
Definition z3_solver.cpp:225
void timeout(unsigned tm) override
Sets timeout for solver in milliseconds.
Definition z3_solver.cpp:155
void push()
Pushes new (empty) solver context.
Definition z3_solver.cpp:101
void reset()
Definition z3_solver.cpp:82
const SymbolicMapping & getSymbolicMapping() const override
Definition z3_solver.cpp:238
void seed(unsigned seed) override
Definition z3_solver.cpp:145
void clearMemory()
Definition z3_solver.cpp:89
void comment(cstring comment) override
Definition z3_solver.cpp:139
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
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:18
Definition common/compiler/compiler_result.cpp:7
std::vector< ordered_map< unsigned, const IR::SymbolicVariable * > > Z3DeclaredVariablesMap
Definition z3_solver.h:32
IR::Expression Constraint
Represents a constraint that can be shipped to and asserted within a solver.
Definition solver.h:23
P4::flat_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:26
Definition phv/solver/action_constraint_solver.cpp:33