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