From 5f04d84459d0146b8548b16ae4e807b7fda67e6f Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Mon, 5 Nov 2012 18:14:34 +0000 Subject: [PATCH] Tests for 32bit version of block ivar layout metadata. llvm-svn: 167387 --- .../arc-captured-32bit-block-var-layout.m | 425 +++++++++++++++++++++ .../arc-captured-block-var-inlined-layout.m | 10 + .../mrr-captured-block-var-inlined-layout.m | 6 + 3 files changed, 441 insertions(+) create mode 100644 clang/test/CodeGenObjC/arc-captured-32bit-block-var-layout.m diff --git a/clang/test/CodeGenObjC/arc-captured-32bit-block-var-layout.m b/clang/test/CodeGenObjC/arc-captured-32bit-block-var-layout.m new file mode 100644 index 0000000..6c72138 --- /dev/null +++ b/clang/test/CodeGenObjC/arc-captured-32bit-block-var-layout.m @@ -0,0 +1,425 @@ +// 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://12184410 + +void x(id y) {} +void y(int a) {} + +extern id opaque_id(); + +void f() { + __weak id wid; + __block int byref_int = 0; + char ch = 'a'; + char ch1 = 'b'; + char ch2 = 'c'; + short sh = 2; + const id bar = (id) opaque_id(); + id baz = 0; + __strong id strong_void_sta; + __block id byref_bab = (id)0; + __block id bl_var1; + int i; double dob; + +// The patterns here are a sequence of bytes, each saying first how +// many sizeof(void*) chunks to skip (high nibble) and then how many +// to scan (low nibble). A zero byte says that we've reached the end +// of the pattern. +// +// All of these patterns start with 01 3x because the block header on +// LP64 consists of an isa pointer (which we're supposed to scan for +// some reason) followed by three words (2 ints, a function pointer, +// 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" + void (^b)() = ^{ + byref_int = sh + ch+ch1+ch2 ; + x(bar); + x(baz); + x((id)strong_void_sta); + x(byref_bab); + }; + 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" + void (^c)() = ^{ + byref_int = sh + ch+ch1+ch2 ; + x(bar); + x(baz); + x((id)strong_void_sta); + x(wid); + bl_var1 = 0; + x(byref_bab); + }; +} + +@class NSString, NSNumber; +void g() { + NSString *foo; + NSNumber *bar; + unsigned int bletch; + __weak id weak_delegate; + 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" + void (^c)() = ^{ + int j = i + bletch; + x(foo); + x(bar); + x(weak_delegate); + x(y); + x(z); + }; + c(); +} + +// Test 5 (unions/structs and their nesting): +void h() { + struct S5 { + int i1; + __unsafe_unretained id o1; + struct V { + int i2; + __unsafe_unretained id o2; + } v1; + int i3; + union UI { + void * i1; + __unsafe_unretained id o1; + int i3; + __unsafe_unretained id o3; + }ui; + }; + + union U { + void * i1; + __unsafe_unretained id o1; + int i3; + __unsafe_unretained id o3; + }ui; + + struct S5 s2; + 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: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [7 x i8] c" ` `\22@\00" + void (^c)() = ^{ + x(s2.ui.o1); + x(u2.o1); + block_id = 0; + }; + c(); +} + +// Test for array of stuff. +void arr1() { + struct S { + __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" + void (^c)() = ^{ + x(imported_s.unsafe_unretained_var[2]); + }; + + c(); +} + +// Test2 for array of stuff. +void arr2() { + struct S { + int a; + __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" + void (^c)() = ^{ + x(imported_s.unsafe_unretained_var[2]); + }; + + c(); +} + +// Test3 for array of stuff. +void arr3() { + struct S { + int a; + __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 + void (^c)() = ^{ + int i = imported_s.a; + }; + + c(); +} + + +// Test4 for array of stuff. +@class B; +void arr4() { + struct S { + struct s0 { + __unsafe_unretained id s_f0; + __unsafe_unretained id s_f1; + } f0; + + __unsafe_unretained id f1; + + struct s1 { + int *f0; + __unsafe_unretained B *f1; + } 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] + void (^c)() = ^{ + id i = captured_s.f0.s_f1; + }; + + c(); +} + +// Test1 bitfield in cpatured aggregate. +void bf1() { + struct S { + int flag : 25; + int flag1: 7; + int flag2 :1; + int flag3: 7; + int flag4: 24; + } s; + +// block variable layout: BL_OPERATOR:0 +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer + int (^c)() = ^{ + return s.flag; + }; + c(); +} + +// Test2 bitfield in cpatured aggregate. +void bf2() { + struct S { + int flag : 1; + } s; + +// block variable layout: BL_OPERATOR:0 +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer + int (^c)() = ^{ + return s.flag; + }; + c(); +} + +// Test3 bitfield in cpatured aggregate. +void bf3() { + + struct { + unsigned short _reserved : 16; + + unsigned char _draggedNodesAreDeletable: 1; + unsigned char _draggedOutsideOutlineView : 1; + unsigned char _adapterRespondsTo_addRootPaths : 1; + unsigned char _adapterRespondsTo_moveDataNodes : 1; + unsigned char _adapterRespondsTo_removeRootDataNode : 1; + unsigned char _adapterRespondsTo_doubleClickDataNode : 1; + unsigned char _adapterRespondsTo_selectDataNode : 1; + unsigned char _adapterRespondsTo_textDidEndEditing : 1; + unsigned char _adapterRespondsTo_updateAndSaveRoots : 1; + unsigned char _adapterRespondsTo_askToDeleteRootNodes : 1; + unsigned char _adapterRespondsTo_contextMenuForSelectedNodes : 1; + unsigned char _adapterRespondsTo_pasteboardFilenamesForNodes : 1; + unsigned char _adapterRespondsTo_writeItemsToPasteboard : 1; + unsigned char _adapterRespondsTo_writeItemsToPasteboardXXXX : 1; + + unsigned int _filler : 32; + } _flags; + +// block variable layout: BL_OPERATOR:0 +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer + unsigned char (^c)() = ^{ + return _flags._draggedNodesAreDeletable; + }; + + c(); +} + +// Test4 unnamed bitfield +void bf4() { + + struct { + unsigned short _reserved : 16; + + unsigned char _draggedNodesAreDeletable: 1; + unsigned char _draggedOutsideOutlineView : 1; + unsigned char _adapterRespondsTo_addRootPaths : 1; + unsigned char _adapterRespondsTo_moveDataNodes : 1; + unsigned char _adapterRespondsTo_removeRootDataNode : 1; + unsigned char _adapterRespondsTo_doubleClickDataNode : 1; + unsigned char _adapterRespondsTo_selectDataNode : 1; + unsigned char _adapterRespondsTo_textDidEndEditing : 1; + + unsigned long long : 64; + + unsigned char _adapterRespondsTo_updateAndSaveRoots : 1; + unsigned char _adapterRespondsTo_askToDeleteRootNodes : 1; + unsigned char _adapterRespondsTo_contextMenuForSelectedNodes : 1; + unsigned char _adapterRespondsTo_pasteboardFilenamesForNodes : 1; + unsigned char _adapterRespondsTo_writeItemsToPasteboard : 1; + unsigned char _adapterRespondsTo_writeItemsToPasteboardXXXX : 1; + + unsigned int _filler : 32; + } _flags; + +// block variable layout: BL_OPERATOR:0 +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer + unsigned char (^c)() = ^{ + return _flags._draggedNodesAreDeletable; + }; + + c(); +} + + + +// Test5 unnamed bitfield. +void bf5() { + struct { + unsigned char flag : 1; + unsigned int : 32; + unsigned char flag1 : 1; + } _flags; + +// block variable layout: BL_OPERATOR:0 +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer + unsigned char (^c)() = ^{ + return _flags.flag; + }; + + c(); +} + + +// Test6 0 length bitfield. +void bf6() { + struct { + unsigned char flag : 1; + unsigned int : 0; + unsigned char flag1 : 1; + } _flags; + +// block variable layout: BL_OPERATOR:0 +// CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [1 x i8] zeroinitializer + unsigned char (^c)() = ^{ + return _flags.flag; + }; + + c(); +} + +// Test7 large number of captured variables. +void Test7() { + __weak id wid; + __weak id wid1, wid2, wid3, wid4; + __weak id wid5, wid6, wid7, wid8; + __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" + void (^b)() = ^{ + x(bar); + x(wid1); + x(wid2); + x(wid3); + x(wid4); + x(wid5); + x(wid6); + x(wid7); + x(wid8); + x(wid9); + x(wid10); + x(wid11); + x(wid12); + x(wid13); + x(wid14); + x(wid15); + x(wid16); + }; +} + + +// Test 8 very large number of captured variables. +void Test8() { +__weak id wid; + __weak id wid1, wid2, wid3, wid4; + __weak id wid5, wid6, wid7, wid8; + __weak id wid9, wid10, wid11, wid12; + __weak id wid13, wid14, wid15, wid16; + __weak id w1, w2, w3, w4; + __weak id w5, w6, w7, w8; + __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] + void (^b)() = ^{ + x(bar); + x(wid1); + x(wid2); + x(wid3); + x(wid4); + x(wid5); + x(wid6); + x(wid7); + x(wid8); + x(wid9); + x(wid10); + x(wid11); + x(wid12); + x(wid13); + x(wid14); + x(wid15); + x(wid16); + x(w1); + x(w2); + x(w3); + x(w4); + x(w5); + x(w6); + x(w7); + x(w8); + x(w9); + x(w10); + x(w11); + x(w12); + x(w13); + x(w14); + x(w15); + x(w16); + x(wid); + }; +} diff --git a/clang/test/CodeGenObjC/arc-captured-block-var-inlined-layout.m b/clang/test/CodeGenObjC/arc-captured-block-var-inlined-layout.m index ad81e54..b930737 100644 --- a/clang/test/CodeGenObjC/arc-captured-block-var-inlined-layout.m +++ b/clang/test/CodeGenObjC/arc-captured-block-var-inlined-layout.m @@ -1,4 +1,5 @@ // 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 // rdar://12184410 void x(id y) {} @@ -16,12 +17,14 @@ void f() { // 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 } 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 } void (^c)() = ^{ x(bar); x(baz); @@ -30,6 +33,7 @@ void f() { // 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 } void (^d)() = ^{ x(bar); x(baz); @@ -40,6 +44,7 @@ void f() { // 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 } __weak id wid; id (^e)() = ^{ x(bar); @@ -52,6 +57,7 @@ void f() { // 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 } __weak id wid1, wid2, wid3, wid4; id (^f)() = ^{ x(bar); @@ -68,6 +74,7 @@ void f() { // 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 } id (^g)() = ^{ byref_int = 1; bl_var1 = 0; @@ -81,12 +88,14 @@ void f() { // 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 } 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 } void (^ii)() = ^{ byref_int = 1; byref_bab = 0; @@ -94,6 +103,7 @@ void f() { // 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 } void (^jj)() = ^{ x(bar); x(wid1); diff --git a/clang/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m b/clang/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m index a0f2ba0..f1e02dd 100644 --- a/clang/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m +++ b/clang/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m @@ -1,4 +1,5 @@ // 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 // rdar://12184410 void x(id y) {} @@ -17,12 +18,14 @@ void f() { // block variable layout: BL_UNRETAINED:1, BL_OPERATOR:0 // CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [2 x i8] c"`\00" +// CHECK-i386: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [2 x i8] c"`\00" void (^b)() = ^{ x(bar); }; // block variable layout: BL_UNRETAINED:2, BL_BYREF:1, BL_OPERATOR:0 // CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"a@\00" +// CHECK-i386: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"a@\00" void (^c)() = ^{ x(bar); x(baz); @@ -31,6 +34,7 @@ void f() { // block variable layout: BL_UNRETAINED:2, BL_BYREF:3, BL_OPERATOR:0 // CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"aB\00 +// CHECK-i386: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"aB\00 void (^d)() = ^{ x(bar); x(baz); @@ -41,6 +45,7 @@ void f() { // block variable layout: BL_UNRETAINED:2, BL_BYREF:3, BL_OPERATOR:0 // CHECK: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"aB\00" +// CHECK-i386: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"aB\00" id (^e)() = ^{ x(bar); x(baz); @@ -52,6 +57,7 @@ void f() { // 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 } void (^ii)() = ^{ byref_int = 1; byref_bab = 0; -- 2.7.4