]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/llvm/tools/clang/lib/AST/APValue.cpp
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / contrib / llvm / tools / clang / lib / AST / APValue.cpp
1 //===--- 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"
15 #include "clang/AST/CharUnits.h"
16 #include "clang/Basic/Diagnostic.h"
17 #include "llvm/ADT/SmallString.h"
18 #include "llvm/Support/raw_ostream.h"
19 #include "llvm/Support/ErrorHandling.h"
20 using namespace clang;
21
22 namespace {
23   struct LV {
24     const Expr* Base;
25     CharUnits Offset;
26   };
27 }
28
29 APValue::APValue(const Expr* B) : Kind(Uninitialized) {
30   MakeLValue(); setLValue(B, CharUnits::Zero());
31 }
32
33 const APValue &APValue::operator=(const APValue &RHS) {
34   if (Kind != RHS.Kind) {
35     MakeUninit();
36     if (RHS.isInt())
37       MakeInt();
38     else if (RHS.isFloat())
39       MakeFloat();
40     else if (RHS.isVector())
41       MakeVector();
42     else if (RHS.isComplexInt())
43       MakeComplexInt();
44     else if (RHS.isComplexFloat())
45       MakeComplexFloat();
46     else if (RHS.isLValue())
47       MakeLValue();
48   }
49   if (isInt())
50     setInt(RHS.getInt());
51   else if (isFloat())
52     setFloat(RHS.getFloat());
53   else if (isVector())
54     setVector(((const Vec *)(const char *)RHS.Data)->Elts,
55               RHS.getVectorLength());
56   else if (isComplexInt())
57     setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag());
58   else if (isComplexFloat())
59     setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag());
60   else if (isLValue())
61     setLValue(RHS.getLValueBase(), RHS.getLValueOffset());
62   return *this;
63 }
64
65 void APValue::MakeUninit() {
66   if (Kind == Int)
67     ((APSInt*)(char*)Data)->~APSInt();
68   else if (Kind == Float)
69     ((APFloat*)(char*)Data)->~APFloat();
70   else if (Kind == Vector)
71     ((Vec*)(char*)Data)->~Vec();
72   else if (Kind == ComplexInt)
73     ((ComplexAPSInt*)(char*)Data)->~ComplexAPSInt();
74   else if (Kind == ComplexFloat)
75     ((ComplexAPFloat*)(char*)Data)->~ComplexAPFloat();
76   else if (Kind == LValue) {
77     ((LV*)(char*)Data)->~LV();
78   }
79   Kind = Uninitialized;
80 }
81
82 void APValue::dump() const {
83   print(llvm::errs());
84   llvm::errs() << '\n';
85 }
86
87 static double GetApproxValue(const llvm::APFloat &F) {
88   llvm::APFloat V = F;
89   bool ignored;
90   V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven,
91             &ignored);
92   return V.convertToDouble();
93 }
94
95 void APValue::print(raw_ostream &OS) const {
96   switch (getKind()) {
97   default: llvm_unreachable("Unknown APValue kind!");
98   case Uninitialized:
99     OS << "Uninitialized";
100     return;
101   case Int:
102     OS << "Int: " << getInt();
103     return;
104   case Float:
105     OS << "Float: " << GetApproxValue(getFloat());
106     return;
107   case Vector:
108     OS << "Vector: " << getVectorElt(0);
109     for (unsigned i = 1; i != getVectorLength(); ++i)
110       OS << ", " << getVectorElt(i);
111     return;
112   case ComplexInt:
113     OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag();
114     return;
115   case ComplexFloat:
116     OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal())
117        << ", " << GetApproxValue(getComplexFloatImag());
118   case LValue:
119     OS << "LValue: <todo>";
120     return;
121   }
122 }
123
124 static void WriteShortAPValueToStream(raw_ostream& Out,
125                                       const APValue& V) {
126   switch (V.getKind()) {
127   default: llvm_unreachable("Unknown APValue kind!");
128   case APValue::Uninitialized:
129     Out << "Uninitialized";
130     break;
131   case APValue::Int:
132     Out << V.getInt();
133     break;
134   case APValue::Float:
135     Out << GetApproxValue(V.getFloat());
136     break;
137   case APValue::Vector:
138     Out << '[';
139     WriteShortAPValueToStream(Out, V.getVectorElt(0));
140     for (unsigned i = 1; i != V.getVectorLength(); ++i) {
141       Out << ", ";
142       WriteShortAPValueToStream(Out, V.getVectorElt(i));
143     }
144     Out << ']';
145     break;
146   case APValue::ComplexInt:
147     Out << V.getComplexIntReal() << "+" << V.getComplexIntImag() << "i";
148     break;
149   case APValue::ComplexFloat:
150     Out << GetApproxValue(V.getComplexFloatReal()) << "+"
151         << GetApproxValue(V.getComplexFloatImag()) << "i";
152     break;
153   case APValue::LValue:
154     Out << "LValue: <todo>";
155     break;
156   }
157 }
158
159 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
160                                            const APValue &V) {
161   llvm::SmallString<64> Buffer;
162   llvm::raw_svector_ostream Out(Buffer);
163   WriteShortAPValueToStream(Out, V);
164   return DB << Out.str();
165 }
166
167 const Expr* APValue::getLValueBase() const {
168   assert(isLValue() && "Invalid accessor");
169   return ((const LV*)(const void*)Data)->Base;
170 }
171
172 CharUnits APValue::getLValueOffset() const {
173     assert(isLValue() && "Invalid accessor");
174     return ((const LV*)(const void*)Data)->Offset;
175 }
176
177 void APValue::setLValue(const Expr *B, const CharUnits &O) {
178   assert(isLValue() && "Invalid accessor");
179   ((LV*)(char*)Data)->Base = B;
180   ((LV*)(char*)Data)->Offset = O;
181 }
182
183 void APValue::MakeLValue() {
184   assert(isUninit() && "Bad state change");
185   new ((void*)(char*)Data) LV();
186   Kind = LValue;
187 }
188