2008-11-16 15:46:48 +08:00
|
|
|
//===--- APValue.cpp - Union class for APFloat/APSInt/Complex -------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the APValue class.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "clang/AST/APValue.h"
|
2010-01-15 20:37:54 +08:00
|
|
|
#include "clang/AST/CharUnits.h"
|
2011-07-19 00:43:53 +08:00
|
|
|
#include "clang/Basic/Diagnostic.h"
|
|
|
|
#include "llvm/ADT/SmallString.h"
|
2008-11-16 15:46:48 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2011-09-23 13:35:21 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2008-11-16 15:46:48 +08:00
|
|
|
using namespace clang;
|
|
|
|
|
2010-01-15 20:37:54 +08:00
|
|
|
namespace {
|
2011-11-07 13:07:52 +08:00
|
|
|
struct LVBase {
|
|
|
|
const Expr *Base;
|
2010-01-15 20:37:54 +08:00
|
|
|
CharUnits Offset;
|
2011-11-07 13:07:52 +08:00
|
|
|
unsigned PathLength;
|
2010-01-15 20:37:54 +08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2011-11-07 13:07:52 +08:00
|
|
|
struct APValue::LV : LVBase {
|
|
|
|
static const unsigned InlinePathSpace =
|
|
|
|
(MaxSize - sizeof(LVBase)) / sizeof(LValuePathEntry);
|
|
|
|
|
|
|
|
/// Path - The sequence of base classes, fields and array indices to follow to
|
|
|
|
/// walk from Base to the subobject. When performing GCC-style folding, there
|
|
|
|
/// may not be such a path.
|
|
|
|
union {
|
|
|
|
LValuePathEntry Path[InlinePathSpace];
|
|
|
|
LValuePathEntry *PathPtr;
|
|
|
|
};
|
|
|
|
|
|
|
|
LV() { PathLength = (unsigned)-1; }
|
|
|
|
~LV() { if (hasPathPtr()) delete [] PathPtr; }
|
|
|
|
|
|
|
|
void allocPath() {
|
|
|
|
if (hasPathPtr()) PathPtr = new LValuePathEntry[PathLength];
|
|
|
|
}
|
|
|
|
|
|
|
|
bool hasPath() const { return PathLength != (unsigned)-1; }
|
|
|
|
bool hasPathPtr() const { return hasPath() && PathLength > InlinePathSpace; }
|
|
|
|
|
|
|
|
LValuePathEntry *getPath() { return hasPathPtr() ? PathPtr : Path; }
|
|
|
|
};
|
|
|
|
|
2011-05-13 11:29:01 +08:00
|
|
|
APValue::APValue(const Expr* B) : Kind(Uninitialized) {
|
2011-11-07 13:07:52 +08:00
|
|
|
MakeLValue();
|
|
|
|
setLValue(B, CharUnits::Zero(), ArrayRef<LValuePathEntry>());
|
2010-01-15 20:37:54 +08:00
|
|
|
}
|
2008-11-16 15:46:48 +08:00
|
|
|
|
|
|
|
const APValue &APValue::operator=(const APValue &RHS) {
|
|
|
|
if (Kind != RHS.Kind) {
|
|
|
|
MakeUninit();
|
|
|
|
if (RHS.isInt())
|
|
|
|
MakeInt();
|
|
|
|
else if (RHS.isFloat())
|
|
|
|
MakeFloat();
|
2009-01-18 09:01:34 +08:00
|
|
|
else if (RHS.isVector())
|
|
|
|
MakeVector();
|
2008-11-16 15:46:48 +08:00
|
|
|
else if (RHS.isComplexInt())
|
|
|
|
MakeComplexInt();
|
|
|
|
else if (RHS.isComplexFloat())
|
|
|
|
MakeComplexFloat();
|
|
|
|
else if (RHS.isLValue())
|
|
|
|
MakeLValue();
|
|
|
|
}
|
|
|
|
if (isInt())
|
|
|
|
setInt(RHS.getInt());
|
|
|
|
else if (isFloat())
|
|
|
|
setFloat(RHS.getFloat());
|
2009-01-18 09:01:34 +08:00
|
|
|
else if (isVector())
|
2010-04-20 00:39:44 +08:00
|
|
|
setVector(((const Vec *)(const char *)RHS.Data)->Elts,
|
|
|
|
RHS.getVectorLength());
|
2008-11-16 15:46:48 +08:00
|
|
|
else if (isComplexInt())
|
|
|
|
setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag());
|
|
|
|
else if (isComplexFloat())
|
|
|
|
setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag());
|
2011-11-07 13:07:52 +08:00
|
|
|
else if (isLValue()) {
|
|
|
|
if (RHS.hasLValuePath())
|
|
|
|
setLValue(RHS.getLValueBase(), RHS.getLValueOffset(),RHS.getLValuePath());
|
|
|
|
else
|
|
|
|
setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath());
|
|
|
|
}
|
2008-11-16 15:46:48 +08:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void APValue::MakeUninit() {
|
|
|
|
if (Kind == Int)
|
2009-09-09 03:57:33 +08:00
|
|
|
((APSInt*)(char*)Data)->~APSInt();
|
2008-11-16 15:46:48 +08:00
|
|
|
else if (Kind == Float)
|
2009-09-09 03:57:33 +08:00
|
|
|
((APFloat*)(char*)Data)->~APFloat();
|
2009-01-18 09:01:34 +08:00
|
|
|
else if (Kind == Vector)
|
2009-09-09 03:57:33 +08:00
|
|
|
((Vec*)(char*)Data)->~Vec();
|
2008-11-16 15:46:48 +08:00
|
|
|
else if (Kind == ComplexInt)
|
2009-09-09 03:57:33 +08:00
|
|
|
((ComplexAPSInt*)(char*)Data)->~ComplexAPSInt();
|
2008-11-16 15:46:48 +08:00
|
|
|
else if (Kind == ComplexFloat)
|
2009-09-09 03:57:33 +08:00
|
|
|
((ComplexAPFloat*)(char*)Data)->~ComplexAPFloat();
|
2008-11-16 15:46:48 +08:00
|
|
|
else if (Kind == LValue) {
|
2009-09-09 03:57:33 +08:00
|
|
|
((LV*)(char*)Data)->~LV();
|
2008-11-16 15:46:48 +08:00
|
|
|
}
|
2009-01-18 09:01:34 +08:00
|
|
|
Kind = Uninitialized;
|
2008-11-16 15:46:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void APValue::dump() const {
|
|
|
|
print(llvm::errs());
|
|
|
|
llvm::errs() << '\n';
|
|
|
|
}
|
|
|
|
|
|
|
|
static double GetApproxValue(const llvm::APFloat &F) {
|
|
|
|
llvm::APFloat V = F;
|
|
|
|
bool ignored;
|
|
|
|
V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven,
|
|
|
|
&ignored);
|
|
|
|
return V.convertToDouble();
|
|
|
|
}
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
void APValue::print(raw_ostream &OS) const {
|
2008-11-16 15:46:48 +08:00
|
|
|
switch (getKind()) {
|
2011-09-23 13:06:16 +08:00
|
|
|
default: llvm_unreachable("Unknown APValue kind!");
|
2008-11-16 15:46:48 +08:00
|
|
|
case Uninitialized:
|
|
|
|
OS << "Uninitialized";
|
|
|
|
return;
|
|
|
|
case Int:
|
|
|
|
OS << "Int: " << getInt();
|
|
|
|
return;
|
|
|
|
case Float:
|
|
|
|
OS << "Float: " << GetApproxValue(getFloat());
|
|
|
|
return;
|
2009-01-18 09:01:34 +08:00
|
|
|
case Vector:
|
2009-01-18 11:20:47 +08:00
|
|
|
OS << "Vector: " << getVectorElt(0);
|
2009-09-09 23:08:12 +08:00
|
|
|
for (unsigned i = 1; i != getVectorLength(); ++i)
|
2009-01-18 11:20:47 +08:00
|
|
|
OS << ", " << getVectorElt(i);
|
2009-01-18 09:01:34 +08:00
|
|
|
return;
|
2008-11-16 15:46:48 +08:00
|
|
|
case ComplexInt:
|
|
|
|
OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag();
|
|
|
|
return;
|
|
|
|
case ComplexFloat:
|
|
|
|
OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal())
|
|
|
|
<< ", " << GetApproxValue(getComplexFloatImag());
|
|
|
|
case LValue:
|
|
|
|
OS << "LValue: <todo>";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
static void WriteShortAPValueToStream(raw_ostream& Out,
|
2011-07-19 00:43:53 +08:00
|
|
|
const APValue& V) {
|
|
|
|
switch (V.getKind()) {
|
2011-09-23 13:06:16 +08:00
|
|
|
default: llvm_unreachable("Unknown APValue kind!");
|
2011-07-19 00:43:53 +08:00
|
|
|
case APValue::Uninitialized:
|
|
|
|
Out << "Uninitialized";
|
|
|
|
break;
|
|
|
|
case APValue::Int:
|
|
|
|
Out << V.getInt();
|
|
|
|
break;
|
|
|
|
case APValue::Float:
|
|
|
|
Out << GetApproxValue(V.getFloat());
|
|
|
|
break;
|
|
|
|
case APValue::Vector:
|
|
|
|
Out << '[';
|
|
|
|
WriteShortAPValueToStream(Out, V.getVectorElt(0));
|
|
|
|
for (unsigned i = 1; i != V.getVectorLength(); ++i) {
|
|
|
|
Out << ", ";
|
|
|
|
WriteShortAPValueToStream(Out, V.getVectorElt(i));
|
|
|
|
}
|
|
|
|
Out << ']';
|
|
|
|
break;
|
|
|
|
case APValue::ComplexInt:
|
|
|
|
Out << V.getComplexIntReal() << "+" << V.getComplexIntImag() << "i";
|
|
|
|
break;
|
|
|
|
case APValue::ComplexFloat:
|
|
|
|
Out << GetApproxValue(V.getComplexFloatReal()) << "+"
|
|
|
|
<< GetApproxValue(V.getComplexFloatImag()) << "i";
|
|
|
|
break;
|
|
|
|
case APValue::LValue:
|
|
|
|
Out << "LValue: <todo>";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
|
|
|
|
const APValue &V) {
|
|
|
|
llvm::SmallString<64> Buffer;
|
|
|
|
llvm::raw_svector_ostream Out(Buffer);
|
|
|
|
WriteShortAPValueToStream(Out, V);
|
|
|
|
return DB << Out.str();
|
|
|
|
}
|
|
|
|
|
2011-05-13 11:29:01 +08:00
|
|
|
const Expr* APValue::getLValueBase() const {
|
2010-01-15 20:37:54 +08:00
|
|
|
assert(isLValue() && "Invalid accessor");
|
|
|
|
return ((const LV*)(const void*)Data)->Base;
|
|
|
|
}
|
|
|
|
|
2011-10-30 04:57:55 +08:00
|
|
|
CharUnits &APValue::getLValueOffset() {
|
|
|
|
assert(isLValue() && "Invalid accessor");
|
|
|
|
return ((LV*)(void*)Data)->Offset;
|
2010-01-15 20:37:54 +08:00
|
|
|
}
|
|
|
|
|
2011-11-07 13:07:52 +08:00
|
|
|
bool APValue::hasLValuePath() const {
|
|
|
|
assert(isLValue() && "Invalid accessor");
|
|
|
|
return ((LV*)(char*)Data)->hasPath();
|
|
|
|
}
|
|
|
|
|
|
|
|
ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const {
|
|
|
|
assert(isLValue() && hasLValuePath() && "Invalid accessor");
|
|
|
|
LV &LVal = *((LV*)(char*)Data);
|
|
|
|
return ArrayRef<LValuePathEntry>(LVal.getPath(), LVal.PathLength);
|
|
|
|
}
|
|
|
|
|
|
|
|
void APValue::setLValue(const Expr *B, const CharUnits &O, NoLValuePath) {
|
|
|
|
assert(isLValue() && "Invalid accessor");
|
|
|
|
LV &LVal = *((LV*)(char*)Data);
|
|
|
|
LVal.Base = B;
|
|
|
|
LVal.Offset = O;
|
|
|
|
LVal.PathLength = (unsigned)-1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void APValue::setLValue(const Expr *B, const CharUnits &O,
|
|
|
|
ArrayRef<LValuePathEntry> Path) {
|
2010-01-15 20:37:54 +08:00
|
|
|
assert(isLValue() && "Invalid accessor");
|
2011-11-07 13:07:52 +08:00
|
|
|
LV &LVal = *((LV*)(char*)Data);
|
|
|
|
LVal.Base = B;
|
|
|
|
LVal.Offset = O;
|
|
|
|
LVal.PathLength = Path.size();
|
|
|
|
memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry));
|
2010-01-15 20:37:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void APValue::MakeLValue() {
|
|
|
|
assert(isUninit() && "Bad state change");
|
2011-11-07 13:07:52 +08:00
|
|
|
assert(sizeof(LV) <= MaxSize && "LV too big");
|
2010-01-15 20:37:54 +08:00
|
|
|
new ((void*)(char*)Data) LV();
|
|
|
|
Kind = LValue;
|
|
|
|
}
|