1// 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 2// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.layout %s 3// rdar://12184410 4// rdar://12752901 5 6void x(id y) {} 7void y(int a) {} 8 9extern id opaque_id(); 10 11void f() { 12 __weak id wid; 13 __block int byref_int = 0; 14 char ch = 'a'; 15 char ch1 = 'b'; 16 char ch2 = 'c'; 17 short sh = 2; 18 const id bar = (id) opaque_id(); 19 id baz = 0; 20 __strong id strong_void_sta; 21 __block id byref_bab = (id)0; 22 __block id bl_var1; 23 int i; double dob; 24 25// The patterns here are a sequence of bytes, each saying first how 26// many sizeof(void*) chunks to skip (high nibble) and then how many 27// to scan (low nibble). A zero byte says that we've reached the end 28// of the pattern. 29// 30// All of these patterns start with 01 3x because the block header on 31// LP64 consists of an isa pointer (which we're supposed to scan for 32// some reason) followed by three words (2 ints, a function pointer, 33// and a descriptor pointer). 34 35// Test 1 36// Inline instruction for block variable layout: 0x0320 (3 strong 2 byref) 37// CHECK-LP64: Inline instruction for block variable layout: 0x0320 38 void (^b)() = ^{ 39 byref_int = sh + ch+ch1+ch2 ; 40 x(bar); 41 x(baz); 42 x((id)strong_void_sta); 43 x(byref_bab); 44 }; 45 b(); 46 47// Test 2 48// Inline instruction for block variable layout: 0x0331 (3 strong 3 byref 1 weak) 49// CHECK-LP64: Inline instruction for block variable layout: 0x0331 50 void (^c)() = ^{ 51 byref_int = sh + ch+ch1+ch2 ; 52 x(bar); 53 x(baz); 54 x((id)strong_void_sta); 55 x(wid); 56 bl_var1 = 0; 57 x(byref_bab); 58 }; 59} 60 61@class NSString, NSNumber; 62void g() { 63 NSString *foo; 64 NSNumber *bar; 65 unsigned int bletch; 66 __weak id weak_delegate; 67 unsigned int i; 68 NSString *y; 69 NSString *z; 70// Inline instruction for block variable layout: 0x0401 (4 strong 0 byref 1 weak) 71// CHECK-LP64: Inline instruction for block variable layout: 0x0401 72 void (^c)() = ^{ 73 int j = i + bletch; 74 x(foo); 75 x(bar); 76 x(weak_delegate); 77 x(y); 78 x(z); 79 }; 80 c(); 81} 82 83// Test 5 (unions/structs and their nesting): 84void h() { 85 struct S5 { 86 int i1; 87 __unsafe_unretained id o1; 88 struct V { 89 int i2; 90 __unsafe_unretained id o2; 91 } v1; 92 int i3; 93 union UI { 94 void * i1; 95 __unsafe_unretained id o1; 96 int i3; 97 __unsafe_unretained id o3; 98 }ui; 99 }; 100 101 union U { 102 void * i1; 103 __unsafe_unretained id o1; 104 int i3; 105 __unsafe_unretained id o3; 106 }ui; 107 108 struct S5 s2; 109 union U u2; 110 __block id block_id; 111 112// 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 113 void (^c)() = ^{ 114 x(s2.ui.o1); 115 x(u2.o1); 116 block_id = 0; 117 }; 118 c(); 119} 120 121// Test for array of stuff. 122void arr1() { 123 struct S { 124 __unsafe_unretained id unsafe_unretained_var[4]; 125 } imported_s; 126 127// CHECK-LP64: block variable layout: BL_UNRETAINED:4, BL_OPERATOR:0 128 void (^c)() = ^{ 129 x(imported_s.unsafe_unretained_var[2]); 130 }; 131 132 c(); 133} 134 135// Test2 for array of stuff. 136void arr2() { 137 struct S { 138 int a; 139 __unsafe_unretained id unsafe_unretained_var[4]; 140 } imported_s; 141 142// CHECK-LP64: block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINED:4, BL_OPERATOR:0 143 void (^c)() = ^{ 144 x(imported_s.unsafe_unretained_var[2]); 145 }; 146 147 c(); 148} 149 150// Test3 for array of stuff. 151void arr3() { 152 struct S { 153 int a; 154 __unsafe_unretained id unsafe_unretained_var[0]; 155 } imported_s; 156 157// CHECK-LP64: block variable layout: BL_OPERATOR:0 158 void (^c)() = ^{ 159 int i = imported_s.a; 160 }; 161 162 c(); 163} 164 165 166// Test4 for array of stuff. 167@class B; 168void arr4() { 169 struct S { 170 struct s0 { 171 __unsafe_unretained id s_f0; 172 __unsafe_unretained id s_f1; 173 } f0; 174 175 __unsafe_unretained id f1; 176 177 struct s1 { 178 int *f0; 179 __unsafe_unretained B *f1; 180 } f4[2][2]; 181 } captured_s; 182 183// 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 184 void (^c)() = ^{ 185 id i = captured_s.f0.s_f1; 186 }; 187 188 c(); 189} 190 191// Test1 bitfield in cpatured aggregate. 192void bf1() { 193 struct S { 194 int flag : 25; 195 int flag1: 7; 196 int flag2 :1; 197 int flag3: 7; 198 int flag4: 24; 199 } s; 200 201// CHECK-LP64: block variable layout: BL_OPERATOR:0 202 int (^c)() = ^{ 203 return s.flag; 204 }; 205 c(); 206} 207 208// Test2 bitfield in cpatured aggregate. 209void bf2() { 210 struct S { 211 int flag : 1; 212 } s; 213 214// CHECK-LP64: block variable layout: BL_OPERATOR:0 215 int (^c)() = ^{ 216 return s.flag; 217 }; 218 c(); 219} 220 221// Test3 bitfield in cpatured aggregate. 222void bf3() { 223 224 struct { 225 unsigned short _reserved : 16; 226 227 unsigned char _draggedNodesAreDeletable: 1; 228 unsigned char _draggedOutsideOutlineView : 1; 229 unsigned char _adapterRespondsTo_addRootPaths : 1; 230 unsigned char _adapterRespondsTo_moveDataNodes : 1; 231 unsigned char _adapterRespondsTo_removeRootDataNode : 1; 232 unsigned char _adapterRespondsTo_doubleClickDataNode : 1; 233 unsigned char _adapterRespondsTo_selectDataNode : 1; 234 unsigned char _adapterRespondsTo_textDidEndEditing : 1; 235 unsigned char _adapterRespondsTo_updateAndSaveRoots : 1; 236 unsigned char _adapterRespondsTo_askToDeleteRootNodes : 1; 237 unsigned char _adapterRespondsTo_contextMenuForSelectedNodes : 1; 238 unsigned char _adapterRespondsTo_pasteboardFilenamesForNodes : 1; 239 unsigned char _adapterRespondsTo_writeItemsToPasteboard : 1; 240 unsigned char _adapterRespondsTo_writeItemsToPasteboardXXXX : 1; 241 242 unsigned int _filler : 32; 243 } _flags; 244 245// CHECK-LP64: block variable layout: BL_OPERATOR:0 246 unsigned char (^c)() = ^{ 247 return _flags._draggedNodesAreDeletable; 248 }; 249 250 c(); 251} 252 253// Test4 unnamed bitfield 254void bf4() { 255 256 struct { 257 unsigned short _reserved : 16; 258 259 unsigned char _draggedNodesAreDeletable: 1; 260 unsigned char _draggedOutsideOutlineView : 1; 261 unsigned char _adapterRespondsTo_addRootPaths : 1; 262 unsigned char _adapterRespondsTo_moveDataNodes : 1; 263 unsigned char _adapterRespondsTo_removeRootDataNode : 1; 264 unsigned char _adapterRespondsTo_doubleClickDataNode : 1; 265 unsigned char _adapterRespondsTo_selectDataNode : 1; 266 unsigned char _adapterRespondsTo_textDidEndEditing : 1; 267 268 unsigned long long : 64; 269 270 unsigned char _adapterRespondsTo_updateAndSaveRoots : 1; 271 unsigned char _adapterRespondsTo_askToDeleteRootNodes : 1; 272 unsigned char _adapterRespondsTo_contextMenuForSelectedNodes : 1; 273 unsigned char _adapterRespondsTo_pasteboardFilenamesForNodes : 1; 274 unsigned char _adapterRespondsTo_writeItemsToPasteboard : 1; 275 unsigned char _adapterRespondsTo_writeItemsToPasteboardXXXX : 1; 276 277 unsigned int _filler : 32; 278 } _flags; 279 280// CHECK-LP64: block variable layout: BL_OPERATOR:0 281 unsigned char (^c)() = ^{ 282 return _flags._draggedNodesAreDeletable; 283 }; 284 285 c(); 286} 287 288 289 290// Test5 unnamed bitfield. 291void bf5() { 292 struct { 293 unsigned char flag : 1; 294 unsigned int : 32; 295 unsigned char flag1 : 1; 296 } _flags; 297 298// CHECK-LP64: block variable layout: BL_OPERATOR:0 299 unsigned char (^c)() = ^{ 300 return _flags.flag; 301 }; 302 303 c(); 304} 305 306 307// Test6 0 length bitfield. 308void bf6() { 309 struct { 310 unsigned char flag : 1; 311 unsigned int : 0; 312 unsigned char flag1 : 1; 313 } _flags; 314 315// CHECK-LP64: block variable layout: BL_OPERATOR:0 316 unsigned char (^c)() = ^{ 317 return _flags.flag; 318 }; 319 320 c(); 321} 322 323// Test7 large number of captured variables. 324void Test7() { 325 __weak id wid; 326 __weak id wid1, wid2, wid3, wid4; 327 __weak id wid5, wid6, wid7, wid8; 328 __weak id wid9, wid10, wid11, wid12; 329 __weak id wid13, wid14, wid15, wid16; 330 const id bar = (id) opaque_id(); 331// CHECK-LP64: block variable layout: BL_STRONG:1, BL_WEAK:16, BL_OPERATOR:0 332 void (^b)() = ^{ 333 x(bar); 334 x(wid1); 335 x(wid2); 336 x(wid3); 337 x(wid4); 338 x(wid5); 339 x(wid6); 340 x(wid7); 341 x(wid8); 342 x(wid9); 343 x(wid10); 344 x(wid11); 345 x(wid12); 346 x(wid13); 347 x(wid14); 348 x(wid15); 349 x(wid16); 350 }; 351} 352 353 354// Test 8 very large number of captured variables. 355void Test8() { 356__weak id wid; 357 __weak id wid1, wid2, wid3, wid4; 358 __weak id wid5, wid6, wid7, wid8; 359 __weak id wid9, wid10, wid11, wid12; 360 __weak id wid13, wid14, wid15, wid16; 361 __weak id w1, w2, w3, w4; 362 __weak id w5, w6, w7, w8; 363 __weak id w9, w10, w11, w12; 364 __weak id w13, w14, w15, w16; 365 const id bar = (id) opaque_id(); 366// CHECK-LP64: block variable layout: BL_STRONG:1, BL_WEAK:16, BL_WEAK:16, BL_WEAK:1, BL_OPERATOR:0 367 void (^b)() = ^{ 368 x(bar); 369 x(wid1); 370 x(wid2); 371 x(wid3); 372 x(wid4); 373 x(wid5); 374 x(wid6); 375 x(wid7); 376 x(wid8); 377 x(wid9); 378 x(wid10); 379 x(wid11); 380 x(wid12); 381 x(wid13); 382 x(wid14); 383 x(wid15); 384 x(wid16); 385 x(w1); 386 x(w2); 387 x(w3); 388 x(w4); 389 x(w5); 390 x(w6); 391 x(w7); 392 x(w8); 393 x(w9); 394 x(w10); 395 x(w11); 396 x(w12); 397 x(w13); 398 x(w14); 399 x(w15); 400 x(w16); 401 x(wid); 402 }; 403} 404