forked from OSchip/llvm-project
Re-implemented generation of objc_memmove_collectable
API for copying GC'able aggregates (Next runtime only). llvm-svn: 80607
This commit is contained in:
parent
6733a7ec15
commit
879d726608
|
@ -37,12 +37,13 @@ class VISIBILITY_HIDDEN AggExprEmitter : public StmtVisitor<AggExprEmitter> {
|
|||
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<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 @@ 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<Expr*>(E));
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<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 @@ 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<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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue