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 28 APValue::APValue(const Expr* B) : Kind(Uninitialized) { 29 MakeLValue(); setLValue(B, CharUnits::Zero()); 30 } 31 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 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 81 void APValue::dump() const { 82 print(llvm::errs()); 83 llvm::errs() << '\n'; 84 } 85 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 94 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 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 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 166 const Expr* APValue::getLValueBase() const { 167 assert(isLValue() && "Invalid accessor"); 168 return ((const LV*)(const void*)Data)->Base; 169 } 170 171 CharUnits APValue::getLValueOffset() const { 172 assert(isLValue() && "Invalid accessor"); 173 return ((const LV*)(const void*)Data)->Offset; 174 } 175 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 182 void APValue::MakeLValue() { 183 assert(isUninit() && "Bad state change"); 184 new ((void*)(char*)Data) LV(); 185 Kind = LValue; 186 } 187 188