1 //===--- APValue.h - Union class for APFloat/APSInt/Complex -----*- C++ -*-===// 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 defines the APValue class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_AST_APVALUE_H 15 #define LLVM_CLANG_AST_APVALUE_H 16 17 #include "llvm/ADT/APSInt.h" 18 #include "llvm/ADT/APFloat.h" 19 20 namespace clang { 21 class CharUnits; 22 class DiagnosticBuilder; 23 class Expr; 24 25 /// APValue - This class implements a discriminated union of [uninitialized] 26 /// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset]. 27 class APValue { 28 typedef llvm::APSInt APSInt; 29 typedef llvm::APFloat APFloat; 30 public: 31 enum ValueKind { 32 Uninitialized, 33 Int, 34 Float, 35 ComplexInt, 36 ComplexFloat, 37 LValue, 38 Vector 39 }; 40 private: 41 ValueKind Kind; 42 43 struct ComplexAPSInt { 44 APSInt Real, Imag; ComplexAPSIntComplexAPSInt45 ComplexAPSInt() : Real(1), Imag(1) {} 46 }; 47 struct ComplexAPFloat { 48 APFloat Real, Imag; ComplexAPFloatComplexAPFloat49 ComplexAPFloat() : Real(0.0), Imag(0.0) {} 50 }; 51 52 struct Vec { 53 APValue *Elts; 54 unsigned NumElts; VecVec55 Vec() : Elts(0), NumElts(0) {} ~VecVec56 ~Vec() { delete[] Elts; } 57 }; 58 59 enum { 60 MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ? 61 sizeof(ComplexAPSInt) : sizeof(ComplexAPFloat)) 62 }; 63 64 union { 65 void *Aligner; 66 char Data[MaxSize]; 67 }; 68 69 public: APValue()70 APValue() : Kind(Uninitialized) {} APValue(const APSInt & I)71 explicit APValue(const APSInt &I) : Kind(Uninitialized) { 72 MakeInt(); setInt(I); 73 } APValue(const APFloat & F)74 explicit APValue(const APFloat &F) : Kind(Uninitialized) { 75 MakeFloat(); setFloat(F); 76 } APValue(const APValue * E,unsigned N)77 explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) { 78 MakeVector(); setVector(E, N); 79 } APValue(const APSInt & R,const APSInt & I)80 APValue(const APSInt &R, const APSInt &I) : Kind(Uninitialized) { 81 MakeComplexInt(); setComplexInt(R, I); 82 } APValue(const APFloat & R,const APFloat & I)83 APValue(const APFloat &R, const APFloat &I) : Kind(Uninitialized) { 84 MakeComplexFloat(); setComplexFloat(R, I); 85 } APValue(const APValue & RHS)86 APValue(const APValue &RHS) : Kind(Uninitialized) { 87 *this = RHS; 88 } APValue(const Expr * B,const CharUnits & O)89 APValue(const Expr* B, const CharUnits &O) : Kind(Uninitialized) { 90 MakeLValue(); setLValue(B, O); 91 } 92 APValue(const Expr* B); 93 ~APValue()94 ~APValue() { 95 MakeUninit(); 96 } 97 getKind()98 ValueKind getKind() const { return Kind; } isUninit()99 bool isUninit() const { return Kind == Uninitialized; } isInt()100 bool isInt() const { return Kind == Int; } isFloat()101 bool isFloat() const { return Kind == Float; } isComplexInt()102 bool isComplexInt() const { return Kind == ComplexInt; } isComplexFloat()103 bool isComplexFloat() const { return Kind == ComplexFloat; } isLValue()104 bool isLValue() const { return Kind == LValue; } isVector()105 bool isVector() const { return Kind == Vector; } 106 107 void print(llvm::raw_ostream &OS) const; 108 void dump() const; 109 getInt()110 APSInt &getInt() { 111 assert(isInt() && "Invalid accessor"); 112 return *(APSInt*)(char*)Data; 113 } getInt()114 const APSInt &getInt() const { 115 return const_cast<APValue*>(this)->getInt(); 116 } 117 getFloat()118 APFloat &getFloat() { 119 assert(isFloat() && "Invalid accessor"); 120 return *(APFloat*)(char*)Data; 121 } getFloat()122 const APFloat &getFloat() const { 123 return const_cast<APValue*>(this)->getFloat(); 124 } 125 getVectorElt(unsigned i)126 APValue &getVectorElt(unsigned i) { 127 assert(isVector() && "Invalid accessor"); 128 return ((Vec*)(char*)Data)->Elts[i]; 129 } getVectorElt(unsigned i)130 const APValue &getVectorElt(unsigned i) const { 131 assert(isVector() && "Invalid accessor"); 132 return ((const Vec*)(const char*)Data)->Elts[i]; 133 } getVectorLength()134 unsigned getVectorLength() const { 135 assert(isVector() && "Invalid accessor"); 136 return ((const Vec*)(const void *)Data)->NumElts; 137 } 138 getComplexIntReal()139 APSInt &getComplexIntReal() { 140 assert(isComplexInt() && "Invalid accessor"); 141 return ((ComplexAPSInt*)(char*)Data)->Real; 142 } getComplexIntReal()143 const APSInt &getComplexIntReal() const { 144 return const_cast<APValue*>(this)->getComplexIntReal(); 145 } 146 getComplexIntImag()147 APSInt &getComplexIntImag() { 148 assert(isComplexInt() && "Invalid accessor"); 149 return ((ComplexAPSInt*)(char*)Data)->Imag; 150 } getComplexIntImag()151 const APSInt &getComplexIntImag() const { 152 return const_cast<APValue*>(this)->getComplexIntImag(); 153 } 154 getComplexFloatReal()155 APFloat &getComplexFloatReal() { 156 assert(isComplexFloat() && "Invalid accessor"); 157 return ((ComplexAPFloat*)(char*)Data)->Real; 158 } getComplexFloatReal()159 const APFloat &getComplexFloatReal() const { 160 return const_cast<APValue*>(this)->getComplexFloatReal(); 161 } 162 getComplexFloatImag()163 APFloat &getComplexFloatImag() { 164 assert(isComplexFloat() && "Invalid accessor"); 165 return ((ComplexAPFloat*)(char*)Data)->Imag; 166 } getComplexFloatImag()167 const APFloat &getComplexFloatImag() const { 168 return const_cast<APValue*>(this)->getComplexFloatImag(); 169 } 170 171 const Expr* getLValueBase() const; 172 CharUnits getLValueOffset() const; 173 setInt(const APSInt & I)174 void setInt(const APSInt &I) { 175 assert(isInt() && "Invalid accessor"); 176 *(APSInt*)(char*)Data = I; 177 } setFloat(const APFloat & F)178 void setFloat(const APFloat &F) { 179 assert(isFloat() && "Invalid accessor"); 180 *(APFloat*)(char*)Data = F; 181 } setVector(const APValue * E,unsigned N)182 void setVector(const APValue *E, unsigned N) { 183 assert(isVector() && "Invalid accessor"); 184 ((Vec*)(char*)Data)->Elts = new APValue[N]; 185 ((Vec*)(char*)Data)->NumElts = N; 186 for (unsigned i = 0; i != N; ++i) 187 ((Vec*)(char*)Data)->Elts[i] = E[i]; 188 } setComplexInt(const APSInt & R,const APSInt & I)189 void setComplexInt(const APSInt &R, const APSInt &I) { 190 assert(R.getBitWidth() == I.getBitWidth() && 191 "Invalid complex int (type mismatch)."); 192 assert(isComplexInt() && "Invalid accessor"); 193 ((ComplexAPSInt*)(char*)Data)->Real = R; 194 ((ComplexAPSInt*)(char*)Data)->Imag = I; 195 } setComplexFloat(const APFloat & R,const APFloat & I)196 void setComplexFloat(const APFloat &R, const APFloat &I) { 197 assert(&R.getSemantics() == &I.getSemantics() && 198 "Invalid complex float (type mismatch)."); 199 assert(isComplexFloat() && "Invalid accessor"); 200 ((ComplexAPFloat*)(char*)Data)->Real = R; 201 ((ComplexAPFloat*)(char*)Data)->Imag = I; 202 } 203 void setLValue(const Expr *B, const CharUnits &O); 204 205 const APValue &operator=(const APValue &RHS); 206 207 private: 208 void MakeUninit(); MakeInt()209 void MakeInt() { 210 assert(isUninit() && "Bad state change"); 211 new ((void*)Data) APSInt(1); 212 Kind = Int; 213 } MakeFloat()214 void MakeFloat() { 215 assert(isUninit() && "Bad state change"); 216 new ((void*)(char*)Data) APFloat(0.0); 217 Kind = Float; 218 } MakeVector()219 void MakeVector() { 220 assert(isUninit() && "Bad state change"); 221 new ((void*)(char*)Data) Vec(); 222 Kind = Vector; 223 } MakeComplexInt()224 void MakeComplexInt() { 225 assert(isUninit() && "Bad state change"); 226 new ((void*)(char*)Data) ComplexAPSInt(); 227 Kind = ComplexInt; 228 } MakeComplexFloat()229 void MakeComplexFloat() { 230 assert(isUninit() && "Bad state change"); 231 new ((void*)(char*)Data) ComplexAPFloat(); 232 Kind = ComplexFloat; 233 } 234 void MakeLValue(); 235 }; 236 237 inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const APValue &V) { 238 V.print(OS); 239 return OS; 240 } 241 242 // Writes a concise representation of V to DB, in a single << operation. 243 const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 244 const APValue &V); 245 246 } // end namespace clang. 247 248 #endif 249