blob: 0f315bbccda20fd908090788df3cf5266b58648a [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"
David Blaikie9fe8c742011-09-23 05:35:21 +000019#include "llvm/Support/ErrorHandling.h"
Chris Lattner64c34f12008-11-16 07:46:48 +000020using namespace clang;
21
Ken Dycka7305832010-01-15 12:37:54 +000022namespace {
23 struct LV {
Peter Collingbourne8cad3042011-05-13 03:29:01 +000024 const Expr* Base;
Ken Dycka7305832010-01-15 12:37:54 +000025 CharUnits Offset;
26 };
27}
28
Peter Collingbourne8cad3042011-05-13 03:29:01 +000029APValue::APValue(const Expr* B) : Kind(Uninitialized) {
Ken Dycka7305832010-01-15 12:37:54 +000030 MakeLValue(); setLValue(B, CharUnits::Zero());
31}
Chris Lattner64c34f12008-11-16 07:46:48 +000032
33const 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();
Nate Begeman3d309f92009-01-18 01:01:34 +000040 else if (RHS.isVector())
41 MakeVector();
Chris Lattner64c34f12008-11-16 07:46:48 +000042 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());
Nate Begeman3d309f92009-01-18 01:01:34 +000053 else if (isVector())
Dan Gohmancb421fa2010-04-19 16:39:44 +000054 setVector(((const Vec *)(const char *)RHS.Data)->Elts,
55 RHS.getVectorLength());
Chris Lattner64c34f12008-11-16 07:46:48 +000056 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
65void APValue::MakeUninit() {
66 if (Kind == Int)
Douglas Gregor98300462009-09-08 19:57:33 +000067 ((APSInt*)(char*)Data)->~APSInt();
Chris Lattner64c34f12008-11-16 07:46:48 +000068 else if (Kind == Float)
Douglas Gregor98300462009-09-08 19:57:33 +000069 ((APFloat*)(char*)Data)->~APFloat();
Nate Begeman3d309f92009-01-18 01:01:34 +000070 else if (Kind == Vector)
Douglas Gregor98300462009-09-08 19:57:33 +000071 ((Vec*)(char*)Data)->~Vec();
Chris Lattner64c34f12008-11-16 07:46:48 +000072 else if (Kind == ComplexInt)
Douglas Gregor98300462009-09-08 19:57:33 +000073 ((ComplexAPSInt*)(char*)Data)->~ComplexAPSInt();
Chris Lattner64c34f12008-11-16 07:46:48 +000074 else if (Kind == ComplexFloat)
Douglas Gregor98300462009-09-08 19:57:33 +000075 ((ComplexAPFloat*)(char*)Data)->~ComplexAPFloat();
Chris Lattner64c34f12008-11-16 07:46:48 +000076 else if (Kind == LValue) {
Douglas Gregor98300462009-09-08 19:57:33 +000077 ((LV*)(char*)Data)->~LV();
Chris Lattner64c34f12008-11-16 07:46:48 +000078 }
Nate Begeman3d309f92009-01-18 01:01:34 +000079 Kind = Uninitialized;
Chris Lattner64c34f12008-11-16 07:46:48 +000080}
81
82void APValue::dump() const {
83 print(llvm::errs());
84 llvm::errs() << '\n';
Chris Lattner64c34f12008-11-16 07:46:48 +000085}
86
87static 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
Chris Lattner5f9e2722011-07-23 10:55:15 +000095void APValue::print(raw_ostream &OS) const {
Chris Lattner64c34f12008-11-16 07:46:48 +000096 switch (getKind()) {
David Blaikieb219cfc2011-09-23 05:06:16 +000097 default: llvm_unreachable("Unknown APValue kind!");
Chris Lattner64c34f12008-11-16 07:46:48 +000098 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;
Nate Begeman3d309f92009-01-18 01:01:34 +0000107 case Vector:
Nate Begeman59b5da62009-01-18 03:20:47 +0000108 OS << "Vector: " << getVectorElt(0);
Mike Stump1eb44332009-09-09 15:08:12 +0000109 for (unsigned i = 1; i != getVectorLength(); ++i)
Nate Begeman59b5da62009-01-18 03:20:47 +0000110 OS << ", " << getVectorElt(i);
Nate Begeman3d309f92009-01-18 01:01:34 +0000111 return;
Chris Lattner64c34f12008-11-16 07:46:48 +0000112 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
Chris Lattner5f9e2722011-07-23 10:55:15 +0000124static void WriteShortAPValueToStream(raw_ostream& Out,
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000125 const APValue& V) {
126 switch (V.getKind()) {
David Blaikieb219cfc2011-09-23 05:06:16 +0000127 default: llvm_unreachable("Unknown APValue kind!");
Jeffrey Yasskin5b106a82011-07-18 16:43:53 +0000128 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
159const 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
Peter Collingbourne8cad3042011-05-13 03:29:01 +0000167const Expr* APValue::getLValueBase() const {
Ken Dycka7305832010-01-15 12:37:54 +0000168 assert(isLValue() && "Invalid accessor");
169 return ((const LV*)(const void*)Data)->Base;
170}
171
Richard Smith47a1eed2011-10-29 20:57:55 +0000172CharUnits &APValue::getLValueOffset() {
173 assert(isLValue() && "Invalid accessor");
174 return ((LV*)(void*)Data)->Offset;
Ken Dycka7305832010-01-15 12:37:54 +0000175}
176
Peter Collingbourne8cad3042011-05-13 03:29:01 +0000177void APValue::setLValue(const Expr *B, const CharUnits &O) {
Ken Dycka7305832010-01-15 12:37:54 +0000178 assert(isLValue() && "Invalid accessor");
179 ((LV*)(char*)Data)->Base = B;
180 ((LV*)(char*)Data)->Offset = O;
181}
182
183void APValue::MakeLValue() {
184 assert(isUninit() && "Bad state change");
185 new ((void*)(char*)Data) LV();
186 Kind = LValue;
187}