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