blob: 2854ee641447bcd1be90d98317bc873d98631ab2 [file] [log] [blame]
Ted Kremeneka90ccfe2008-01-31 19:34:24 +00001//= RValues.cpp - Abstract RValues for Path-Sens. Value Tracking -*- 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 RValue, LValue, and NonLValue, classes that represent
11// abstract r-values for use with path-sensitive value tracking.
12//
13//===----------------------------------------------------------------------===//
14
15#include "RValues.h"
16
17using namespace clang;
18using llvm::dyn_cast;
19using llvm::cast;
20using llvm::APSInt;
21
22//===----------------------------------------------------------------------===//
23// SymbolManager.
24//===----------------------------------------------------------------------===//
25
26SymbolID SymbolManager::getSymbol(ParmVarDecl* D) {
27 SymbolID& X = DataToSymbol[D];
28
29 if (!X.isInitialized()) {
30 X = SymbolToData.size();
31 SymbolToData.push_back(D);
32 }
33
34 return X;
35}
36
37SymbolManager::SymbolManager() {}
38SymbolManager::~SymbolManager() {}
39
40//===----------------------------------------------------------------------===//
41// ValueManager.
42//===----------------------------------------------------------------------===//
43
44ValueManager::~ValueManager() {
45 // Note that the dstor for the contents of APSIntSet will never be called,
46 // so we iterate over the set and invoke the dstor for each APSInt. This
47 // frees an aux. memory allocated to represent very large constants.
48 for (APSIntSetTy::iterator I=APSIntSet.begin(), E=APSIntSet.end(); I!=E; ++I)
49 I->getValue().~APSInt();
50}
51
52APSInt& ValueManager::getValue(const APSInt& X) {
53 llvm::FoldingSetNodeID ID;
54 void* InsertPos;
55 typedef llvm::FoldingSetNodeWrapper<APSInt> FoldNodeTy;
56
57 X.Profile(ID);
58 FoldNodeTy* P = APSIntSet.FindNodeOrInsertPos(ID, InsertPos);
59
60 if (!P) {
61 P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
62 new (P) FoldNodeTy(X);
63 APSIntSet.InsertNode(P, InsertPos);
64 }
65
66 return *P;
67}
68
69APSInt& ValueManager::getValue(uint64_t X, unsigned BitWidth, bool isUnsigned) {
70 APSInt V(BitWidth, isUnsigned);
71 V = X;
72 return getValue(V);
73}
74
75APSInt& ValueManager::getValue(uint64_t X, QualType T, SourceLocation Loc) {
76 unsigned bits = Ctx.getTypeSize(T, Loc);
77 APSInt V(bits, T->isUnsignedIntegerType());
78 V = X;
79 return getValue(V);
80}
81
Ted Kremeneka6e4d212008-02-01 06:36:40 +000082//===----------------------------------------------------------------------===//
83// Transfer function for Casts.
84//===----------------------------------------------------------------------===//
85
86RValue RValue::Cast(ValueManager& ValMgr, Expr* CastExpr) const {
87 switch (getBaseKind()) {
88 default: assert(false && "Invalid RValue."); break;
89 case LValueKind: return cast<LValue>(this)->Cast(ValMgr, CastExpr);
90 case NonLValueKind: return cast<NonLValue>(this)->Cast(ValMgr, CastExpr);
91 case UninitializedKind: case InvalidKind: break;
92 }
93
94 return *this;
95}
96
97RValue LValue::Cast(ValueManager& ValMgr, Expr* CastExpr) const {
98 if (CastExpr->getType()->isPointerType())
99 return *this;
100
101 assert (CastExpr->getType()->isIntegerType());
102
103 if (!isa<ConcreteIntLValue>(*this))
104 return InvalidValue();
105
106 APSInt V = cast<ConcreteIntLValue>(this)->getValue();
107 QualType T = CastExpr->getType();
108 V.setIsUnsigned(T->isUnsignedIntegerType());
109 V.extOrTrunc(ValMgr.getContext().getTypeSize(T, CastExpr->getLocStart()));
110 return ConcreteInt(ValMgr.getValue(V));
111}
112
113RValue NonLValue::Cast(ValueManager& ValMgr, Expr* CastExpr) const {
114 if (!isa<ConcreteInt>(this))
115 return InvalidValue();
116
117 APSInt V = cast<ConcreteInt>(this)->getValue();
118 QualType T = CastExpr->getType();
119 V.setIsUnsigned(T->isUnsignedIntegerType());
120 V.extOrTrunc(ValMgr.getContext().getTypeSize(T, CastExpr->getLocStart()));
121
122 if (CastExpr->getType()->isPointerType())
123 return ConcreteIntLValue(ValMgr.getValue(V));
124 else
125 return ConcreteInt(ValMgr.getValue(V));
126}
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000127
128//===----------------------------------------------------------------------===//
129// Transfer function dispatch for Non-LValues.
130//===----------------------------------------------------------------------===//
131
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000132NonLValue NonLValue::UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const {
133 switch (getSubKind()) {
134 case ConcreteIntKind:
135 return cast<ConcreteInt>(this)->UnaryMinus(ValMgr, U);
136 default:
137 return cast<NonLValue>(InvalidValue());
138 }
139}
140
Ted Kremenekc5d3b4c2008-02-04 16:58:30 +0000141NonLValue NonLValue::BitwiseComplement(ValueManager& ValMgr) const {
142 switch (getSubKind()) {
143 case ConcreteIntKind:
144 return cast<ConcreteInt>(this)->BitwiseComplement(ValMgr);
145 default:
146 return cast<NonLValue>(InvalidValue());
147 }
148}
149
150
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000151#define NONLVALUE_DISPATCH_CASE(k1,k2,Op)\
152case (k1##Kind*NumNonLValueKind+k2##Kind):\
153return cast<k1>(*this).Op(ValMgr,cast<k2>(RHS));
154
155#define NONLVALUE_DISPATCH(Op)\
156switch (getSubKind()*NumNonLValueKind+RHS.getSubKind()){\
157NONLVALUE_DISPATCH_CASE(ConcreteInt,ConcreteInt,Op)\
158default:\
159if (getBaseKind() == UninitializedKind ||\
160RHS.getBaseKind() == UninitializedKind)\
161return cast<NonLValue>(UninitializedValue());\
162assert (!isValid() || !RHS.isValid() && "Missing case.");\
163break;\
164}\
165return cast<NonLValue>(InvalidValue());
166
167NonLValue NonLValue::Add(ValueManager& ValMgr, const NonLValue& RHS) const {
168 NONLVALUE_DISPATCH(Add)
169}
170
171NonLValue NonLValue::Sub(ValueManager& ValMgr, const NonLValue& RHS) const {
172 NONLVALUE_DISPATCH(Sub)
173}
174
175NonLValue NonLValue::Mul(ValueManager& ValMgr, const NonLValue& RHS) const {
176 NONLVALUE_DISPATCH(Mul)
177}
178
179NonLValue NonLValue::Div(ValueManager& ValMgr, const NonLValue& RHS) const {
180 NONLVALUE_DISPATCH(Div)
181}
182
183NonLValue NonLValue::Rem(ValueManager& ValMgr, const NonLValue& RHS) const {
184 NONLVALUE_DISPATCH(Rem)
185}
186
187NonLValue NonLValue::EQ(ValueManager& ValMgr, const NonLValue& RHS) const {
188 NONLVALUE_DISPATCH(EQ)
189}
190
191NonLValue NonLValue::NE(ValueManager& ValMgr, const NonLValue& RHS) const {
192 NONLVALUE_DISPATCH(NE)
193}
194
195#undef NONLVALUE_DISPATCH_CASE
196#undef NONLVALUE_DISPATCH
197
198//===----------------------------------------------------------------------===//
199// Transfer function dispatch for LValues.
200//===----------------------------------------------------------------------===//
201
202
203NonLValue LValue::EQ(ValueManager& ValMgr, const LValue& RHS) const {
204 if (getSubKind() != RHS.getSubKind())
205 return NonLValue::GetIntTruthValue(ValMgr, false);
206
207 switch (getSubKind()) {
208 default:
209 assert(false && "EQ not implemented for this LValue.");
210 return cast<NonLValue>(InvalidValue());
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000211
212 case ConcreteIntLValueKind: {
213 bool b = cast<ConcreteIntLValue>(this)->getValue() ==
214 cast<ConcreteIntLValue>(RHS).getValue();
215
216 return NonLValue::GetIntTruthValue(ValMgr, b);
217 }
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000218
219 case LValueDeclKind: {
220 bool b = cast<LValueDecl>(*this) == cast<LValueDecl>(RHS);
221 return NonLValue::GetIntTruthValue(ValMgr, b);
222 }
223 }
224}
225
226NonLValue LValue::NE(ValueManager& ValMgr, const LValue& RHS) const {
227 if (getSubKind() != RHS.getSubKind())
228 return NonLValue::GetIntTruthValue(ValMgr, true);
229
230 switch (getSubKind()) {
231 default:
232 assert(false && "EQ not implemented for this LValue.");
233 return cast<NonLValue>(InvalidValue());
234
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000235 case ConcreteIntLValueKind: {
236 bool b = cast<ConcreteIntLValue>(this)->getValue() !=
237 cast<ConcreteIntLValue>(RHS).getValue();
238
239 return NonLValue::GetIntTruthValue(ValMgr, b);
240 }
241
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000242 case LValueDeclKind: {
243 bool b = cast<LValueDecl>(*this) != cast<LValueDecl>(RHS);
244 return NonLValue::GetIntTruthValue(ValMgr, b);
245 }
246 }
247}
248
249
250//===----------------------------------------------------------------------===//
251// Utility methods for constructing Non-LValues.
252//===----------------------------------------------------------------------===//
253
254NonLValue NonLValue::GetValue(ValueManager& ValMgr, uint64_t X, QualType T,
255 SourceLocation Loc) {
256
257 return ConcreteInt(ValMgr.getValue(X, T, Loc));
258}
259
260NonLValue NonLValue::GetValue(ValueManager& ValMgr, IntegerLiteral* I) {
261 return ConcreteInt(ValMgr.getValue(APSInt(I->getValue(),
262 I->getType()->isUnsignedIntegerType())));
263}
264
265RValue RValue::GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl* D) {
266 QualType T = D->getType();
267
268 if (T->isPointerType() || T->isReferenceType())
269 return SymbolicLValue(SymMgr.getSymbol(D));
270 else
271 return SymbolicNonLValue(SymMgr.getSymbol(D));
272}
273
274//===----------------------------------------------------------------------===//
275// Pretty-Printing.
276//===----------------------------------------------------------------------===//
277
278void RValue::print(std::ostream& Out) const {
279 switch (getBaseKind()) {
280 case InvalidKind:
281 Out << "Invalid";
282 break;
283
284 case NonLValueKind:
285 cast<NonLValue>(this)->print(Out);
286 break;
287
288 case LValueKind:
289 cast<LValue>(this)->print(Out);
290 break;
291
292 case UninitializedKind:
293 Out << "Uninitialized";
294 break;
295
296 default:
297 assert (false && "Invalid RValue.");
298 }
299}
300
301void NonLValue::print(std::ostream& Out) const {
302 switch (getSubKind()) {
303 case ConcreteIntKind:
304 Out << cast<ConcreteInt>(this)->getValue().toString();
305 break;
306
307 case SymbolicNonLValueKind:
308 Out << '$' << cast<SymbolicNonLValue>(this)->getSymbolID();
309 break;
310
311 default:
312 assert (false && "Pretty-printed not implemented for this NonLValue.");
313 break;
314 }
315}
316
317void LValue::print(std::ostream& Out) const {
Ted Kremeneka6e4d212008-02-01 06:36:40 +0000318 switch (getSubKind()) {
319 case ConcreteIntLValueKind:
320 Out << cast<ConcreteIntLValue>(this)->getValue().toString()
321 << " (LValue)";
322 break;
323
Ted Kremeneka90ccfe2008-01-31 19:34:24 +0000324 case SymbolicLValueKind:
325 Out << '$' << cast<SymbolicLValue>(this)->getSymbolID();
326 break;
327
328 case LValueDeclKind:
329 Out << '&'
330 << cast<LValueDecl>(this)->getDecl()->getIdentifier()->getName();
331 break;
332
333 default:
334 assert (false && "Pretty-printed not implemented for this LValue.");
335 break;
336 }
337}