1// RUN: %clang_cc1 -fblocks -fobjc-gc -triple x86_64-apple-darwin -fobjc-runtime=macosx-fragile-10.5 -print-ivar-layout -emit-llvm -o /dev/null %s > %t-64.layout 2// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.layout %s 3 4struct S { 5 int i1; 6 id o1; 7 struct V { 8 int i2; 9 id o2; 10 } v1; 11 int i3; 12 id o3; 13}; 14 15__weak id wid; 16void x(id y) {} 17void y(int a) {} 18 19extern id opaque_id(void); 20 21void f(void) { 22 __block int byref_int = 0; 23 char ch = 'a'; 24 char ch1 = 'b'; 25 char ch2 = 'c'; 26 short sh = 2; 27 const id bar = (id) opaque_id(); 28 id baz = 0; 29 __strong void *strong_void_sta; 30 __block id byref_bab = (id)0; 31 __block void *bl_var1; 32 int i; double dob; 33 34// The patterns here are a sequence of bytes, each saying first how 35// many sizeof(void*) chunks to skip (high nibble) and then how many 36// to scan (low nibble). A zero byte says that we've reached the end 37// of the pattern. 38// 39// All of these patterns start with 01 3x because the block header on 40// LP64 consists of an isa pointer (which we're supposed to scan for 41// some reason) followed by three words (2 ints, a function pointer, 42// and a descriptor pointer). 43 44// FIXME: do these really have to be named L_OBJC_CLASS_NAME_xxx? 45// FIXME: sequences should never end in x0 00 instead of just 00 46 47// Test 1 48// byref int, short, char, char, char, id, id, strong void*, byref id 49// CHECK-LP64: block variable layout for block: 0x01, 0x35, 0x10, 0x00 50 void (^b)(void) = ^{ 51 byref_int = sh + ch+ch1+ch2 ; 52 x(bar); 53 x(baz); 54 x((id)strong_void_sta); 55 x(byref_bab); 56 }; 57 b(); 58 59// Test 2 60// byref int, short, char, char, char, id, id, strong void*, byref void*, byref id 61// 01 36 10 00 62// CHECK-LP64: block variable layout for block: 0x01, 0x36, 0x10, 0x00 63 void (^c)(void) = ^{ 64 byref_int = sh + ch+ch1+ch2 ; 65 x(bar); 66 x(baz); 67 x((id)strong_void_sta); 68 x(wid); 69 bl_var1 = 0; 70 x(byref_bab); 71 }; 72 c(); 73 74// Test 3 75// byref int, short, char, char, char, id, id, byref void*, int, double, byref id 76// 01 34 11 30 00 77// FIXME: we'd get a better format here if we sorted by scannability, not just alignment 78// CHECK-LP64: block variable layout for block: 0x01, 0x35, 0x30, 0x00 79 void (^d)(void) = ^{ 80 byref_int = sh + ch+ch1+ch2 ; 81 x(bar); 82 x(baz); 83 x(wid); 84 bl_var1 = 0; 85 y(i + dob); 86 x(byref_bab); 87 }; 88 d(); 89 90// Test 4 91// struct S (int, id, int, id, int, id) 92// 01 41 11 11 00 93// CHECK-LP64: block variable layout for block: 0x01, 0x41, 0x11, 0x11, 0x00 94 struct S s2; 95 void (^e)(void) = ^{ 96 x(s2.o1); 97 }; 98 e(); 99} 100 101// Test 5 (unions/structs and their nesting): 102void Test5(void) { 103 struct S5 { 104 int i1; 105 id o1; 106 struct V { 107 int i2; 108 id o2; 109 } v1; 110 int i3; 111 union UI { 112 void * i1; 113 id o1; 114 int i3; 115 id o3; 116 }ui; 117 }; 118 119 union U { 120 void * i1; 121 id o1; 122 int i3; 123 id o3; 124 }ui; 125 126 struct S5 s2; 127 union U u2; 128 129// struct s2 (int, id, int, id, int, id?), union u2 (id?) 130// 01 41 11 12 00 131// CHECK-LP64: block variable layout for block: 0x01, 0x41, 0x11, 0x12, 0x00 132 void (^c)(void) = ^{ 133 x(s2.ui.o1); 134 x(u2.o1); 135 }; 136 c(); 137} 138 139void CFRelease(id); 140void notifyBlock(id dependentBlock) { 141 id singleObservationToken; 142 id token; 143 void (^b)(void); 144 145// id, id, void(^)(void) 146// 01 33 00 147// CHECK-LP64: block variable layout for block: 0x01, 0x33, 0x00 148 void (^wrapperBlock)(void) = ^(void) { 149 CFRelease(singleObservationToken); 150 CFRelease(singleObservationToken); 151 CFRelease(token); 152 CFRelease(singleObservationToken); 153 b(); 154 }; 155 wrapperBlock(); 156} 157 158void test_empty_block(void) { 159// 01 00 160// CHECK-LP64: block variable layout for block: 0x01, 0x30, 0x00 161 void (^wrapperBlock)(void) = ^(void) { 162 }; 163 wrapperBlock(); 164} 165 166typedef union { char ch[8]; } SS; 167typedef struct { SS s[4]; } CS; 168void test_union_in_layout(void) { 169 CS cs; 170 ^{ cs; }; 171} 172