blob: e2f7c6193760188199cc9f7268910ed7fd6fba5c [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
Peter Collingbourne8cad3042011-05-13 03:29:01 +000058APValue::APValue(const Expr* B) : Kind(Uninitialized) {
Richard Smith9a17a682011-11-07 05:07:52 +000059 MakeLValue();
60 setLValue(B, CharUnits::Zero(), ArrayRef<LValuePathEntry>());
Ken Dycka7305832010-01-15 12:37:54 +000061}
Chris Lattner64c34f12008-11-16 07:46:48 +000062
63const APValue &APValue::operator=(const APValue &RHS) {
64 if (Kind != RHS.Kind) {
65 MakeUninit();
66 if (RHS.isInt())
67 MakeInt();
68 else if (RHS.isFloat())
69 MakeFloat();
Nate Begeman3d309f92009-01-18 01:01:34 +000070 else if (RHS.isVector())
71 MakeVector();
Chris Lattner64c34f12008-11-16 07:46:48 +000072 else if (RHS.isComplexInt())
73 MakeComplexInt();
74 else if (RHS.isComplexFloat())
75 MakeComplexFloat();
76 else if (RHS.isLValue())
77 MakeLValue();
78 }
79 if (isInt())
80 setInt(RHS.getInt());
81 else if (isFloat())
82 setFloat(RHS.getFloat());
Nate Begeman3d309f92009-01-18 01:01:34 +000083 else if (isVector())
Dan Gohmancb421fa2010-04-19 16:39:44 +000084 setVector(((const Vec *)(const char *)RHS.Data)->Elts,
85 RHS.getVectorLength());
Chris Lattner64c34f12008-11-16 07:46:48 +000086 else if (isComplexInt())
87 setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag());
88 else if (isComplexFloat())
89 setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag());
Richard Smith9a17a682011-11-07 05:07:52 +000090 else if (isLValue()) {
91 if (RHS.hasLValuePath())
92 setLValue(RHS.getLValueBase(), RHS.getLValueOffset(),RHS.getLValuePath());
93 else
94 setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath());
95 }
Chris Lattner64c34f12008-11-16 07:46:48 +000096 return *this;
97}
98
99void APValue::MakeUninit() {
100 if (Kind == Int)
Douglas Gregor98300462009-09-08 19:57:33 +0000101 ((APSInt*)(char*)Data)->~APSInt();
Chris Lattner64c34f12008-11-16 07:46:48 +0000102 else if (Kind == Float)
Douglas Gregor98300462009-09-08 19:57:33 +0000103 ((APFloat*)(char*)Data)->~APFloat();
Nate Begeman3d309f92009-01-18 01:01:34 +0000104 else if (Kind == Vector)
Douglas Gregor98300462009-09-08 19:57:33 +0000105 ((Vec*)(char*)Data)->~Vec();
Chris Lattner64c34f12008-11-16 07:46:48 +0000106 else if (Kind == ComplexInt)
Douglas Gregor98300462009-09-08 19:57:33 +0000107 ((ComplexAPSInt*)(char*)Data)->~ComplexAPSInt();
Chris Lattner64c34f12008-11-16 07:46:48 +0000108 else if (Kind == ComplexFloat)
Douglas Gregor98300462009-09-08 19:57:33 +0000109 ((ComplexAPFloat*)(char*)Data)->~ComplexAPFloat();
Chris Lattner64c34f12008-11-16 07:46:48 +0000110 else if (Kind == LValue) {
Douglas Gregor98300462009-09-08 19:57:33 +0000111 ((LV*)(char*)Data)->~LV();
Chris Lattner64c34f12008-11-16 07:46:48 +0000112 }
Nate Begeman3d309f92009-01-18 01:01:34 +0000113 Kind = Uninitialized;
Chris Lattner64c34f12008-11-16 07:46:48 +0000114}
115
116void APValue::dump() const {
117 print(llvm::errs());
118 llvm::errs() << '\n';
Chris Lattner64c34f12008-11-16 07:46:48 +0000119}
120
121static double GetApproxValue(const llvm::APFloat &F) {
122 llvm::APFloat V = F;
123 bool ignored;
124 V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven,
125 &ignored);
126 return V.convertToDouble();
127}
128
Chris Lattner5f9e2722011-07-23 10:55:15 +0000129void APValue::print(raw_ostream &OS) const {
Chris Lattner64c34f12008-11-16 07:46:48 +0000130 switch (getKind()) {
David Blaikieb219cfc2011-09-23 05:06:16 +0000131 default: llvm_unreachable("Unknown APValue kind!");
Chris Lattner64c34f12008-11-16 07:46:48 +0000132 case Uninitialized:
133 OS << "Uninitialized";
134 return;
135 case Int:
136 OS << "Int: " << getInt();
137 return;
138 case Float:
139 OS << "Float: " << GetApproxValue(getFloat());
140 return;
Nate Begeman3d309f92009-01-18 01:01:34 +0000141 case Vector:
Nate Begeman59b5da62009-01-18 03:20:47 +0000142 OS << "Vector: " << getVectorElt(0);
Mike Stump1eb44332009-09-09 15:08:12 +0000143 for (unsigned i = 1; i != getVectorLength(); ++i)
Nate Begeman59b5da62009-01-18 03:20:47 +0000144 OS << ", " << getVectorElt(i);
Nate Begeman3d309f92009-01-18 01:01:34 +0000145 return;
Chris Lattner64c34f12008-11-16 07:46:48 +0000146 case ComplexInt:
147 OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag();
148 return;
149 case ComplexFloat:
150 OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal())
151 << ", " << GetApproxValue(getComplexFloatImag());
152 case LValue:
153 OS << "LValue: <todo>";
154 return;
155 }
156}
157
Chris Lattner5f9e2722011-07-23 10:55:15 +0000158static void WriteShortAPValueToStream(raw_ostream& Out,
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000159 const APValue& V) {
160 switch (V.getKind()) {
David Blaikieb219cfc2011-09-23 05:06:16 +0000161 default: llvm_unreachable("Unknown APValue kind!");
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000162 case APValue::Uninitialized:
163 Out << "Uninitialized";
164 break;
165 case APValue::Int:
166 Out << V.getInt();
167 break;
168 case APValue::Float:
169 Out << GetApproxValue(V.getFloat());
170 break;
171 case APValue::Vector:
172 Out << '[';
173 WriteShortAPValueToStream(Out, V.getVectorElt(0));
174 for (unsigned i = 1; i != V.getVectorLength(); ++i) {
175 Out << ", ";
176 WriteShortAPValueToStream(Out, V.getVectorElt(i));
177 }
178 Out << ']';
179 break;
180 case APValue::ComplexInt:
181 Out << V.getComplexIntReal() << "+" << V.getComplexIntImag() << "i";
182 break;
183 case APValue::ComplexFloat:
184 Out << GetApproxValue(V.getComplexFloatReal()) << "+"
185 << GetApproxValue(V.getComplexFloatImag()) << "i";
186 break;
187 case APValue::LValue:
188 Out << "LValue: <todo>";
189 break;
190 }
191}
192
193const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
194 const APValue &V) {
195 llvm::SmallString<64> Buffer;
196 llvm::raw_svector_ostream Out(Buffer);
197 WriteShortAPValueToStream(Out, V);
198 return DB << Out.str();
199}
200
Peter Collingbourne8cad3042011-05-13 03:29:01 +0000201const Expr* APValue::getLValueBase() const {
Ken Dycka7305832010-01-15 12:37:54 +0000202 assert(isLValue() && "Invalid accessor");
203 return ((const LV*)(const void*)Data)->Base;
204}
205
Richard Smith47a1eed2011-10-29 20:57:55 +0000206CharUnits &APValue::getLValueOffset() {
207 assert(isLValue() && "Invalid accessor");
208 return ((LV*)(void*)Data)->Offset;
Ken Dycka7305832010-01-15 12:37:54 +0000209}
210
Richard Smith9a17a682011-11-07 05:07:52 +0000211bool APValue::hasLValuePath() const {
Ken Dycka7305832010-01-15 12:37:54 +0000212 assert(isLValue() && "Invalid accessor");
Richard Smith38dce9b2011-11-07 07:31:09 +0000213 return ((const LV*)(const char*)Data)->hasPath();
Richard Smith9a17a682011-11-07 05:07:52 +0000214}
215
216ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const {
217 assert(isLValue() && hasLValuePath() && "Invalid accessor");
Richard Smith38dce9b2011-11-07 07:31:09 +0000218 const LV &LVal = *((const LV*)(const char*)Data);
Richard Smith9a17a682011-11-07 05:07:52 +0000219 return ArrayRef<LValuePathEntry>(LVal.getPath(), LVal.PathLength);
220}
221
222void APValue::setLValue(const Expr *B, const CharUnits &O, NoLValuePath) {
223 assert(isLValue() && "Invalid accessor");
224 LV &LVal = *((LV*)(char*)Data);
225 LVal.Base = B;
226 LVal.Offset = O;
227 LVal.PathLength = (unsigned)-1;
228}
229
230void APValue::setLValue(const Expr *B, const CharUnits &O,
231 ArrayRef<LValuePathEntry> Path) {
232 assert(isLValue() && "Invalid accessor");
233 LV &LVal = *((LV*)(char*)Data);
234 LVal.Base = B;
235 LVal.Offset = O;
236 LVal.PathLength = Path.size();
Richard Smith38dce9b2011-11-07 07:31:09 +0000237 LVal.allocPath();
Richard Smith9a17a682011-11-07 05:07:52 +0000238 memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry));
Ken Dycka7305832010-01-15 12:37:54 +0000239}
240
241void APValue::MakeLValue() {
242 assert(isUninit() && "Bad state change");
Richard Smith9a17a682011-11-07 05:07:52 +0000243 assert(sizeof(LV) <= MaxSize && "LV too big");
Ken Dycka7305832010-01-15 12:37:54 +0000244 new ((void*)(char*)Data) LV();
245 Kind = LValue;
246}