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