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