1 //== BasicConstraintManager.cpp - Manage basic constraints.------*- C++ -*--==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines BasicConstraintManager, a class that tracks simple
11 // equality and inequality constraints on symbolic values of GRState.
13 //===----------------------------------------------------------------------===//
15 #include "SimpleConstraintManager.h"
16 #include "clang/GR/PathSensitive/GRState.h"
17 #include "clang/GR/PathSensitive/GRStateTrait.h"
18 #include "clang/GR/PathSensitive/GRTransferFuncs.h"
19 #include "llvm/Support/raw_ostream.h"
21 using namespace clang
;
24 namespace { class ConstNotEq
{}; }
25 namespace { class ConstEq
{}; }
27 typedef llvm::ImmutableMap
<SymbolRef
,GRState::IntSetTy
> ConstNotEqTy
;
28 typedef llvm::ImmutableMap
<SymbolRef
,const llvm::APSInt
*> ConstEqTy
;
30 static int ConstEqIndex
= 0;
31 static int ConstNotEqIndex
= 0;
35 struct GRStateTrait
<ConstNotEq
> : public GRStatePartialTrait
<ConstNotEqTy
> {
36 static inline void* GDMIndex() { return &ConstNotEqIndex
; }
40 struct GRStateTrait
<ConstEq
> : public GRStatePartialTrait
<ConstEqTy
> {
41 static inline void* GDMIndex() { return &ConstEqIndex
; }
46 // BasicConstraintManager only tracks equality and inequality constraints of
47 // constants and integer variables.
48 class BasicConstraintManager
49 : public SimpleConstraintManager
{
50 GRState::IntSetTy::Factory ISetFactory
;
52 BasicConstraintManager(GRStateManager
&statemgr
, GRSubEngine
&subengine
)
53 : SimpleConstraintManager(subengine
),
54 ISetFactory(statemgr
.getAllocator()) {}
56 const GRState
*assumeSymNE(const GRState
* state
, SymbolRef sym
,
57 const llvm::APSInt
& V
,
58 const llvm::APSInt
& Adjustment
);
60 const GRState
*assumeSymEQ(const GRState
* state
, SymbolRef sym
,
61 const llvm::APSInt
& V
,
62 const llvm::APSInt
& Adjustment
);
64 const GRState
*assumeSymLT(const GRState
* state
, SymbolRef sym
,
65 const llvm::APSInt
& V
,
66 const llvm::APSInt
& Adjustment
);
68 const GRState
*assumeSymGT(const GRState
* state
, SymbolRef sym
,
69 const llvm::APSInt
& V
,
70 const llvm::APSInt
& Adjustment
);
72 const GRState
*assumeSymGE(const GRState
* state
, SymbolRef sym
,
73 const llvm::APSInt
& V
,
74 const llvm::APSInt
& Adjustment
);
76 const GRState
*assumeSymLE(const GRState
* state
, SymbolRef sym
,
77 const llvm::APSInt
& V
,
78 const llvm::APSInt
& Adjustment
);
80 const GRState
* AddEQ(const GRState
* state
, SymbolRef sym
, const llvm::APSInt
& V
);
82 const GRState
* AddNE(const GRState
* state
, SymbolRef sym
, const llvm::APSInt
& V
);
84 const llvm::APSInt
* getSymVal(const GRState
* state
, SymbolRef sym
) const;
85 bool isNotEqual(const GRState
* state
, SymbolRef sym
, const llvm::APSInt
& V
)
87 bool isEqual(const GRState
* state
, SymbolRef sym
, const llvm::APSInt
& V
)
90 const GRState
* RemoveDeadBindings(const GRState
* state
, SymbolReaper
& SymReaper
);
92 void print(const GRState
* state
, llvm::raw_ostream
& Out
,
93 const char* nl
, const char *sep
);
96 } // end anonymous namespace
98 ConstraintManager
* clang::CreateBasicConstraintManager(GRStateManager
& statemgr
,
99 GRSubEngine
&subengine
) {
100 return new BasicConstraintManager(statemgr
, subengine
);
105 BasicConstraintManager::assumeSymNE(const GRState
*state
, SymbolRef sym
,
106 const llvm::APSInt
&V
,
107 const llvm::APSInt
&Adjustment
) {
108 // First, determine if sym == X, where X+Adjustment != V.
109 llvm::APSInt Adjusted
= V
-Adjustment
;
110 if (const llvm::APSInt
* X
= getSymVal(state
, sym
)) {
111 bool isFeasible
= (*X
!= Adjusted
);
112 return isFeasible
? state
: NULL
;
115 // Second, determine if sym+Adjustment != V.
116 if (isNotEqual(state
, sym
, Adjusted
))
119 // If we reach here, sym is not a constant and we don't know if it is != V.
120 // Make that assumption.
121 return AddNE(state
, sym
, Adjusted
);
125 BasicConstraintManager::assumeSymEQ(const GRState
*state
, SymbolRef sym
,
126 const llvm::APSInt
&V
,
127 const llvm::APSInt
&Adjustment
) {
128 // First, determine if sym == X, where X+Adjustment != V.
129 llvm::APSInt Adjusted
= V
-Adjustment
;
130 if (const llvm::APSInt
* X
= getSymVal(state
, sym
)) {
131 bool isFeasible
= (*X
== Adjusted
);
132 return isFeasible
? state
: NULL
;
135 // Second, determine if sym+Adjustment != V.
136 if (isNotEqual(state
, sym
, Adjusted
))
139 // If we reach here, sym is not a constant and we don't know if it is == V.
140 // Make that assumption.
141 return AddEQ(state
, sym
, Adjusted
);
144 // The logic for these will be handled in another ConstraintManager.
146 BasicConstraintManager::assumeSymLT(const GRState
*state
, SymbolRef sym
,
147 const llvm::APSInt
&V
,
148 const llvm::APSInt
&Adjustment
) {
149 // Is 'V' the smallest possible value?
150 if (V
== llvm::APSInt::getMinValue(V
.getBitWidth(), V
.isUnsigned())) {
151 // sym cannot be any value less than 'V'. This path is infeasible.
155 // FIXME: For now have assuming x < y be the same as assuming sym != V;
156 return assumeSymNE(state
, sym
, V
, Adjustment
);
160 BasicConstraintManager::assumeSymGT(const GRState
*state
, SymbolRef sym
,
161 const llvm::APSInt
&V
,
162 const llvm::APSInt
&Adjustment
) {
163 // Is 'V' the largest possible value?
164 if (V
== llvm::APSInt::getMaxValue(V
.getBitWidth(), V
.isUnsigned())) {
165 // sym cannot be any value greater than 'V'. This path is infeasible.
169 // FIXME: For now have assuming x > y be the same as assuming sym != V;
170 return assumeSymNE(state
, sym
, V
, Adjustment
);
174 BasicConstraintManager::assumeSymGE(const GRState
*state
, SymbolRef sym
,
175 const llvm::APSInt
&V
,
176 const llvm::APSInt
&Adjustment
) {
177 // Reject a path if the value of sym is a constant X and !(X+Adj >= V).
178 if (const llvm::APSInt
*X
= getSymVal(state
, sym
)) {
179 bool isFeasible
= (*X
>= V
-Adjustment
);
180 return isFeasible
? state
: NULL
;
183 // Sym is not a constant, but it is worth looking to see if V is the
184 // maximum integer value.
185 if (V
== llvm::APSInt::getMaxValue(V
.getBitWidth(), V
.isUnsigned())) {
186 llvm::APSInt Adjusted
= V
-Adjustment
;
188 // If we know that sym != V (after adjustment), then this condition
189 // is infeasible since there is no other value greater than V.
190 bool isFeasible
= !isNotEqual(state
, sym
, Adjusted
);
192 // If the path is still feasible then as a consequence we know that
193 // 'sym+Adjustment == V' because there are no larger values.
194 // Add this constraint.
195 return isFeasible
? AddEQ(state
, sym
, Adjusted
) : NULL
;
202 BasicConstraintManager::assumeSymLE(const GRState
*state
, SymbolRef sym
,
203 const llvm::APSInt
&V
,
204 const llvm::APSInt
&Adjustment
) {
205 // Reject a path if the value of sym is a constant X and !(X+Adj <= V).
206 if (const llvm::APSInt
* X
= getSymVal(state
, sym
)) {
207 bool isFeasible
= (*X
<= V
-Adjustment
);
208 return isFeasible
? state
: NULL
;
211 // Sym is not a constant, but it is worth looking to see if V is the
212 // minimum integer value.
213 if (V
== llvm::APSInt::getMinValue(V
.getBitWidth(), V
.isUnsigned())) {
214 llvm::APSInt Adjusted
= V
-Adjustment
;
216 // If we know that sym != V (after adjustment), then this condition
217 // is infeasible since there is no other value less than V.
218 bool isFeasible
= !isNotEqual(state
, sym
, Adjusted
);
220 // If the path is still feasible then as a consequence we know that
221 // 'sym+Adjustment == V' because there are no smaller values.
222 // Add this constraint.
223 return isFeasible
? AddEQ(state
, sym
, Adjusted
) : NULL
;
229 const GRState
* BasicConstraintManager::AddEQ(const GRState
* state
, SymbolRef sym
,
230 const llvm::APSInt
& V
) {
231 // Create a new state with the old binding replaced.
232 return state
->set
<ConstEq
>(sym
, &state
->getBasicVals().getValue(V
));
235 const GRState
* BasicConstraintManager::AddNE(const GRState
* state
, SymbolRef sym
,
236 const llvm::APSInt
& V
) {
238 // First, retrieve the NE-set associated with the given symbol.
239 ConstNotEqTy::data_type
* T
= state
->get
<ConstNotEq
>(sym
);
240 GRState::IntSetTy S
= T
? *T
: ISetFactory
.getEmptySet();
242 // Now add V to the NE set.
243 S
= ISetFactory
.add(S
, &state
->getBasicVals().getValue(V
));
245 // Create a new state with the old binding replaced.
246 return state
->set
<ConstNotEq
>(sym
, S
);
249 const llvm::APSInt
* BasicConstraintManager::getSymVal(const GRState
* state
,
250 SymbolRef sym
) const {
251 const ConstEqTy::data_type
* T
= state
->get
<ConstEq
>(sym
);
252 return T
? *T
: NULL
;
255 bool BasicConstraintManager::isNotEqual(const GRState
* state
, SymbolRef sym
,
256 const llvm::APSInt
& V
) const {
258 // Retrieve the NE-set associated with the given symbol.
259 const ConstNotEqTy::data_type
* T
= state
->get
<ConstNotEq
>(sym
);
261 // See if V is present in the NE-set.
262 return T
? T
->contains(&state
->getBasicVals().getValue(V
)) : false;
265 bool BasicConstraintManager::isEqual(const GRState
* state
, SymbolRef sym
,
266 const llvm::APSInt
& V
) const {
267 // Retrieve the EQ-set associated with the given symbol.
268 const ConstEqTy::data_type
* T
= state
->get
<ConstEq
>(sym
);
269 // See if V is present in the EQ-set.
270 return T
? **T
== V
: false;
273 /// Scan all symbols referenced by the constraints. If the symbol is not alive
274 /// as marked in LSymbols, mark it as dead in DSymbols.
276 BasicConstraintManager::RemoveDeadBindings(const GRState
* state
,
277 SymbolReaper
& SymReaper
) {
279 ConstEqTy CE
= state
->get
<ConstEq
>();
280 ConstEqTy::Factory
& CEFactory
= state
->get_context
<ConstEq
>();
282 for (ConstEqTy::iterator I
= CE
.begin(), E
= CE
.end(); I
!=E
; ++I
) {
283 SymbolRef sym
= I
.getKey();
284 if (SymReaper
.maybeDead(sym
))
285 CE
= CEFactory
.remove(CE
, sym
);
287 state
= state
->set
<ConstEq
>(CE
);
289 ConstNotEqTy CNE
= state
->get
<ConstNotEq
>();
290 ConstNotEqTy::Factory
& CNEFactory
= state
->get_context
<ConstNotEq
>();
292 for (ConstNotEqTy::iterator I
= CNE
.begin(), E
= CNE
.end(); I
!= E
; ++I
) {
293 SymbolRef sym
= I
.getKey();
294 if (SymReaper
.maybeDead(sym
))
295 CNE
= CNEFactory
.remove(CNE
, sym
);
298 return state
->set
<ConstNotEq
>(CNE
);
301 void BasicConstraintManager::print(const GRState
* state
, llvm::raw_ostream
& Out
,
302 const char* nl
, const char *sep
) {
303 // Print equality constraints.
305 ConstEqTy CE
= state
->get
<ConstEq
>();
308 Out
<< nl
<< sep
<< "'==' constraints:";
309 for (ConstEqTy::iterator I
= CE
.begin(), E
= CE
.end(); I
!=E
; ++I
)
310 Out
<< nl
<< " $" << I
.getKey() << " : " << *I
.getData();
313 // Print != constraints.
315 ConstNotEqTy CNE
= state
->get
<ConstNotEq
>();
317 if (!CNE
.isEmpty()) {
318 Out
<< nl
<< sep
<< "'!=' constraints:";
320 for (ConstNotEqTy::iterator I
= CNE
.begin(), EI
= CNE
.end(); I
!=EI
; ++I
) {
321 Out
<< nl
<< " $" << I
.getKey() << " : ";
324 GRState::IntSetTy::iterator J
= I
.getData().begin(),
325 EJ
= I
.getData().end();
327 for ( ; J
!= EJ
; ++J
) {
328 if (isFirst
) isFirst
= false;
331 Out
<< (*J
)->getSExtValue(); // Hack: should print to raw_ostream.