Use stronger typing for the flags on AggValueSlot and require

creators to tell us whether something needs GC barriers.
No functionality change.

llvm-svn: 138581
This commit is contained in:
John McCall 2011-08-25 20:40:09 +00:00
parent 7aecbc7661
commit 8d6fc9583d
11 changed files with 87 additions and 60 deletions

View File

@ -398,8 +398,10 @@ static void EmitBaseInitializer(CodeGenFunction &CGF,
BaseClassDecl,
isBaseVirtual);
AggValueSlot AggSlot = AggValueSlot::forAddr(V, Qualifiers(),
/*Lifetime*/ true);
AggValueSlot AggSlot =
AggValueSlot::forAddr(V, Qualifiers(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers);
CGF.EmitAggExpr(BaseInit->getInit(), AggSlot);
@ -436,8 +438,10 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF,
CGF.EmitComplexExprIntoAddr(MemberInit->getInit(), Dest,
LHS.isVolatileQualified());
} else {
AggValueSlot Slot = AggValueSlot::forAddr(Dest, LHS.getQuals(),
/*Lifetime*/ true);
AggValueSlot Slot =
AggValueSlot::forAddr(Dest, LHS.getQuals(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers);
CGF.EmitAggExpr(MemberInit->getInit(), Slot);
}
@ -1324,7 +1328,9 @@ CodeGenFunction::EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor
llvm::Value *ThisPtr = LoadCXXThis();
AggValueSlot AggSlot =
AggValueSlot::forAddr(ThisPtr, Qualifiers(), /*Lifetime*/ true);
AggValueSlot::forAddr(ThisPtr, Qualifiers(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers);
EmitAggExpr(Ctor->init_begin()[0]->getInit(), AggSlot);

View File

@ -1044,7 +1044,9 @@ void CodeGenFunction::EmitExprAsInit(const Expr *init,
StoreComplexToAddr(complex, lvalue.getAddress(), lvalue.isVolatile());
} else {
// TODO: how can we delay here if D is captured by its initializer?
EmitAggExpr(init, AggValueSlot::forLValue(lvalue, true, false));
EmitAggExpr(init, AggValueSlot::forLValue(lvalue,
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers));
}
}

View File

@ -46,7 +46,8 @@ static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
} else if (type->isAnyComplexType()) {
CGF.EmitComplexExprIntoAddr(Init, DeclPtr, lv.isVolatile());
} else {
CGF.EmitAggExpr(Init, AggValueSlot::forLValue(lv, true));
CGF.EmitAggExpr(Init, AggValueSlot::forLValue(lv,AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers));
}
}

View File

@ -1032,8 +1032,9 @@ static void InitCatchParam(CodeGenFunction &CGF,
CGF.EHStack.pushTerminate();
// Perform the copy construction.
CGF.EmitAggExpr(copyExpr, AggValueSlot::forAddr(ParamAddr, Qualifiers(),
false));
CGF.EmitAggExpr(copyExpr, AggValueSlot::forAddr(ParamAddr, Qualifiers(),
AggValueSlot::IsNotDestructed,
AggValueSlot::DoesNotNeedGCBarriers));
// Leave the terminate scope.
CGF.EHStack.popTerminate();

View File

@ -136,7 +136,9 @@ void CodeGenFunction::EmitAnyExprToMem(const Expr *E,
if (E->getType()->isAnyComplexType())
EmitComplexExprIntoAddr(E, Location, Quals.hasVolatile());
else if (hasAggregateLLVMType(E->getType()))
EmitAggExpr(E, AggValueSlot::forAddr(Location, Quals, IsInit));
EmitAggExpr(E, AggValueSlot::forAddr(Location, Quals,
AggValueSlot::IsDestructed_t(IsInit),
AggValueSlot::DoesNotNeedGCBarriers));
else {
RValue RV = RValue::get(EmitScalarExpr(E, /*Ignore*/ false));
LValue LV = MakeAddrLValue(Location, E->getType());
@ -354,8 +356,11 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E,
!E->getType()->isAnyComplexType()) {
ReferenceTemporary = CreateReferenceTemporary(CGF, E->getType(),
InitializedDecl);
AggValueSlot::IsDestructed_t isDestructed
= AggValueSlot::IsDestructed_t(InitializedDecl != 0);
AggSlot = AggValueSlot::forAddr(ReferenceTemporary, Qualifiers(),
InitializedDecl != 0);
isDestructed,
AggValueSlot::DoesNotNeedGCBarriers);
}
if (InitializedDecl) {

View File

@ -71,6 +71,12 @@ public:
void EmitGCMove(const Expr *E, RValue Src);
AggValueSlot::NeedsGCBarriers_t needsGC(QualType T) {
if (CGF.getLangOptions().getGCMode() && TypeRequiresGCollection(T))
return AggValueSlot::NeedsGCBarriers;
return AggValueSlot::DoesNotNeedGCBarriers;
}
bool TypeRequiresGCollection(QualType T);
//===--------------------------------------------------------------------===//
@ -426,10 +432,8 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {
// as it may change the 'forwarding' field via call to Block_copy.
LValue RHS = CGF.EmitLValue(E->getRHS());
LValue LHS = CGF.EmitLValue(E->getLHS());
bool GCollection = false;
if (CGF.getContext().getLangOptions().getGCMode())
GCollection = TypeRequiresGCollection(E->getLHS()->getType());
Dest = AggValueSlot::forLValue(LHS, true, GCollection);
Dest = AggValueSlot::forLValue(LHS, AggValueSlot::IsDestructed,
needsGC(E->getLHS()->getType()));
EmitFinalDestCopy(E, RHS, true);
return;
}
@ -451,13 +455,10 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {
}
CGF.EmitStoreThroughPropertyRefLValue(Src, LHS);
} else {
bool GCollection = false;
if (CGF.getContext().getLangOptions().getGCMode())
GCollection = TypeRequiresGCollection(E->getLHS()->getType());
// Codegen the RHS so that it stores directly into the LHS.
AggValueSlot LHSSlot = AggValueSlot::forLValue(LHS, true,
GCollection);
AggValueSlot LHSSlot =
AggValueSlot::forLValue(LHS, AggValueSlot::IsDestructed,
needsGC(E->getLHS()->getType()));
CGF.EmitAggExpr(E->getRHS(), LHSSlot, false);
EmitFinalDestCopy(E, LHS, true);
}
@ -596,7 +597,9 @@ AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV) {
} else if (type->isAnyComplexType()) {
CGF.EmitComplexExprIntoAddr(E, LV.getAddress(), false);
} else if (CGF.hasAggregateLLVMType(type)) {
CGF.EmitAggExpr(E, AggValueSlot::forLValue(LV, true, false,
CGF.EmitAggExpr(E, AggValueSlot::forLValue(LV,
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
Dest.isZeroed()));
} else if (LV.isSimple()) {
CGF.EmitScalarInit(E, /*D=*/0, LV, /*Captured=*/false);
@ -1036,7 +1039,8 @@ LValue CodeGenFunction::EmitAggExprToLValue(const Expr *E) {
assert(hasAggregateLLVMType(E->getType()) && "Invalid argument!");
llvm::Value *Temp = CreateMemTemp(E->getType());
LValue LV = MakeAddrLValue(Temp, E->getType());
EmitAggExpr(E, AggValueSlot::forLValue(LV, false));
EmitAggExpr(E, AggValueSlot::forLValue(LV, AggValueSlot::IsNotDestructed,
AggValueSlot::DoesNotNeedGCBarriers));
return LV;
}

View File

@ -703,7 +703,9 @@ static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const CXXNewExpr *E,
AllocType.isVolatileQualified());
else {
AggValueSlot Slot
= AggValueSlot::forAddr(NewPtr, AllocType.getQualifiers(), true);
= AggValueSlot::forAddr(NewPtr, AllocType.getQualifiers(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers);
CGF.EmitAggExpr(Init, Slot);
}
}

View File

@ -818,7 +818,9 @@ void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP,
ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(Field);
LValue LV = EmitLValueForIvar(TypeOfSelfObject(),
LoadObjCSelf(), Ivar, 0);
EmitAggExpr(IvarInit->getInit(), AggValueSlot::forLValue(LV, true));
EmitAggExpr(IvarInit->getInit(),
AggValueSlot::forLValue(LV, AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers));
}
// constructor returns 'self'.
CodeGenTypes &Types = CGM.getTypes();

View File

@ -784,7 +784,9 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
} else if (RV->getType()->isAnyComplexType()) {
EmitComplexExprIntoAddr(RV, ReturnValue, false);
} else {
EmitAggExpr(RV, AggValueSlot::forAddr(ReturnValue, Qualifiers(), true));
EmitAggExpr(RV, AggValueSlot::forAddr(ReturnValue, Qualifiers(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers));
}
EmitBranchThroughCleanup(ReturnBlock);

View File

@ -337,62 +337,63 @@ class AggValueSlot {
// Qualifiers
Qualifiers Quals;
// Associated flags.
bool LifetimeFlag : 1;
bool RequiresGCollection : 1;
/// IsZeroed - This is set to true if the destination is known to be zero
/// ZeroedFlag - This is set to true if the destination is known to be zero
/// before the assignment into it. This means that zero fields don't need to
/// be set.
bool IsZeroed : 1;
bool ZeroedFlag : 1;
public:
enum IsZeroed_t { IsNotZeroed, IsZeroed };
enum IsDestructed_t { IsNotDestructed, IsDestructed };
enum NeedsGCBarriers_t { DoesNotNeedGCBarriers, NeedsGCBarriers };
/// ignored - Returns an aggregate value slot indicating that the
/// aggregate value is being ignored.
static AggValueSlot ignored() {
AggValueSlot AV;
AV.Addr = 0;
AV.Quals = Qualifiers();
AV.LifetimeFlag = AV.RequiresGCollection = AV.IsZeroed =0;
AV.LifetimeFlag = AV.RequiresGCollection = AV.ZeroedFlag = 0;
return AV;
}
/// forAddr - Make a slot for an aggregate value.
///
/// \param Volatile - true if the slot should be volatile-initialized
/// \param quals - The qualifiers that dictate how the slot should
/// be initialied. Only 'volatile' and the Objective-C lifetime
/// qualifiers matter.
///
/// \param Qualifiers - The qualifiers that dictate how the slot
/// should be initialied. Only 'volatile' and the Objective-C
/// lifetime qualifiers matter.
///
/// \param LifetimeExternallyManaged - true if the slot's lifetime
/// is being externally managed; false if a destructor should be
/// registered for any temporaries evaluated into the slot
/// \param RequiresGCollection - true if the slot is located
/// \param isDestructed - true if something else is responsible
/// for calling destructors on this object
/// \param needsGC - true if the slot is potentially located
/// somewhere that ObjC GC calls should be emitted for
static AggValueSlot forAddr(llvm::Value *Addr, Qualifiers Quals,
bool LifetimeExternallyManaged,
bool RequiresGCollection = false,
bool IsZeroed = false) {
static AggValueSlot forAddr(llvm::Value *addr, Qualifiers quals,
IsDestructed_t isDestructed,
NeedsGCBarriers_t needsGC,
IsZeroed_t isZeroed = IsNotZeroed) {
AggValueSlot AV;
AV.Addr = Addr;
AV.Quals = Quals;
AV.LifetimeFlag = LifetimeExternallyManaged;
AV.RequiresGCollection = RequiresGCollection;
AV.IsZeroed = IsZeroed;
AV.Addr = addr;
AV.Quals = quals;
AV.LifetimeFlag = isDestructed;
AV.RequiresGCollection = needsGC;
AV.ZeroedFlag = isZeroed;
return AV;
}
static AggValueSlot forLValue(LValue LV, bool LifetimeExternallyManaged,
bool RequiresGCollection = false,
bool IsZeroed = false) {
static AggValueSlot forLValue(LValue LV, IsDestructed_t isDestructed,
NeedsGCBarriers_t needsGC,
IsZeroed_t isZeroed = IsNotZeroed) {
return forAddr(LV.getAddress(), LV.getQuals(),
LifetimeExternallyManaged, RequiresGCollection, IsZeroed);
isDestructed, needsGC, isZeroed);
}
bool isLifetimeExternallyManaged() const {
return LifetimeFlag;
IsDestructed_t isLifetimeExternallyManaged() const {
return IsDestructed_t(LifetimeFlag);
}
void setLifetimeExternallyManaged(bool Managed = true) {
LifetimeFlag = Managed;
@ -408,8 +409,8 @@ public:
return Quals.getObjCLifetime();
}
bool requiresGCollection() const {
return RequiresGCollection;
NeedsGCBarriers_t requiresGCollection() const {
return NeedsGCBarriers_t(RequiresGCollection);
}
llvm::Value *getAddr() const {
@ -424,9 +425,9 @@ public:
return RValue::getAggregate(getAddr(), isVolatile());
}
void setZeroed(bool V = true) { IsZeroed = V; }
bool isZeroed() const {
return IsZeroed;
void setZeroed(bool V = true) { ZeroedFlag = V; }
IsZeroed_t isZeroed() const {
return IsZeroed_t(ZeroedFlag);
}
};

View File

@ -1465,7 +1465,8 @@ public:
/// aggregate type.
AggValueSlot CreateAggTemp(QualType T, const Twine &Name = "tmp") {
return AggValueSlot::forAddr(CreateMemTemp(T, Name), T.getQualifiers(),
false);
AggValueSlot::IsNotDestructed,
AggValueSlot::DoesNotNeedGCBarriers);
}
/// Emit a cast to void* in the appropriate address space.