From 879d7266086313b128238901246a3dbb0939b08a Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Mon, 31 Aug 2009 19:33:16 +0000 Subject: [PATCH] Re-implemented generation of objc_memmove_collectable API for copying GC'able aggregates (Next runtime only). llvm-svn: 80607 --- clang/lib/CodeGen/CGExprAgg.cpp | 29 ++++++++++++-------- clang/lib/CodeGen/CGObjCGNU.cpp | 4 +-- clang/lib/CodeGen/CGObjCMac.cpp | 14 +++++++--- clang/lib/CodeGen/CGObjCRuntime.h | 2 +- clang/lib/CodeGen/CodeGenFunction.h | 5 ++-- clang/test/CodeGenObjC/objc-gc-aggr-assign.m | 6 +++- 6 files changed, 38 insertions(+), 22 deletions(-) diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 4155738a22f0..f8e9c56b1825 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -37,12 +37,13 @@ class VISIBILITY_HIDDEN AggExprEmitter : public StmtVisitor { bool VolatileDest; bool IgnoreResult; bool IsInitializer; + bool RequiresGCollection; public: AggExprEmitter(CodeGenFunction &cgf, llvm::Value *destPtr, bool v, - bool ignore, bool isinit) + bool ignore, bool isinit, bool requiresGCollection) : CGF(cgf), Builder(CGF.Builder), DestPtr(destPtr), VolatileDest(v), IgnoreResult(ignore), - IsInitializer(isinit) { + IsInitializer(isinit), RequiresGCollection(requiresGCollection) { } //===--------------------------------------------------------------------===// @@ -145,6 +146,12 @@ void AggExprEmitter::EmitFinalDestCopy(const Expr *E, RValue Src, bool Ignore) { DestPtr = CGF.CreateTempAlloca(CGF.ConvertType(E->getType()), "agg.tmp"); } + if (RequiresGCollection) { + CGF.CGM.getObjCRuntime().EmitGCMemmoveCollectable(CGF, + DestPtr, Src.getAggregateAddr(), + E->getType()); + return; + } // If the result of the assignment is used, copy the LHS there also. // FIXME: Pass VolatileDest as well. I think we also need to merge volatile // from the source as well, as we can't eliminate it if either operand @@ -262,19 +269,15 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { CGF.EmitObjCPropertySet(LHS.getKVCRefExpr(), 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()) - if (FDTTy->getDecl()->hasObjectMember()) { - LValue RHS = CGF.EmitLValue(E->getRHS()); - CGF.CGM.getObjCRuntime().EmitGCMemmoveCollectable(CGF, LHS.getAddress(), - RHS.getAddress(), - CGF.getContext().getTypeSize(LHSTy) / 8); - return; - } + RequiresGCollection = FDTTy->getDecl()->hasObjectMember(); } // Codegen the RHS so that it stores directly into the LHS. - CGF.EmitAggExpr(E->getRHS(), LHS.getAddress(), LHS.isVolatileQualified()); + CGF.EmitAggExpr(E->getRHS(), LHS.getAddress(), LHS.isVolatileQualified(), + false, false, RequiresGCollection); EmitFinalDestCopy(E, LHS, true); } } @@ -525,13 +528,15 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { /// true, DestPtr cannot be 0. void CodeGenFunction::EmitAggExpr(const Expr *E, llvm::Value *DestPtr, bool VolatileDest, bool IgnoreResult, - bool IsInitializer) { + bool IsInitializer, + bool RequiresGCollection) { assert(E && hasAggregateLLVMType(E->getType()) && "Invalid aggregate expression to emit"); assert ((DestPtr != 0 || VolatileDest == false) && "volatile aggregate can't be 0"); - AggExprEmitter(*this, DestPtr, VolatileDest, IgnoreResult, IsInitializer) + AggExprEmitter(*this, DestPtr, VolatileDest, IgnoreResult, IsInitializer, + RequiresGCollection) .Visit(const_cast(E)); } diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index 6ed13a444f86..63d45e9bd7b2 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -162,7 +162,7 @@ public: virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, llvm::Value *DestPtr, llvm::Value *SrcPtr, - unsigned long size); + QualType Ty); virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy, llvm::Value *BaseValue, @@ -1598,7 +1598,7 @@ void CGObjCGNU::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, void CGObjCGNU::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, llvm::Value *DestPtr, llvm::Value *SrcPtr, - unsigned long size) { + QualType Ty) { return; } diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index e16c3ee2582e..26bc976a86c1 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -1130,7 +1130,7 @@ public: llvm::Value *src, llvm::Value *dest); virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, llvm::Value *dest, llvm::Value *src, - unsigned long size); + QualType Ty); virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy, @@ -1359,7 +1359,7 @@ public: llvm::Value *src, llvm::Value *dest); virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, llvm::Value *dest, llvm::Value *src, - unsigned long size); + QualType Ty); virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy, llvm::Value *BaseValue, @@ -2786,7 +2786,10 @@ void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, llvm::Value *DestPtr, llvm::Value *SrcPtr, - unsigned long size) { + QualType Ty) { + // Get size info for this aggregate. + std::pair TypeInfo = CGM.getContext().getTypeInfo(Ty); + unsigned long size = TypeInfo.second/8; SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy); DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy); llvm::Value *N = llvm::ConstantInt::get(ObjCTypes.LongTy, size); @@ -5315,7 +5318,10 @@ void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable( CodeGen::CodeGenFunction &CGF, llvm::Value *DestPtr, llvm::Value *SrcPtr, - unsigned long size) { + QualType Ty) { + // Get size info for this aggregate. + std::pair TypeInfo = CGM.getContext().getTypeInfo(Ty); + unsigned long size = TypeInfo.second/8; SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy); DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy); llvm::Value *N = llvm::ConstantInt::get(ObjCTypes.LongTy, size); diff --git a/clang/lib/CodeGen/CGObjCRuntime.h b/clang/lib/CodeGen/CGObjCRuntime.h index ec72bcd59999..d82df9d881d7 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.h +++ b/clang/lib/CodeGen/CGObjCRuntime.h @@ -197,7 +197,7 @@ public: virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, llvm::Value *DestPtr, llvm::Value *SrcPtr, - unsigned long) = 0; + QualType Ty) = 0; }; /// Creates an instance of an Objective-C runtime class. diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 2815939517b8..046a619e8a7b 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -897,12 +897,13 @@ public: /// aggregate type. The result is computed into DestPtr. Note that if /// DestPtr is null, the value of the aggregate expression is not needed. void EmitAggExpr(const Expr *E, llvm::Value *DestPtr, bool VolatileDest, - bool IgnoreResult = false, bool IsInitializer = false); + bool IgnoreResult = false, bool IsInitializer = false, + bool RequiresGCollection = false); /// EmitGCMemmoveCollectable - Emit special API for structs with object /// pointers. void EmitGCMemmoveCollectable(llvm::Value *DestPtr, llvm::Value *SrcPtr, - unsigned long); + QualType Ty); /// EmitComplexExpr - Emit the computation of the specified expression of /// complex type, returning the result. diff --git a/clang/test/CodeGenObjC/objc-gc-aggr-assign.m b/clang/test/CodeGenObjC/objc-gc-aggr-assign.m index b6b08ffefdb7..96a9fdf65409 100644 --- a/clang/test/CodeGenObjC/objc-gc-aggr-assign.m +++ b/clang/test/CodeGenObjC/objc-gc-aggr-assign.m @@ -1,5 +1,5 @@ // RUN: clang-cc -fnext-runtime -fobjc-gc -emit-llvm -o %t %s && -// RUN: grep objc_memmove_collectable %t | grep call | count 2 +// RUN: grep objc_memmove_collectable %t | grep call | count 3 static int count; @@ -40,3 +40,7 @@ struct type_s get(void) return some; } +void f(const struct type_s *in, struct type_s *out) { + *out = *in; +} +