From 90a2d39d3082518566d5a22409a7bbba0d42f054 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Thu, 17 Jan 2013 00:25:06 +0000 Subject: [PATCH] objC block layout: Patch reorders block layout to produce more inline layout metadata. // rdar://12752901 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172683 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBlocks.cpp | 49 +++++++++++-- .../arc-captured-32bit-block-var-layout-2.m | 32 +++------ .../arc-captured-32bit-block-var-layout.m | 59 ++++++---------- .../arc-captured-block-var-inlined-layout.m | 68 +++++++++++-------- .../arc-captured-block-var-layout.m | 66 ++++++------------ test/CodeGenObjC/block-var-layout.m | 20 +++--- .../mrr-captured-block-var-inlined-layout.m | 32 ++++----- test/CodeGenObjCXX/block-var-layout.mm | 21 +++--- 8 files changed, 169 insertions(+), 178 deletions(-) diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 84d8808bb3..b199e76325 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -182,13 +182,16 @@ namespace { struct BlockLayoutChunk { CharUnits Alignment; CharUnits Size; + Qualifiers::ObjCLifetime Lifetime; const BlockDecl::Capture *Capture; // null for 'this' llvm::Type *Type; BlockLayoutChunk(CharUnits align, CharUnits size, + Qualifiers::ObjCLifetime lifetime, const BlockDecl::Capture *capture, llvm::Type *type) - : Alignment(align), Size(size), Capture(capture), Type(type) {} + : Alignment(align), Size(size), Lifetime(lifetime), + Capture(capture), Type(type) {} /// Tell the block info that this chunk has the given field index. void setIndex(CGBlockInfo &info, unsigned index) { @@ -200,9 +203,35 @@ namespace { } }; - /// Order by descending alignment. + /// Order by 1) all __strong together 2) next, all byfref together 3) next, + /// all __weak together. Preserve descending alignment in all situations. bool operator<(const BlockLayoutChunk &left, const BlockLayoutChunk &right) { - return left.Alignment > right.Alignment; + CharUnits LeftValue, RightValue; + bool LeftByref = left.Capture ? left.Capture->isByRef() : false; + bool RightByref = right.Capture ? right.Capture->isByRef() : false; + + if (left.Lifetime == Qualifiers::OCL_Strong && + left.Alignment >= right.Alignment) + LeftValue = CharUnits::fromQuantity(64); + else if (LeftByref && left.Alignment >= right.Alignment) + LeftValue = CharUnits::fromQuantity(32); + else if (left.Lifetime == Qualifiers::OCL_Weak && + left.Alignment >= right.Alignment) + LeftValue = CharUnits::fromQuantity(16); + else + LeftValue = left.Alignment; + if (right.Lifetime == Qualifiers::OCL_Strong && + right.Alignment >= left.Alignment) + RightValue = CharUnits::fromQuantity(64); + else if (RightByref && right.Alignment >= left.Alignment) + RightValue = CharUnits::fromQuantity(32); + else if (right.Lifetime == Qualifiers::OCL_Weak && + right.Alignment >= left.Alignment) + RightValue = CharUnits::fromQuantity(16); + else + RightValue = right.Alignment; + + return LeftValue > RightValue; } } @@ -337,7 +366,9 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF, = CGM.getContext().getTypeInfoInChars(thisType); maxFieldAlign = std::max(maxFieldAlign, tinfo.second); - layout.push_back(BlockLayoutChunk(tinfo.second, tinfo.first, 0, llvmType)); + layout.push_back(BlockLayoutChunk(tinfo.second, tinfo.first, + Qualifiers::OCL_None, + 0, llvmType)); } // Next, all the block captures. @@ -358,6 +389,7 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF, maxFieldAlign = std::max(maxFieldAlign, tinfo.second); layout.push_back(BlockLayoutChunk(tinfo.second, tinfo.first, + Qualifiers::OCL_None, &*ci, llvmType)); continue; } @@ -371,8 +403,9 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF, // If we have a lifetime qualifier, honor it for capture purposes. // That includes *not* copying it if it's __unsafe_unretained. - if (Qualifiers::ObjCLifetime lifetime - = variable->getType().getObjCLifetime()) { + Qualifiers::ObjCLifetime lifetime = + variable->getType().getObjCLifetime(); + if (lifetime) { switch (lifetime) { case Qualifiers::OCL_None: llvm_unreachable("impossible"); case Qualifiers::OCL_ExplicitNone: @@ -387,6 +420,8 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF, // Block pointers require copy/dispose. So do Objective-C pointers. } else if (variable->getType()->isObjCRetainableType()) { info.NeedsCopyDispose = true; + // used for mrr below. + lifetime = Qualifiers::OCL_Strong; // So do types that require non-trivial copy construction. } else if (ci->hasCopyExpr()) { @@ -413,7 +448,7 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF, llvm::Type *llvmType = CGM.getTypes().ConvertTypeForMem(VT); - layout.push_back(BlockLayoutChunk(align, size, &*ci, llvmType)); + layout.push_back(BlockLayoutChunk(align, size, lifetime, &*ci, llvmType)); } // If that was everything, we're done here. diff --git a/test/CodeGenObjC/arc-captured-32bit-block-var-layout-2.m b/test/CodeGenObjC/arc-captured-32bit-block-var-layout-2.m index 909d413138..3072316963 100644 --- a/test/CodeGenObjC/arc-captured-32bit-block-var-layout-2.m +++ b/test/CodeGenObjC/arc-captured-32bit-block-var-layout-2.m @@ -1,6 +1,7 @@ -// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple i386-apple-darwin -O0 -emit-llvm %s -o %t-64.s -// RUN: FileCheck --input-file=%t-64.s %s -// rdar://12773256 +// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple i386-apple-darwin -O0 -print-ivar-layout -emit-llvm -o /dev/null %s > %t-32.layout +// RUN: FileCheck --input-file=%t-32.layout %s +// rdar://12184410 +// rdar://12752901 @class NSString; extern void NSLog(NSString *format, ...); @@ -10,43 +11,32 @@ int main() { NSString *strong; unsigned long long eightByte = 0x8001800181818181ull; // Test1 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"\220\00" +// CHECK: block variable layout: BL_NON_OBJECT_WORD:3, BL_STRONG:1, BL_OPERATOR:0 void (^block1)() = ^{ printf("%#llx", eightByte); NSLog(@"%@", strong); }; -// %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0*, i64, %0* }>, align 8 -// block variable layout: BL_NON_OBJECT_WORD:3, BL_STRONG:1, BL_OPERATOR:0 // Test2 int i = 1; -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"#0\00" +// CHECK: block variable layout: BL_NON_OBJECT_WORD:3, BL_STRONG:1, BL_OPERATOR:0 void (^block2)() = ^{ printf("%#llx, %d", eightByte, i); NSLog(@"%@", strong); }; -// %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32, i64, i32, %0* }>, align 8 -// block variable layout: BL_NON_OBJECT_WORD:4, BL_STRONG:1, BL_OPERATOR:0 // Test3 char ch = 'a'; -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"\220\00" +// CHECK: block variable layout: BL_NON_OBJECT_WORD:3, BL_STRONG:1, BL_OPERATOR:0 void (^block3)() = ^{ printf("%c %#llx", ch, eightByte); NSLog(@"%@", strong); }; -// %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0*, i64, %0*, i8 }>, align 8 -// block variable layout: BL_NON_OBJECT_WORD:3, BL_STRONG:1, BL_OPERATOR:0 // Test4 unsigned long fourByte = 0x8001ul; -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c" 0\00" - void (^block4)() = ^{ printf("%c %#lx", ch, fourByte); NSLog(@"%@", strong); }; // block variable layout: BL_NON_OBJECT_WORD:1, BL_STRONG:1, BL_OPERATOR:0 -// %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32, %0*, i8 }>, align 4 +// CHECK: Inline instruction for block variable layout: 0x0100 + void (^block4)() = ^{ printf("%c %#lx", ch, fourByte); NSLog(@"%@", strong); }; // Test5 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"\220\00" +// CHECK: block variable layout: BL_NON_OBJECT_WORD:3, BL_STRONG:1, BL_OPERATOR:0 void (^block5)() = ^{ NSLog(@"%@", strong); printf("%c %#llx", ch, eightByte); }; -// %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0*, i64, %0*, i8 }>, align 8 -// block variable layout: BL_NON_OBJECT_WORD:3, BL_STRONG:1, BL_OPERATOR:0 // Test6 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK: block variable layout: BL_OPERATOR:0 void (^block6)() = ^{ printf("%#llx", eightByte); }; -// %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, [4 x i8], i64 }>, align 8 -// block variable layout: BL_OPERATOR:0 } /** diff --git a/test/CodeGenObjC/arc-captured-32bit-block-var-layout.m b/test/CodeGenObjC/arc-captured-32bit-block-var-layout.m index 6c72138f93..7ecdb4b1e9 100644 --- a/test/CodeGenObjC/arc-captured-32bit-block-var-layout.m +++ b/test/CodeGenObjC/arc-captured-32bit-block-var-layout.m @@ -1,6 +1,7 @@ -// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple i386-apple-darwin -O0 -emit-llvm %s -o %t-64.s -// RUN: FileCheck --input-file=%t-64.s %s +// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple i386-apple-darwin -O0 -print-ivar-layout -emit-llvm -o /dev/null %s > %t-32.layout +// RUN: FileCheck --input-file=%t-32.layout %s // rdar://12184410 +// rdar://12752901 void x(id y) {} void y(int a) {} @@ -32,8 +33,7 @@ void f() { // and a descriptor pointer). // Test 1 -// block variable layout: BL_BYREF:1, BL_STRONG:3, BL_BYREF:1, BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"@2@\00" +// CHECK: Inline instruction for block variable layout: 0x0320 void (^b)() = ^{ byref_int = sh + ch+ch1+ch2 ; x(bar); @@ -44,8 +44,7 @@ void f() { b(); // Test 2 -// block variable layout: BL_BYREF:1, BL_STRONG:3, BL_WEAK:1, BL_BYREF:2, BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"@2PA\00" +// CHECK: Inline instruction for block variable layout: 0x0331 void (^c)() = ^{ byref_int = sh + ch+ch1+ch2 ; x(bar); @@ -66,8 +65,7 @@ void g() { unsigned int i; NSString *y; NSString *z; -// block variable layout: BL_STRONG:2, BL_WEAK:1, BL_STRONG:2, BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"!1P1\00" +// CHECK: Inline instruction for block variable layout: 0x0401 void (^c)() = ^{ int j = i + bletch; x(foo); @@ -112,7 +110,7 @@ void h() { block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, BL_NON_OBJECT_WORD:3, BL_BYREF:1, BL_OPERATOR:0 */ -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [7 x i8] c" ` `\22@\00" +// CHECK: block variable layout: BL_BYREF:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_OPERATOR:0 void (^c)() = ^{ x(s2.ui.o1); x(u2.o1); @@ -127,8 +125,7 @@ void arr1() { __unsafe_unretained id unsafe_unretained_var[4]; } imported_s; -// block variable layout: BL_UNRETAINE:4, BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [2 x i8] c"c\00" +// CHECK: block variable layout: BL_UNRETAINED:4, BL_OPERATOR:0 void (^c)() = ^{ x(imported_s.unsafe_unretained_var[2]); }; @@ -143,8 +140,7 @@ void arr2() { __unsafe_unretained id unsafe_unretained_var[4]; } imported_s; -// block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINE:4, BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c" c\00" +// CHECK: block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINED:4, BL_OPERATOR:0 void (^c)() = ^{ x(imported_s.unsafe_unretained_var[2]); }; @@ -159,8 +155,7 @@ void arr3() { __unsafe_unretained id unsafe_unretained_var[0]; } imported_s; -// block variable layout: BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK: block variable layout: BL_OPERATOR:0 void (^c)() = ^{ int i = imported_s.a; }; @@ -186,15 +181,7 @@ void arr4() { } f4[2][2]; } captured_s; -/** -block variable layout: BL_UNRETAINE:3, - BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, - BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, - BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, - BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, - BL_OPERATOR:0 -*/ -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [10 x i8] +// CHECK: block variable layout: BL_UNRETAINED:3, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_OPERATOR:0 void (^c)() = ^{ id i = captured_s.f0.s_f1; }; @@ -212,8 +199,7 @@ void bf1() { int flag4: 24; } s; -// block variable layout: BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK: block variable layout: BL_OPERATOR:0 int (^c)() = ^{ return s.flag; }; @@ -226,8 +212,7 @@ void bf2() { int flag : 1; } s; -// block variable layout: BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK: block variable layout: BL_OPERATOR:0 int (^c)() = ^{ return s.flag; }; @@ -258,8 +243,7 @@ void bf3() { unsigned int _filler : 32; } _flags; -// block variable layout: BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK: block variable layout: BL_OPERATOR:0 unsigned char (^c)() = ^{ return _flags._draggedNodesAreDeletable; }; @@ -294,8 +278,7 @@ void bf4() { unsigned int _filler : 32; } _flags; -// block variable layout: BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK: block variable layout: BL_OPERATOR:0 unsigned char (^c)() = ^{ return _flags._draggedNodesAreDeletable; }; @@ -313,8 +296,7 @@ void bf5() { unsigned char flag1 : 1; } _flags; -// block variable layout: BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK: block variable layout: BL_OPERATOR:0 unsigned char (^c)() = ^{ return _flags.flag; }; @@ -331,8 +313,7 @@ void bf6() { unsigned char flag1 : 1; } _flags; -// block variable layout: BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK: block variable layout: BL_OPERATOR:0 unsigned char (^c)() = ^{ return _flags.flag; }; @@ -348,8 +329,7 @@ void Test7() { __weak id wid9, wid10, wid11, wid12; __weak id wid13, wid14, wid15, wid16; const id bar = (id) opaque_id(); -//block variable layout: BL_STRONG:1, BL_WEAK:16, BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"0_\00" +// CHECK: block variable layout: BL_STRONG:1, BL_WEAK:16, BL_OPERATOR:0 void (^b)() = ^{ x(bar); x(wid1); @@ -384,8 +364,7 @@ __weak id wid; __weak id w9, w10, w11, w12; __weak id w13, w14, w15, w16; const id bar = (id) opaque_id(); -// block variable layout: BL_STRONG:1, BL_WEAK:16, BL_WEAK:16, BL_WEAK:1, BL_OPERATOR:0 -// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] +// CHECK: block variable layout: BL_STRONG:1, BL_WEAK:16, BL_WEAK:16, BL_WEAK:1, BL_OPERATOR:0 void (^b)() = ^{ x(bar); x(wid1); diff --git a/test/CodeGenObjC/arc-captured-block-var-inlined-layout.m b/test/CodeGenObjC/arc-captured-block-var-inlined-layout.m index b93073711c..28c5bb4f5b 100644 --- a/test/CodeGenObjC/arc-captured-block-var-inlined-layout.m +++ b/test/CodeGenObjC/arc-captured-block-var-inlined-layout.m @@ -1,5 +1,7 @@ -// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple x86_64-apple-darwin -O0 -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple i386-apple-darwin -O0 -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-i386 %s +// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple x86_64-apple-darwin -O0 -print-ivar-layout -emit-llvm -o /dev/null %s > %t-64.layout +// RUN: FileCheck --input-file=%t-64.layout %s +// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple i386-apple-darwin -O0 -print-ivar-layout -emit-llvm -o /dev/null %s > %t-32.layout +// RUN: FileCheck -check-prefix=CHECK-i386 --input-file=%t-32.layout %s // rdar://12184410 void x(id y) {} @@ -15,25 +17,22 @@ void f() { __block id byref_bab = (id)0; __block id bl_var1; -// Inline instruction for block variable layout: 0x0100 -// CHECK: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i64 256 } -// CHECK-i386: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i32 256 } +// CHECK: Inline instruction for block variable layout: 0x0100 +// CHECK-i386: Inline instruction for block variable layout: 0x0100 void (^b)() = ^{ x(bar); }; -// Inline instruction for block variable layout: 0x0210 -// CHECK: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i64 528 } -// CHECK-i386: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i32 528 } +// CHECK: Inline instruction for block variable layout: 0x0210 +// CHECK-i386: Inline instruction for block variable layout: 0x0210 void (^c)() = ^{ x(bar); x(baz); byref_int = 1; }; -// Inline instruction for block variable layout: 0x0230 -// CHECK: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i64 560 } -// CHECK-i386: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i32 560 } +// CHECK: Inline instruction for block variable layout: 0x0230 +// CHECK-i386: Inline instruction for block variable layout: 0x0230 void (^d)() = ^{ x(bar); x(baz); @@ -42,9 +41,8 @@ void f() { byref_bab = 0; }; -// Inline instruction for block variable layout: 0x0231 -// CHECK: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i64 561 } -// CHECK-i386: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i32 561 } +// CHECK: Inline instruction for block variable layout: 0x0231 +// CHECK-i386: Inline instruction for block variable layout: 0x0231 __weak id wid; id (^e)() = ^{ x(bar); @@ -55,9 +53,8 @@ void f() { return wid; }; -// Inline instruction for block variable layout: 0x0235 -// CHECK: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i64 565 } -// CHECK-i386: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i32 565 } +// CHECK: Inline instruction for block variable layout: 0x0235 +// CHECK-i386: Inline instruction for block variable layout: 0x0235 __weak id wid1, wid2, wid3, wid4; id (^f)() = ^{ x(bar); @@ -72,9 +69,8 @@ void f() { return wid; }; -// Inline instruction for block variable layout: 0x035 -// CHECK: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i64 53 } -// CHECK-i386: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i32 53 } +// CHECK: Inline instruction for block variable layout: 0x035 +// CHECK-i386: Inline instruction for block variable layout: 0x035 id (^g)() = ^{ byref_int = 1; bl_var1 = 0; @@ -86,27 +82,41 @@ void f() { return wid; }; -// Inline instruction for block variable layout: 0x01 -// CHECK: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i64 1 } -// CHECK-i386: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i32 1 } +// CHECK: Inline instruction for block variable layout: 0x01 +// CHECK-i386: Inline instruction for block variable layout: 0x01 id (^h)() = ^{ return wid; }; -// Inline instruction for block variable layout: 0x020 -// CHECK: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i64 32 } -// CHECK-i386: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i32 32 } +// CHECK: Inline instruction for block variable layout: 0x020 +// CHECK-i386: Inline instruction for block variable layout: 0x020 void (^ii)() = ^{ byref_int = 1; byref_bab = 0; }; -// Inline instruction for block variable layout: 0x0102 -// CHECK: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i64 258 } -// CHECK-i386: i8* getelementptr inbounds ([6 x i8]* {{@.*}}, i32 0, i32 0), i32 258 } +// CHECK: Inline instruction for block variable layout: 0x0102 +// CHECK-i386: Inline instruction for block variable layout: 0x0102 void (^jj)() = ^{ x(bar); x(wid1); x(wid2); }; } + +// rdar://12752901 +@class NSString; +extern void NSLog(NSString *format, ...); +typedef void (^dispatch_block_t)(void); +int main() { + __strong NSString *s1 = 0; + __strong NSString *s2 = 0; + __weak NSString *w1 = 0; + + +// CHECK: Inline instruction for block variable layout: 0x0201 +// CHECK-i386: Inline instruction for block variable layout: 0x0201 + dispatch_block_t block2 = ^{ + NSLog(@"%@, %@, %@", s1, w1, s2); + }; +} diff --git a/test/CodeGenObjC/arc-captured-block-var-layout.m b/test/CodeGenObjC/arc-captured-block-var-layout.m index 77f042e7c2..bc203072e7 100644 --- a/test/CodeGenObjC/arc-captured-block-var-layout.m +++ b/test/CodeGenObjC/arc-captured-block-var-layout.m @@ -1,6 +1,7 @@ -// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple x86_64-apple-darwin -O0 -emit-llvm %s -o %t-64.s -// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s +// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple x86_64-apple-darwin -O0 -print-ivar-layout -emit-llvm -o /dev/null %s > %t-64.layout +// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.layout %s // rdar://12184410 +// rdar://12752901 void x(id y) {} void y(int a) {} @@ -32,8 +33,8 @@ void f() { // and a descriptor pointer). // Test 1 -// block variable layout: BL_BYREF:1, BL_STRONG:3, BL_BYREF:1, BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"@2@\00" +// Inline instruction for block variable layout: 0x0320 (3 strong 2 byref) +// CHECK-LP64: Inline instruction for block variable layout: 0x0320 void (^b)() = ^{ byref_int = sh + ch+ch1+ch2 ; x(bar); @@ -44,8 +45,8 @@ void f() { b(); // Test 2 -// block variable layout: BL_BYREF:1, BL_STRONG:3, BL_WEAK:1, BL_BYREF:2, BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"@2PA\00" +// Inline instruction for block variable layout: 0x0331 (3 strong 3 byref 1 weak) +// CHECK-LP64: Inline instruction for block variable layout: 0x0331 void (^c)() = ^{ byref_int = sh + ch+ch1+ch2 ; x(bar); @@ -66,8 +67,8 @@ void g() { unsigned int i; NSString *y; NSString *z; -// block variable layout: BL_STRONG:2, BL_WEAK:1, BL_STRONG:2, BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"1P1\00" +// Inline instruction for block variable layout: 0x0401 (4 strong 0 byref 1 weak) +// CHECK-LP64: Inline instruction for block variable layout: 0x0401 void (^c)() = ^{ int j = i + bletch; x(foo); @@ -108,11 +109,7 @@ void h() { union U u2; __block id block_id; -/** -block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, BL_NON_OBJECT_WORD:1, - BL_UNRETAINE:1, BL_NON_OBJECT_WORD:3, BL_BYREF:1, BL_OPERATOR:0 -*/ -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [7 x i8] c" ` `\22@\00" +// CHECK-LP64: block variable layout: BL_BYREF:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_OPERATOR:0 void (^c)() = ^{ x(s2.ui.o1); x(u2.o1); @@ -127,8 +124,7 @@ void arr1() { __unsafe_unretained id unsafe_unretained_var[4]; } imported_s; -// block variable layout: BL_UNRETAINE:4, BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [2 x i8] c"c\00" +// CHECK-LP64: block variable layout: BL_UNRETAINED:4, BL_OPERATOR:0 void (^c)() = ^{ x(imported_s.unsafe_unretained_var[2]); }; @@ -143,8 +139,7 @@ void arr2() { __unsafe_unretained id unsafe_unretained_var[4]; } imported_s; -// block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINE:4, BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c" c\00" +// CHECK-LP64: block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINED:4, BL_OPERATOR:0 void (^c)() = ^{ x(imported_s.unsafe_unretained_var[2]); }; @@ -159,8 +154,7 @@ void arr3() { __unsafe_unretained id unsafe_unretained_var[0]; } imported_s; -// block variable layout: BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK-LP64: block variable layout: BL_OPERATOR:0 void (^c)() = ^{ int i = imported_s.a; }; @@ -186,15 +180,7 @@ void arr4() { } f4[2][2]; } captured_s; -/** -block variable layout: BL_UNRETAINE:3, - BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, - BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, - BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, - BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, - BL_OPERATOR:0 -*/ -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [10 x i8] +// CHECK-LP64: block variable layout: BL_UNRETAINED:3, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_OPERATOR:0 void (^c)() = ^{ id i = captured_s.f0.s_f1; }; @@ -212,8 +198,7 @@ void bf1() { int flag4: 24; } s; -// block variable layout: BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK-LP64: block variable layout: BL_OPERATOR:0 int (^c)() = ^{ return s.flag; }; @@ -226,8 +211,7 @@ void bf2() { int flag : 1; } s; -// block variable layout: BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK-LP64: block variable layout: BL_OPERATOR:0 int (^c)() = ^{ return s.flag; }; @@ -258,8 +242,7 @@ void bf3() { unsigned int _filler : 32; } _flags; -// block variable layout: BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK-LP64: block variable layout: BL_OPERATOR:0 unsigned char (^c)() = ^{ return _flags._draggedNodesAreDeletable; }; @@ -294,8 +277,7 @@ void bf4() { unsigned int _filler : 32; } _flags; -// block variable layout: BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK-LP64: block variable layout: BL_OPERATOR:0 unsigned char (^c)() = ^{ return _flags._draggedNodesAreDeletable; }; @@ -313,8 +295,7 @@ void bf5() { unsigned char flag1 : 1; } _flags; -// block variable layout: BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK-LP64: block variable layout: BL_OPERATOR:0 unsigned char (^c)() = ^{ return _flags.flag; }; @@ -331,8 +312,7 @@ void bf6() { unsigned char flag1 : 1; } _flags; -// block variable layout: BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer +// CHECK-LP64: block variable layout: BL_OPERATOR:0 unsigned char (^c)() = ^{ return _flags.flag; }; @@ -348,8 +328,7 @@ void Test7() { __weak id wid9, wid10, wid11, wid12; __weak id wid13, wid14, wid15, wid16; const id bar = (id) opaque_id(); -//block variable layout: BL_STRONG:1, BL_WEAK:16, BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"0_\00" +// CHECK-LP64: block variable layout: BL_STRONG:1, BL_WEAK:16, BL_OPERATOR:0 void (^b)() = ^{ x(bar); x(wid1); @@ -384,8 +363,7 @@ __weak id wid; __weak id w9, w10, w11, w12; __weak id w13, w14, w15, w16; const id bar = (id) opaque_id(); -// block variable layout: BL_STRONG:1, BL_WEAK:16, BL_WEAK:16, BL_WEAK:1, BL_OPERATOR:0 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] +// CHECK-LP64: block variable layout: BL_STRONG:1, BL_WEAK:16, BL_WEAK:16, BL_WEAK:1, BL_OPERATOR:0 void (^b)() = ^{ x(bar); x(wid1); diff --git a/test/CodeGenObjC/block-var-layout.m b/test/CodeGenObjC/block-var-layout.m index 71b14dab24..ab9523126c 100644 --- a/test/CodeGenObjC/block-var-layout.m +++ b/test/CodeGenObjC/block-var-layout.m @@ -1,5 +1,6 @@ -// RUN: %clang_cc1 -fblocks -fobjc-gc -triple x86_64-apple-darwin -fobjc-runtime=macosx-fragile-10.5 -O0 -emit-llvm %s -o %t-64.s -// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s +// RUN: %clang_cc1 -fblocks -fobjc-gc -triple x86_64-apple-darwin -fobjc-runtime=macosx-fragile-10.5 -O0 -print-ivar-layout -emit-llvm -o /dev/null %s > %t-64.layout +// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.layout %s +// rdar://12752901 struct S { int i1; @@ -46,8 +47,7 @@ void f() { // Test 1 // byref int, short, char, char, char, id, id, strong void*, byref id -// 01 35 10 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"\015\10\00" +// CHECK-LP64: block variable layout for block: 0x01, 0x35, 0x10, 0x00 void (^b)() = ^{ byref_int = sh + ch+ch1+ch2 ; x(bar); @@ -60,7 +60,7 @@ void f() { // Test 2 // byref int, short, char, char, char, id, id, strong void*, byref void*, byref id // 01 36 10 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"\016\10\00" +// CHECK-LP64: block variable layout for block: 0x01, 0x36, 0x10, 0x00 void (^c)() = ^{ byref_int = sh + ch+ch1+ch2 ; x(bar); @@ -76,7 +76,7 @@ void f() { // byref int, short, char, char, char, id, id, byref void*, int, double, byref id // 01 34 11 30 00 // FIXME: we'd get a better format here if we sorted by scannability, not just alignment -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\014\11 \00" +// CHECK-LP64: block variable layout for block: 0x01, 0x35, 0x30, 0x00 void (^d)() = ^{ byref_int = sh + ch+ch1+ch2 ; x(bar); @@ -91,7 +91,7 @@ void f() { // Test 4 // struct S (int, id, int, id, int, id) // 01 41 11 11 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\01A\11\11\00" +// CHECK-LP64: block variable layout for block: 0x01, 0x41, 0x11, 0x11, 0x00 struct S s2; void (^e)() = ^{ x(s2.o1); @@ -129,7 +129,7 @@ void Test5() { // struct s2 (int, id, int, id, int, id?), union u2 (id?) // 01 41 11 12 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\01A\11\12\00" +// CHECK-LP64: block variable layout for block: 0x01, 0x41, 0x11, 0x12, 0x00 void (^c)() = ^{ x(s2.ui.o1); x(u2.o1); @@ -146,7 +146,7 @@ void notifyBlock(id dependentBlock) { // id, id, void(^)() // 01 33 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"\013\00" +// CHECK-LP64: block variable layout for block: 0x01, 0x33, 0x00 void (^wrapperBlock)() = ^() { CFRelease(singleObservationToken); CFRelease(singleObservationToken); @@ -159,7 +159,7 @@ void notifyBlock(id dependentBlock) { void test_empty_block() { // 01 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [2 x i8] c"\01\00" +// CHECK-LP64: block variable layout for block: 0x01, 0x00 void (^wrapperBlock)() = ^() { }; wrapperBlock(); diff --git a/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m b/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m index 0be4553325..bb3a20bb29 100644 --- a/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m +++ b/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m @@ -1,5 +1,8 @@ -// RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin -O0 -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -fblocks -triple i386-apple-darwin -O0 -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-i386 %s +// RUN: %clang_cc1 -fblocks -fobjc-runtime-has-weak -triple x86_64-apple-darwin -O0 -print-ivar-layout -emit-llvm -o /dev/null %s > %t-64.layout +// RUN: FileCheck --input-file=%t-64.layout %s +// RUN: %clang_cc1 -fblocks -fobjc-runtime-has-weak -triple i386-apple-darwin -O0 -print-ivar-layout -emit-llvm -o /dev/null %s > %t-32.layout +// RUN: FileCheck -check-prefix=CHECK-i386 --input-file=%t-32.layout %s +// rdar://12184410 // rdar://12184410 void x(id y) {} @@ -17,17 +20,15 @@ void f() { __block id bl_var1; // block variable layout: BL_STRONG:1, BL_OPERATOR:0 -// Inline instruction for block variable layout: 0x0100 -// CHECK: internal constant{{.*}}i64 256 -// CHECK-i386: internal constant{{.*}}i32 256 +// CHECK: Inline instruction for block variable layout: 0x0100 +// CHECK-i386: Inline instruction for block variable layout: 0x0100 void (^b)() = ^{ x(bar); }; // block variable layout: BL_STRONG:2, BL_BYREF:1, BL_OPERATOR:0 -// Inline instruction for block variable layout: 0x0210 -// CHECK: internal constant{{.*}}i64 528 -// CHECK-i386: internal constant{{.*}}i32 528 +// CHECK: Inline instruction for block variable layout: 0x0210 +// CHECK-i386: Inline instruction for block variable layout: 0x0210 void (^c)() = ^{ x(bar); x(baz); @@ -35,9 +36,8 @@ void f() { }; // block variable layout: BL_STRONG:2, BL_BYREF:3, BL_OPERATOR:0 -// Inline instruction for block variable layout: 0x0230 -// CHECK: internal constant{{.*}}i64 560 -// CHECK-i386: internal constant{{.*}}i32 560 +// CHECK: Inline instruction for block variable layout: 0x0230 +// CHECK-i386: Inline instruction for block variable layout: 0x0230 void (^d)() = ^{ x(bar); x(baz); @@ -47,9 +47,8 @@ void f() { }; // block variable layout: BL_STRONG:2, BL_BYREF:3, BL_OPERATOR:0 -// Inline instruction for block variable layout: 0x0230 -// CHECK: internal constant{{.*}}i64 560 -// CHECK-i386: internal constant{{.*}}i32 560 +// CHECK: Inline instruction for block variable layout: 0x0230 +// CHECK-i386: Inline instruction for block variable layout: 0x0230 id (^e)() = ^{ x(bar); x(baz); @@ -59,9 +58,8 @@ void f() { return wid; }; -// Inline instruction for block variable layout: 0x020 -// CHECK: internal constant{{.*}}i64 32 -// CHECK-i386: internal constant{{.*}}i32 32 +// CHECK: Inline instruction for block variable layout: 0x020 +// CHECK-i386: Inline instruction for block variable layout: 0x020 void (^ii)() = ^{ byref_int = 1; byref_bab = 0; diff --git a/test/CodeGenObjCXX/block-var-layout.mm b/test/CodeGenObjCXX/block-var-layout.mm index f8b6b9c886..08dbc02aff 100644 --- a/test/CodeGenObjCXX/block-var-layout.mm +++ b/test/CodeGenObjCXX/block-var-layout.mm @@ -1,5 +1,7 @@ -// RUN: %clang_cc1 -x objective-c++ -fblocks -fobjc-gc -triple x86_64-apple-darwin -fobjc-runtime=macosx-fragile-10.5 -emit-llvm %s -o %t-64.ll -// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.ll %s +// RUN: %clang_cc1 -x objective-c++ -fblocks -fobjc-gc -triple x86_64-apple-darwin -fobjc-runtime=macosx-fragile-10.5 -O0 -print-ivar-layout -emit-llvm -o /dev/null %s > %t-64.layout +// RUN: FileCheck --input-file=%t-64.layout %s +// rdar://12184410 +// rdar://12752901 // See commentary in test/CodeGenObjC/block-var-layout.m, from which // this is largely cloned. @@ -37,7 +39,7 @@ void f() { // Test 1 // byref int, short, char, char, char, id, id, strong void*, byref id // 01 35 10 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"\015\10\00" +// CHECK: block variable layout for block: 0x01, 0x35, 0x10, 0x00 void (^b)() = ^{ byref_int = sh + ch+ch1+ch2 ; x(bar); @@ -50,7 +52,7 @@ void f() { // Test 2 // byref int, short, char, char, char, id, id, strong void*, byref void*, byref id // 01 36 10 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"\016\10\00" +// CHECK: 0x01, 0x36, 0x10, 0x00 void (^c)() = ^{ byref_int = sh + ch+ch1+ch2 ; x(bar); @@ -65,8 +67,7 @@ void f() { // Test 3 // byref int, short, char, char, char, id, id, byref void*, int, double, byref id // 01 34 11 30 00 -// FIXME: we'd get a better format here if we sorted by scannability, not just alignment -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\014\11 \00" +// CHECK: block variable layout for block: 0x01, 0x35, 0x30, 0x00 void (^d)() = ^{ byref_int = sh + ch+ch1+ch2 ; x(bar); @@ -81,7 +82,7 @@ void (^d)() = ^{ // Test4 // struct S (int, id, int, id, int, id) // 01 41 11 11 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\01A\11\11\00" +// CHECK: block variable layout for block: 0x01, 0x41, 0x11, 0x11, 0x00 struct S s2; void (^e)() = ^{ x(s2.o1); @@ -119,7 +120,7 @@ void Test5() { // struct s2 (int, id, int, id, int, id?), union u2 (id?) // 01 41 11 12 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\01A\11\12\00" +// CHECK: block variable layout for block: 0x01, 0x41, 0x11, 0x12, 0x00 void (^c)() = ^{ x(s2.ui.o1); x(u2.o1); @@ -137,7 +138,7 @@ void notifyBlock(id dependentBlock) { // id, id, void(^)() // 01 33 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"\013\00" +// CHECK: block variable layout for block: 0x01, 0x33, 0x00 void (^wrapperBlock)() = ^() { CFRelease(singleObservationToken); CFRelease(singleObservationToken); @@ -150,7 +151,7 @@ void notifyBlock(id dependentBlock) { void test_empty_block() { // 01 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [2 x i8] c"\01\00" +// CHECK: block variable layout for block: 0x01, 0x00 void (^wrapperBlock)() = ^() { }; wrapperBlock(); -- 2.50.1