blob: 8d737a9472dea38a794bff48de22c477bf8b76bd [file] [log] [blame]
Ted Kremenek8ad19872008-03-07 20:13:31 +00001//=== BasicValueFactory.cpp - Basic values for Path Sens analysis --*- C++ -*-//
Ted Kremenek94e915e2008-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 Kremenek8ad19872008-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 Kremenek94e915e2008-02-16 01:12:31 +000013//
14//===----------------------------------------------------------------------===//
15
Ted Kremenek8ad19872008-03-07 20:13:31 +000016#include "clang/Analysis/PathSensitive/BasicValueFactory.h"
Ted Kremenekfe1a0b12008-04-22 21:10:18 +000017#include "clang/Analysis/PathSensitive/RValues.h"
Ted Kremenek94e915e2008-02-16 01:12:31 +000018
19using namespace clang;
20
Ted Kremenek465f25a2008-04-29 22:17:41 +000021typedef std::pair<RVal, uintptr_t> RValData;
Ted Kremenekc4385b42008-04-29 23:24:44 +000022typedef std::pair<RVal, RVal> RValPair;
23
Ted Kremenekfe1a0b12008-04-22 21:10:18 +000024
25namespace llvm {
Ted Kremenek465f25a2008-04-29 22:17:41 +000026template<> struct FoldingSetTrait<RValData> {
27 static inline void Profile(const RValData& X, llvm::FoldingSetNodeID& ID) {
Ted Kremenekfe1a0b12008-04-22 21:10:18 +000028 X.first.Profile(ID);
Ted Kremenek465f25a2008-04-29 22:17:41 +000029 ID.AddPointer( (void*) X.second);
Ted Kremenekfe1a0b12008-04-22 21:10:18 +000030 }
31};
Ted Kremenekc4385b42008-04-29 23:24:44 +000032
33template<> struct FoldingSetTrait<RValPair> {
34 static inline void Profile(const RValPair& X, llvm::FoldingSetNodeID& ID) {
35 X.first.Profile(ID);
36 X.second.Profile(ID);
37 }
38};
Ted Kremenekfe1a0b12008-04-22 21:10:18 +000039}
40
Ted Kremenek465f25a2008-04-29 22:17:41 +000041typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<RValData> >
Ted Kremenekfe1a0b12008-04-22 21:10:18 +000042 PersistentRValsTy;
43
Ted Kremenekc4385b42008-04-29 23:24:44 +000044typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<RValPair> >
45 PersistentRValPairsTy;
46
Ted Kremenek8ad19872008-03-07 20:13:31 +000047BasicValueFactory::~BasicValueFactory() {
Ted Kremenek94e915e2008-02-16 01:12:31 +000048 // Note that the dstor for the contents of APSIntSet will never be called,
49 // so we iterate over the set and invoke the dstor for each APSInt. This
50 // frees an aux. memory allocated to represent very large constants.
51 for (APSIntSetTy::iterator I=APSIntSet.begin(), E=APSIntSet.end(); I!=E; ++I)
52 I->getValue().~APSInt();
Ted Kremenekfe1a0b12008-04-22 21:10:18 +000053
54 delete (PersistentRValsTy*) PersistentRVals;
Ted Kremenekc4385b42008-04-29 23:24:44 +000055 delete (PersistentRValPairsTy*) PersistentRValPairs;
Ted Kremenek94e915e2008-02-16 01:12:31 +000056}
57
Ted Kremenek8ad19872008-03-07 20:13:31 +000058const llvm::APSInt& BasicValueFactory::getValue(const llvm::APSInt& X) {
Ted Kremenek94e915e2008-02-16 01:12:31 +000059 llvm::FoldingSetNodeID ID;
60 void* InsertPos;
61 typedef llvm::FoldingSetNodeWrapper<llvm::APSInt> FoldNodeTy;
62
63 X.Profile(ID);
64 FoldNodeTy* P = APSIntSet.FindNodeOrInsertPos(ID, InsertPos);
65
66 if (!P) {
67 P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
68 new (P) FoldNodeTy(X);
69 APSIntSet.InsertNode(P, InsertPos);
70 }
71
72 return *P;
73}
74
Ted Kremenek8ad19872008-03-07 20:13:31 +000075const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, unsigned BitWidth,
Ted Kremenek94e915e2008-02-16 01:12:31 +000076 bool isUnsigned) {
77 llvm::APSInt V(BitWidth, isUnsigned);
78 V = X;
79 return getValue(V);
80}
81
Ted Kremenek8ad19872008-03-07 20:13:31 +000082const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, QualType T) {
Ted Kremenek94e915e2008-02-16 01:12:31 +000083
Chris Lattner8cd0e932008-03-05 18:54:05 +000084 unsigned bits = Ctx.getTypeSize(T);
Ted Kremenek94e915e2008-02-16 01:12:31 +000085 llvm::APSInt V(bits, T->isUnsignedIntegerType());
86 V = X;
87 return getValue(V);
88}
89
90const SymIntConstraint&
Ted Kremenek8ad19872008-03-07 20:13:31 +000091BasicValueFactory::getConstraint(SymbolID sym, BinaryOperator::Opcode Op,
Ted Kremenek94e915e2008-02-16 01:12:31 +000092 const llvm::APSInt& V) {
93
94 llvm::FoldingSetNodeID ID;
95 SymIntConstraint::Profile(ID, sym, Op, V);
96 void* InsertPos;
97
98 SymIntConstraint* C = SymIntCSet.FindNodeOrInsertPos(ID, InsertPos);
99
100 if (!C) {
101 C = (SymIntConstraint*) BPAlloc.Allocate<SymIntConstraint>();
102 new (C) SymIntConstraint(sym, Op, V);
103 SymIntCSet.InsertNode(C, InsertPos);
104 }
105
106 return *C;
107}
108
Ted Kremenekc2d07202008-02-28 20:32:03 +0000109const llvm::APSInt*
Ted Kremenek8ad19872008-03-07 20:13:31 +0000110BasicValueFactory::EvaluateAPSInt(BinaryOperator::Opcode Op,
Ted Kremenek94e915e2008-02-16 01:12:31 +0000111 const llvm::APSInt& V1, const llvm::APSInt& V2) {
112
113 switch (Op) {
114 default:
115 assert (false && "Invalid Opcode.");
116
117 case BinaryOperator::Mul:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000118 return &getValue( V1 * V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +0000119
120 case BinaryOperator::Div:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000121 return &getValue( V1 / V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +0000122
123 case BinaryOperator::Rem:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000124 return &getValue( V1 % V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +0000125
126 case BinaryOperator::Add:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000127 return &getValue( V1 + V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +0000128
129 case BinaryOperator::Sub:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000130 return &getValue( V1 - V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +0000131
Ted Kremenekc2d07202008-02-28 20:32:03 +0000132 case BinaryOperator::Shl: {
133
134 // FIXME: This logic should probably go higher up, where we can
135 // test these conditions symbolically.
Ted Kremenek94e915e2008-02-16 01:12:31 +0000136
Ted Kremenekc2d07202008-02-28 20:32:03 +0000137 // FIXME: Expand these checks to include all undefined behavior.
138
139 if (V2.isSigned() && V2.isNegative())
140 return NULL;
141
142 uint64_t Amt = V2.getZExtValue();
143
144 if (Amt > V1.getBitWidth())
145 return NULL;
146
147 return &getValue( V1.operator<<( (unsigned) Amt ));
148 }
149
150 case BinaryOperator::Shr: {
151
152 // FIXME: This logic should probably go higher up, where we can
153 // test these conditions symbolically.
154
155 // FIXME: Expand these checks to include all undefined behavior.
156
157 if (V2.isSigned() && V2.isNegative())
158 return NULL;
159
160 uint64_t Amt = V2.getZExtValue();
161
162 if (Amt > V1.getBitWidth())
163 return NULL;
164
165 return &getValue( V1.operator>>( (unsigned) Amt ));
166 }
Ted Kremenek94e915e2008-02-16 01:12:31 +0000167
168 case BinaryOperator::LT:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000169 return &getTruthValue( V1 < V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +0000170
171 case BinaryOperator::GT:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000172 return &getTruthValue( V1 > V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +0000173
174 case BinaryOperator::LE:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000175 return &getTruthValue( V1 <= V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +0000176
177 case BinaryOperator::GE:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000178 return &getTruthValue( V1 >= V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +0000179
180 case BinaryOperator::EQ:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000181 return &getTruthValue( V1 == V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +0000182
183 case BinaryOperator::NE:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000184 return &getTruthValue( V1 != V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +0000185
186 // Note: LAnd, LOr, Comma are handled specially by higher-level logic.
187
188 case BinaryOperator::And:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000189 return &getValue( V1 & V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +0000190
191 case BinaryOperator::Or:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000192 return &getValue( V1 | V2 );
Ted Kremenek7c79a792008-02-19 20:53:37 +0000193
194 case BinaryOperator::Xor:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000195 return &getValue( V1 ^ V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +0000196 }
197}
Ted Kremenekfe1a0b12008-04-22 21:10:18 +0000198
199
Ted Kremenek465f25a2008-04-29 22:17:41 +0000200const std::pair<RVal, uintptr_t>&
201BasicValueFactory::getPersistentRValWithData(const RVal& V, uintptr_t Data) {
Ted Kremenekfe1a0b12008-04-22 21:10:18 +0000202
203 // Lazily create the folding set.
204 if (!PersistentRVals) PersistentRVals = new PersistentRValsTy();
205
206 llvm::FoldingSetNodeID ID;
207 void* InsertPos;
208 V.Profile(ID);
Ted Kremenek465f25a2008-04-29 22:17:41 +0000209 ID.AddPointer((void*) Data);
Ted Kremenekfe1a0b12008-04-22 21:10:18 +0000210
211 PersistentRValsTy& Map = *((PersistentRValsTy*) PersistentRVals);
212
Ted Kremenek465f25a2008-04-29 22:17:41 +0000213 typedef llvm::FoldingSetNodeWrapper<RValData> FoldNodeTy;
Ted Kremenekfe1a0b12008-04-22 21:10:18 +0000214 FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
215
216 if (!P) {
217 P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
Ted Kremenek465f25a2008-04-29 22:17:41 +0000218 new (P) FoldNodeTy(std::make_pair(V, Data));
Ted Kremenekfe1a0b12008-04-22 21:10:18 +0000219 Map.InsertNode(P, InsertPos);
220 }
221
Ted Kremenek465f25a2008-04-29 22:17:41 +0000222 return P->getValue();
Ted Kremenekfe1a0b12008-04-22 21:10:18 +0000223}
Ted Kremenekc4385b42008-04-29 23:24:44 +0000224
225const std::pair<RVal, RVal>&
226BasicValueFactory::getPersistentRValPair(const RVal& V1, const RVal& V2) {
227
228 // Lazily create the folding set.
229 if (!PersistentRValPairs) PersistentRValPairs = new PersistentRValPairsTy();
230
231 llvm::FoldingSetNodeID ID;
232 void* InsertPos;
233 V1.Profile(ID);
234 V2.Profile(ID);
235
236 PersistentRValPairsTy& Map = *((PersistentRValPairsTy*) PersistentRValPairs);
237
238 typedef llvm::FoldingSetNodeWrapper<RValPair> FoldNodeTy;
239 FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
240
241 if (!P) {
242 P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
243 new (P) FoldNodeTy(std::make_pair(V1, V2));
244 Map.InsertNode(P, InsertPos);
245 }
246
247 return P->getValue();
248}
249