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