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