Re-implemented generation of objc_memmove_collectable
API for copying GC'able aggregates (Next runtime only).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80607 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index 4155738..f8e9c56 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -37,12 +37,13 @@
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 @@
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 @@
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<RecordType>())
- 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 @@
/// 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<Expr*>(E));
}
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index 6ed13a4..63d45e9 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -162,7 +162,7 @@
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::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
llvm::Value *DestPtr,
llvm::Value *SrcPtr,
- unsigned long size) {
+ QualType Ty) {
return;
}
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index e16c3ee..26bc976 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -1130,7 +1130,7 @@
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 @@
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::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
llvm::Value *DestPtr,
llvm::Value *SrcPtr,
- unsigned long size) {
+ QualType Ty) {
+ // Get size info for this aggregate.
+ std::pair<uint64_t, unsigned> 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 @@
CodeGen::CodeGenFunction &CGF,
llvm::Value *DestPtr,
llvm::Value *SrcPtr,
- unsigned long size) {
+ QualType Ty) {
+ // Get size info for this aggregate.
+ std::pair<uint64_t, unsigned> 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/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h
index ec72bcd..d82df9d 100644
--- a/lib/CodeGen/CGObjCRuntime.h
+++ b/lib/CodeGen/CGObjCRuntime.h
@@ -197,7 +197,7 @@
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/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 2815939..046a619 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -897,12 +897,13 @@
/// 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/test/CodeGenObjC/objc-gc-aggr-assign.m b/test/CodeGenObjC/objc-gc-aggr-assign.m
index b6b08ff..96a9fdf 100644
--- a/test/CodeGenObjC/objc-gc-aggr-assign.m
+++ b/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 @@
return some;
}
+void f(const struct type_s *in, struct type_s *out) {
+ *out = *in;
+}
+