Home | History | Annotate | Download | only in AST
      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