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