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 // rdar://12184410 4 // rdar://12752901 5 6 void x(id y) {} 7 void y(int a) {} 8 9 extern id opaque_id(); 10 11 void 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 block variable layout: 0x0320, BL_STRONG:3, BL_BYREF:2, BL_OPERATOR:0 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 block variable layout: 0x0331, BL_STRONG:3, BL_BYREF:3, BL_WEAK:1, BL_OPERATOR:0 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; 62 void 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 block variable layout: 0x0401, BL_STRONG:4, BL_WEAK:1, BL_OPERATOR:0 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): 84 void 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. 122 void 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. 136 void 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. 151 void 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; 168 void 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. 192 void 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. 209 void 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. 222 void 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 254 void 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. 291 void 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. 308 void 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. 324 void 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. 355 void 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