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 "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