klee
Constraints.cpp
Go to the documentation of this file.
1//===-- Constraints.cpp ---------------------------------------------------===//
2//
3// The KLEE Symbolic Virtual Machine
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
11
13#include "klee/Module/KModule.h"
15
16#include "llvm/IR/Function.h"
17#include "llvm/Support/CommandLine.h"
18
19#include <map>
20
21using namespace klee;
22
23namespace {
24llvm::cl::opt<bool> RewriteEqualities(
25 "rewrite-equalities",
26 llvm::cl::desc("Rewrite existing constraints when an equality with a "
27 "constant is added (default=true)"),
28 llvm::cl::init(true),
29 llvm::cl::cat(SolvingCat));
30} // namespace
31
33private:
35
36public:
37 ExprReplaceVisitor(const ref<Expr> &_src, const ref<Expr> &_dst)
38 : src(_src), dst(_dst) {}
39
40 Action visitExpr(const Expr &e) override {
41 if (e == *src) {
42 return Action::changeTo(dst);
43 }
44 return Action::doChildren();
45 }
46
47 Action visitExprPost(const Expr &e) override {
48 if (e == *src) {
49 return Action::changeTo(dst);
50 }
51 return Action::doChildren();
52 }
53};
54
56private:
57 const std::map< ref<Expr>, ref<Expr> > &replacements;
58
59public:
61 const std::map<ref<Expr>, ref<Expr>> &_replacements)
62 : ExprVisitor(true), replacements(_replacements) {}
63
64 Action visitExprPost(const Expr &e) override {
65 auto it = replacements.find(ref<Expr>(const_cast<Expr *>(&e)));
66 if (it!=replacements.end()) {
67 return Action::changeTo(it->second);
68 }
69 return Action::doChildren();
70 }
71};
72
73bool ConstraintManager::rewriteConstraints(ExprVisitor &visitor) {
74 ConstraintSet old;
75 bool changed = false;
76
77 std::swap(constraints, old);
78 for (auto &ce : old) {
79 ref<Expr> e = visitor.visit(ce);
80
81 if (e!=ce) {
82 addConstraintInternal(e); // enable further reductions
83 changed = true;
84 } else {
86 }
87 }
88
89 return changed;
90}
91
93 const ref<Expr> &e) {
94
95 if (isa<ConstantExpr>(e))
96 return e;
97
98 std::map< ref<Expr>, ref<Expr> > equalities;
99
100 for (auto &constraint : constraints) {
101 if (const EqExpr *ee = dyn_cast<EqExpr>(constraint)) {
102 if (isa<ConstantExpr>(ee->left)) {
103 equalities.insert(std::make_pair(ee->right,
104 ee->left));
105 } else {
106 equalities.insert(
107 std::make_pair(constraint, ConstantExpr::alloc(1, Expr::Bool)));
108 }
109 } else {
110 equalities.insert(
111 std::make_pair(constraint, ConstantExpr::alloc(1, Expr::Bool)));
112 }
113 }
114
115 return ExprReplaceVisitor2(equalities).visit(e);
116}
117
119 // rewrite any known equalities and split Ands into different conjuncts
120
121 switch (e->getKind()) {
122 case Expr::Constant:
123 assert(cast<ConstantExpr>(e)->isTrue() &&
124 "attempt to add invalid (false) constraint");
125 break;
126
127 // split to enable finer grained independence and other optimizations
128 case Expr::And: {
129 BinaryExpr *be = cast<BinaryExpr>(e);
132 break;
133 }
134
135 case Expr::Eq: {
136 if (RewriteEqualities) {
137 // XXX: should profile the effects of this and the overhead.
138 // traversing the constraints looking for equalities is hardly the
139 // slowest thing we do, but it is probably nicer to have a
140 // ConstraintSet ADT which efficiently remembers obvious patterns
141 // (byte-constant comparison).
142 BinaryExpr *be = cast<BinaryExpr>(e);
143 if (isa<ConstantExpr>(be->left)) {
144 ExprReplaceVisitor visitor(be->right, be->left);
145 rewriteConstraints(visitor);
146 }
147 }
149 break;
150 }
151
152 default:
154 break;
155 }
156}
157
159 ref<Expr> simplified = simplifyExpr(constraints, e);
160 addConstraintInternal(simplified);
161}
162
164 : constraints(_constraints) {}
165
166bool ConstraintSet::empty() const { return constraints.empty(); }
167
169 return constraints.begin();
170}
171
173 return constraints.end();
174}
175
176size_t ConstraintSet::size() const noexcept { return constraints.size(); }
177
178void ConstraintSet::push_back(const ref<Expr> &e) { constraints.push_back(e); }
Action visitExprPost(const Expr &e) override
Definition: Constraints.cpp:64
ExprReplaceVisitor2(const std::map< ref< Expr >, ref< Expr > > &_replacements)
Definition: Constraints.cpp:60
const std::map< ref< Expr >, ref< Expr > > & replacements
Definition: Constraints.cpp:57
Action visitExprPost(const Expr &e) override
Definition: Constraints.cpp:47
ExprReplaceVisitor(const ref< Expr > &_src, const ref< Expr > &_dst)
Definition: Constraints.cpp:37
Action visitExpr(const Expr &e) override
Definition: Constraints.cpp:40
ref< Expr > left
Definition: Expr.h:370
ref< Expr > right
Definition: Expr.h:370
static ref< ConstantExpr > alloc(const llvm::APInt &v)
Definition: Expr.h:1065
void addConstraintInternal(const ref< Expr > &constraint)
Add constraint to the set of constraints.
bool rewriteConstraints(ExprVisitor &visitor)
Definition: Constraints.cpp:73
ConstraintSet & constraints
Definition: Constraints.h:76
void addConstraint(const ref< Expr > &constraint)
static ref< Expr > simplifyExpr(const ConstraintSet &constraints, const ref< Expr > &expr)
Definition: Constraints.cpp:92
ConstraintManager(ConstraintSet &constraints)
const_iterator constraint_iterator
Definition: Constraints.h:27
constraints_ty constraints
Definition: Constraints.h:44
void push_back(const ref< Expr > &e)
constraint_iterator end() const
constraint_iterator begin() const
size_t size() const noexcept
bool empty() const
static Action changeTo(const ref< Expr > &expr)
Definition: ExprVisitor.h:36
static Action doChildren()
Definition: ExprVisitor.h:39
ref< Expr > visit(const ref< Expr > &e)
Definition: ExprVisitor.cpp:26
Class representing symbolic expressions.
Definition: Expr.h:91
virtual Kind getKind() const =0
@ And
Definition: Expr.h:147
@ Constant
Definition: Expr.h:113
@ Eq
Definition: Expr.h:155
static const Width Bool
Definition: Expr.h:100
Definition: main.cpp:291
llvm::cl::OptionCategory SolvingCat