[cfe-commits] r104454 - /cfe/trunk/lib/CodeGen/CGExprAgg.cpp
John McCall
rjmccall at apple.com
Sat May 22 15:13:32 PDT 2010
Author: rjmccall
Date: Sat May 22 17:13:32 2010
New Revision: 104454
URL: http://llvm.org/viewvc/llvm-project?rev=104454&view=rev
Log:
Re-teach IR gen to perform GC moves on rvalues resulting from various ObjC
expressions. Essentially, GC breaks a certain form of the return-value
optimization.
Modified:
cfe/trunk/lib/CodeGen/CGExprAgg.cpp
Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=104454&r1=104453&r2=104454&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Sat May 22 17:13:32 2010
@@ -39,8 +39,14 @@
bool RequiresGCollection;
ReturnValueSlot getReturnValueSlot() const {
+ // If the destination slot requires garbage collection, we can't
+ // use the real return value slot, because we have to use the GC
+ // API.
+ if (RequiresGCollection) return ReturnValueSlot();
+
return ReturnValueSlot(DestPtr, VolatileDest);
}
+
public:
AggExprEmitter(CodeGenFunction &cgf, llvm::Value *destPtr, bool v,
bool ignore, bool isinit, bool requiresGCollection)
@@ -62,6 +68,10 @@
void EmitFinalDestCopy(const Expr *E, LValue Src, bool Ignore = false);
void EmitFinalDestCopy(const Expr *E, RValue Src, bool Ignore = false);
+ void EmitGCMove(const Expr *E, RValue Src);
+
+ bool TypeRequiresGCollection(QualType T);
+
//===--------------------------------------------------------------------===//
// Visitor Methods
//===--------------------------------------------------------------------===//
@@ -141,6 +151,39 @@
EmitFinalDestCopy(E, LV);
}
+/// \brief True if the given aggregate type requires special GC API calls.
+bool AggExprEmitter::TypeRequiresGCollection(QualType T) {
+ // Only record types have members that might require garbage collection.
+ const RecordType *RecordTy = T->getAs<RecordType>();
+ if (!RecordTy) return false;
+
+ // Don't mess with non-trivial C++ types.
+ RecordDecl *Record = RecordTy->getDecl();
+ if (isa<CXXRecordDecl>(Record) &&
+ (!cast<CXXRecordDecl>(Record)->hasTrivialCopyConstructor() ||
+ !cast<CXXRecordDecl>(Record)->hasTrivialDestructor()))
+ return false;
+
+ // Check whether the type has an object member.
+ return Record->hasObjectMember();
+}
+
+/// \brief Perform the final move to DestPtr if RequiresGCollection is set.
+///
+/// The idea is that you do something like this:
+/// RValue Result = EmitSomething(..., getReturnValueSlot());
+/// EmitGCMove(E, Result);
+/// If GC doesn't interfere, this will cause the result to be emitted
+/// directly into the return value slot. If GC does interfere, a final
+/// move will be performed.
+void AggExprEmitter::EmitGCMove(const Expr *E, RValue Src) {
+ if (!RequiresGCollection) return;
+
+ CGF.CGM.getObjCRuntime().EmitGCMemmoveCollectable(CGF, DestPtr,
+ Src.getAggregateAddr(),
+ E->getType());
+}
+
/// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired.
void AggExprEmitter::EmitFinalDestCopy(const Expr *E, RValue Src, bool Ignore) {
assert(Src.isAggregate() && "value must be aggregate value!");
@@ -308,28 +351,24 @@
return;
}
- // If the struct doesn't require GC, we can just pass the destination
- // directly to EmitCall.
- if (!RequiresGCollection) {
- CGF.EmitCallExpr(E, getReturnValueSlot());
- return;
- }
-
- RValue RV = CGF.EmitCallExpr(E);
- EmitFinalDestCopy(E, RV);
+ RValue RV = CGF.EmitCallExpr(E, getReturnValueSlot());
+ EmitGCMove(E, RV);
}
void AggExprEmitter::VisitObjCMessageExpr(ObjCMessageExpr *E) {
- CGF.EmitObjCMessageExpr(E, getReturnValueSlot());
+ RValue RV = CGF.EmitObjCMessageExpr(E, getReturnValueSlot());
+ EmitGCMove(E, RV);
}
void AggExprEmitter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
- CGF.EmitObjCPropertyGet(E, getReturnValueSlot());
+ RValue RV = CGF.EmitObjCPropertyGet(E, getReturnValueSlot());
+ EmitGCMove(E, RV);
}
void AggExprEmitter::VisitObjCImplicitSetterGetterRefExpr(
ObjCImplicitSetterGetterRefExpr *E) {
- CGF.EmitObjCPropertyGet(E, getReturnValueSlot());
+ RValue RV = CGF.EmitObjCPropertyGet(E, getReturnValueSlot());
+ EmitGCMove(E, RV);
}
void AggExprEmitter::VisitBinComma(const BinaryOperator *E) {
@@ -435,11 +474,9 @@
RValue::getAggregate(AggLoc, VolatileDest));
} else {
bool RequiresGCollection = false;
- if (CGF.getContext().getLangOptions().NeXTRuntime) {
- QualType LHSTy = E->getLHS()->getType();
- if (const RecordType *FDTTy = LHSTy.getTypePtr()->getAs<RecordType>())
- RequiresGCollection = FDTTy->getDecl()->hasObjectMember();
- }
+ if (CGF.getContext().getLangOptions().getGCMode())
+ RequiresGCollection = TypeRequiresGCollection(E->getLHS()->getType());
+
// Codegen the RHS so that it stores directly into the LHS.
CGF.EmitAggExpr(E->getRHS(), LHS.getAddress(), LHS.isVolatileQualified(),
false, false, RequiresGCollection);
More information about the cfe-commits
mailing list