1 //===--- APValue.cpp - Union class for APFloat/APSInt/Complex -------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the APValue class.
12 //===----------------------------------------------------------------------===//
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;
29 APValue::APValue(const Expr* B) : Kind(Uninitialized) {
30 MakeLValue(); setLValue(B, CharUnits::Zero());
33 const APValue &APValue::operator=(const APValue &RHS) {
34 if (Kind != RHS.Kind) {
38 else if (RHS.isFloat())
40 else if (RHS.isVector())
42 else if (RHS.isComplexInt())
44 else if (RHS.isComplexFloat())
46 else if (RHS.isLValue())
52 setFloat(RHS.getFloat());
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());
61 setLValue(RHS.getLValueBase(), RHS.getLValueOffset());
65 void APValue::MakeUninit() {
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();
82 void APValue::dump() const {
87 static double GetApproxValue(const llvm::APFloat &F) {
90 V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven,
92 return V.convertToDouble();
95 void APValue::print(raw_ostream &OS) const {
97 default: llvm_unreachable("Unknown APValue kind!");
99 OS << "Uninitialized";
102 OS << "Int: " << getInt();
105 OS << "Float: " << GetApproxValue(getFloat());
108 OS << "Vector: " << getVectorElt(0);
109 for (unsigned i = 1; i != getVectorLength(); ++i)
110 OS << ", " << getVectorElt(i);
113 OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag();
116 OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal())
117 << ", " << GetApproxValue(getComplexFloatImag());
119 OS << "LValue: <todo>";
124 static void WriteShortAPValueToStream(raw_ostream& Out,
126 switch (V.getKind()) {
127 default: llvm_unreachable("Unknown APValue kind!");
128 case APValue::Uninitialized:
129 Out << "Uninitialized";
135 Out << GetApproxValue(V.getFloat());
137 case APValue::Vector:
139 WriteShortAPValueToStream(Out, V.getVectorElt(0));
140 for (unsigned i = 1; i != V.getVectorLength(); ++i) {
142 WriteShortAPValueToStream(Out, V.getVectorElt(i));
146 case APValue::ComplexInt:
147 Out << V.getComplexIntReal() << "+" << V.getComplexIntImag() << "i";
149 case APValue::ComplexFloat:
150 Out << GetApproxValue(V.getComplexFloatReal()) << "+"
151 << GetApproxValue(V.getComplexFloatImag()) << "i";
153 case APValue::LValue:
154 Out << "LValue: <todo>";
159 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
161 llvm::SmallString<64> Buffer;
162 llvm::raw_svector_ostream Out(Buffer);
163 WriteShortAPValueToStream(Out, V);
164 return DB << Out.str();
167 const Expr* APValue::getLValueBase() const {
168 assert(isLValue() && "Invalid accessor");
169 return ((const LV*)(const void*)Data)->Base;
172 CharUnits APValue::getLValueOffset() const {
173 assert(isLValue() && "Invalid accessor");
174 return ((const LV*)(const void*)Data)->Offset;
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;
183 void APValue::MakeLValue() {
184 assert(isUninit() && "Bad state change");
185 new ((void*)(char*)Data) LV();