blob: af34642bead96e7e4ffac38871450b6c80b0b335 [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 }
48
49 bool hasPath() const { return PathLength != (unsigned)-1; }
50 bool hasPathPtr() const { return hasPath() && PathLength > InlinePathSpace; }
51
52 LValuePathEntry *getPath() { return hasPathPtr() ? PathPtr : Path; }
Richard Smith38dce9b2011-11-07 07:31:09 +000053 const LValuePathEntry *getPath() const {
54 return hasPathPtr() ? PathPtr : Path;
55 }
Richard Smith9a17a682011-11-07 05:07:52 +000056};
57
Richard Smithcc5d4f62011-11-07 09:22:26 +000058// FIXME: Reduce the malloc traffic here.
59
60APValue::Arr::Arr(unsigned NumElts, unsigned Size) :
61 Elts(new APValue[NumElts + (NumElts != Size ? 1 : 0)]),
62 NumElts(NumElts), ArrSize(Size) {}
63APValue::Arr::~Arr() { delete [] Elts; }
64
Peter Collingbourne8cad3042011-05-13 03:29:01 +000065APValue::APValue(const Expr* B) : Kind(Uninitialized) {
Richard Smith9a17a682011-11-07 05:07:52 +000066 MakeLValue();
67 setLValue(B, CharUnits::Zero(), ArrayRef<LValuePathEntry>());
Ken Dycka7305832010-01-15 12:37:54 +000068}
Chris Lattner64c34f12008-11-16 07:46:48 +000069
70const APValue &APValue::operator=(const APValue &RHS) {
71 if (Kind != RHS.Kind) {
72 MakeUninit();
73 if (RHS.isInt())
74 MakeInt();
75 else if (RHS.isFloat())
76 MakeFloat();
Nate Begeman3d309f92009-01-18 01:01:34 +000077 else if (RHS.isVector())
78 MakeVector();
Chris Lattner64c34f12008-11-16 07:46:48 +000079 else if (RHS.isComplexInt())
80 MakeComplexInt();
81 else if (RHS.isComplexFloat())
82 MakeComplexFloat();
83 else if (RHS.isLValue())
84 MakeLValue();
Richard Smithcc5d4f62011-11-07 09:22:26 +000085 else if (RHS.isArray())
86 MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize());
Chris Lattner64c34f12008-11-16 07:46:48 +000087 }
88 if (isInt())
89 setInt(RHS.getInt());
90 else if (isFloat())
91 setFloat(RHS.getFloat());
Nate Begeman3d309f92009-01-18 01:01:34 +000092 else if (isVector())
Dan Gohmancb421fa2010-04-19 16:39:44 +000093 setVector(((const Vec *)(const char *)RHS.Data)->Elts,
94 RHS.getVectorLength());
Chris Lattner64c34f12008-11-16 07:46:48 +000095 else if (isComplexInt())
96 setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag());
97 else if (isComplexFloat())
98 setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag());
Richard Smith9a17a682011-11-07 05:07:52 +000099 else if (isLValue()) {
100 if (RHS.hasLValuePath())
101 setLValue(RHS.getLValueBase(), RHS.getLValueOffset(),RHS.getLValuePath());
102 else
103 setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath());
Richard Smithcc5d4f62011-11-07 09:22:26 +0000104 } else if (isArray()) {
105 for (unsigned I = 0, N = RHS.getArrayInitializedElts(); I != N; ++I)
106 getArrayInitializedElt(I) = RHS.getArrayInitializedElt(I);
107 if (RHS.hasArrayFiller())
108 getArrayFiller() = RHS.getArrayFiller();
Richard Smith9a17a682011-11-07 05:07:52 +0000109 }
Chris Lattner64c34f12008-11-16 07:46:48 +0000110 return *this;
111}
112
113void APValue::MakeUninit() {
114 if (Kind == Int)
Douglas Gregor98300462009-09-08 19:57:33 +0000115 ((APSInt*)(char*)Data)->~APSInt();
Chris Lattner64c34f12008-11-16 07:46:48 +0000116 else if (Kind == Float)
Douglas Gregor98300462009-09-08 19:57:33 +0000117 ((APFloat*)(char*)Data)->~APFloat();
Nate Begeman3d309f92009-01-18 01:01:34 +0000118 else if (Kind == Vector)
Douglas Gregor98300462009-09-08 19:57:33 +0000119 ((Vec*)(char*)Data)->~Vec();
Chris Lattner64c34f12008-11-16 07:46:48 +0000120 else if (Kind == ComplexInt)
Douglas Gregor98300462009-09-08 19:57:33 +0000121 ((ComplexAPSInt*)(char*)Data)->~ComplexAPSInt();
Chris Lattner64c34f12008-11-16 07:46:48 +0000122 else if (Kind == ComplexFloat)
Douglas Gregor98300462009-09-08 19:57:33 +0000123 ((ComplexAPFloat*)(char*)Data)->~ComplexAPFloat();
Richard Smithcc5d4f62011-11-07 09:22:26 +0000124 else if (Kind == LValue)
Douglas Gregor98300462009-09-08 19:57:33 +0000125 ((LV*)(char*)Data)->~LV();
Richard Smithcc5d4f62011-11-07 09:22:26 +0000126 else if (Kind == Array)
127 ((Arr*)(char*)Data)->~Arr();
Nate Begeman3d309f92009-01-18 01:01:34 +0000128 Kind = Uninitialized;
Chris Lattner64c34f12008-11-16 07:46:48 +0000129}
130
131void APValue::dump() const {
132 print(llvm::errs());
133 llvm::errs() << '\n';
Chris Lattner64c34f12008-11-16 07:46:48 +0000134}
135
136static double GetApproxValue(const llvm::APFloat &F) {
137 llvm::APFloat V = F;
138 bool ignored;
139 V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven,
140 &ignored);
141 return V.convertToDouble();
142}
143
Chris Lattner5f9e2722011-07-23 10:55:15 +0000144void APValue::print(raw_ostream &OS) const {
Chris Lattner64c34f12008-11-16 07:46:48 +0000145 switch (getKind()) {
David Blaikieb219cfc2011-09-23 05:06:16 +0000146 default: llvm_unreachable("Unknown APValue kind!");
Chris Lattner64c34f12008-11-16 07:46:48 +0000147 case Uninitialized:
148 OS << "Uninitialized";
149 return;
150 case Int:
151 OS << "Int: " << getInt();
152 return;
153 case Float:
154 OS << "Float: " << GetApproxValue(getFloat());
155 return;
Nate Begeman3d309f92009-01-18 01:01:34 +0000156 case Vector:
Nate Begeman59b5da62009-01-18 03:20:47 +0000157 OS << "Vector: " << getVectorElt(0);
Mike Stump1eb44332009-09-09 15:08:12 +0000158 for (unsigned i = 1; i != getVectorLength(); ++i)
Nate Begeman59b5da62009-01-18 03:20:47 +0000159 OS << ", " << getVectorElt(i);
Nate Begeman3d309f92009-01-18 01:01:34 +0000160 return;
Chris Lattner64c34f12008-11-16 07:46:48 +0000161 case ComplexInt:
162 OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag();
163 return;
164 case ComplexFloat:
165 OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal())
166 << ", " << GetApproxValue(getComplexFloatImag());
Richard Smithcc5d4f62011-11-07 09:22:26 +0000167 return;
Chris Lattner64c34f12008-11-16 07:46:48 +0000168 case LValue:
169 OS << "LValue: <todo>";
170 return;
Richard Smithcc5d4f62011-11-07 09:22:26 +0000171 case Array:
172 OS << "Array: ";
173 for (unsigned I = 0, N = getArrayInitializedElts(); I != N; ++I) {
174 OS << getArrayInitializedElt(I);
175 if (I != getArraySize() - 1) OS << ", ";
176 }
177 if (hasArrayFiller())
178 OS << getArraySize() - getArrayInitializedElts() << " x "
179 << getArrayFiller();
180 return;
Chris Lattner64c34f12008-11-16 07:46:48 +0000181 }
182}
183
Chris Lattner5f9e2722011-07-23 10:55:15 +0000184static void WriteShortAPValueToStream(raw_ostream& Out,
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000185 const APValue& V) {
186 switch (V.getKind()) {
David Blaikieb219cfc2011-09-23 05:06:16 +0000187 default: llvm_unreachable("Unknown APValue kind!");
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000188 case APValue::Uninitialized:
189 Out << "Uninitialized";
190 break;
191 case APValue::Int:
192 Out << V.getInt();
193 break;
194 case APValue::Float:
195 Out << GetApproxValue(V.getFloat());
196 break;
197 case APValue::Vector:
198 Out << '[';
199 WriteShortAPValueToStream(Out, V.getVectorElt(0));
200 for (unsigned i = 1; i != V.getVectorLength(); ++i) {
201 Out << ", ";
202 WriteShortAPValueToStream(Out, V.getVectorElt(i));
203 }
204 Out << ']';
205 break;
206 case APValue::ComplexInt:
207 Out << V.getComplexIntReal() << "+" << V.getComplexIntImag() << "i";
208 break;
209 case APValue::ComplexFloat:
210 Out << GetApproxValue(V.getComplexFloatReal()) << "+"
211 << GetApproxValue(V.getComplexFloatImag()) << "i";
212 break;
213 case APValue::LValue:
214 Out << "LValue: <todo>";
215 break;
Richard Smithcc5d4f62011-11-07 09:22:26 +0000216 case APValue::Array:
217 Out << '{';
218 if (unsigned N = V.getArrayInitializedElts()) {
219 Out << V.getArrayInitializedElt(0);
220 for (unsigned I = 1; I != N; ++I)
221 Out << ", " << V.getArrayInitializedElt(I);
222 }
223 Out << '}';
224 break;
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000225 }
226}
227
228const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
229 const APValue &V) {
230 llvm::SmallString<64> Buffer;
231 llvm::raw_svector_ostream Out(Buffer);
232 WriteShortAPValueToStream(Out, V);
233 return DB << Out.str();
234}
235
Peter Collingbourne8cad3042011-05-13 03:29:01 +0000236const Expr* APValue::getLValueBase() const {
Ken Dycka7305832010-01-15 12:37:54 +0000237 assert(isLValue() && "Invalid accessor");
238 return ((const LV*)(const void*)Data)->Base;
239}
240
Richard Smith47a1eed2011-10-29 20:57:55 +0000241CharUnits &APValue::getLValueOffset() {
242 assert(isLValue() && "Invalid accessor");
243 return ((LV*)(void*)Data)->Offset;
Ken Dycka7305832010-01-15 12:37:54 +0000244}
245
Richard Smith9a17a682011-11-07 05:07:52 +0000246bool APValue::hasLValuePath() const {
Ken Dycka7305832010-01-15 12:37:54 +0000247 assert(isLValue() && "Invalid accessor");
Richard Smith38dce9b2011-11-07 07:31:09 +0000248 return ((const LV*)(const char*)Data)->hasPath();
Richard Smith9a17a682011-11-07 05:07:52 +0000249}
250
251ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const {
252 assert(isLValue() && hasLValuePath() && "Invalid accessor");
Richard Smith38dce9b2011-11-07 07:31:09 +0000253 const LV &LVal = *((const LV*)(const char*)Data);
Richard Smith9a17a682011-11-07 05:07:52 +0000254 return ArrayRef<LValuePathEntry>(LVal.getPath(), LVal.PathLength);
255}
256
257void APValue::setLValue(const Expr *B, const CharUnits &O, NoLValuePath) {
258 assert(isLValue() && "Invalid accessor");
259 LV &LVal = *((LV*)(char*)Data);
260 LVal.Base = B;
261 LVal.Offset = O;
262 LVal.PathLength = (unsigned)-1;
263}
264
265void APValue::setLValue(const Expr *B, const CharUnits &O,
266 ArrayRef<LValuePathEntry> Path) {
267 assert(isLValue() && "Invalid accessor");
268 LV &LVal = *((LV*)(char*)Data);
269 LVal.Base = B;
270 LVal.Offset = O;
271 LVal.PathLength = Path.size();
Richard Smith38dce9b2011-11-07 07:31:09 +0000272 LVal.allocPath();
Richard Smith9a17a682011-11-07 05:07:52 +0000273 memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry));
Ken Dycka7305832010-01-15 12:37:54 +0000274}
275
276void APValue::MakeLValue() {
277 assert(isUninit() && "Bad state change");
Richard Smith9a17a682011-11-07 05:07:52 +0000278 assert(sizeof(LV) <= MaxSize && "LV too big");
Ken Dycka7305832010-01-15 12:37:54 +0000279 new ((void*)(char*)Data) LV();
280 Kind = LValue;
281}
Richard Smithcc5d4f62011-11-07 09:22:26 +0000282
283void APValue::MakeArray(unsigned InitElts, unsigned Size) {
284 assert(isUninit() && "Bad state change");
285 new ((void*)(char*)Data) Arr(InitElts, Size);
286 Kind = Array;
287}