1 // RUN: %clang_cc1 -x objective-c++ -fblocks -fobjc-gc -triple x86_64-apple-darwin -emit-llvm %s -o %t-64.ll 2 // RUN: FileCheck -check-prefix LP64 --input-file=%t-64.ll %s 3 4 // See commentary in test/CodeGenObjC/block-var-layout.m, from which 5 // this is largely cloned. 6 7 struct S { 8 int i1; 9 id o1; 10 struct V { 11 int i2; 12 id o2; 13 } v1; 14 int i3; 15 id o3; 16 }; 17 18 __weak id wid; 19 void x(id y) {} 20 void y(int a) {} 21 22 extern id opaque_id(); 23 24 void f() { 25 __block int byref_int = 0; 26 char ch = 'a'; 27 char ch1 = 'b'; 28 char ch2 = 'c'; 29 short sh = 2; 30 const id bar = (id) opaque_id(); 31 id baz = 0; 32 __strong void *strong_void_sta; 33 __block id byref_bab = (id)0; 34 __block void *bl_var1; 35 int i; double dob; 36 37 // Test 1 38 // byref int, short, char, char, char, id, id, strong void*, byref id 39 // 01 35 10 00 40 // CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"\015\10\00" 41 void (^b)() = ^{ 42 byref_int = sh + ch+ch1+ch2 ; 43 x(bar); 44 x(baz); 45 x((id)strong_void_sta); 46 x(byref_bab); 47 }; 48 b(); 49 50 // Test 2 51 // byref int, short, char, char, char, id, id, strong void*, byref void*, byref id 52 // 01 36 10 00 53 // CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"\016\10\00" 54 void (^c)() = ^{ 55 byref_int = sh + ch+ch1+ch2 ; 56 x(bar); 57 x(baz); 58 x((id)strong_void_sta); 59 x(wid); 60 bl_var1 = 0; 61 x(byref_bab); 62 }; 63 c(); 64 65 // Test 3 66 // byref int, short, char, char, char, id, id, byref void*, int, double, byref id 67 // 01 34 11 30 00 68 // FIXME: we'd get a better format here if we sorted by scannability, not just alignment 69 // CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\014\11 \00" 70 void (^d)() = ^{ 71 byref_int = sh + ch+ch1+ch2 ; 72 x(bar); 73 x(baz); 74 x(wid); 75 bl_var1 = 0; 76 y(i + dob); 77 x(byref_bab); 78 }; 79 d(); 80 81 // Test4 82 // struct S (int, id, int, id, int, id) 83 // 01 41 11 11 84 // CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\01A\11\11\00" 85 struct S s2; 86 void (^e)() = ^{ 87 x(s2.o1); 88 }; 89 e(); 90 } 91 92 // Test 5 (unions/structs and their nesting): 93 void Test5() { 94 struct S5 { 95 int i1; 96 id o1; 97 struct V { 98 int i2; 99 id o2; 100 } v1; 101 int i3; 102 union UI { 103 void * i1; 104 id o1; 105 int i3; 106 id o3; 107 }ui; 108 }; 109 110 union U { 111 void * i1; 112 id o1; 113 int i3; 114 id o3; 115 }ui; 116 117 struct S5 s2; 118 union U u2; 119 120 // struct s2 (int, id, int, id, int, id?), union u2 (id?) 121 // 01 41 11 12 70 00 122 // CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [6 x i8] c"\01A\11\12p\00" 123 void (^c)() = ^{ 124 x(s2.ui.o1); 125 x(u2.o1); 126 }; 127 c(); 128 129 } 130 131 // rdar: //8417746 132 void CFRelease(id); 133 void notifyBlock(id dependentBlock) { 134 id singleObservationToken; 135 id token; 136 void (^b)(); 137 138 // id, id, void(^)() 139 // 01 33 00 140 // CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"\013\00" 141 void (^wrapperBlock)() = ^() { 142 CFRelease(singleObservationToken); 143 CFRelease(singleObservationToken); 144 CFRelease(token); 145 CFRelease(singleObservationToken); 146 b(); 147 }; 148 wrapperBlock(); 149 } 150 151 void test_empty_block() { 152 // 01 00 153 // CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [2 x i8] c"\01\00" 154 void (^wrapperBlock)() = ^() { 155 }; 156 wrapperBlock(); 157 } 158