blob: 7ce305e4cf524e7d6db888bf0c8dc3e973848216 [file] [log] [blame]
Ted Kremenek240f1f02008-03-07 20:13:31 +00001//=== BasicValueFactory.cpp - Basic values for Path Sens analysis --*- C++ -*-//
Ted Kremenekd70d0b02008-02-16 01:12:31 +00002//
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//
Ted Kremenek240f1f02008-03-07 20:13:31 +000010// This file defines BasicValueFactory, a class that manages the lifetime
11// of APSInt objects and symbolic constraints used by GRExprEngine
12// and related classes.
Ted Kremenekd70d0b02008-02-16 01:12:31 +000013//
14//===----------------------------------------------------------------------===//
15
Ted Kremenek240f1f02008-03-07 20:13:31 +000016#include "clang/Analysis/PathSensitive/BasicValueFactory.h"
Ted Kremenekd70d0b02008-02-16 01:12:31 +000017
18using namespace clang;
19
Zhongxing Xu6764b722008-10-30 04:58:00 +000020void CompoundValData::Profile(llvm::FoldingSetNodeID& ID, QualType T,
Ted Kremenek632e8b82008-10-30 17:44:46 +000021 llvm::ImmutableList<SVal> L) {
Zhongxing Xu6764b722008-10-30 04:58:00 +000022 T.Profile(ID);
Ted Kremenek632e8b82008-10-30 17:44:46 +000023 ID.AddPointer(L.getInternalPointer());
Zhongxing Xu6764b722008-10-30 04:58:00 +000024}
25
Zhongxing Xu1c96b242008-10-17 05:57:07 +000026typedef std::pair<SVal, uintptr_t> SValData;
27typedef std::pair<SVal, SVal> SValPair;
Ted Kremenek4d0348b2008-04-29 23:24:44 +000028
Ted Kremenek0fe33bc2008-04-22 21:10:18 +000029namespace llvm {
Zhongxing Xu1c96b242008-10-17 05:57:07 +000030template<> struct FoldingSetTrait<SValData> {
31 static inline void Profile(const SValData& X, llvm::FoldingSetNodeID& ID) {
Ted Kremenek0fe33bc2008-04-22 21:10:18 +000032 X.first.Profile(ID);
Ted Kremenek718c4f72008-04-29 22:17:41 +000033 ID.AddPointer( (void*) X.second);
Ted Kremenek0fe33bc2008-04-22 21:10:18 +000034 }
35};
Ted Kremenek4d0348b2008-04-29 23:24:44 +000036
Zhongxing Xu1c96b242008-10-17 05:57:07 +000037template<> struct FoldingSetTrait<SValPair> {
38 static inline void Profile(const SValPair& X, llvm::FoldingSetNodeID& ID) {
Ted Kremenek4d0348b2008-04-29 23:24:44 +000039 X.first.Profile(ID);
40 X.second.Profile(ID);
41 }
42};
Ted Kremenek0fe33bc2008-04-22 21:10:18 +000043}
44
Zhongxing Xu1c96b242008-10-17 05:57:07 +000045typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<SValData> >
46 PersistentSValsTy;
Ted Kremenek0fe33bc2008-04-22 21:10:18 +000047
Zhongxing Xu1c96b242008-10-17 05:57:07 +000048typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<SValPair> >
49 PersistentSValPairsTy;
Ted Kremenek4d0348b2008-04-29 23:24:44 +000050
Ted Kremenek240f1f02008-03-07 20:13:31 +000051BasicValueFactory::~BasicValueFactory() {
Ted Kremenekd70d0b02008-02-16 01:12:31 +000052 // Note that the dstor for the contents of APSIntSet will never be called,
53 // so we iterate over the set and invoke the dstor for each APSInt. This
54 // frees an aux. memory allocated to represent very large constants.
55 for (APSIntSetTy::iterator I=APSIntSet.begin(), E=APSIntSet.end(); I!=E; ++I)
56 I->getValue().~APSInt();
Ted Kremenek0fe33bc2008-04-22 21:10:18 +000057
Zhongxing Xu1c96b242008-10-17 05:57:07 +000058 delete (PersistentSValsTy*) PersistentSVals;
59 delete (PersistentSValPairsTy*) PersistentSValPairs;
Ted Kremenekd70d0b02008-02-16 01:12:31 +000060}
61
Ted Kremenek240f1f02008-03-07 20:13:31 +000062const llvm::APSInt& BasicValueFactory::getValue(const llvm::APSInt& X) {
Ted Kremenekd70d0b02008-02-16 01:12:31 +000063 llvm::FoldingSetNodeID ID;
64 void* InsertPos;
65 typedef llvm::FoldingSetNodeWrapper<llvm::APSInt> FoldNodeTy;
66
67 X.Profile(ID);
68 FoldNodeTy* P = APSIntSet.FindNodeOrInsertPos(ID, InsertPos);
69
70 if (!P) {
71 P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
72 new (P) FoldNodeTy(X);
73 APSIntSet.InsertNode(P, InsertPos);
74 }
75
76 return *P;
77}
78
Zhongxing Xue8a964b2008-11-22 13:21:46 +000079const llvm::APSInt& BasicValueFactory::getValue(const llvm::APInt& X,
80 bool isUnsigned) {
81 llvm::APSInt V(X, isUnsigned);
82 return getValue(V);
83}
84
Ted Kremenek240f1f02008-03-07 20:13:31 +000085const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, unsigned BitWidth,
Ted Kremenekd70d0b02008-02-16 01:12:31 +000086 bool isUnsigned) {
87 llvm::APSInt V(BitWidth, isUnsigned);
88 V = X;
89 return getValue(V);
90}
91
Ted Kremenek240f1f02008-03-07 20:13:31 +000092const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, QualType T) {
Ted Kremenekd70d0b02008-02-16 01:12:31 +000093
Chris Lattner98be4942008-03-05 18:54:05 +000094 unsigned bits = Ctx.getTypeSize(T);
Ted Kremenekd70d0b02008-02-16 01:12:31 +000095 llvm::APSInt V(bits, T->isUnsignedIntegerType());
96 V = X;
97 return getValue(V);
98}
99
100const SymIntConstraint&
Ted Kremenek240f1f02008-03-07 20:13:31 +0000101BasicValueFactory::getConstraint(SymbolID sym, BinaryOperator::Opcode Op,
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000102 const llvm::APSInt& V) {
103
104 llvm::FoldingSetNodeID ID;
105 SymIntConstraint::Profile(ID, sym, Op, V);
106 void* InsertPos;
107
108 SymIntConstraint* C = SymIntCSet.FindNodeOrInsertPos(ID, InsertPos);
109
110 if (!C) {
111 C = (SymIntConstraint*) BPAlloc.Allocate<SymIntConstraint>();
112 new (C) SymIntConstraint(sym, Op, V);
113 SymIntCSet.InsertNode(C, InsertPos);
114 }
115
116 return *C;
117}
118
Zhongxing Xu6764b722008-10-30 04:58:00 +0000119const CompoundValData*
Ted Kremenek632e8b82008-10-30 17:44:46 +0000120BasicValueFactory::getCompoundValData(QualType T,
121 llvm::ImmutableList<SVal> Vals) {
122
Zhongxing Xu6764b722008-10-30 04:58:00 +0000123 llvm::FoldingSetNodeID ID;
Ted Kremenek632e8b82008-10-30 17:44:46 +0000124 CompoundValData::Profile(ID, T, Vals);
Zhongxing Xu6764b722008-10-30 04:58:00 +0000125 void* InsertPos;
126
127 CompoundValData* D = CompoundValDataSet.FindNodeOrInsertPos(ID, InsertPos);
128
129 if (!D) {
130 D = (CompoundValData*) BPAlloc.Allocate<CompoundValData>();
Ted Kremenek632e8b82008-10-30 17:44:46 +0000131 new (D) CompoundValData(T, Vals);
Zhongxing Xu6764b722008-10-30 04:58:00 +0000132 CompoundValDataSet.InsertNode(D, InsertPos);
133 }
134
135 return D;
136}
137
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000138const llvm::APSInt*
Ted Kremenek240f1f02008-03-07 20:13:31 +0000139BasicValueFactory::EvaluateAPSInt(BinaryOperator::Opcode Op,
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000140 const llvm::APSInt& V1, const llvm::APSInt& V2) {
141
142 switch (Op) {
143 default:
144 assert (false && "Invalid Opcode.");
145
146 case BinaryOperator::Mul:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000147 return &getValue( V1 * V2 );
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000148
149 case BinaryOperator::Div:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000150 return &getValue( V1 / V2 );
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000151
152 case BinaryOperator::Rem:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000153 return &getValue( V1 % V2 );
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000154
155 case BinaryOperator::Add:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000156 return &getValue( V1 + V2 );
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000157
158 case BinaryOperator::Sub:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000159 return &getValue( V1 - V2 );
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000160
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000161 case BinaryOperator::Shl: {
162
163 // FIXME: This logic should probably go higher up, where we can
164 // test these conditions symbolically.
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000165
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000166 // FIXME: Expand these checks to include all undefined behavior.
167
168 if (V2.isSigned() && V2.isNegative())
169 return NULL;
170
171 uint64_t Amt = V2.getZExtValue();
172
173 if (Amt > V1.getBitWidth())
174 return NULL;
175
176 return &getValue( V1.operator<<( (unsigned) Amt ));
177 }
178
179 case BinaryOperator::Shr: {
180
181 // FIXME: This logic should probably go higher up, where we can
182 // test these conditions symbolically.
183
184 // FIXME: Expand these checks to include all undefined behavior.
185
186 if (V2.isSigned() && V2.isNegative())
187 return NULL;
188
189 uint64_t Amt = V2.getZExtValue();
190
191 if (Amt > V1.getBitWidth())
192 return NULL;
193
194 return &getValue( V1.operator>>( (unsigned) Amt ));
195 }
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000196
197 case BinaryOperator::LT:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000198 return &getTruthValue( V1 < V2 );
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000199
200 case BinaryOperator::GT:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000201 return &getTruthValue( V1 > V2 );
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000202
203 case BinaryOperator::LE:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000204 return &getTruthValue( V1 <= V2 );
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000205
206 case BinaryOperator::GE:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000207 return &getTruthValue( V1 >= V2 );
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000208
209 case BinaryOperator::EQ:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000210 return &getTruthValue( V1 == V2 );
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000211
212 case BinaryOperator::NE:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000213 return &getTruthValue( V1 != V2 );
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000214
215 // Note: LAnd, LOr, Comma are handled specially by higher-level logic.
216
217 case BinaryOperator::And:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000218 return &getValue( V1 & V2 );
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000219
220 case BinaryOperator::Or:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000221 return &getValue( V1 | V2 );
Ted Kremenek1caf26a2008-02-19 20:53:37 +0000222
223 case BinaryOperator::Xor:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000224 return &getValue( V1 ^ V2 );
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000225 }
226}
Ted Kremenek0fe33bc2008-04-22 21:10:18 +0000227
228
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000229const std::pair<SVal, uintptr_t>&
230BasicValueFactory::getPersistentSValWithData(const SVal& V, uintptr_t Data) {
Ted Kremenek0fe33bc2008-04-22 21:10:18 +0000231
232 // Lazily create the folding set.
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000233 if (!PersistentSVals) PersistentSVals = new PersistentSValsTy();
Ted Kremenek0fe33bc2008-04-22 21:10:18 +0000234
235 llvm::FoldingSetNodeID ID;
236 void* InsertPos;
237 V.Profile(ID);
Ted Kremenek718c4f72008-04-29 22:17:41 +0000238 ID.AddPointer((void*) Data);
Ted Kremenek0fe33bc2008-04-22 21:10:18 +0000239
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000240 PersistentSValsTy& Map = *((PersistentSValsTy*) PersistentSVals);
Ted Kremenek0fe33bc2008-04-22 21:10:18 +0000241
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000242 typedef llvm::FoldingSetNodeWrapper<SValData> FoldNodeTy;
Ted Kremenek0fe33bc2008-04-22 21:10:18 +0000243 FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
244
245 if (!P) {
246 P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
Ted Kremenek718c4f72008-04-29 22:17:41 +0000247 new (P) FoldNodeTy(std::make_pair(V, Data));
Ted Kremenek0fe33bc2008-04-22 21:10:18 +0000248 Map.InsertNode(P, InsertPos);
249 }
250
Ted Kremenek718c4f72008-04-29 22:17:41 +0000251 return P->getValue();
Ted Kremenek0fe33bc2008-04-22 21:10:18 +0000252}
Ted Kremenek4d0348b2008-04-29 23:24:44 +0000253
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000254const std::pair<SVal, SVal>&
255BasicValueFactory::getPersistentSValPair(const SVal& V1, const SVal& V2) {
Ted Kremenek4d0348b2008-04-29 23:24:44 +0000256
257 // Lazily create the folding set.
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000258 if (!PersistentSValPairs) PersistentSValPairs = new PersistentSValPairsTy();
Ted Kremenek4d0348b2008-04-29 23:24:44 +0000259
260 llvm::FoldingSetNodeID ID;
261 void* InsertPos;
262 V1.Profile(ID);
263 V2.Profile(ID);
264
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000265 PersistentSValPairsTy& Map = *((PersistentSValPairsTy*) PersistentSValPairs);
Ted Kremenek4d0348b2008-04-29 23:24:44 +0000266
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000267 typedef llvm::FoldingSetNodeWrapper<SValPair> FoldNodeTy;
Ted Kremenek4d0348b2008-04-29 23:24:44 +0000268 FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
269
270 if (!P) {
271 P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
272 new (P) FoldNodeTy(std::make_pair(V1, V2));
273 Map.InsertNode(P, InsertPos);
274 }
275
276 return P->getValue();
277}
278
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000279const SVal* BasicValueFactory::getPersistentSVal(SVal X) {
280 return &getPersistentSValWithData(X, 0).first;
Ted Kremenek7360fda2008-09-18 23:09:54 +0000281}
282
283