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 LVBase { 24 const Expr *Base; 25 CharUnits Offset; 26 unsigned PathLength; 27 }; 28 } 29 30 struct 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; } 53 const LValuePathEntry *getPath() const { 54 return hasPathPtr() ? PathPtr : Path; 55 } 56 }; 57 58 // FIXME: Reduce the malloc traffic here. 59 60 APValue::Arr::Arr(unsigned NumElts, unsigned Size) : 61 Elts(new APValue[NumElts + (NumElts != Size ? 1 : 0)]), 62 NumElts(NumElts), ArrSize(Size) {} 63 APValue::Arr::~Arr() { delete [] Elts; } 64 65 APValue::APValue(const Expr* B) : Kind(Uninitialized) { 66 MakeLValue(); 67 setLValue(B, CharUnits::Zero(), ArrayRef<LValuePathEntry>()); 68 } 69 70 const APValue &APValue::operator=(const APValue &RHS) { 71 if (Kind != RHS.Kind) { 72 MakeUninit(); 73 if (RHS.isInt()) 74 MakeInt(); 75 else if (RHS.isFloat()) 76 MakeFloat(); 77 else if (RHS.isVector()) 78 MakeVector(); 79 else if (RHS.isComplexInt()) 80 MakeComplexInt(); 81 else if (RHS.isComplexFloat()) 82 MakeComplexFloat(); 83 else if (RHS.isLValue()) 84 MakeLValue(); 85 else if (RHS.isArray()) 86 MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize()); 87 } 88 if (isInt()) 89 setInt(RHS.getInt()); 90 else if (isFloat()) 91 setFloat(RHS.getFloat()); 92 else if (isVector()) 93 setVector(((const Vec *)(const char *)RHS.Data)->Elts, 94 RHS.getVectorLength()); 95 else if (isComplexInt()) 96 setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag()); 97 else if (isComplexFloat()) 98 setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag()); 99 else if (isLValue()) { 100 if (RHS.hasLValuePath()) 101 setLValue(RHS.getLValueBase(), RHS.getLValueOffset(),RHS.getLValuePath()); 102 else 103 setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath()); 104 } else if (isArray()) { 105 for (unsigned I = 0, N = RHS.getArrayInitializedElts(); I != N; ++I) 106 getArrayInitializedElt(I) = RHS.getArrayInitializedElt(I); 107 if (RHS.hasArrayFiller()) 108 getArrayFiller() = RHS.getArrayFiller(); 109 } 110 return *this; 111 } 112 113 void APValue::MakeUninit() { 114 if (Kind == Int) 115 ((APSInt*)(char*)Data)->~APSInt(); 116 else if (Kind == Float) 117 ((APFloat*)(char*)Data)->~APFloat(); 118 else if (Kind == Vector) 119 ((Vec*)(char*)Data)->~Vec(); 120 else if (Kind == ComplexInt) 121 ((ComplexAPSInt*)(char*)Data)->~ComplexAPSInt(); 122 else if (Kind == ComplexFloat) 123 ((ComplexAPFloat*)(char*)Data)->~ComplexAPFloat(); 124 else if (Kind == LValue) 125 ((LV*)(char*)Data)->~LV(); 126 else if (Kind == Array) 127 ((Arr*)(char*)Data)->~Arr(); 128 Kind = Uninitialized; 129 } 130 131 void APValue::dump() const { 132 print(llvm::errs()); 133 llvm::errs() << '\n'; 134 } 135 136 static double GetApproxValue(const llvm::APFloat &F) { 137 llvm::APFloat V = F; 138 bool ignored; 139 V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven, 140 &ignored); 141 return V.convertToDouble(); 142 } 143 144 void APValue::print(raw_ostream &OS) const { 145 switch (getKind()) { 146 default: llvm_unreachable("Unknown APValue kind!"); 147 case Uninitialized: 148 OS << "Uninitialized"; 149 return; 150 case Int: 151 OS << "Int: " << getInt(); 152 return; 153 case Float: 154 OS << "Float: " << GetApproxValue(getFloat()); 155 return; 156 case Vector: 157 OS << "Vector: " << getVectorElt(0); 158 for (unsigned i = 1; i != getVectorLength(); ++i) 159 OS << ", " << getVectorElt(i); 160 return; 161 case ComplexInt: 162 OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag(); 163 return; 164 case ComplexFloat: 165 OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal()) 166 << ", " << GetApproxValue(getComplexFloatImag()); 167 return; 168 case LValue: 169 OS << "LValue: <todo>"; 170 return; 171 case Array: 172 OS << "Array: "; 173 for (unsigned I = 0, N = getArrayInitializedElts(); I != N; ++I) { 174 OS << getArrayInitializedElt(I); 175 if (I != getArraySize() - 1) OS << ", "; 176 } 177 if (hasArrayFiller()) 178 OS << getArraySize() - getArrayInitializedElts() << " x " 179 << getArrayFiller(); 180 return; 181 } 182 } 183 184 static void WriteShortAPValueToStream(raw_ostream& Out, 185 const APValue& V) { 186 switch (V.getKind()) { 187 default: llvm_unreachable("Unknown APValue kind!"); 188 case APValue::Uninitialized: 189 Out << "Uninitialized"; 190 break; 191 case APValue::Int: 192 Out << V.getInt(); 193 break; 194 case APValue::Float: 195 Out << GetApproxValue(V.getFloat()); 196 break; 197 case APValue::Vector: 198 Out << '['; 199 WriteShortAPValueToStream(Out, V.getVectorElt(0)); 200 for (unsigned i = 1; i != V.getVectorLength(); ++i) { 201 Out << ", "; 202 WriteShortAPValueToStream(Out, V.getVectorElt(i)); 203 } 204 Out << ']'; 205 break; 206 case APValue::ComplexInt: 207 Out << V.getComplexIntReal() << "+" << V.getComplexIntImag() << "i"; 208 break; 209 case APValue::ComplexFloat: 210 Out << GetApproxValue(V.getComplexFloatReal()) << "+" 211 << GetApproxValue(V.getComplexFloatImag()) << "i"; 212 break; 213 case APValue::LValue: 214 Out << "LValue: <todo>"; 215 break; 216 case APValue::Array: 217 Out << '{'; 218 if (unsigned N = V.getArrayInitializedElts()) { 219 Out << V.getArrayInitializedElt(0); 220 for (unsigned I = 1; I != N; ++I) 221 Out << ", " << V.getArrayInitializedElt(I); 222 } 223 Out << '}'; 224 break; 225 } 226 } 227 228 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, 229 const APValue &V) { 230 llvm::SmallString<64> Buffer; 231 llvm::raw_svector_ostream Out(Buffer); 232 WriteShortAPValueToStream(Out, V); 233 return DB << Out.str(); 234 } 235 236 const Expr* APValue::getLValueBase() const { 237 assert(isLValue() && "Invalid accessor"); 238 return ((const LV*)(const void*)Data)->Base; 239 } 240 241 CharUnits &APValue::getLValueOffset() { 242 assert(isLValue() && "Invalid accessor"); 243 return ((LV*)(void*)Data)->Offset; 244 } 245 246 bool APValue::hasLValuePath() const { 247 assert(isLValue() && "Invalid accessor"); 248 return ((const LV*)(const char*)Data)->hasPath(); 249 } 250 251 ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const { 252 assert(isLValue() && hasLValuePath() && "Invalid accessor"); 253 const LV &LVal = *((const LV*)(const char*)Data); 254 return ArrayRef<LValuePathEntry>(LVal.getPath(), LVal.PathLength); 255 } 256 257 void APValue::setLValue(const Expr *B, const CharUnits &O, NoLValuePath) { 258 assert(isLValue() && "Invalid accessor"); 259 LV &LVal = *((LV*)(char*)Data); 260 LVal.Base = B; 261 LVal.Offset = O; 262 LVal.PathLength = (unsigned)-1; 263 } 264 265 void APValue::setLValue(const Expr *B, const CharUnits &O, 266 ArrayRef<LValuePathEntry> Path) { 267 assert(isLValue() && "Invalid accessor"); 268 LV &LVal = *((LV*)(char*)Data); 269 LVal.Base = B; 270 LVal.Offset = O; 271 LVal.PathLength = Path.size(); 272 LVal.allocPath(); 273 memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry)); 274 } 275 276 void APValue::MakeLValue() { 277 assert(isUninit() && "Bad state change"); 278 assert(sizeof(LV) <= MaxSize && "LV too big"); 279 new ((void*)(char*)Data) LV(); 280 Kind = LValue; 281 } 282 283 void APValue::MakeArray(unsigned InitElts, unsigned Size) { 284 assert(isUninit() && "Bad state change"); 285 new ((void*)(char*)Data) Arr(InitElts, Size); 286 Kind = Array; 287 } 288