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