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