Convert the type of the LValue offset variable in APValue to CharUnits, moving

the LValue-related methods of APValue out of line to avoid header file leaching.

llvm-svn: 93512
This commit is contained in:
Ken Dyck
2010-01-15 12:37:54 +00:00
parent 306f155a84
commit 02990837ad
4 changed files with 84 additions and 59 deletions

View File

@@ -18,6 +18,7 @@
#include "llvm/ADT/APFloat.h"
namespace clang {
class CharUnits;
class Expr;
/// APValue - This class implements a discriminated union of [uninitialized]
@@ -47,10 +48,6 @@ private:
ComplexAPFloat() : Real(0.0), Imag(0.0) {}
};
struct LV {
Expr* Base;
uint64_t Offset;
};
struct Vec {
APValue *Elts;
unsigned NumElts;
@@ -88,9 +85,11 @@ public:
APValue(const APValue &RHS) : Kind(Uninitialized) {
*this = RHS;
}
APValue(Expr* B, uint64_t O) : Kind(Uninitialized) {
APValue(Expr* B, const CharUnits &O) : Kind(Uninitialized) {
MakeLValue(); setLValue(B, O);
}
APValue(Expr* B);
~APValue() {
MakeUninit();
}
@@ -164,14 +163,8 @@ public:
return const_cast<APValue*>(this)->getComplexFloatImag();
}
Expr* getLValueBase() const {
assert(isLValue() && "Invalid accessor");
return ((const LV*)(const void*)Data)->Base;
}
uint64_t getLValueOffset() const {
assert(isLValue() && "Invalid accessor");
return ((const LV*)(const void*)Data)->Offset;
}
Expr* getLValueBase() const;
CharUnits getLValueOffset() const;
void setInt(const APSInt &I) {
assert(isInt() && "Invalid accessor");
@@ -202,11 +195,7 @@ public:
((ComplexAPFloat*)(char*)Data)->Real = R;
((ComplexAPFloat*)(char*)Data)->Imag = I;
}
void setLValue(Expr *B, uint64_t O) {
assert(isLValue() && "Invalid accessor");
((LV*)(char*)Data)->Base = B;
((LV*)(char*)Data)->Offset = O;
}
void setLValue(Expr *B, const CharUnits &O);
const APValue &operator=(const APValue &RHS);
@@ -237,11 +226,7 @@ private:
new ((void*)(char*)Data) ComplexAPFloat();
Kind = ComplexFloat;
}
void MakeLValue() {
assert(isUninit() && "Bad state change");
new ((void*)(char*)Data) LV();
Kind = LValue;
}
void MakeLValue();
};
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const APValue &V) {

View File

@@ -12,9 +12,20 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/APValue.h"
#include "clang/AST/CharUnits.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
namespace {
struct LV {
Expr* Base;
CharUnits Offset;
};
}
APValue::APValue(Expr* B) : Kind(Uninitialized) {
MakeLValue(); setLValue(B, CharUnits::Zero());
}
const APValue &APValue::operator=(const APValue &RHS) {
if (Kind != RHS.Kind) {
@@ -106,3 +117,25 @@ void APValue::print(llvm::raw_ostream &OS) const {
}
}
Expr* APValue::getLValueBase() const {
assert(isLValue() && "Invalid accessor");
return ((const LV*)(const void*)Data)->Base;
}
CharUnits APValue::getLValueOffset() const {
assert(isLValue() && "Invalid accessor");
return ((const LV*)(const void*)Data)->Offset;
}
void APValue::setLValue(Expr *B, const CharUnits &O) {
assert(isLValue() && "Invalid accessor");
((LV*)(char*)Data)->Base = B;
((LV*)(char*)Data)->Offset = O;
}
void APValue::MakeLValue() {
assert(isUninit() && "Bad state change");
new ((void*)(char*)Data) LV();
Kind = LValue;
}

View File

@@ -70,7 +70,7 @@ static bool EvaluateComplex(const Expr *E, APValue &Result, EvalInfo &Info);
static bool EvalPointerValueAsBool(APValue& Value, bool& Result) {
// FIXME: Is this accurate for all kinds of bases? If not, what would
// the check look like?
Result = Value.getLValueBase() || Value.getLValueOffset();
Result = Value.getLValueBase() || !Value.getLValueOffset().isZero();
return true;
}
@@ -224,11 +224,11 @@ public:
APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
APValue VisitDeclRefExpr(DeclRefExpr *E);
APValue VisitPredefinedExpr(PredefinedExpr *E) { return APValue(E, 0); }
APValue VisitPredefinedExpr(PredefinedExpr *E) { return APValue(E); }
APValue VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
APValue VisitMemberExpr(MemberExpr *E);
APValue VisitStringLiteral(StringLiteral *E) { return APValue(E, 0); }
APValue VisitObjCEncodeExpr(ObjCEncodeExpr *E) { return APValue(E, 0); }
APValue VisitStringLiteral(StringLiteral *E) { return APValue(E); }
APValue VisitObjCEncodeExpr(ObjCEncodeExpr *E) { return APValue(E); }
APValue VisitArraySubscriptExpr(ArraySubscriptExpr *E);
APValue VisitUnaryDeref(UnaryOperator *E);
APValue VisitUnaryExtension(const UnaryOperator *E)
@@ -256,12 +256,12 @@ static bool EvaluateLValue(const Expr* E, APValue& Result, EvalInfo &Info) {
APValue LValueExprEvaluator::VisitDeclRefExpr(DeclRefExpr *E) {
if (isa<FunctionDecl>(E->getDecl())) {
return APValue(E, 0);
return APValue(E);
} else if (VarDecl* VD = dyn_cast<VarDecl>(E->getDecl())) {
if (!Info.AnyLValue && !VD->hasGlobalStorage())
return APValue();
if (!VD->getType()->isReferenceType())
return APValue(E, 0);
return APValue(E);
// FIXME: Check whether VD might be overridden!
const VarDecl *Def = 0;
if (const Expr *Init = VD->getDefinition(Def))
@@ -274,7 +274,7 @@ APValue LValueExprEvaluator::VisitDeclRefExpr(DeclRefExpr *E) {
APValue LValueExprEvaluator::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
if (!Info.AnyLValue && !E->isFileScope())
return APValue();
return APValue(E, 0);
return APValue(E);
}
APValue LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) {
@@ -311,7 +311,8 @@ APValue LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) {
}
result.setLValue(result.getLValueBase(),
result.getLValueOffset() + RL.getFieldOffset(i) / 8);
result.getLValueOffset() +
CharUnits::fromQuantity(RL.getFieldOffset(i) / 8));
return result;
}
@@ -330,7 +331,7 @@ APValue LValueExprEvaluator::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
CharUnits Offset = Index.getSExtValue() * ElementSize;
Result.setLValue(Result.getLValueBase(),
Result.getLValueOffset() + Offset.getQuantity());
Result.getLValueOffset() + Offset);
return Result;
}
@@ -365,22 +366,22 @@ public:
{ return Visit(E->getSubExpr()); }
APValue VisitUnaryAddrOf(const UnaryOperator *E);
APValue VisitObjCStringLiteral(ObjCStringLiteral *E)
{ return APValue(E, 0); }
{ return APValue(E); }
APValue VisitAddrLabelExpr(AddrLabelExpr *E)
{ return APValue(E, 0); }
{ return APValue(E); }
APValue VisitCallExpr(CallExpr *E);
APValue VisitBlockExpr(BlockExpr *E) {
if (!E->hasBlockDeclRefExprs())
return APValue(E, 0);
return APValue(E);
return APValue();
}
APValue VisitImplicitValueInitExpr(ImplicitValueInitExpr *E)
{ return APValue((Expr*)0, 0); }
{ return APValue((Expr*)0); }
APValue VisitConditionalOperator(ConditionalOperator *E);
APValue VisitChooseExpr(ChooseExpr *E)
{ return Visit(E->getChosenSubExpr(Info.Ctx)); }
APValue VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E)
{ return APValue((Expr*)0, 0); }
{ return APValue((Expr*)0); }
// FIXME: Missing: @protocol, @selector
};
} // end anonymous namespace
@@ -419,14 +420,14 @@ APValue PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
else
SizeOfPointee = Info.Ctx.getTypeSizeInChars(PointeeType);
CharUnits Offset = CharUnits::fromQuantity(ResultLValue.getLValueOffset());
CharUnits Offset = ResultLValue.getLValueOffset();
if (E->getOpcode() == BinaryOperator::Add)
Offset += AdditionalOffset.getLimitedValue() * SizeOfPointee;
else
Offset -= AdditionalOffset.getLimitedValue() * SizeOfPointee;
return APValue(ResultLValue.getLValueBase(), Offset.getQuantity());
return APValue(ResultLValue.getLValueBase(), Offset);
}
APValue PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) {
@@ -461,7 +462,8 @@ APValue PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
if (Result.isInt()) {
Result.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType()));
return APValue(0, Result.getInt().getZExtValue());
return APValue(0,
CharUnits::fromQuantity(Result.getInt().getZExtValue()));
}
// Cast is of an lvalue, no need to change value.
@@ -483,7 +485,8 @@ APValue PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
if (Result.isInt()) {
Result.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType()));
return APValue(0, Result.getInt().getZExtValue());
return APValue(0,
CharUnits::fromQuantity(Result.getInt().getZExtValue()));
}
// Cast is of an lvalue, no need to change value.
@@ -504,7 +507,7 @@ APValue PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
APValue PointerExprEvaluator::VisitCallExpr(CallExpr *E) {
if (E->isBuiltinCall(Info.Ctx) ==
Builtin::BI__builtin___CFStringMakeConstantString)
return APValue(E, 0);
return APValue(E);
return APValue();
}
@@ -979,8 +982,7 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
&& !VD->getType()->isVariablyModifiedType()
&& !VD->getType()->isDependentType()) {
CharUnits Size = Info.Ctx.getTypeSizeInChars(VD->getType());
CharUnits Offset =
CharUnits::fromQuantity(Base.Val.getLValueOffset());
CharUnits Offset = Base.Val.getLValueOffset();
if (!Offset.isNegative() && Offset <= Size)
Size -= Offset;
else
@@ -1154,7 +1156,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
if (LHSValue.getLValueBase()) {
if (!E->isEqualityOp())
return false;
if (RHSValue.getLValueBase() || RHSValue.getLValueOffset())
if (RHSValue.getLValueBase() || !RHSValue.getLValueOffset().isZero())
return false;
bool bres;
if (!EvalPointerValueAsBool(LHSValue, bres))
@@ -1163,7 +1165,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
} else if (RHSValue.getLValueBase()) {
if (!E->isEqualityOp())
return false;
if (LHSValue.getLValueBase() || LHSValue.getLValueOffset())
if (LHSValue.getLValueBase() || !LHSValue.getLValueOffset().isZero())
return false;
bool bres;
if (!EvalPointerValueAsBool(RHSValue, bres))
@@ -1175,11 +1177,13 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
const QualType Type = E->getLHS()->getType();
const QualType ElementType = Type->getAs<PointerType>()->getPointeeType();
uint64_t D = LHSValue.getLValueOffset() - RHSValue.getLValueOffset();
CharUnits ElementSize = CharUnits::One();
if (!ElementType->isVoidType() && !ElementType->isFunctionType())
D /= Info.Ctx.getTypeSizeInChars(ElementType).getQuantity();
ElementSize = Info.Ctx.getTypeSizeInChars(ElementType);
return Success(D, E);
CharUnits Diff = LHSValue.getLValueOffset() -
RHSValue.getLValueOffset();
return Success(Diff / ElementSize, E);
}
bool Result;
if (E->getOpcode() == BinaryOperator::EQ) {
@@ -1207,21 +1211,23 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
// Handle cases like (unsigned long)&a + 4.
if (E->isAdditiveOp() && Result.isLValue() && RHSVal.isInt()) {
uint64_t offset = Result.getLValueOffset();
CharUnits Offset = Result.getLValueOffset();
CharUnits AdditionalOffset = CharUnits::fromQuantity(
RHSVal.getInt().getZExtValue());
if (E->getOpcode() == BinaryOperator::Add)
offset += RHSVal.getInt().getZExtValue();
Offset += AdditionalOffset;
else
offset -= RHSVal.getInt().getZExtValue();
Result = APValue(Result.getLValueBase(), offset);
Offset -= AdditionalOffset;
Result = APValue(Result.getLValueBase(), Offset);
return true;
}
// Handle cases like 4 + (unsigned long)&a
if (E->getOpcode() == BinaryOperator::Add &&
RHSVal.isLValue() && Result.isInt()) {
uint64_t offset = RHSVal.getLValueOffset();
offset += Result.getInt().getZExtValue();
Result = APValue(RHSVal.getLValueBase(), offset);
CharUnits Offset = RHSVal.getLValueOffset();
Offset += CharUnits::fromQuantity(Result.getInt().getZExtValue());
Result = APValue(RHSVal.getLValueBase(), Offset);
return true;
}
@@ -1351,7 +1357,7 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
return false;
if (LV.getLValueBase())
return false;
return Success(LV.getLValueOffset(), E);
return Success(LV.getLValueOffset().getQuantity(), E);
}
if (E->getOpcode() == UnaryOperator::LNot) {
@@ -1434,7 +1440,8 @@ bool IntExprEvaluator::VisitCastExpr(CastExpr *E) {
return true;
}
APSInt AsInt = Info.Ctx.MakeIntValue(LV.getLValueOffset(), SrcType);
APSInt AsInt = Info.Ctx.MakeIntValue(LV.getLValueOffset().getQuantity(),
SrcType);
return Success(HandleIntToIntCast(DestType, SrcType, AsInt, Info.Ctx), E);
}

View File

@@ -810,7 +810,7 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E,
const llvm::Type *DestTy = getTypes().ConvertTypeForMem(DestType);
llvm::Constant *Offset =
llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
Result.Val.getLValueOffset());
Result.Val.getLValueOffset().getQuantity());
llvm::Constant *C;
if (const Expr *LVBase = Result.Val.getLValueBase()) {