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