Home | History | Annotate | Download | only in AST
      1 //===--- APValue.cpp - Union class for APFloat/APSInt/Complex -------------===//
      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 implements the APValue class.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "clang/AST/APValue.h"
     15 #include "clang/AST/CharUnits.h"
     16 #include "clang/Basic/Diagnostic.h"
     17 #include "llvm/ADT/SmallString.h"
     18 #include "llvm/Support/raw_ostream.h"
     19 using namespace clang;
     20 
     21 namespace {
     22   struct LV {
     23     const Expr* Base;
     24     CharUnits Offset;
     25   };
     26 }
     27 
     28 APValue::APValue(const Expr* B) : Kind(Uninitialized) {
     29   MakeLValue(); setLValue(B, CharUnits::Zero());
     30 }
     31 
     32 const APValue &APValue::operator=(const APValue &RHS) {
     33   if (Kind != RHS.Kind) {
     34     MakeUninit();
     35     if (RHS.isInt())
     36       MakeInt();
     37     else if (RHS.isFloat())
     38       MakeFloat();
     39     else if (RHS.isVector())
     40       MakeVector();
     41     else if (RHS.isComplexInt())
     42       MakeComplexInt();
     43     else if (RHS.isComplexFloat())
     44       MakeComplexFloat();
     45     else if (RHS.isLValue())
     46       MakeLValue();
     47   }
     48   if (isInt())
     49     setInt(RHS.getInt());
     50   else if (isFloat())
     51     setFloat(RHS.getFloat());
     52   else if (isVector())
     53     setVector(((const Vec *)(const char *)RHS.Data)->Elts,
     54               RHS.getVectorLength());
     55   else if (isComplexInt())
     56     setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag());
     57   else if (isComplexFloat())
     58     setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag());
     59   else if (isLValue())
     60     setLValue(RHS.getLValueBase(), RHS.getLValueOffset());
     61   return *this;
     62 }
     63 
     64 void APValue::MakeUninit() {
     65   if (Kind == Int)
     66     ((APSInt*)(char*)Data)->~APSInt();
     67   else if (Kind == Float)
     68     ((APFloat*)(char*)Data)->~APFloat();
     69   else if (Kind == Vector)
     70     ((Vec*)(char*)Data)->~Vec();
     71   else if (Kind == ComplexInt)
     72     ((ComplexAPSInt*)(char*)Data)->~ComplexAPSInt();
     73   else if (Kind == ComplexFloat)
     74     ((ComplexAPFloat*)(char*)Data)->~ComplexAPFloat();
     75   else if (Kind == LValue) {
     76     ((LV*)(char*)Data)->~LV();
     77   }
     78   Kind = Uninitialized;
     79 }
     80 
     81 void APValue::dump() const {
     82   print(llvm::errs());
     83   llvm::errs() << '\n';
     84 }
     85 
     86 static double GetApproxValue(const llvm::APFloat &F) {
     87   llvm::APFloat V = F;
     88   bool ignored;
     89   V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven,
     90             &ignored);
     91   return V.convertToDouble();
     92 }
     93 
     94 void APValue::print(llvm::raw_ostream &OS) const {
     95   switch (getKind()) {
     96   default: assert(0 && "Unknown APValue kind!");
     97   case Uninitialized:
     98     OS << "Uninitialized";
     99     return;
    100   case Int:
    101     OS << "Int: " << getInt();
    102     return;
    103   case Float:
    104     OS << "Float: " << GetApproxValue(getFloat());
    105     return;
    106   case Vector:
    107     OS << "Vector: " << getVectorElt(0);
    108     for (unsigned i = 1; i != getVectorLength(); ++i)
    109       OS << ", " << getVectorElt(i);
    110     return;
    111   case ComplexInt:
    112     OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag();
    113     return;
    114   case ComplexFloat:
    115     OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal())
    116        << ", " << GetApproxValue(getComplexFloatImag());
    117   case LValue:
    118     OS << "LValue: <todo>";
    119     return;
    120   }
    121 }
    122 
    123 static void WriteShortAPValueToStream(llvm::raw_ostream& Out,
    124                                       const APValue& V) {
    125   switch (V.getKind()) {
    126   default: assert(0 && "Unknown APValue kind!");
    127   case APValue::Uninitialized:
    128     Out << "Uninitialized";
    129     break;
    130   case APValue::Int:
    131     Out << V.getInt();
    132     break;
    133   case APValue::Float:
    134     Out << GetApproxValue(V.getFloat());
    135     break;
    136   case APValue::Vector:
    137     Out << '[';
    138     WriteShortAPValueToStream(Out, V.getVectorElt(0));
    139     for (unsigned i = 1; i != V.getVectorLength(); ++i) {
    140       Out << ", ";
    141       WriteShortAPValueToStream(Out, V.getVectorElt(i));
    142     }
    143     Out << ']';
    144     break;
    145   case APValue::ComplexInt:
    146     Out << V.getComplexIntReal() << "+" << V.getComplexIntImag() << "i";
    147     break;
    148   case APValue::ComplexFloat:
    149     Out << GetApproxValue(V.getComplexFloatReal()) << "+"
    150         << GetApproxValue(V.getComplexFloatImag()) << "i";
    151     break;
    152   case APValue::LValue:
    153     Out << "LValue: <todo>";
    154     break;
    155   }
    156 }
    157 
    158 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
    159                                            const APValue &V) {
    160   llvm::SmallString<64> Buffer;
    161   llvm::raw_svector_ostream Out(Buffer);
    162   WriteShortAPValueToStream(Out, V);
    163   return DB << Out.str();
    164 }
    165 
    166 const Expr* APValue::getLValueBase() const {
    167   assert(isLValue() && "Invalid accessor");
    168   return ((const LV*)(const void*)Data)->Base;
    169 }
    170 
    171 CharUnits APValue::getLValueOffset() const {
    172     assert(isLValue() && "Invalid accessor");
    173     return ((const LV*)(const void*)Data)->Offset;
    174 }
    175 
    176 void APValue::setLValue(const Expr *B, const CharUnits &O) {
    177   assert(isLValue() && "Invalid accessor");
    178   ((LV*)(char*)Data)->Base = B;
    179   ((LV*)(char*)Data)->Offset = O;
    180 }
    181 
    182 void APValue::MakeLValue() {
    183   assert(isUninit() && "Bad state change");
    184   new ((void*)(char*)Data) LV();
    185   Kind = LValue;
    186 }
    187 
    188