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; 45 ComplexAPSInt() : Real(1), Imag(1) {} 46 }; 47 struct ComplexAPFloat { 48 APFloat Real, Imag; 49 ComplexAPFloat() : Real(0.0), Imag(0.0) {} 50 }; 51 52 struct Vec { 53 APValue *Elts; 54 unsigned NumElts; 55 Vec() : Elts(0), NumElts(0) {} 56 ~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: 70 APValue() : Kind(Uninitialized) {} 71 explicit APValue(const APSInt &I) : Kind(Uninitialized) { 72 MakeInt(); setInt(I); 73 } 74 explicit APValue(const APFloat &F) : Kind(Uninitialized) { 75 MakeFloat(); setFloat(F); 76 } 77 explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) { 78 MakeVector(); setVector(E, N); 79 } 80 APValue(const APSInt &R, const APSInt &I) : Kind(Uninitialized) { 81 MakeComplexInt(); setComplexInt(R, I); 82 } 83 APValue(const APFloat &R, const APFloat &I) : Kind(Uninitialized) { 84 MakeComplexFloat(); setComplexFloat(R, I); 85 } 86 APValue(const APValue &RHS) : Kind(Uninitialized) { 87 *this = RHS; 88 } 89 APValue(const Expr* B, const CharUnits &O) : Kind(Uninitialized) { 90 MakeLValue(); setLValue(B, O); 91 } 92 APValue(const Expr* B); 93 94 ~APValue() { 95 MakeUninit(); 96 } 97 98 ValueKind getKind() const { return Kind; } 99 bool isUninit() const { return Kind == Uninitialized; } 100 bool isInt() const { return Kind == Int; } 101 bool isFloat() const { return Kind == Float; } 102 bool isComplexInt() const { return Kind == ComplexInt; } 103 bool isComplexFloat() const { return Kind == ComplexFloat; } 104 bool isLValue() const { return Kind == LValue; } 105 bool isVector() const { return Kind == Vector; } 106 107 void print(llvm::raw_ostream &OS) const; 108 void dump() const; 109 110 APSInt &getInt() { 111 assert(isInt() && "Invalid accessor"); 112 return *(APSInt*)(char*)Data; 113 } 114 const APSInt &getInt() const { 115 return const_cast<APValue*>(this)->getInt(); 116 } 117 118 APFloat &getFloat() { 119 assert(isFloat() && "Invalid accessor"); 120 return *(APFloat*)(char*)Data; 121 } 122 const APFloat &getFloat() const { 123 return const_cast<APValue*>(this)->getFloat(); 124 } 125 126 APValue &getVectorElt(unsigned i) { 127 assert(isVector() && "Invalid accessor"); 128 return ((Vec*)(char*)Data)->Elts[i]; 129 } 130 const APValue &getVectorElt(unsigned i) const { 131 assert(isVector() && "Invalid accessor"); 132 return ((const Vec*)(const char*)Data)->Elts[i]; 133 } 134 unsigned getVectorLength() const { 135 assert(isVector() && "Invalid accessor"); 136 return ((const Vec*)(const void *)Data)->NumElts; 137 } 138 139 APSInt &getComplexIntReal() { 140 assert(isComplexInt() && "Invalid accessor"); 141 return ((ComplexAPSInt*)(char*)Data)->Real; 142 } 143 const APSInt &getComplexIntReal() const { 144 return const_cast<APValue*>(this)->getComplexIntReal(); 145 } 146 147 APSInt &getComplexIntImag() { 148 assert(isComplexInt() && "Invalid accessor"); 149 return ((ComplexAPSInt*)(char*)Data)->Imag; 150 } 151 const APSInt &getComplexIntImag() const { 152 return const_cast<APValue*>(this)->getComplexIntImag(); 153 } 154 155 APFloat &getComplexFloatReal() { 156 assert(isComplexFloat() && "Invalid accessor"); 157 return ((ComplexAPFloat*)(char*)Data)->Real; 158 } 159 const APFloat &getComplexFloatReal() const { 160 return const_cast<APValue*>(this)->getComplexFloatReal(); 161 } 162 163 APFloat &getComplexFloatImag() { 164 assert(isComplexFloat() && "Invalid accessor"); 165 return ((ComplexAPFloat*)(char*)Data)->Imag; 166 } 167 const APFloat &getComplexFloatImag() const { 168 return const_cast<APValue*>(this)->getComplexFloatImag(); 169 } 170 171 const Expr* getLValueBase() const; 172 CharUnits getLValueOffset() const; 173 174 void setInt(const APSInt &I) { 175 assert(isInt() && "Invalid accessor"); 176 *(APSInt*)(char*)Data = I; 177 } 178 void setFloat(const APFloat &F) { 179 assert(isFloat() && "Invalid accessor"); 180 *(APFloat*)(char*)Data = F; 181 } 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 } 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 } 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(); 209 void MakeInt() { 210 assert(isUninit() && "Bad state change"); 211 new ((void*)Data) APSInt(1); 212 Kind = Int; 213 } 214 void MakeFloat() { 215 assert(isUninit() && "Bad state change"); 216 new ((void*)(char*)Data) APFloat(0.0); 217 Kind = Float; 218 } 219 void MakeVector() { 220 assert(isUninit() && "Bad state change"); 221 new ((void*)(char*)Data) Vec(); 222 Kind = Vector; 223 } 224 void MakeComplexInt() { 225 assert(isUninit() && "Bad state change"); 226 new ((void*)(char*)Data) ComplexAPSInt(); 227 Kind = ComplexInt; 228 } 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