• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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