• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// RUN: %clang_cc1 -fblocks -fobjc-gc -triple x86_64-apple-darwin -O0 -emit-llvm %s -o %t-64.s
2// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
3
4struct 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;
16void x(id y) {}
17void y(int a) {}
18
19extern id opaque_id();
20
21void 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):
103void 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
141void CFRelease(id);
142void 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
160void 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