blob: 8bd58facf2f84370bc3eee77fd4c4612e818f4f5 [file] [log] [blame]
Ted Kremenekd27f8162008-01-15 23:55:06 +00001//===-- GRConstants.cpp - Simple, Path-Sens. Constant Prop. ------*- C++ -*-==//
2//
Ted Kremenekab2b8c52008-01-23 19:59:44 +00003// The LLValM Compiler Infrastructure
Ted Kremenekd27f8162008-01-15 23:55:06 +00004//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Constant Propagation via Graph Reachability
11//
12// This files defines a simple analysis that performs path-sensitive
13// constant propagation within a function. An example use of this analysis
14// is to perform simple checks for NULL dereferences.
15//
16//===----------------------------------------------------------------------===//
17
18#include "clang/Analysis/PathSensitive/GREngine.h"
19#include "clang/AST/Expr.h"
20#include "clang/Analysis/Analyses/LiveVariables.h"
Ted Kremenekd27f8162008-01-15 23:55:06 +000021
22#include "llvm/Support/Casting.h"
23#include "llvm/Support/DataTypes.h"
24#include "llvm/ADT/APSInt.h"
25#include "llvm/ADT/FoldingSet.h"
26#include "llvm/ADT/ImmutableMap.h"
Ted Kremenek3c6c6722008-01-16 17:56:25 +000027#include "llvm/ADT/SmallVector.h"
Ted Kremenekab2b8c52008-01-23 19:59:44 +000028#include "llvm/Support/Allocator.h"
Ted Kremenekd27f8162008-01-15 23:55:06 +000029#include "llvm/Support/Compiler.h"
30
Ted Kremenekab2b8c52008-01-23 19:59:44 +000031#include "llvm/Support/Streams.h"
32
Ted Kremenekaa66a322008-01-16 21:46:15 +000033#ifndef NDEBUG
34#include "llvm/Support/GraphWriter.h"
35#include <sstream>
36#endif
37
Ted Kremenekd27f8162008-01-15 23:55:06 +000038using namespace clang;
Ted Kremenekd27f8162008-01-15 23:55:06 +000039using llvm::dyn_cast;
40using llvm::cast;
41
42//===----------------------------------------------------------------------===//
Ted Kremenekab2b8c52008-01-23 19:59:44 +000043/// ValueKey - A variant smart pointer that wraps either a ValueDecl* or a
Ted Kremenekd27f8162008-01-15 23:55:06 +000044/// Stmt*. Use cast<> or dyn_cast<> to get actual pointer type
45//===----------------------------------------------------------------------===//
46namespace {
Ted Kremenekab2b8c52008-01-23 19:59:44 +000047
48class VISIBILITY_HIDDEN ValueKey {
Ted Kremenek0525a4f2008-01-16 19:47:19 +000049 uintptr_t Raw;
Ted Kremenekd27f8162008-01-15 23:55:06 +000050public:
Ted Kremenekab2b8c52008-01-23 19:59:44 +000051 enum Kind { IsSubExp=0x0, IsDecl=0x1, IsBlkExpr=0x2, Flags=0x3 };
Ted Kremenekd27f8162008-01-15 23:55:06 +000052 inline void* getPtr() const { return reinterpret_cast<void*>(Raw & ~Flags); }
Ted Kremenekab2b8c52008-01-23 19:59:44 +000053 inline Kind getKind() const { return (Kind) (Raw & Flags); }
Ted Kremenekd27f8162008-01-15 23:55:06 +000054
Ted Kremenekab2b8c52008-01-23 19:59:44 +000055 ValueKey(const ValueDecl* VD)
56 : Raw(reinterpret_cast<uintptr_t>(VD) | IsDecl) {}
57
58 ValueKey(Stmt* S, bool isBlkExpr)
59 : Raw(reinterpret_cast<uintptr_t>(S) | (isBlkExpr ? IsBlkExpr : IsSubExp)){}
Ted Kremenekd27f8162008-01-15 23:55:06 +000060
61 bool isSubExpr() const { return getKind() == IsSubExp; }
Ted Kremenekab2b8c52008-01-23 19:59:44 +000062 bool isDecl() const { return getKind() == IsDecl; }
Ted Kremenekd27f8162008-01-15 23:55:06 +000063
64 inline void Profile(llvm::FoldingSetNodeID& ID) const {
Ted Kremenek98491852008-01-16 05:51:13 +000065 ID.AddPointer(getPtr());
66 ID.AddInteger((unsigned) getKind());
Ted Kremenekab2b8c52008-01-23 19:59:44 +000067 }
68
69 inline bool operator==(const ValueKey& X) const {
70 return Raw == X.Raw;
71 }
72
73 inline bool operator!=(const ValueKey& X) const {
74 return !operator==(X);
75 }
76
77 inline bool operator<(const ValueKey& X) const {
78 Kind k = getKind(), Xk = X.getKind();
79
80 return k == Xk ? getPtr() < X.getPtr()
81 : ((unsigned) k) < ((unsigned) Xk);
Ted Kremenekb3d2dca2008-01-16 23:33:44 +000082 }
Ted Kremenekd27f8162008-01-15 23:55:06 +000083};
84} // end anonymous namespace
85
Ted Kremenekab2b8c52008-01-23 19:59:44 +000086// Machinery to get cast<> and dyn_cast<> working with ValueKey.
Ted Kremenekd27f8162008-01-15 23:55:06 +000087namespace llvm {
Ted Kremenekab2b8c52008-01-23 19:59:44 +000088 template<> inline bool isa<ValueDecl,ValueKey>(const ValueKey& V) {
89 return V.getKind() == ValueKey::IsDecl;
Ted Kremenekd27f8162008-01-15 23:55:06 +000090 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +000091 template<> inline bool isa<Stmt,ValueKey>(const ValueKey& V) {
92 return ((unsigned) V.getKind()) != ValueKey::IsDecl;
Ted Kremenekd27f8162008-01-15 23:55:06 +000093 }
Ted Kremenekab2b8c52008-01-23 19:59:44 +000094 template<> struct VISIBILITY_HIDDEN cast_retty_impl<ValueDecl,ValueKey> {
Ted Kremenekaa66a322008-01-16 21:46:15 +000095 typedef const ValueDecl* ret_type;
Ted Kremenekd27f8162008-01-15 23:55:06 +000096 };
Ted Kremenekab2b8c52008-01-23 19:59:44 +000097 template<> struct VISIBILITY_HIDDEN cast_retty_impl<Stmt,ValueKey> {
Ted Kremenekd27f8162008-01-15 23:55:06 +000098 typedef const Stmt* ret_type;
99 };
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000100 template<> struct VISIBILITY_HIDDEN simplify_type<ValueKey> {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000101 typedef void* SimpleType;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000102 static inline SimpleType getSimplifiedValue(const ValueKey &V) {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000103 return V.getPtr();
104 }
105 };
106} // end llvm namespace
107
108//===----------------------------------------------------------------------===//
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000109// ValueManager.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000110//===----------------------------------------------------------------------===//
111
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000112namespace {
113
114typedef llvm::ImmutableSet<llvm::APSInt > APSIntSetTy;
115
116class VISIBILITY_HIDDEN ValueManager {
117
118
119 APSIntSetTy::Factory APSIntSetFactory;
120
121public:
122 ValueManager() {}
123 ~ValueManager() {}
124
125 APSIntSetTy GetEmptyAPSIntSet() {
126 return APSIntSetFactory.GetEmptySet();
127 }
128
129 APSIntSetTy AddToSet(const APSIntSetTy& Set, const llvm::APSInt& Val) {
130 return APSIntSetFactory.Add(Set, Val);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000131 }
132};
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000133} // end anonymous namespace
134
135//===----------------------------------------------------------------------===//
136// Expression Values.
137//===----------------------------------------------------------------------===//
138
139namespace {
140
141class VISIBILITY_HIDDEN ExprValue {
142public:
143 enum Kind { // L-Values.
144 LValueDeclKind = 0x0,
145 // Special "Invalid" value.
146 InvalidValueKind = 0x1,
147 // R-Values.
148 RValueMayEqualSetKind = 0x2,
149 // Note that the Lvalue and RValue "kinds" overlap;
150 // the "InvalidValue" class can be used either as
151 // an LValue or RValue.
152 MinLValueKind = 0x0, MaxLValueKind = 0x1,
153 MinRValueKind = 0x1, MaxRValueKind = 0x2 };
154
155private:
156 enum Kind kind;
157 void* Data;
158
159protected:
160 ExprValue(Kind k, void* d) : kind(k), Data(d) {}
161
162 void* getRawPtr() const { return Data; }
163
164public:
165 ~ExprValue() {};
166
167 void Profile(llvm::FoldingSetNodeID& ID) const {
168 ID.AddInteger((unsigned) getKind());
169 ID.AddPointer(Data);
170 }
171
172 bool operator==(const ExprValue& RHS) const {
173 return kind == RHS.kind && Data == RHS.Data;
174 }
175
176 Kind getKind() const { return kind; }
177 bool isValid() const { return getKind() != InvalidValueKind; }
178
179 void print(std::ostream& OS) const;
180 void print() const { print(*llvm::cerr.stream()); }
181
182 // Implement isa<T> support.
183 static inline bool classof(const ExprValue*) { return true; }
184};
185
186class VISIBILITY_HIDDEN InvalidValue : public ExprValue {
187public:
188 InvalidValue() : ExprValue(InvalidValueKind, NULL) {}
189
190 static inline bool classof(const ExprValue* V) {
191 return V->getKind() == InvalidValueKind;
192 }
193};
194
195} // end anonymous namespace
196
197//===----------------------------------------------------------------------===//
198// "R-Values": Interface.
199//===----------------------------------------------------------------------===//
200
201namespace {
202class VISIBILITY_HIDDEN RValue : public ExprValue {
203protected:
204 RValue(Kind k, void* d) : ExprValue(k,d) {}
205
206public:
207 RValue Add(ValueManager& ValMgr, const RValue& RHS) const;
208 RValue Sub(ValueManager& ValMgr, const RValue& RHS) const;
209
210 static RValue GetRValue(ValueManager& ValMgr, IntegerLiteral* S);
211
212 // Implement isa<T> support.
213 static inline bool classof(const ExprValue* V) {
214 return V->getKind() >= MinRValueKind;
215 }
216};
217
218class VISIBILITY_HIDDEN RValueMayEqualSet : public RValue {
219public:
220 RValueMayEqualSet(const APSIntSetTy& S)
221 : RValue(RValueMayEqualSetKind, S.getRoot()) {}
222
223 APSIntSetTy GetValues() const {
224 return APSIntSetTy(reinterpret_cast<APSIntSetTy::TreeTy*>(getRawPtr()));
225 }
226
227 RValueMayEqualSet Add(ValueManager& ValMgr, const RValueMayEqualSet& V) const;
228 RValueMayEqualSet Sub(ValueManager& ValMgr, const RValueMayEqualSet& V) const;
229
230 // Implement isa<T> support.
231 static inline bool classof(const ExprValue* V) {
232 return V->getKind() == RValueMayEqualSetKind;
233 }
234};
235} // end anonymous namespace
236
237//===----------------------------------------------------------------------===//
238// "R-Values": Implementation.
239//===----------------------------------------------------------------------===//
240
241#define RVALUE_DISPATCH_CASE(k1,k2,Op)\
242case ((k1##Kind+(MaxRValueKind-MinRValueKind))+(k2##Kind - MinRValueKind)):\
243 return cast<k1>(*this).Op(ValMgr,cast<k2>(RHS));
244
245#define RVALUE_DISPATCH(Op)\
246switch (getKind()+(MaxRValueKind-MinRValueKind)+(RHS.getKind()-MinRValueKind)){\
247 RVALUE_DISPATCH_CASE(RValueMayEqualSet,RValueMayEqualSet,Op)\
248 default:\
249 assert (!isValid() || !RHS.isValid() && "Missing case.");\
250 break;\
251}\
252return cast<RValue>(InvalidValue());
253
254RValue RValue::Add(ValueManager& ValMgr, const RValue& RHS) const {
255 RVALUE_DISPATCH(Add)
256}
257
258RValue RValue::Sub(ValueManager& ValMgr, const RValue& RHS) const {
259 RVALUE_DISPATCH(Sub)
260}
261
262#undef RVALUE_DISPATCH_CASE
263#undef RVALUE_DISPATCH
264
265RValueMayEqualSet
266RValueMayEqualSet::Add(ValueManager& ValMgr,
267 const RValueMayEqualSet& RHS) const {
268
269 APSIntSetTy S1 = GetValues();
270 APSIntSetTy S2 = RHS.GetValues();
271
272 APSIntSetTy M = ValMgr.GetEmptyAPSIntSet();
273
274 for (APSIntSetTy::iterator I1=S1.begin(), E1=S2.end(); I1!=E1; ++I1)
275 for (APSIntSetTy::iterator I2=S2.begin(), E2=S2.end(); I2!=E2; ++I2)
276 M = ValMgr.AddToSet(M, *I1 + *I2);
277
278 return M;
279}
280
281RValueMayEqualSet
282RValueMayEqualSet::Sub(ValueManager& ValMgr,
283 const RValueMayEqualSet& RHS) const {
284
285 APSIntSetTy S1 = GetValues();
286 APSIntSetTy S2 = RHS.GetValues();
287
288 APSIntSetTy M = ValMgr.GetEmptyAPSIntSet();
289
290 for (APSIntSetTy::iterator I1=S1.begin(), E1=S2.end(); I1!=E1; ++I1)
291 for (APSIntSetTy::iterator I2=S2.begin(), E2=S2.end(); I2!=E2; ++I2)
292 M = ValMgr.AddToSet(M, *I1 - *I2);
293
294 return M;
295}
296
297RValue RValue::GetRValue(ValueManager& ValMgr, IntegerLiteral* S) {
298 return RValueMayEqualSet(ValMgr.AddToSet(ValMgr.GetEmptyAPSIntSet(),
299 S->getValue()));
300}
301
302//===----------------------------------------------------------------------===//
303// "L-Values".
304//===----------------------------------------------------------------------===//
305
306namespace {
307
308class VISIBILITY_HIDDEN LValue : public ExprValue {
309protected:
310 LValue(Kind k, void* D) : ExprValue(k, D) {}
311
312public:
313 // Implement isa<T> support.
314 static inline bool classof(const ExprValue* V) {
315 return V->getKind() <= MaxLValueKind;
316 }
317};
318
319class VISIBILITY_HIDDEN LValueDecl : public LValue {
320public:
321 LValueDecl(ValueDecl* vd) : LValue(LValueDeclKind,vd) {}
322
323 ValueDecl* getDecl() const {
324 return static_cast<ValueDecl*>(getRawPtr());
325 }
326
327 // Implement isa<T> support.
328 static inline bool classof(const ExprValue* V) {
329 return V->getKind() == LValueDeclKind;
330 }
331};
332} // end anonymous namespace
333
334//===----------------------------------------------------------------------===//
335// Pretty-Printing.
336//===----------------------------------------------------------------------===//
337
338void ExprValue::print(std::ostream& Out) const {
339 switch (getKind()) {
340 case InvalidValueKind:
341 Out << "Invalid"; break;
342
343 case RValueMayEqualSetKind: {
344 Out << "MayEqual{";
345 APSIntSetTy S = cast<RValueMayEqualSet>(this)->GetValues();
346
347 for (APSIntSetTy::iterator I=S.begin(), E=S.end(); I!=E; ++I)
348 Out << ' ' << (*I).toString();
349
350 Out << " }";
351 break;
352 }
353
354 default:
355 assert (false && "Pretty-printed not implemented for this ExprValue.");
356 break;
357 }
358}
359
360//===----------------------------------------------------------------------===//
361// ValueMapTy - A ImmutableMap type Stmt*/Decl* to ExprValues.
362//===----------------------------------------------------------------------===//
363
364typedef llvm::ImmutableMap<ValueKey,ExprValue> ValueMapTy;
365
366namespace clang {
367 template<>
368 struct VISIBILITY_HIDDEN GRTrait<ValueMapTy> {
369 static inline void* toPtr(ValueMapTy M) {
370 return reinterpret_cast<void*>(M.getRoot());
371 }
372 static inline ValueMapTy toState(void* P) {
373 return ValueMapTy(static_cast<ValueMapTy::TreeTy*>(P));
374 }
375 };
Ted Kremenekd27f8162008-01-15 23:55:06 +0000376}
377
378//===----------------------------------------------------------------------===//
379// The Checker!
380//===----------------------------------------------------------------------===//
381
382namespace {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000383
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000384class VISIBILITY_HIDDEN GRConstants {
Ted Kremenekd27f8162008-01-15 23:55:06 +0000385
386public:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000387 typedef ValueMapTy StateTy;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000388 typedef GRNodeBuilder<GRConstants> NodeBuilder;
389 typedef ExplodedNode<StateTy> NodeTy;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000390
391 class NodeSet {
392 typedef llvm::SmallVector<NodeTy*,3> ImplTy;
393 ImplTy Impl;
394 public:
395
396 NodeSet() {}
397 NodeSet(NodeTy* N) { assert (N && !N->isInfeasible()); Impl.push_back(N); }
398
399 void Add(NodeTy* N) { if (N && !N->isInfeasible()) Impl.push_back(N); }
400
401 typedef ImplTy::iterator iterator;
402 typedef ImplTy::const_iterator const_iterator;
403
404 unsigned size() const { return Impl.size(); }
405
406 iterator begin() { return Impl.begin(); }
407 iterator end() { return Impl.end(); }
408
409 const_iterator begin() const { return Impl.begin(); }
410 const_iterator end() const { return Impl.end(); }
411 };
Ted Kremenekd27f8162008-01-15 23:55:06 +0000412
413protected:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000414 /// Liveness - live-variables information the ValueDecl* and block-level
415 /// Expr* in the CFG. Used to prune out dead state.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000416 LiveVariables* Liveness;
417
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000418 /// Builder - The current GRNodeBuilder which is used when building the nodes
419 /// for a given statement.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000420 NodeBuilder* Builder;
421
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000422 /// StateMgr - Object that manages the data for all created states.
423 ValueMapTy::Factory StateMgr;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000424
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000425 /// ValueMgr - Object that manages the data for all created ExprValues.
426 ValueManager ValMgr;
427
428 /// cfg - the current CFG.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000429 CFG* cfg;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000430
431 /// StmtEntryNode - The immediate predecessor node.
432 NodeTy* StmtEntryNode;
433
434 /// CurrentStmt - The current block-level statement.
435 Stmt* CurrentStmt;
436
437 bool StateCleaned;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000438
Ted Kremenekd27f8162008-01-15 23:55:06 +0000439public:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000440 GRConstants() : Liveness(NULL), Builder(NULL), cfg(NULL),
441 StmtEntryNode(NULL), CurrentStmt(NULL) {}
Ted Kremenekd27f8162008-01-15 23:55:06 +0000442
443 ~GRConstants() { delete Liveness; }
444
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000445 /// getCFG - Returns the CFG associated with this analysis.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000446 CFG& getCFG() { assert (cfg); return *cfg; }
447
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000448 /// Initialize - Initialize the checker's state based on the specified
449 /// CFG. This results in liveness information being computed for
450 /// each block-level statement in the CFG.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000451 void Initialize(CFG& c) {
452 cfg = &c;
453 Liveness = new LiveVariables(c);
454 Liveness->runOnCFG(c);
Ted Kremenek79649df2008-01-17 18:25:22 +0000455 Liveness->runOnAllBlocks(c, NULL, true);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000456 }
457
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000458 /// getInitialState - Return the initial state used for the root vertex
459 /// in the ExplodedGraph.
Ted Kremenekd27f8162008-01-15 23:55:06 +0000460 StateTy getInitialState() {
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000461 return StateMgr.GetEmptyMap();
Ted Kremenekd27f8162008-01-15 23:55:06 +0000462 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000463
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000464 /// ProcessStmt - Called by GREngine. Used to generate new successor
465 /// nodes by processing the 'effects' of a block-level statement.
466 void ProcessStmt(Stmt* S, NodeBuilder& builder);
467
468 /// RemoveDeadBindings - Return a new state that is the same as 'M' except
469 /// that all subexpression mappings are removed and that any
470 /// block-level expressions that are not live at 'S' also have their
471 /// mappings removed.
472 StateTy RemoveDeadBindings(Stmt* S, StateTy M);
473
474 StateTy SetValue(StateTy St, Stmt* S, const ExprValue& V,
475 bool isBlkExpr = false);
476
477 StateTy SetValue(StateTy St, const LValue& LV, const ExprValue& V);
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000478
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000479 ExprValue GetValue(const StateTy& St, Stmt* S);
480 ExprValue GetValue(const StateTy& St, const LValue& LV);
481 LValue GetLValue(const StateTy& St, Stmt* S);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000482
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000483 void Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, StateTy St);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000484
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000485 /// Visit - Transfer function logic for all statements. Dispatches to
486 /// other functions that handle specific kinds of statements.
487 void Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst);
488
489 /// VisitBinaryOperator - Transfer function logic for binary operators.
490 void VisitBinaryOperator(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
Ted Kremenekd27f8162008-01-15 23:55:06 +0000491};
492} // end anonymous namespace
493
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000494
Ted Kremenekd27f8162008-01-15 23:55:06 +0000495void GRConstants::ProcessStmt(Stmt* S, NodeBuilder& builder) {
496 Builder = &builder;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000497
498 StmtEntryNode = builder.getLastNode();
499 CurrentStmt = S;
500 NodeSet Dst;
501 StateCleaned = false;
502
503 Visit(S, StmtEntryNode, Dst);
504
505 // If no nodes were generated, generate a new node that has all the
506 // dead mappings removed.
507 if (Dst.size() == 1 && *Dst.begin() == StmtEntryNode) {
508 StateTy St = RemoveDeadBindings(S, StmtEntryNode->getState());
509 builder.generateNode(S, St, StmtEntryNode);
510 }
Ted Kremenekf84469b2008-01-18 00:41:32 +0000511
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000512 CurrentStmt = NULL;
513 StmtEntryNode = NULL;
514 Builder = NULL;
Ted Kremenekd27f8162008-01-15 23:55:06 +0000515}
516
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000517
518ExprValue GRConstants::GetValue(const StateTy& St, const LValue& LV) {
519 switch (LV.getKind()) {
520 case ExprValue::LValueDeclKind: {
521 StateTy::TreeTy* T = St.SlimFind(cast<LValueDecl>(LV).getDecl());
522 return T ? T->getValue().second : InvalidValue();
523 }
524 default:
525 assert (false && "Invalid LValue.");
Ted Kremenekca3e8572008-01-16 22:28:08 +0000526 break;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000527 }
528
529 return InvalidValue();
530}
531
532ExprValue GRConstants::GetValue(const StateTy& St, Stmt* S) {
533 if (Expr* E = dyn_cast<Expr>(S))
534 S = E->IgnoreParens();
535
536 switch (S->getStmtClass()) {
537 case Stmt::DeclRefExprClass:
538 return GetValue(St, LValueDecl(cast<DeclRefExpr>(S)->getDecl()));
Ted Kremenekca3e8572008-01-16 22:28:08 +0000539
540 case Stmt::IntegerLiteralClass:
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000541 return RValue::GetRValue(ValMgr, cast<IntegerLiteral>(S));
542
543 default:
Ted Kremenekca3e8572008-01-16 22:28:08 +0000544 break;
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000545 };
546
547 StateTy::TreeTy* T = St.SlimFind(ValueKey(S, getCFG().isBlkExpr(S)));
548 return T ? T->getValue().second : InvalidValue();
549}
550
551LValue GRConstants::GetLValue(const StateTy& St, Stmt* S) {
552 if (Expr* E = dyn_cast<Expr>(S))
553 S = E->IgnoreParens();
554
555 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S))
556 return LValueDecl(DR->getDecl());
557
558 return cast<LValue>(GetValue(St, S));
559}
560
561GRConstants::StateTy GRConstants::SetValue(StateTy St, Stmt* S,
562 const ExprValue& V, bool isBlkExpr) {
563
564 if (!StateCleaned) {
565 St = RemoveDeadBindings(CurrentStmt, St);
566 StateCleaned = true;
567 }
568
569 return V.isValid() ? StateMgr.Add(St, ValueKey(S,isBlkExpr), V)
570 : St;
571}
572
573GRConstants::StateTy GRConstants::SetValue(StateTy St, const LValue& LV,
574 const ExprValue& V) {
575 if (!LV.isValid())
576 return St;
577
578 if (!StateCleaned) {
579 St = RemoveDeadBindings(CurrentStmt, St);
580 StateCleaned = true;
Ted Kremenekca3e8572008-01-16 22:28:08 +0000581 }
Ted Kremenek0525a4f2008-01-16 19:47:19 +0000582
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000583 switch (LV.getKind()) {
584 case ExprValue::LValueDeclKind:
585 return V.isValid() ? StateMgr.Add(St, cast<LValueDecl>(LV).getDecl(), V)
586 : StateMgr.Remove(St, cast<LValueDecl>(LV).getDecl());
587
588 default:
589 assert ("SetValue for given LValue type not yet implemented.");
590 return St;
591 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000592}
593
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000594GRConstants::StateTy GRConstants::RemoveDeadBindings(Stmt* Loc, StateTy M) {
Ted Kremenekf84469b2008-01-18 00:41:32 +0000595 // Note: in the code below, we can assign a new map to M since the
596 // iterators are iterating over the tree of the *original* map.
Ted Kremenekf84469b2008-01-18 00:41:32 +0000597 StateTy::iterator I = M.begin(), E = M.end();
598
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000599 // Remove old bindings for subexpressions.
600 for (; I!=E && I.getKey().getKind() == ValueKey::IsSubExp; ++I)
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000601 M = StateMgr.Remove(M, I.getKey());
Ted Kremenekf84469b2008-01-18 00:41:32 +0000602
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000603 // Remove bindings for "dead" decls.
604 for (; I!=E && I.getKey().getKind() == ValueKey::IsDecl; ++I)
605 if (VarDecl* V = dyn_cast<VarDecl>(cast<ValueDecl>(I.getKey())))
606 if (!Liveness->isLive(Loc, V))
607 M = StateMgr.Remove(M, I.getKey());
608
609 // Remove bindings for "dead" block-level expressions.
610 for (; I!=E; ++I)
611 if (!Liveness->isLive(Loc, cast<Stmt>(I.getKey())))
612 M = StateMgr.Remove(M, I.getKey());
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000613
614 return M;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000615}
616
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000617void GRConstants::Nodify(NodeSet& Dst, Stmt* S, GRConstants::NodeTy* Pred,
618 GRConstants::StateTy St) {
619
620 // If the state hasn't changed, don't generate a new node.
621 if (St == Pred->getState())
622 return;
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000623
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000624 Dst.Add(Builder->generateNode(S, St, Pred));
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000625}
Ted Kremenekd27f8162008-01-15 23:55:06 +0000626
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000627void GRConstants::VisitBinaryOperator(BinaryOperator* B,
628 GRConstants::NodeTy* Pred,
629 GRConstants::NodeSet& Dst) {
630 NodeSet S1;
631 Visit(B->getLHS(), Pred, S1);
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000632
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000633 for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
634 NodeTy* N1 = *I1;
Ted Kremeneke00fe3f2008-01-17 00:52:48 +0000635
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000636 // When getting the value for the LHS, check if we are in an assignment.
637 // In such cases, we want to (initially) treat the LHS as an LValue,
638 // so we use GetLValue instead of GetValue so that DeclRefExpr's are
639 // evaluated to LValueDecl's instead of to an RValue.
640 const ExprValue& V1 =
641 B->isAssignmentOp() ? GetLValue(N1->getState(), B->getLHS())
642 : GetValue(N1->getState(), B->getLHS());
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000643
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000644 NodeSet S2;
645 Visit(B->getRHS(), N1, S2);
646
647 for (NodeSet::iterator I2=S2.begin(), E2=S2.end(); I2 != E2; ++I2) {
648 NodeTy* N2 = *I2;
649 StateTy St = N2->getState();
650 const ExprValue& V2 = GetValue(St, B->getRHS());
651
652 switch (B->getOpcode()) {
653 case BinaryOperator::Add: {
654 const RValue& R1 = cast<RValue>(V1);
655 const RValue& R2 = cast<RValue>(V2);
656
657 Nodify(Dst, B, N2, SetValue(St, B, R1.Add(ValMgr, R2)));
658 break;
659 }
660
661 case BinaryOperator::Sub: {
662 const RValue& R1 = cast<RValue>(V1);
663 const RValue& R2 = cast<RValue>(V2);
664
665 Nodify(Dst, B, N2, SetValue(St, B, R1.Sub(ValMgr, R2)));
666 break;
667 }
668
669 case BinaryOperator::Assign: {
670 const LValue& L1 = cast<LValue>(V1);
671 const RValue& R2 = cast<RValue>(V2);
672
673 Nodify(Dst, B, N2, SetValue(SetValue(St, B, R2), L1, R2));
674 break;
675 }
676
677 default:
678 Dst.Add(N2);
679 break;
680 }
Ted Kremenekcb448ca2008-01-16 00:53:15 +0000681 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000682 }
Ted Kremenekd27f8162008-01-15 23:55:06 +0000683}
Ted Kremenekee985462008-01-16 18:18:48 +0000684
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000685
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000686void GRConstants::Visit(Stmt* S, GRConstants::NodeTy* Pred,
687 GRConstants::NodeSet& Dst) {
688
689 // FIXME: add metadata to the CFG so that we can disable
690 // this check when we KNOW that there is no block-level subexpression.
691 // The motivation is that this check requires a hashtable lookup.
692
693 if (S != CurrentStmt && getCFG().isBlkExpr(S)) {
694 Dst.Add(Pred);
695 return;
696 }
697
698 switch (S->getStmtClass()) {
699 case Stmt::BinaryOperatorClass:
700 VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
701 break;
702
703 case Stmt::ParenExprClass:
704 Visit(cast<ParenExpr>(S)->getSubExpr(), Pred, Dst);
705 break;
706
707 default:
708 Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
709 break;
Ted Kremenek79649df2008-01-17 18:25:22 +0000710 }
Ted Kremenek1ccd31c2008-01-16 19:42:59 +0000711}
712
Ted Kremenekee985462008-01-16 18:18:48 +0000713//===----------------------------------------------------------------------===//
714// Driver.
715//===----------------------------------------------------------------------===//
716
Ted Kremenekaa66a322008-01-16 21:46:15 +0000717#ifndef NDEBUG
718namespace llvm {
719template<>
720struct VISIBILITY_HIDDEN DOTGraphTraits<GRConstants::NodeTy*> :
721 public DefaultDOTGraphTraits {
722
723 static std::string getNodeLabel(const GRConstants::NodeTy* N, void*) {
724 std::ostringstream Out;
725
726 Out << "Vertex: " << (void*) N << '\n';
727 ProgramPoint Loc = N->getLocation();
728
729 switch (Loc.getKind()) {
730 case ProgramPoint::BlockEntranceKind:
731 Out << "Block Entrance: B"
732 << cast<BlockEntrance>(Loc).getBlock()->getBlockID();
733 break;
734
735 case ProgramPoint::BlockExitKind:
736 assert (false);
737 break;
738
739 case ProgramPoint::PostStmtKind: {
740 const PostStmt& L = cast<PostStmt>(Loc);
741 Out << "Stmt: " << (void*) L.getStmt() << '\n';
742 L.getStmt()->printPretty(Out);
743 break;
744 }
745
746 default: {
747 const BlockEdge& E = cast<BlockEdge>(Loc);
748 Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
749 << E.getDst()->getBlockID() << ')';
750 }
751 }
752
753 Out << "\n{";
754
755 GRConstants::StateTy M = N->getState();
756 bool isFirst = true;
757
758 for (GRConstants::StateTy::iterator I=M.begin(), E=M.end(); I!=E; ++I) {
759 if (!isFirst)
760 Out << '\n';
761 else
762 isFirst = false;
763
764 if (ValueDecl* V = dyn_cast<ValueDecl>(I.getKey())) {
765 Out << "Decl: " << (void*) V << ", " << V->getName();
766 }
767 else {
768 Stmt* E = cast<Stmt>(I.getKey());
769 Out << "Stmt: " << (void*) E;
770 }
771
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000772 Out << " => ";
773 I.getData().print(Out);
Ted Kremenekaa66a322008-01-16 21:46:15 +0000774 }
775
776 Out << " }";
777
778 return Out.str();
779 }
780};
781} // end llvm namespace
782#endif
783
Ted Kremenekee985462008-01-16 18:18:48 +0000784namespace clang {
785void RunGRConstants(CFG& cfg) {
786 GREngine<GRConstants> Engine(cfg);
787 Engine.ExecuteWorkList();
Ted Kremenekaa66a322008-01-16 21:46:15 +0000788#ifndef NDEBUG
789 llvm::ViewGraph(*Engine.getGraph().roots_begin(),"GRConstants");
790#endif
Ted Kremenekee985462008-01-16 18:18:48 +0000791}
Ted Kremenekab2b8c52008-01-23 19:59:44 +0000792} // end clang namespace