diff options
-rw-r--r-- | lib/CodeGen/CGObjCMac.cpp | 31 | ||||
-rw-r--r-- | test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m | 59 |
2 files changed, 85 insertions, 5 deletions
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 676f22ebc5..514f550ad4 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -942,6 +942,8 @@ protected: unsigned int BytePos, bool ForStrongLayout, bool &HasUnion); + Qualifiers::ObjCLifetime GetObjCLifeTime(QualType QT); + void UpdateRunSkipBlockVars(bool IsByref, Qualifiers::ObjCLifetime LifeTime, unsigned FieldOffset, @@ -1962,6 +1964,25 @@ llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM, return C; } +Qualifiers::ObjCLifetime CGObjCCommonMac::GetObjCLifeTime(QualType FQT) { + if (CGM.getLangOpts().ObjCAutoRefCount) + return FQT.getObjCLifetime(); + + // MRR, is more ad hoc. + if (FQT.isObjCGCStrong()) + return Qualifiers::OCL_Strong; + if (FQT.isObjCGCWeak()) + return Qualifiers::OCL_Weak; + + if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType()) + return Qualifiers::OCL_Strong; + + if (const PointerType *PT = FQT->getAs<PointerType>()) + return (GetObjCLifeTime(PT->getPointeeType())); + + return Qualifiers::OCL_None; +} + void CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref, Qualifiers::ObjCLifetime LifeTime, unsigned FieldOffset, @@ -2074,7 +2095,7 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout, } } else { UpdateRunSkipBlockVars(false, - Field->getType().getObjCLifetime(), + GetObjCLifeTime(FQT), BytePos + FieldOffset, FieldSize); } @@ -2089,7 +2110,7 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout, ((BitFieldSize % ByteSizeInBits) != 0); Size += LastBitfieldOrUnnamedOffset; UpdateRunSkipBlockVars(false, - LastFieldBitfieldOrUnnamed->getType().getObjCLifetime(), + GetObjCLifeTime(LastFieldBitfieldOrUnnamed->getType()), BytePos + LastBitfieldOrUnnamedOffset, Size*ByteSizeInBits); } else { @@ -2098,7 +2119,7 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout, unsigned FieldSize = CGM.getContext().getTypeSize(LastFieldBitfieldOrUnnamed->getType()); UpdateRunSkipBlockVars(false, - LastFieldBitfieldOrUnnamed->getType().getObjCLifetime(), + GetObjCLifeTime(LastFieldBitfieldOrUnnamed->getType()), BytePos + LastBitfieldOrUnnamedOffset, FieldSize); } @@ -2106,7 +2127,7 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout, if (MaxField) UpdateRunSkipBlockVars(false, - MaxField->getType().getObjCLifetime(), + GetObjCLifeTime(MaxField->getType()), BytePos + MaxFieldOffset, MaxUnionSize); } @@ -2274,7 +2295,7 @@ llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM, } unsigned fieldSize = ci->isByRef() ? WordSizeInBits : CGM.getContext().getTypeSize(type); - UpdateRunSkipBlockVars(ci->isByRef(), type.getObjCLifetime(), + UpdateRunSkipBlockVars(ci->isByRef(), GetObjCLifeTime(type), fieldOffset, fieldSize); } diff --git a/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m b/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m new file mode 100644 index 0000000000..c715caa310 --- /dev/null +++ b/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m @@ -0,0 +1,59 @@ +// RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin -O0 -emit-llvm %s -o %t-64.s +// rdar://12184410 + +void x(id y) {} +void y(int a) {} + +extern id opaque_id(); +__weak id wid; + +void f() { + __block int byref_int = 0; + const id bar = (id) opaque_id(); + id baz = 0; + __strong id strong_void_sta; + __block id byref_bab = (id)0; + __block id bl_var1; + +// Inline instruction for block variable layout: 0x0100 +// CKECK-LP64: i8* getelementptr inbounds ([6 x i8]* @.str, i32 0, i32 0), i64 256 } + void (^b)() = ^{ + x(bar); + }; + +// Inline instruction for block variable layout: 0x0210 +// CKECK-LP64: i8* getelementptr inbounds ([6 x i8]* @.str, i32 0, i32 0), i64 528 } + void (^c)() = ^{ + x(bar); + x(baz); + byref_int = 1; + }; + +// Inline instruction for block variable layout: 0x0230 +// CKECK-LP64: i8* getelementptr inbounds ([6 x i8]* @.str, i32 0, i32 0), i64 560 } + void (^d)() = ^{ + x(bar); + x(baz); + byref_int = 1; + bl_var1 = 0; + byref_bab = 0; + }; + +// Inline instruction for block variable layout: 0x0230 +// CKECK-LP64: i8* getelementptr inbounds ([6 x i8]* @.str, i32 0, i32 0), i64 560 } + id (^e)() = ^{ + x(bar); + x(baz); + byref_int = 1; + bl_var1 = 0; + byref_bab = 0; + return wid; + }; + +// Inline instruction for block variable layout: 0x020 +// CKECK-LP64: i8* getelementptr inbounds ([6 x i8]* @.str, i32 0, i32 0), i64 32 } + void (^ii)() = ^{ + byref_int = 1; + byref_bab = 0; + }; +} |