blob: e64bf7cbce3f12a4cb9cc1a5b974459051226b04 [file] [log] [blame]
Chris Lattner64c34f12008-11-16 07:46:48 +00001//===--- APValue.cpp - Union class for APFloat/APSInt/Complex -------------===//
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 file implements the APValue class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/AST/APValue.h"
Ken Dycka7305832010-01-15 12:37:54 +000015#include "clang/AST/CharUnits.h"
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +000016#include "clang/Basic/Diagnostic.h"
17#include "llvm/ADT/SmallString.h"
Chris Lattner64c34f12008-11-16 07:46:48 +000018#include "llvm/Support/raw_ostream.h"
David Blaikie9fe8c742011-09-23 05:35:21 +000019#include "llvm/Support/ErrorHandling.h"
Chris Lattner64c34f12008-11-16 07:46:48 +000020using namespace clang;
21
Ken Dycka7305832010-01-15 12:37:54 +000022namespace {
Richard Smith9a17a682011-11-07 05:07:52 +000023 struct LVBase {
24 const Expr *Base;
Ken Dycka7305832010-01-15 12:37:54 +000025 CharUnits Offset;
Richard Smith9a17a682011-11-07 05:07:52 +000026 unsigned PathLength;
Ken Dycka7305832010-01-15 12:37:54 +000027 };
28}
29
Richard Smith9a17a682011-11-07 05:07:52 +000030struct APValue::LV : LVBase {
31 static const unsigned InlinePathSpace =
32 (MaxSize - sizeof(LVBase)) / sizeof(LValuePathEntry);
33
34 /// Path - The sequence of base classes, fields and array indices to follow to
35 /// walk from Base to the subobject. When performing GCC-style folding, there
36 /// may not be such a path.
37 union {
38 LValuePathEntry Path[InlinePathSpace];
39 LValuePathEntry *PathPtr;
40 };
41
42 LV() { PathLength = (unsigned)-1; }
43 ~LV() { if (hasPathPtr()) delete [] PathPtr; }
44
45 void allocPath() {
46 if (hasPathPtr()) PathPtr = new LValuePathEntry[PathLength];
47 }
Richard Smith180f4792011-11-10 06:34:14 +000048 void freePath() { if (hasPathPtr()) delete [] PathPtr; }
Richard Smith9a17a682011-11-07 05:07:52 +000049
50 bool hasPath() const { return PathLength != (unsigned)-1; }
51 bool hasPathPtr() const { return hasPath() && PathLength > InlinePathSpace; }
52
53 LValuePathEntry *getPath() { return hasPathPtr() ? PathPtr : Path; }
Richard Smith38dce9b2011-11-07 07:31:09 +000054 const LValuePathEntry *getPath() const {
55 return hasPathPtr() ? PathPtr : Path;
56 }
Richard Smith9a17a682011-11-07 05:07:52 +000057};
58
Richard Smithcc5d4f62011-11-07 09:22:26 +000059// FIXME: Reduce the malloc traffic here.
60
61APValue::Arr::Arr(unsigned NumElts, unsigned Size) :
62 Elts(new APValue[NumElts + (NumElts != Size ? 1 : 0)]),
63 NumElts(NumElts), ArrSize(Size) {}
64APValue::Arr::~Arr() { delete [] Elts; }
65
Richard Smith180f4792011-11-10 06:34:14 +000066APValue::StructData::StructData(unsigned NumBases, unsigned NumFields) :
67 Elts(new APValue[NumBases+NumFields]),
68 NumBases(NumBases), NumFields(NumFields) {}
69APValue::StructData::~StructData() {
70 delete [] Elts;
71}
72
73APValue::UnionData::UnionData() : Field(0), Value(new APValue) {}
74APValue::UnionData::~UnionData () {
75 delete Value;
76}
77
Peter Collingbourne8cad3042011-05-13 03:29:01 +000078APValue::APValue(const Expr* B) : Kind(Uninitialized) {
Richard Smith9a17a682011-11-07 05:07:52 +000079 MakeLValue();
80 setLValue(B, CharUnits::Zero(), ArrayRef<LValuePathEntry>());
Ken Dycka7305832010-01-15 12:37:54 +000081}
Chris Lattner64c34f12008-11-16 07:46:48 +000082
83const APValue &APValue::operator=(const APValue &RHS) {
Richard Smith180f4792011-11-10 06:34:14 +000084 if (this == &RHS)
85 return *this;
86 if (Kind != RHS.Kind || Kind == Array || Kind == Struct) {
Chris Lattner64c34f12008-11-16 07:46:48 +000087 MakeUninit();
88 if (RHS.isInt())
89 MakeInt();
90 else if (RHS.isFloat())
91 MakeFloat();
Nate Begeman3d309f92009-01-18 01:01:34 +000092 else if (RHS.isVector())
93 MakeVector();
Chris Lattner64c34f12008-11-16 07:46:48 +000094 else if (RHS.isComplexInt())
95 MakeComplexInt();
96 else if (RHS.isComplexFloat())
97 MakeComplexFloat();
98 else if (RHS.isLValue())
99 MakeLValue();
Richard Smithcc5d4f62011-11-07 09:22:26 +0000100 else if (RHS.isArray())
101 MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize());
Richard Smith180f4792011-11-10 06:34:14 +0000102 else if (RHS.isStruct())
103 MakeStruct(RHS.getStructNumBases(), RHS.getStructNumFields());
104 else if (RHS.isUnion())
105 MakeUnion();
Chris Lattner64c34f12008-11-16 07:46:48 +0000106 }
107 if (isInt())
108 setInt(RHS.getInt());
109 else if (isFloat())
110 setFloat(RHS.getFloat());
Nate Begeman3d309f92009-01-18 01:01:34 +0000111 else if (isVector())
Dan Gohmancb421fa2010-04-19 16:39:44 +0000112 setVector(((const Vec *)(const char *)RHS.Data)->Elts,
113 RHS.getVectorLength());
Chris Lattner64c34f12008-11-16 07:46:48 +0000114 else if (isComplexInt())
115 setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag());
116 else if (isComplexFloat())
117 setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag());
Richard Smith9a17a682011-11-07 05:07:52 +0000118 else if (isLValue()) {
119 if (RHS.hasLValuePath())
120 setLValue(RHS.getLValueBase(), RHS.getLValueOffset(),RHS.getLValuePath());
121 else
122 setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath());
Richard Smithcc5d4f62011-11-07 09:22:26 +0000123 } else if (isArray()) {
124 for (unsigned I = 0, N = RHS.getArrayInitializedElts(); I != N; ++I)
125 getArrayInitializedElt(I) = RHS.getArrayInitializedElt(I);
126 if (RHS.hasArrayFiller())
127 getArrayFiller() = RHS.getArrayFiller();
Richard Smith180f4792011-11-10 06:34:14 +0000128 } else if (isStruct()) {
129 for (unsigned I = 0, N = RHS.getStructNumBases(); I != N; ++I)
130 getStructBase(I) = RHS.getStructBase(I);
131 for (unsigned I = 0, N = RHS.getStructNumFields(); I != N; ++I)
132 getStructField(I) = RHS.getStructField(I);
133 } else if (isUnion())
134 setUnion(RHS.getUnionField(), RHS.getUnionValue());
Chris Lattner64c34f12008-11-16 07:46:48 +0000135 return *this;
136}
137
138void APValue::MakeUninit() {
139 if (Kind == Int)
Douglas Gregor98300462009-09-08 19:57:33 +0000140 ((APSInt*)(char*)Data)->~APSInt();
Chris Lattner64c34f12008-11-16 07:46:48 +0000141 else if (Kind == Float)
Douglas Gregor98300462009-09-08 19:57:33 +0000142 ((APFloat*)(char*)Data)->~APFloat();
Nate Begeman3d309f92009-01-18 01:01:34 +0000143 else if (Kind == Vector)
Douglas Gregor98300462009-09-08 19:57:33 +0000144 ((Vec*)(char*)Data)->~Vec();
Chris Lattner64c34f12008-11-16 07:46:48 +0000145 else if (Kind == ComplexInt)
Douglas Gregor98300462009-09-08 19:57:33 +0000146 ((ComplexAPSInt*)(char*)Data)->~ComplexAPSInt();
Chris Lattner64c34f12008-11-16 07:46:48 +0000147 else if (Kind == ComplexFloat)
Douglas Gregor98300462009-09-08 19:57:33 +0000148 ((ComplexAPFloat*)(char*)Data)->~ComplexAPFloat();
Richard Smithcc5d4f62011-11-07 09:22:26 +0000149 else if (Kind == LValue)
Douglas Gregor98300462009-09-08 19:57:33 +0000150 ((LV*)(char*)Data)->~LV();
Richard Smithcc5d4f62011-11-07 09:22:26 +0000151 else if (Kind == Array)
152 ((Arr*)(char*)Data)->~Arr();
Richard Smith180f4792011-11-10 06:34:14 +0000153 else if (Kind == Struct)
154 ((StructData*)(char*)Data)->~StructData();
155 else if (Kind == Union)
156 ((UnionData*)(char*)Data)->~UnionData();
Nate Begeman3d309f92009-01-18 01:01:34 +0000157 Kind = Uninitialized;
Chris Lattner64c34f12008-11-16 07:46:48 +0000158}
159
160void APValue::dump() const {
161 print(llvm::errs());
162 llvm::errs() << '\n';
Chris Lattner64c34f12008-11-16 07:46:48 +0000163}
164
165static double GetApproxValue(const llvm::APFloat &F) {
166 llvm::APFloat V = F;
167 bool ignored;
168 V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven,
169 &ignored);
170 return V.convertToDouble();
171}
172
Chris Lattner5f9e2722011-07-23 10:55:15 +0000173void APValue::print(raw_ostream &OS) const {
Chris Lattner64c34f12008-11-16 07:46:48 +0000174 switch (getKind()) {
Chris Lattner64c34f12008-11-16 07:46:48 +0000175 case Uninitialized:
176 OS << "Uninitialized";
177 return;
178 case Int:
179 OS << "Int: " << getInt();
180 return;
181 case Float:
182 OS << "Float: " << GetApproxValue(getFloat());
183 return;
Nate Begeman3d309f92009-01-18 01:01:34 +0000184 case Vector:
Nate Begeman59b5da62009-01-18 03:20:47 +0000185 OS << "Vector: " << getVectorElt(0);
Mike Stump1eb44332009-09-09 15:08:12 +0000186 for (unsigned i = 1; i != getVectorLength(); ++i)
Nate Begeman59b5da62009-01-18 03:20:47 +0000187 OS << ", " << getVectorElt(i);
Nate Begeman3d309f92009-01-18 01:01:34 +0000188 return;
Chris Lattner64c34f12008-11-16 07:46:48 +0000189 case ComplexInt:
190 OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag();
191 return;
192 case ComplexFloat:
193 OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal())
194 << ", " << GetApproxValue(getComplexFloatImag());
Richard Smithcc5d4f62011-11-07 09:22:26 +0000195 return;
Chris Lattner64c34f12008-11-16 07:46:48 +0000196 case LValue:
197 OS << "LValue: <todo>";
198 return;
Richard Smithcc5d4f62011-11-07 09:22:26 +0000199 case Array:
200 OS << "Array: ";
201 for (unsigned I = 0, N = getArrayInitializedElts(); I != N; ++I) {
202 OS << getArrayInitializedElt(I);
203 if (I != getArraySize() - 1) OS << ", ";
204 }
205 if (hasArrayFiller())
206 OS << getArraySize() - getArrayInitializedElts() << " x "
207 << getArrayFiller();
208 return;
Richard Smith180f4792011-11-10 06:34:14 +0000209 case Struct:
210 OS << "Struct ";
211 if (unsigned N = getStructNumBases()) {
212 OS << " bases: " << getStructBase(0);
213 for (unsigned I = 1; I != N; ++I)
214 OS << ", " << getStructBase(I);
215 }
216 if (unsigned N = getStructNumFields()) {
217 OS << " fields: " << getStructField(0);
218 for (unsigned I = 1; I != N; ++I)
219 OS << ", " << getStructField(I);
220 }
221 return;
222 case Union:
223 OS << "Union: " << getUnionValue();
224 return;
Chris Lattner64c34f12008-11-16 07:46:48 +0000225 }
Richard Smith180f4792011-11-10 06:34:14 +0000226 llvm_unreachable("Unknown APValue kind!");
Chris Lattner64c34f12008-11-16 07:46:48 +0000227}
228
Chris Lattner5f9e2722011-07-23 10:55:15 +0000229static void WriteShortAPValueToStream(raw_ostream& Out,
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000230 const APValue& V) {
231 switch (V.getKind()) {
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000232 case APValue::Uninitialized:
233 Out << "Uninitialized";
Richard Smith180f4792011-11-10 06:34:14 +0000234 return;
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000235 case APValue::Int:
236 Out << V.getInt();
Richard Smith180f4792011-11-10 06:34:14 +0000237 return;
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000238 case APValue::Float:
239 Out << GetApproxValue(V.getFloat());
Richard Smith180f4792011-11-10 06:34:14 +0000240 return;
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000241 case APValue::Vector:
242 Out << '[';
243 WriteShortAPValueToStream(Out, V.getVectorElt(0));
244 for (unsigned i = 1; i != V.getVectorLength(); ++i) {
245 Out << ", ";
246 WriteShortAPValueToStream(Out, V.getVectorElt(i));
247 }
248 Out << ']';
Richard Smith180f4792011-11-10 06:34:14 +0000249 return;
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000250 case APValue::ComplexInt:
251 Out << V.getComplexIntReal() << "+" << V.getComplexIntImag() << "i";
Richard Smith180f4792011-11-10 06:34:14 +0000252 return;
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000253 case APValue::ComplexFloat:
254 Out << GetApproxValue(V.getComplexFloatReal()) << "+"
255 << GetApproxValue(V.getComplexFloatImag()) << "i";
Richard Smith180f4792011-11-10 06:34:14 +0000256 return;
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000257 case APValue::LValue:
258 Out << "LValue: <todo>";
Richard Smith180f4792011-11-10 06:34:14 +0000259 return;
Richard Smithcc5d4f62011-11-07 09:22:26 +0000260 case APValue::Array:
261 Out << '{';
262 if (unsigned N = V.getArrayInitializedElts()) {
263 Out << V.getArrayInitializedElt(0);
264 for (unsigned I = 1; I != N; ++I)
265 Out << ", " << V.getArrayInitializedElt(I);
266 }
267 Out << '}';
Richard Smith180f4792011-11-10 06:34:14 +0000268 return;
269 case APValue::Struct:
270 Out << '{';
271 if (unsigned N = V.getStructNumBases()) {
272 Out << V.getStructBase(0);
273 for (unsigned I = 1; I != N; ++I)
274 Out << ", " << V.getStructBase(I);
275 if (V.getStructNumFields())
276 Out << ", ";
277 }
278 if (unsigned N = V.getStructNumFields()) {
279 Out << V.getStructField(0);
280 for (unsigned I = 1; I != N; ++I)
281 Out << ", " << V.getStructField(I);
282 }
283 Out << '}';
284 return;
285 case APValue::Union:
286 Out << '{' << V.getUnionValue() << '}';
287 return;
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000288 }
Richard Smith180f4792011-11-10 06:34:14 +0000289 llvm_unreachable("Unknown APValue kind!");
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000290}
291
292const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
293 const APValue &V) {
294 llvm::SmallString<64> Buffer;
295 llvm::raw_svector_ostream Out(Buffer);
296 WriteShortAPValueToStream(Out, V);
297 return DB << Out.str();
298}
299
Peter Collingbourne8cad3042011-05-13 03:29:01 +0000300const Expr* APValue::getLValueBase() const {
Ken Dycka7305832010-01-15 12:37:54 +0000301 assert(isLValue() && "Invalid accessor");
302 return ((const LV*)(const void*)Data)->Base;
303}
304
Richard Smith47a1eed2011-10-29 20:57:55 +0000305CharUnits &APValue::getLValueOffset() {
306 assert(isLValue() && "Invalid accessor");
307 return ((LV*)(void*)Data)->Offset;
Ken Dycka7305832010-01-15 12:37:54 +0000308}
309
Richard Smith9a17a682011-11-07 05:07:52 +0000310bool APValue::hasLValuePath() const {
Ken Dycka7305832010-01-15 12:37:54 +0000311 assert(isLValue() && "Invalid accessor");
Richard Smith38dce9b2011-11-07 07:31:09 +0000312 return ((const LV*)(const char*)Data)->hasPath();
Richard Smith9a17a682011-11-07 05:07:52 +0000313}
314
315ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const {
316 assert(isLValue() && hasLValuePath() && "Invalid accessor");
Richard Smith38dce9b2011-11-07 07:31:09 +0000317 const LV &LVal = *((const LV*)(const char*)Data);
Richard Smith9a17a682011-11-07 05:07:52 +0000318 return ArrayRef<LValuePathEntry>(LVal.getPath(), LVal.PathLength);
319}
320
321void APValue::setLValue(const Expr *B, const CharUnits &O, NoLValuePath) {
322 assert(isLValue() && "Invalid accessor");
323 LV &LVal = *((LV*)(char*)Data);
Richard Smith180f4792011-11-10 06:34:14 +0000324 LVal.freePath();
Richard Smith9a17a682011-11-07 05:07:52 +0000325 LVal.Base = B;
326 LVal.Offset = O;
327 LVal.PathLength = (unsigned)-1;
328}
329
330void APValue::setLValue(const Expr *B, const CharUnits &O,
331 ArrayRef<LValuePathEntry> Path) {
332 assert(isLValue() && "Invalid accessor");
333 LV &LVal = *((LV*)(char*)Data);
Richard Smith180f4792011-11-10 06:34:14 +0000334 LVal.freePath();
Richard Smith9a17a682011-11-07 05:07:52 +0000335 LVal.Base = B;
336 LVal.Offset = O;
337 LVal.PathLength = Path.size();
Richard Smith38dce9b2011-11-07 07:31:09 +0000338 LVal.allocPath();
Richard Smith9a17a682011-11-07 05:07:52 +0000339 memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry));
Ken Dycka7305832010-01-15 12:37:54 +0000340}
341
342void APValue::MakeLValue() {
343 assert(isUninit() && "Bad state change");
Richard Smith9a17a682011-11-07 05:07:52 +0000344 assert(sizeof(LV) <= MaxSize && "LV too big");
Ken Dycka7305832010-01-15 12:37:54 +0000345 new ((void*)(char*)Data) LV();
346 Kind = LValue;
347}
Richard Smithcc5d4f62011-11-07 09:22:26 +0000348
349void APValue::MakeArray(unsigned InitElts, unsigned Size) {
350 assert(isUninit() && "Bad state change");
351 new ((void*)(char*)Data) Arr(InitElts, Size);
352 Kind = Array;
353}