blob: 27d9234d761f1aacfd300a239228f63c9fa14414 [file] [log] [blame]
Chris Lattner64c34f12008-11-16 07:46:48 +00001//===--- 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"
Ken Dycka7305832010-01-15 12:37:54 +000015#include "clang/AST/CharUnits.h"
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +000016#include "clang/Basic/Diagnostic.h"
17#include "llvm/ADT/SmallString.h"
Chris Lattner64c34f12008-11-16 07:46:48 +000018#include "llvm/Support/raw_ostream.h"
19using namespace clang;
20
Ken Dycka7305832010-01-15 12:37:54 +000021namespace {
22 struct LV {
Peter Collingbourne8cad3042011-05-13 03:29:01 +000023 const Expr* Base;
Ken Dycka7305832010-01-15 12:37:54 +000024 CharUnits Offset;
25 };
26}
27
Peter Collingbourne8cad3042011-05-13 03:29:01 +000028APValue::APValue(const Expr* B) : Kind(Uninitialized) {
Ken Dycka7305832010-01-15 12:37:54 +000029 MakeLValue(); setLValue(B, CharUnits::Zero());
30}
Chris Lattner64c34f12008-11-16 07:46:48 +000031
32const 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();
Nate Begeman3d309f92009-01-18 01:01:34 +000039 else if (RHS.isVector())
40 MakeVector();
Chris Lattner64c34f12008-11-16 07:46:48 +000041 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());
Nate Begeman3d309f92009-01-18 01:01:34 +000052 else if (isVector())
Dan Gohmancb421fa2010-04-19 16:39:44 +000053 setVector(((const Vec *)(const char *)RHS.Data)->Elts,
54 RHS.getVectorLength());
Chris Lattner64c34f12008-11-16 07:46:48 +000055 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
64void APValue::MakeUninit() {
65 if (Kind == Int)
Douglas Gregor98300462009-09-08 19:57:33 +000066 ((APSInt*)(char*)Data)->~APSInt();
Chris Lattner64c34f12008-11-16 07:46:48 +000067 else if (Kind == Float)
Douglas Gregor98300462009-09-08 19:57:33 +000068 ((APFloat*)(char*)Data)->~APFloat();
Nate Begeman3d309f92009-01-18 01:01:34 +000069 else if (Kind == Vector)
Douglas Gregor98300462009-09-08 19:57:33 +000070 ((Vec*)(char*)Data)->~Vec();
Chris Lattner64c34f12008-11-16 07:46:48 +000071 else if (Kind == ComplexInt)
Douglas Gregor98300462009-09-08 19:57:33 +000072 ((ComplexAPSInt*)(char*)Data)->~ComplexAPSInt();
Chris Lattner64c34f12008-11-16 07:46:48 +000073 else if (Kind == ComplexFloat)
Douglas Gregor98300462009-09-08 19:57:33 +000074 ((ComplexAPFloat*)(char*)Data)->~ComplexAPFloat();
Chris Lattner64c34f12008-11-16 07:46:48 +000075 else if (Kind == LValue) {
Douglas Gregor98300462009-09-08 19:57:33 +000076 ((LV*)(char*)Data)->~LV();
Chris Lattner64c34f12008-11-16 07:46:48 +000077 }
Nate Begeman3d309f92009-01-18 01:01:34 +000078 Kind = Uninitialized;
Chris Lattner64c34f12008-11-16 07:46:48 +000079}
80
81void APValue::dump() const {
82 print(llvm::errs());
83 llvm::errs() << '\n';
Chris Lattner64c34f12008-11-16 07:46:48 +000084}
85
86static 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
Chris Lattner5f9e2722011-07-23 10:55:15 +000094void APValue::print(raw_ostream &OS) const {
Chris Lattner64c34f12008-11-16 07:46:48 +000095 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;
Nate Begeman3d309f92009-01-18 01:01:34 +0000106 case Vector:
Nate Begeman59b5da62009-01-18 03:20:47 +0000107 OS << "Vector: " << getVectorElt(0);
Mike Stump1eb44332009-09-09 15:08:12 +0000108 for (unsigned i = 1; i != getVectorLength(); ++i)
Nate Begeman59b5da62009-01-18 03:20:47 +0000109 OS << ", " << getVectorElt(i);
Nate Begeman3d309f92009-01-18 01:01:34 +0000110 return;
Chris Lattner64c34f12008-11-16 07:46:48 +0000111 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
Chris Lattner5f9e2722011-07-23 10:55:15 +0000123static void WriteShortAPValueToStream(raw_ostream& Out,
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000124 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
158const 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
Peter Collingbourne8cad3042011-05-13 03:29:01 +0000166const Expr* APValue::getLValueBase() const {
Ken Dycka7305832010-01-15 12:37:54 +0000167 assert(isLValue() && "Invalid accessor");
168 return ((const LV*)(const void*)Data)->Base;
169}
170
171CharUnits APValue::getLValueOffset() const {
172 assert(isLValue() && "Invalid accessor");
173 return ((const LV*)(const void*)Data)->Offset;
174}
175
Peter Collingbourne8cad3042011-05-13 03:29:01 +0000176void APValue::setLValue(const Expr *B, const CharUnits &O) {
Ken Dycka7305832010-01-15 12:37:54 +0000177 assert(isLValue() && "Invalid accessor");
178 ((LV*)(char*)Data)->Base = B;
179 ((LV*)(char*)Data)->Offset = O;
180}
181
182void APValue::MakeLValue() {
183 assert(isUninit() && "Bad state change");
184 new ((void*)(char*)Data) LV();
185 Kind = LValue;
186}
187