blob: 55451a959ee03e9f50a1bf342c5b1af946955b5d [file] [log] [blame]
Ted Kremenek9153f732008-02-05 07:17:49 +00001//= ValueState.cpp - Path-Sens. "State" for tracking valuues -----*- C++ -*--=//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This files defines SymbolID, VarBindKey, and ValueState.
11//
12//===----------------------------------------------------------------------===//
13
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +000014#include "ValueState.h"
15
16using namespace clang;
17
Ted Kremenek862d5bb2008-02-06 00:54:14 +000018bool ValueState::isNotEqual(SymbolID sym, const llvm::APSInt& V) const {
19 // First, retrieve the NE-set associated with the given symbol.
20 ConstantNotEqTy::TreeTy* T = Data->ConstantNotEq.SlimFind(sym);
21
22 if (!T)
23 return false;
24
25 // Second, see if V is present in the NE-set.
26 return T->getValue().second.contains(&V);
27}
28
29const llvm::APSInt* ValueState::getSymVal(SymbolID sym) const {
30 ConstantEqTy::TreeTy* T = Data->ConstantEq.SlimFind(sym);
31 return T ? T->getValue().second : NULL;
32}
33
Ted Kremenekb87d9092008-02-08 19:17:19 +000034ValueState
35ValueStateManager::RemoveDeadBindings(ValueState St, Stmt* Loc,
36 const LiveVariables& Liveness) {
37
38 // This code essentially performs a "mark-and-sweep" of the VariableBindings.
39 // The roots are any Block-level exprs and Decls that our liveness algorithm
40 // tells us are live. We then see what Decls they may reference, and keep
41 // those around. This code more than likely can be made faster, and the
42 // frequency of which this method is called should be experimented with
43 // for optimum performance.
44
45 llvm::SmallVector<ValueDecl*, 10> WList;
46
47 for (StateTy::vb_iterator I = St.begin(), E = St.end(); I!=E ; ++I) {
48
49 // Remove old bindings for subexpressions.
50 if (I.getKey().isSubExpr()) {
51 St = Remove(St, I.getKey());
52 continue;
53 }
54
55 if (I.getKey().isBlkExpr()) {
56 if (Liveness.isLive(Loc, cast<Stmt>(I.getKey()))) {
57 if (isa<lval::DeclVal>(I.getData())) {
58 lval::DeclVal LV = cast<lval::DeclVal>(I.getData());
59 WList.push_back(LV.getDecl());
60 }
61 }
62 else
63 St = Remove(St, I.getKey());
64
65 continue;
66 }
67
68 assert (I.getKey().isDecl());
69
70 if (VarDecl* V = dyn_cast<VarDecl>(cast<ValueDecl>(I.getKey())))
71 if (Liveness.isLive(Loc, V))
72 WList.push_back(V);
73 }
74
75 llvm::SmallPtrSet<ValueDecl*, 10> Marked;
76
77 while (!WList.empty()) {
78 ValueDecl* V = WList.back();
79 WList.pop_back();
80
81 if (Marked.count(V))
82 continue;
83
84 Marked.insert(V);
85
86 if (V->getType()->isPointerType()) {
87 const LValue& LV = cast<LValue>(GetValue(St, lval::DeclVal(V)));
88
89 if (!isa<lval::DeclVal>(LV))
90 continue;
91
92 const lval::DeclVal& LVD = cast<lval::DeclVal>(LV);
93 WList.push_back(LVD.getDecl());
94 }
95 }
96
97 for (StateTy::vb_iterator I = St.begin(), E = St.end(); I!=E ; ++I)
98 if (I.getKey().isDecl())
99 if (VarDecl* V = dyn_cast<VarDecl>(cast<ValueDecl>(I.getKey())))
100 if (!Marked.count(V))
101 St = Remove(St, V);
102
103 return St;
104}
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000105
106
Ted Kremenekd131c4f2008-02-07 05:48:01 +0000107RValue ValueStateManager::GetValue(const StateTy& St, const LValue& LV,
108 QualType* T) {
Ted Kremenek22031182008-02-08 02:57:34 +0000109 if (isa<UnknownVal>(LV))
110 return UnknownVal();
Ted Kremenek3271f8d2008-02-07 04:16:04 +0000111
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +0000112 switch (LV.getSubKind()) {
Ted Kremenek329f8542008-02-05 21:52:21 +0000113 case lval::DeclValKind: {
Ted Kremenek53c641a2008-02-08 03:02:48 +0000114 StateTy::VarBindingsTy::TreeTy* T =
115 St.getImpl()->VarBindings.SlimFind(cast<lval::DeclVal>(LV).getDecl());
Ted Kremenek9153f732008-02-05 07:17:49 +0000116
Ted Kremenek22031182008-02-08 02:57:34 +0000117 return T ? T->getValue().second : UnknownVal();
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +0000118 }
Ted Kremenekd131c4f2008-02-07 05:48:01 +0000119
120 // FIXME: We should bind how far a "ContentsOf" will go...
121
122 case lval::SymbolValKind: {
123 const lval::SymbolVal& SV = cast<lval::SymbolVal>(LV);
124 assert (T);
125
126 if (T->getTypePtr()->isPointerType())
127 return lval::SymbolVal(SymMgr.getContentsOfSymbol(SV.getSymbol()));
128 else
129 return nonlval::SymbolVal(SymMgr.getContentsOfSymbol(SV.getSymbol()));
130 }
131
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +0000132 default:
133 assert (false && "Invalid LValue.");
134 break;
135 }
136
Ted Kremenek22031182008-02-08 02:57:34 +0000137 return UnknownVal();
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +0000138}
139
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000140ValueStateManager::StateTy
141ValueStateManager::AddNE(StateTy St, SymbolID sym, const llvm::APSInt& V) {
142 // First, retrieve the NE-set associated with the given symbol.
143 ValueState::ConstantNotEqTy::TreeTy* T =
144 St.getImpl()->ConstantNotEq.SlimFind(sym);
145
146 ValueState::IntSetTy S = T ? T->getValue().second : ISetFactory.GetEmptySet();
147
148 // Now add V to the NE set.
149 S = ISetFactory.Add(S, &V);
150
151 // Create a new state with the old binding replaced.
152 ValueStateImpl NewStateImpl = *St.getImpl();
153 NewStateImpl.ConstantNotEq = CNEFactory.Add(NewStateImpl.ConstantNotEq,
154 sym, S);
155
156 // Get the persistent copy.
157 return getPersistentState(NewStateImpl);
158}
159
160ValueStateManager::StateTy
161ValueStateManager::AddEQ(StateTy St, SymbolID sym, const llvm::APSInt& V) {
162 // Create a new state with the old binding replaced.
163 ValueStateImpl NewStateImpl = *St.getImpl();
164 NewStateImpl.ConstantEq = CEFactory.Add(NewStateImpl.ConstantEq, sym, &V);
165
166 // Get the persistent copy.
167 return getPersistentState(NewStateImpl);
168}
169
Ted Kremenekf233d482008-02-05 00:26:40 +0000170RValue ValueStateManager::GetValue(const StateTy& St, Stmt* S, bool* hasVal) {
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +0000171 for (;;) {
172 switch (S->getStmtClass()) {
173
174 // ParenExprs are no-ops.
175
176 case Stmt::ParenExprClass:
177 S = cast<ParenExpr>(S)->getSubExpr();
178 continue;
179
180 // DeclRefExprs can either evaluate to an LValue or a Non-LValue
181 // (assuming an implicit "load") depending on the context. In this
182 // context we assume that we are retrieving the value contained
183 // within the referenced variables.
184
185 case Stmt::DeclRefExprClass:
Ted Kremenek329f8542008-02-05 21:52:21 +0000186 return GetValue(St, lval::DeclVal(cast<DeclRefExpr>(S)->getDecl()));
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +0000187
188 // Integer literals evaluate to an RValue. Simply retrieve the
189 // RValue for the literal.
190
191 case Stmt::IntegerLiteralClass:
192 return NonLValue::GetValue(ValMgr, cast<IntegerLiteral>(S));
193
194 // Casts where the source and target type are the same
195 // are no-ops. We blast through these to get the descendant
196 // subexpression that has a value.
197
198 case Stmt::ImplicitCastExprClass: {
199 ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
200 if (C->getType() == C->getSubExpr()->getType()) {
201 S = C->getSubExpr();
202 continue;
203 }
204 break;
205 }
206
207 case Stmt::CastExprClass: {
208 CastExpr* C = cast<CastExpr>(S);
209 if (C->getType() == C->getSubExpr()->getType()) {
210 S = C->getSubExpr();
211 continue;
212 }
213 break;
214 }
215
216 // Handle all other Stmt* using a lookup.
217
218 default:
219 break;
220 };
221
222 break;
223 }
224
Ted Kremenek53c641a2008-02-08 03:02:48 +0000225 StateTy::VarBindingsTy::TreeTy* T =
226 St.getImpl()->VarBindings.SlimFind(S);
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +0000227
Ted Kremenekf233d482008-02-05 00:26:40 +0000228 if (T) {
229 if (hasVal) *hasVal = true;
230 return T->getValue().second;
231 }
232 else {
233 if (hasVal) *hasVal = false;
Ted Kremenek22031182008-02-08 02:57:34 +0000234 return UnknownVal();
Ted Kremenekf233d482008-02-05 00:26:40 +0000235 }
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +0000236}
237
238LValue ValueStateManager::GetLValue(const StateTy& St, Stmt* S) {
239
240 while (ParenExpr* P = dyn_cast<ParenExpr>(S))
241 S = P->getSubExpr();
242
243 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S))
Ted Kremenek329f8542008-02-05 21:52:21 +0000244 return lval::DeclVal(DR->getDecl());
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +0000245
Ted Kremenek5b6dc2d2008-02-07 01:08:27 +0000246 if (UnaryOperator* U = dyn_cast<UnaryOperator>(S))
247 if (U->getOpcode() == UnaryOperator::Deref)
248 return cast<LValue>(GetValue(St, U->getSubExpr()));
249
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +0000250 return cast<LValue>(GetValue(St, S));
251}
252
253
254ValueStateManager::StateTy
255ValueStateManager::SetValue(StateTy St, Stmt* S, bool isBlkExpr,
256 const RValue& V) {
257
258 assert (S);
Ted Kremenek22031182008-02-08 02:57:34 +0000259 return V.isKnown() ? Add(St, VarBindKey(S, isBlkExpr), V) : St;
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +0000260}
261
262ValueStateManager::StateTy
263ValueStateManager::SetValue(StateTy St, const LValue& LV, const RValue& V) {
264
265 switch (LV.getSubKind()) {
Ted Kremenek329f8542008-02-05 21:52:21 +0000266 case lval::DeclValKind:
Ted Kremenek22031182008-02-08 02:57:34 +0000267 return V.isKnown() ? Add(St, cast<lval::DeclVal>(LV).getDecl(), V)
Ted Kremenek329f8542008-02-05 21:52:21 +0000268 : Remove(St, cast<lval::DeclVal>(LV).getDecl());
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +0000269
270 default:
271 assert ("SetValue for given LValue type not yet implemented.");
272 return St;
273 }
274}
275
Ted Kremenek9153f732008-02-05 07:17:49 +0000276ValueStateManager::StateTy
277ValueStateManager::Remove(StateTy St, VarBindKey K) {
278
279 // Create a new state with the old binding removed.
280 ValueStateImpl NewStateImpl = *St.getImpl();
Ted Kremenek53c641a2008-02-08 03:02:48 +0000281 NewStateImpl.VarBindings =
282 VBFactory.Remove(NewStateImpl.VarBindings, K);
Ted Kremenek9153f732008-02-05 07:17:49 +0000283
284 // Get the persistent copy.
285 return getPersistentState(NewStateImpl);
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +0000286}
Ted Kremenek9153f732008-02-05 07:17:49 +0000287
288ValueStateManager::StateTy
289ValueStateManager::Add(StateTy St, VarBindKey K, const RValue& V) {
Ted Kremenekf66ea2cd2008-02-04 21:59:22 +0000290
Ted Kremenek9153f732008-02-05 07:17:49 +0000291 // Create a new state with the old binding removed.
292 ValueStateImpl NewStateImpl = *St.getImpl();
Ted Kremenek53c641a2008-02-08 03:02:48 +0000293 NewStateImpl.VarBindings =
294 VBFactory.Add(NewStateImpl.VarBindings, K, V);
Ted Kremenek9153f732008-02-05 07:17:49 +0000295
296 // Get the persistent copy.
297 return getPersistentState(NewStateImpl);
298}
299
300
301ValueStateManager::StateTy
302ValueStateManager::getInitialState() {
303
304 // Create a state with empty variable bindings.
Ted Kremenek174aea42008-02-05 18:51:06 +0000305 ValueStateImpl StateImpl(VBFactory.GetEmptyMap(),
Ted Kremenek862d5bb2008-02-06 00:54:14 +0000306 CNEFactory.GetEmptyMap(),
307 CEFactory.GetEmptyMap());
Ted Kremenek9153f732008-02-05 07:17:49 +0000308
309 return getPersistentState(StateImpl);
310}
311
312ValueStateManager::StateTy
313ValueStateManager::getPersistentState(const ValueStateImpl &State) {
314
315 llvm::FoldingSetNodeID ID;
316 State.Profile(ID);
317 void* InsertPos;
318
319 if (ValueStateImpl* I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
320 return I;
321
Ted Kremenek41652a92008-02-06 02:45:20 +0000322 ValueStateImpl* I = (ValueStateImpl*) Alloc.Allocate<ValueStateImpl>();
Ted Kremenek9153f732008-02-05 07:17:49 +0000323 new (I) ValueStateImpl(State);
324 StateSet.InsertNode(I, InsertPos);
325 return I;
326}