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