blob: 146ebad0553f921b7fac5fa70ccd9f134e2b9c10 [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 {
Richard Smith1bf9a9e2011-11-12 22:28:03 +000024 APValue::LValueBase 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
Chris Lattner64c34f12008-11-16 07:46:48 +000078const APValue &APValue::operator=(const APValue &RHS) {
Richard Smith180f4792011-11-10 06:34:14 +000079 if (this == &RHS)
80 return *this;
81 if (Kind != RHS.Kind || Kind == Array || Kind == Struct) {
Chris Lattner64c34f12008-11-16 07:46:48 +000082 MakeUninit();
83 if (RHS.isInt())
84 MakeInt();
85 else if (RHS.isFloat())
86 MakeFloat();
Nate Begeman3d309f92009-01-18 01:01:34 +000087 else if (RHS.isVector())
88 MakeVector();
Chris Lattner64c34f12008-11-16 07:46:48 +000089 else if (RHS.isComplexInt())
90 MakeComplexInt();
91 else if (RHS.isComplexFloat())
92 MakeComplexFloat();
93 else if (RHS.isLValue())
94 MakeLValue();
Richard Smithcc5d4f62011-11-07 09:22:26 +000095 else if (RHS.isArray())
96 MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize());
Richard Smith180f4792011-11-10 06:34:14 +000097 else if (RHS.isStruct())
98 MakeStruct(RHS.getStructNumBases(), RHS.getStructNumFields());
99 else if (RHS.isUnion())
100 MakeUnion();
Chris Lattner64c34f12008-11-16 07:46:48 +0000101 }
102 if (isInt())
103 setInt(RHS.getInt());
104 else if (isFloat())
105 setFloat(RHS.getFloat());
Nate Begeman3d309f92009-01-18 01:01:34 +0000106 else if (isVector())
Dan Gohmancb421fa2010-04-19 16:39:44 +0000107 setVector(((const Vec *)(const char *)RHS.Data)->Elts,
108 RHS.getVectorLength());
Chris Lattner64c34f12008-11-16 07:46:48 +0000109 else if (isComplexInt())
110 setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag());
111 else if (isComplexFloat())
112 setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag());
Richard Smith9a17a682011-11-07 05:07:52 +0000113 else if (isLValue()) {
114 if (RHS.hasLValuePath())
115 setLValue(RHS.getLValueBase(), RHS.getLValueOffset(),RHS.getLValuePath());
116 else
117 setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath());
Richard Smithcc5d4f62011-11-07 09:22:26 +0000118 } else if (isArray()) {
119 for (unsigned I = 0, N = RHS.getArrayInitializedElts(); I != N; ++I)
120 getArrayInitializedElt(I) = RHS.getArrayInitializedElt(I);
121 if (RHS.hasArrayFiller())
122 getArrayFiller() = RHS.getArrayFiller();
Richard Smith180f4792011-11-10 06:34:14 +0000123 } else if (isStruct()) {
124 for (unsigned I = 0, N = RHS.getStructNumBases(); I != N; ++I)
125 getStructBase(I) = RHS.getStructBase(I);
126 for (unsigned I = 0, N = RHS.getStructNumFields(); I != N; ++I)
127 getStructField(I) = RHS.getStructField(I);
128 } else if (isUnion())
129 setUnion(RHS.getUnionField(), RHS.getUnionValue());
Chris Lattner64c34f12008-11-16 07:46:48 +0000130 return *this;
131}
132
133void APValue::MakeUninit() {
134 if (Kind == Int)
Douglas Gregor98300462009-09-08 19:57:33 +0000135 ((APSInt*)(char*)Data)->~APSInt();
Chris Lattner64c34f12008-11-16 07:46:48 +0000136 else if (Kind == Float)
Douglas Gregor98300462009-09-08 19:57:33 +0000137 ((APFloat*)(char*)Data)->~APFloat();
Nate Begeman3d309f92009-01-18 01:01:34 +0000138 else if (Kind == Vector)
Douglas Gregor98300462009-09-08 19:57:33 +0000139 ((Vec*)(char*)Data)->~Vec();
Chris Lattner64c34f12008-11-16 07:46:48 +0000140 else if (Kind == ComplexInt)
Douglas Gregor98300462009-09-08 19:57:33 +0000141 ((ComplexAPSInt*)(char*)Data)->~ComplexAPSInt();
Chris Lattner64c34f12008-11-16 07:46:48 +0000142 else if (Kind == ComplexFloat)
Douglas Gregor98300462009-09-08 19:57:33 +0000143 ((ComplexAPFloat*)(char*)Data)->~ComplexAPFloat();
Richard Smithcc5d4f62011-11-07 09:22:26 +0000144 else if (Kind == LValue)
Douglas Gregor98300462009-09-08 19:57:33 +0000145 ((LV*)(char*)Data)->~LV();
Richard Smithcc5d4f62011-11-07 09:22:26 +0000146 else if (Kind == Array)
147 ((Arr*)(char*)Data)->~Arr();
Richard Smith180f4792011-11-10 06:34:14 +0000148 else if (Kind == Struct)
149 ((StructData*)(char*)Data)->~StructData();
150 else if (Kind == Union)
151 ((UnionData*)(char*)Data)->~UnionData();
Nate Begeman3d309f92009-01-18 01:01:34 +0000152 Kind = Uninitialized;
Chris Lattner64c34f12008-11-16 07:46:48 +0000153}
154
155void APValue::dump() const {
156 print(llvm::errs());
157 llvm::errs() << '\n';
Chris Lattner64c34f12008-11-16 07:46:48 +0000158}
159
160static double GetApproxValue(const llvm::APFloat &F) {
161 llvm::APFloat V = F;
162 bool ignored;
163 V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven,
164 &ignored);
165 return V.convertToDouble();
166}
167
Chris Lattner5f9e2722011-07-23 10:55:15 +0000168void APValue::print(raw_ostream &OS) const {
Chris Lattner64c34f12008-11-16 07:46:48 +0000169 switch (getKind()) {
Chris Lattner64c34f12008-11-16 07:46:48 +0000170 case Uninitialized:
171 OS << "Uninitialized";
172 return;
173 case Int:
174 OS << "Int: " << getInt();
175 return;
176 case Float:
177 OS << "Float: " << GetApproxValue(getFloat());
178 return;
Nate Begeman3d309f92009-01-18 01:01:34 +0000179 case Vector:
Nate Begeman59b5da62009-01-18 03:20:47 +0000180 OS << "Vector: " << getVectorElt(0);
Mike Stump1eb44332009-09-09 15:08:12 +0000181 for (unsigned i = 1; i != getVectorLength(); ++i)
Nate Begeman59b5da62009-01-18 03:20:47 +0000182 OS << ", " << getVectorElt(i);
Nate Begeman3d309f92009-01-18 01:01:34 +0000183 return;
Chris Lattner64c34f12008-11-16 07:46:48 +0000184 case ComplexInt:
185 OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag();
186 return;
187 case ComplexFloat:
188 OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal())
189 << ", " << GetApproxValue(getComplexFloatImag());
Richard Smithcc5d4f62011-11-07 09:22:26 +0000190 return;
Chris Lattner64c34f12008-11-16 07:46:48 +0000191 case LValue:
192 OS << "LValue: <todo>";
193 return;
Richard Smithcc5d4f62011-11-07 09:22:26 +0000194 case Array:
195 OS << "Array: ";
196 for (unsigned I = 0, N = getArrayInitializedElts(); I != N; ++I) {
197 OS << getArrayInitializedElt(I);
198 if (I != getArraySize() - 1) OS << ", ";
199 }
200 if (hasArrayFiller())
201 OS << getArraySize() - getArrayInitializedElts() << " x "
202 << getArrayFiller();
203 return;
Richard Smith180f4792011-11-10 06:34:14 +0000204 case Struct:
205 OS << "Struct ";
206 if (unsigned N = getStructNumBases()) {
207 OS << " bases: " << getStructBase(0);
208 for (unsigned I = 1; I != N; ++I)
209 OS << ", " << getStructBase(I);
210 }
211 if (unsigned N = getStructNumFields()) {
212 OS << " fields: " << getStructField(0);
213 for (unsigned I = 1; I != N; ++I)
214 OS << ", " << getStructField(I);
215 }
216 return;
217 case Union:
218 OS << "Union: " << getUnionValue();
219 return;
Chris Lattner64c34f12008-11-16 07:46:48 +0000220 }
Richard Smith180f4792011-11-10 06:34:14 +0000221 llvm_unreachable("Unknown APValue kind!");
Chris Lattner64c34f12008-11-16 07:46:48 +0000222}
223
Chris Lattner5f9e2722011-07-23 10:55:15 +0000224static void WriteShortAPValueToStream(raw_ostream& Out,
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000225 const APValue& V) {
226 switch (V.getKind()) {
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000227 case APValue::Uninitialized:
228 Out << "Uninitialized";
Richard Smith180f4792011-11-10 06:34:14 +0000229 return;
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000230 case APValue::Int:
231 Out << V.getInt();
Richard Smith180f4792011-11-10 06:34:14 +0000232 return;
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000233 case APValue::Float:
234 Out << GetApproxValue(V.getFloat());
Richard Smith180f4792011-11-10 06:34:14 +0000235 return;
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000236 case APValue::Vector:
237 Out << '[';
238 WriteShortAPValueToStream(Out, V.getVectorElt(0));
239 for (unsigned i = 1; i != V.getVectorLength(); ++i) {
240 Out << ", ";
241 WriteShortAPValueToStream(Out, V.getVectorElt(i));
242 }
243 Out << ']';
Richard Smith180f4792011-11-10 06:34:14 +0000244 return;
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000245 case APValue::ComplexInt:
246 Out << V.getComplexIntReal() << "+" << V.getComplexIntImag() << "i";
Richard Smith180f4792011-11-10 06:34:14 +0000247 return;
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000248 case APValue::ComplexFloat:
249 Out << GetApproxValue(V.getComplexFloatReal()) << "+"
250 << GetApproxValue(V.getComplexFloatImag()) << "i";
Richard Smith180f4792011-11-10 06:34:14 +0000251 return;
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000252 case APValue::LValue:
253 Out << "LValue: <todo>";
Richard Smith180f4792011-11-10 06:34:14 +0000254 return;
Richard Smithcc5d4f62011-11-07 09:22:26 +0000255 case APValue::Array:
256 Out << '{';
257 if (unsigned N = V.getArrayInitializedElts()) {
258 Out << V.getArrayInitializedElt(0);
259 for (unsigned I = 1; I != N; ++I)
260 Out << ", " << V.getArrayInitializedElt(I);
261 }
262 Out << '}';
Richard Smith180f4792011-11-10 06:34:14 +0000263 return;
264 case APValue::Struct:
265 Out << '{';
266 if (unsigned N = V.getStructNumBases()) {
267 Out << V.getStructBase(0);
268 for (unsigned I = 1; I != N; ++I)
269 Out << ", " << V.getStructBase(I);
270 if (V.getStructNumFields())
271 Out << ", ";
272 }
273 if (unsigned N = V.getStructNumFields()) {
274 Out << V.getStructField(0);
275 for (unsigned I = 1; I != N; ++I)
276 Out << ", " << V.getStructField(I);
277 }
278 Out << '}';
279 return;
280 case APValue::Union:
281 Out << '{' << V.getUnionValue() << '}';
282 return;
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000283 }
Richard Smith180f4792011-11-10 06:34:14 +0000284 llvm_unreachable("Unknown APValue kind!");
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000285}
286
287const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
288 const APValue &V) {
289 llvm::SmallString<64> Buffer;
290 llvm::raw_svector_ostream Out(Buffer);
291 WriteShortAPValueToStream(Out, V);
292 return DB << Out.str();
293}
294
Richard Smith1bf9a9e2011-11-12 22:28:03 +0000295const APValue::LValueBase APValue::getLValueBase() const {
Ken Dycka7305832010-01-15 12:37:54 +0000296 assert(isLValue() && "Invalid accessor");
297 return ((const LV*)(const void*)Data)->Base;
298}
299
Richard Smith47a1eed2011-10-29 20:57:55 +0000300CharUnits &APValue::getLValueOffset() {
301 assert(isLValue() && "Invalid accessor");
302 return ((LV*)(void*)Data)->Offset;
Ken Dycka7305832010-01-15 12:37:54 +0000303}
304
Richard Smith9a17a682011-11-07 05:07:52 +0000305bool APValue::hasLValuePath() const {
Ken Dycka7305832010-01-15 12:37:54 +0000306 assert(isLValue() && "Invalid accessor");
Richard Smith38dce9b2011-11-07 07:31:09 +0000307 return ((const LV*)(const char*)Data)->hasPath();
Richard Smith9a17a682011-11-07 05:07:52 +0000308}
309
310ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const {
311 assert(isLValue() && hasLValuePath() && "Invalid accessor");
Richard Smith38dce9b2011-11-07 07:31:09 +0000312 const LV &LVal = *((const LV*)(const char*)Data);
Richard Smith9a17a682011-11-07 05:07:52 +0000313 return ArrayRef<LValuePathEntry>(LVal.getPath(), LVal.PathLength);
314}
315
Richard Smith1bf9a9e2011-11-12 22:28:03 +0000316void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath) {
Richard Smith9a17a682011-11-07 05:07:52 +0000317 assert(isLValue() && "Invalid accessor");
318 LV &LVal = *((LV*)(char*)Data);
Richard Smith180f4792011-11-10 06:34:14 +0000319 LVal.freePath();
Richard Smith9a17a682011-11-07 05:07:52 +0000320 LVal.Base = B;
321 LVal.Offset = O;
322 LVal.PathLength = (unsigned)-1;
323}
324
Richard Smith1bf9a9e2011-11-12 22:28:03 +0000325void APValue::setLValue(LValueBase B, const CharUnits &O,
Richard Smith9a17a682011-11-07 05:07:52 +0000326 ArrayRef<LValuePathEntry> Path) {
327 assert(isLValue() && "Invalid accessor");
328 LV &LVal = *((LV*)(char*)Data);
Richard Smith180f4792011-11-10 06:34:14 +0000329 LVal.freePath();
Richard Smith9a17a682011-11-07 05:07:52 +0000330 LVal.Base = B;
331 LVal.Offset = O;
332 LVal.PathLength = Path.size();
Richard Smith38dce9b2011-11-07 07:31:09 +0000333 LVal.allocPath();
Richard Smith9a17a682011-11-07 05:07:52 +0000334 memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry));
Ken Dycka7305832010-01-15 12:37:54 +0000335}
336
337void APValue::MakeLValue() {
338 assert(isUninit() && "Bad state change");
Richard Smith9a17a682011-11-07 05:07:52 +0000339 assert(sizeof(LV) <= MaxSize && "LV too big");
Ken Dycka7305832010-01-15 12:37:54 +0000340 new ((void*)(char*)Data) LV();
341 Kind = LValue;
342}
Richard Smithcc5d4f62011-11-07 09:22:26 +0000343
344void APValue::MakeArray(unsigned InitElts, unsigned Size) {
345 assert(isUninit() && "Bad state change");
346 new ((void*)(char*)Data) Arr(InitElts, Size);
347 Kind = Array;
348}