APValue.h revision 64c34f1c6f613eef02a7b488f8edadbe7a8650a8
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
20namespace clang {
21  class Expr;
22
23/// APValue - This class implements a discriminated union of [uninitialized]
24/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset].
25class APValue {
26  typedef llvm::APSInt APSInt;
27  typedef llvm::APFloat APFloat;
28public:
29  enum ValueKind {
30    Uninitialized,
31    Int,
32    Float,
33    ComplexInt,
34    ComplexFloat,
35    LValue
36  };
37private:
38  ValueKind Kind;
39
40  struct ComplexAPSInt {
41    APSInt Real, Imag;
42    ComplexAPSInt() : Real(1), Imag(1) {}
43  };
44  struct ComplexAPFloat {
45    APFloat Real, Imag;
46    ComplexAPFloat() : Real(0.0), Imag(0.0) {}
47  };
48
49  struct LV {
50    Expr* Base;
51    uint64_t Offset;
52  };
53
54  enum {
55    MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ?
56               sizeof(ComplexAPSInt) : sizeof(ComplexAPFloat))
57  };
58
59  /// Data - space for the largest member in units of void*.  This is an effort
60  /// to ensure that the APSInt/APFloat values have proper alignment.
61  void *Data[(MaxSize+sizeof(void*)-1)/sizeof(void*)];
62
63public:
64  APValue() : Kind(Uninitialized) {}
65  explicit APValue(const APSInt &I) : Kind(Uninitialized) {
66    MakeInt(); setInt(I);
67  }
68  explicit APValue(const APFloat &F) : Kind(Uninitialized) {
69    MakeFloat(); setFloat(F);
70  }
71  APValue(const APSInt &R, const APSInt &I) : Kind(Uninitialized) {
72    MakeComplexInt(); setComplexInt(R, I);
73  }
74  APValue(const APFloat &R, const APFloat &I) : Kind(Uninitialized) {
75    MakeComplexFloat(); setComplexFloat(R, I);
76  }
77  APValue(const APValue &RHS) : Kind(Uninitialized) {
78    *this = RHS;
79  }
80  APValue(Expr* B, uint64_t O) : Kind(Uninitialized) {
81    MakeLValue(); setLValue(B, O);
82  }
83  ~APValue() {
84    MakeUninit();
85  }
86
87  ValueKind getKind() const { return Kind; }
88  bool isUninit() const { return Kind == Uninitialized; }
89  bool isInt() const { return Kind == Int; }
90  bool isFloat() const { return Kind == Float; }
91  bool isComplexInt() const { return Kind == ComplexInt; }
92  bool isComplexFloat() const { return Kind == ComplexFloat; }
93  bool isLValue() const { return Kind == LValue; }
94
95  void print(llvm::raw_ostream &OS) const;
96  void dump() const;
97
98  APSInt &getInt() {
99    assert(isInt() && "Invalid accessor");
100    return *(APSInt*)(void*)Data;
101  }
102  const APSInt &getInt() const {
103    return const_cast<APValue*>(this)->getInt();
104  }
105
106  APFloat &getFloat() {
107    assert(isFloat() && "Invalid accessor");
108    return *(APFloat*)(void*)Data;
109  }
110  const APFloat &getFloat() const {
111    return const_cast<APValue*>(this)->getFloat();
112  }
113
114  APSInt &getComplexIntReal() {
115    assert(isComplexInt() && "Invalid accessor");
116    return ((ComplexAPSInt*)(void*)Data)->Real;
117  }
118  const APSInt &getComplexIntReal() const {
119    return const_cast<APValue*>(this)->getComplexIntReal();
120  }
121
122  APSInt &getComplexIntImag() {
123    assert(isComplexInt() && "Invalid accessor");
124    return ((ComplexAPSInt*)(void*)Data)->Imag;
125  }
126  const APSInt &getComplexIntImag() const {
127    return const_cast<APValue*>(this)->getComplexIntImag();
128  }
129
130  APFloat &getComplexFloatReal() {
131    assert(isComplexFloat() && "Invalid accessor");
132    return ((ComplexAPFloat*)(void*)Data)->Real;
133  }
134  const APFloat &getComplexFloatReal() const {
135    return const_cast<APValue*>(this)->getComplexFloatReal();
136  }
137
138  APFloat &getComplexFloatImag() {
139    assert(isComplexFloat() && "Invalid accessor");
140    return ((ComplexAPFloat*)(void*)Data)->Imag;
141  }
142  const APFloat &getComplexFloatImag() const {
143    return const_cast<APValue*>(this)->getComplexFloatImag();
144  }
145
146  Expr* getLValueBase() const {
147    assert(isLValue() && "Invalid accessor");
148    return ((const LV*)(const void*)Data)->Base;
149  }
150  uint64_t getLValueOffset() const {
151    assert(isLValue() && "Invalid accessor");
152    return ((const LV*)(const void*)Data)->Offset;
153  }
154
155  void setInt(const APSInt &I) {
156    assert(isInt() && "Invalid accessor");
157    *(APSInt*)(void*)Data = I;
158  }
159  void setFloat(const APFloat &F) {
160    assert(isFloat() && "Invalid accessor");
161    *(APFloat*)(void*)Data = F;
162  }
163  void setComplexInt(const APSInt &R, const APSInt &I) {
164    assert(isComplexInt() && "Invalid accessor");
165    ((ComplexAPSInt*)(void*)Data)->Real = R;
166    ((ComplexAPSInt*)(void*)Data)->Imag = I;
167  }
168  void setComplexFloat(const APFloat &R, const APFloat &I) {
169    assert(isComplexFloat() && "Invalid accessor");
170    ((ComplexAPFloat*)(void*)Data)->Real = R;
171    ((ComplexAPFloat*)(void*)Data)->Imag = I;
172  }
173  void setLValue(Expr *B, uint64_t O) {
174    assert(isLValue() && "Invalid accessor");
175    ((LV*)(void*)Data)->Base = B;
176    ((LV*)(void*)Data)->Offset = O;
177  }
178
179  const APValue &operator=(const APValue &RHS);
180
181private:
182  void MakeUninit();
183  void MakeInt() {
184    assert(isUninit() && "Bad state change");
185    new ((void*)Data) APSInt(1);
186    Kind = Int;
187  }
188  void MakeFloat() {
189    assert(isUninit() && "Bad state change");
190    new ((APFloat*)(void*)Data) APFloat(0.0);
191    Kind = Float;
192  }
193  void MakeComplexInt() {
194    assert(isUninit() && "Bad state change");
195    new ((ComplexAPSInt*)(void*)Data) ComplexAPSInt();
196    Kind = ComplexInt;
197  }
198  void MakeComplexFloat() {
199    assert(isUninit() && "Bad state change");
200    new ((ComplexAPFloat*)(void*)Data) ComplexAPFloat();
201    Kind = ComplexFloat;
202  }
203  void MakeLValue() {
204    assert(isUninit() && "Bad state change");
205    new ((LV*)(void*)Data) LV();
206    Kind = LValue;
207  }
208};
209
210inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const APValue &V) {
211  V.print(OS);
212  return OS;
213}
214
215} // end namespace clang.
216
217#endif
218