blob: 3a8cd2fd75e6e44581483af344ee04f2ff057b74 [file] [log] [blame]
John McCall460ce582015-10-22 18:38:17 +00001// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-10.10 -emit-llvm -fblocks -fobjc-weak -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-MODERN
2// RUN: %clang_cc1 -triple i386-apple-darwin10 -fobjc-runtime=macosx-fragile-10.10 -emit-llvm -fblocks -fobjc-weak -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-FRAGILE
3
4@interface Object
5- (instancetype) retain;
6- (void) run;
7@end
8
John McCalld80218f2015-11-19 02:27:55 +00009// The ivars in HighlyAlignedSubclass should be placed in the tail-padding
10// of the superclass. Ensure that they're still covered by layouts.
11@interface HighlyAligned : Object {
12 __attribute__((aligned(32))) void *array[2];
13}
14@end
15// CHECK-MODERN: @"OBJC_IVAR_$_HighlyAlignedSubclass.ivar2" = global i64 24,
16// CHECK-MODERN: @"OBJC_IVAR_$_HighlyAlignedSubclass.ivar" = global i64 16,
17// CHECK-MODERN: @OBJC_CLASS_NAME_{{.*}} = {{.*}} c"\02\00"
18// CHECK-MODERN: @"\01l_OBJC_CLASS_RO_$_HighlyAlignedSubclass" = {{.*}} {
19// CHECK-FRAGILE: @OBJC_INSTANCE_VARIABLES_HighlyAlignedSubclass = {{.*}}, i32 8 }, {{.*}}, i32 12 }]
20// CHECK-FRAGILE: @OBJC_CLASS_NAME_{{.*}} = {{.*}} c"\02\00"
21// CHECK-FRAGILE: @OBJC_CLASS_HighlyAlignedSubclass
22@interface HighlyAlignedSubclass : HighlyAligned {
23 __weak id ivar;
24 __weak id ivar2;
25}
26@end
27@implementation HighlyAlignedSubclass @end
28
John McCall460ce582015-10-22 18:38:17 +000029// CHECK-MODERN: @OBJC_CLASS_NAME_{{.*}} = {{.*}} c"\01\00"
30// CHECK-MODERN: @"\01l_OBJC_CLASS_RO_$_Foo" = {{.*}} { i32 772
31// 772 == 0x304
32// ^ HasMRCWeakIvars
33// ^ HasCXXDestructorOnly
34// ^ HasCXXStructors
35
36// CHECK-FRAGILE: @OBJC_CLASS_NAME_{{.*}} = {{.*}} c"\01\00"
37// CHECK-FRAGILE: @OBJC_CLASS_Foo = {{.*}} i32 134225921,
38// 134225921 == 0x08002001
39// ^ HasMRCWeakIvars
40// ^ HasCXXStructors
41// ^ Factory
42@interface Foo : Object {
43 __weak id ivar;
44}
45@end
46
47@implementation Foo
48// CHECK-LABEL: define internal void @"\01-[Foo .cxx_destruct]"
Pete Cooper2cd35962018-12-18 20:33:00 +000049// CHECK: call void @llvm.objc.destroyWeak
John McCall460ce582015-10-22 18:38:17 +000050@end
51
52
53void test1(__weak id x) {}
54// CHECK-LABEL: define void @test1
55// CHECK: [[X:%.*]] = alloca i8*,
Pete Cooper2cd35962018-12-18 20:33:00 +000056// CHECK-NEXT: @llvm.objc.initWeak
57// CHECK-NEXT: @llvm.objc.destroyWeak
John McCall460ce582015-10-22 18:38:17 +000058// CHECK-NEXT: ret void
59
60void test2(id y) {
61 __weak id z = y;
62}
63// CHECK-LABEL: define void @test2
64// CHECK: [[Y:%.*]] = alloca i8*,
65// CHECK-NEXT: [[Z:%.*]] = alloca i8*,
66// CHECK-NEXT: store
67// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
Pete Cooper2cd35962018-12-18 20:33:00 +000068// CHECK-NEXT: call i8* @llvm.objc.initWeak(i8** [[Z]], i8* [[T0]])
69// CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[Z]])
John McCall460ce582015-10-22 18:38:17 +000070// CHECK-NEXT: ret void
71
72void test3(id y) {
73 __weak id z;
74 z = y;
75}
76// CHECK-LABEL: define void @test3
77// CHECK: [[Y:%.*]] = alloca i8*,
78// CHECK-NEXT: [[Z:%.*]] = alloca i8*,
79// CHECK-NEXT: store
80// CHECK-NEXT: store i8* null, i8** [[Z]]
81// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
Pete Cooper2cd35962018-12-18 20:33:00 +000082// CHECK-NEXT: call i8* @llvm.objc.storeWeak(i8** [[Z]], i8* [[T0]])
83// CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[Z]])
John McCall460ce582015-10-22 18:38:17 +000084// CHECK-NEXT: ret void
85
86void test4(__weak id *p) {
87 id y = *p;
88}
89// CHECK-LABEL: define void @test4
90// CHECK: [[P:%.*]] = alloca i8**,
91// CHECK-NEXT: [[Y:%.*]] = alloca i8*,
92// CHECK-NEXT: store
93// CHECK-NEXT: [[T0:%.*]] = load i8**, i8*** [[P]]
Pete Cooper2cd35962018-12-18 20:33:00 +000094// CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.loadWeak(i8** [[T0]])
John McCall460ce582015-10-22 18:38:17 +000095// CHECK-NEXT: store i8* [[T1]], i8** [[Y]]
96// CHECK-NEXT: ret void
97
98void test5(__weak id *p) {
99 id y = [*p retain];
100}
101// CHECK-LABEL: define void @test5
102// CHECK: [[P:%.*]] = alloca i8**,
103// CHECK-NEXT: [[Y:%.*]] = alloca i8*,
104// CHECK-NEXT: store
105// CHECK-NEXT: [[T0:%.*]] = load i8**, i8*** [[P]]
Pete Cooper2cd35962018-12-18 20:33:00 +0000106// CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.loadWeakRetained(i8** [[T0]])
John McCall460ce582015-10-22 18:38:17 +0000107// CHECK-NEXT: store i8* [[T1]], i8** [[Y]]
108// CHECK-NEXT: ret void
109
110void test6(__weak Foo **p) {
111 Foo *y = [*p retain];
112}
113// CHECK-LABEL: define void @test6
114// CHECK: [[P:%.*]] = alloca [[FOO:%.*]]**,
115// CHECK-NEXT: [[Y:%.*]] = alloca [[FOO]]*,
116// CHECK-NEXT: store
117// CHECK-NEXT: [[T0:%.*]] = load [[FOO]]**, [[FOO]]*** [[P]]
118// CHECK-NEXT: [[T1:%.*]] = bitcast [[FOO]]** [[T0]] to i8**
Pete Cooper2cd35962018-12-18 20:33:00 +0000119// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.loadWeakRetained(i8** [[T1]])
John McCall460ce582015-10-22 18:38:17 +0000120// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[FOO]]*
121// CHECK-NEXT: store [[FOO]]* [[T3]], [[FOO]]** [[Y]]
122// CHECK-NEXT: ret void
123
124extern id get_object(void);
125extern void use_block(void (^)(void));
126
127void test7(void) {
128 __weak Foo *p = get_object();
129 use_block(^{ [p run ]; });
130}
131// CHECK-LABEL: define void @test7
132// CHECK: [[P:%.*]] = alloca [[FOO]]*,
133// CHECK: [[T0:%.*]] = call i8* @get_object()
134// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[FOO]]*
135// CHECK-NEXT: [[T2:%.*]] = bitcast [[FOO]]** [[P]] to i8**
136// CHECK-NEXT: [[T3:%.*]] = bitcast [[FOO]]* [[T1]] to i8*
Pete Cooper2cd35962018-12-18 20:33:00 +0000137// CHECK-NEXT: call i8* @llvm.objc.initWeak(i8** [[T2]], i8* [[T3]])
138// CHECK: call void @llvm.objc.copyWeak
John McCall460ce582015-10-22 18:38:17 +0000139// CHECK: call void @use_block
Pete Cooper2cd35962018-12-18 20:33:00 +0000140// CHECK: call void @llvm.objc.destroyWeak
John McCall460ce582015-10-22 18:38:17 +0000141
Akira Hatanaka9978da32018-08-10 15:09:24 +0000142// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block
Pete Cooper2cd35962018-12-18 20:33:00 +0000143// CHECK: @llvm.objc.copyWeak
John McCall460ce582015-10-22 18:38:17 +0000144
Akira Hatanaka9978da32018-08-10 15:09:24 +0000145// CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block
Pete Cooper2cd35962018-12-18 20:33:00 +0000146// CHECK: @llvm.objc.destroyWeak
John McCall460ce582015-10-22 18:38:17 +0000147
148void test8(void) {
149 __block __weak Foo *p = get_object();
150 use_block(^{ [p run ]; });
151}
152// CHECK-LABEL: define void @test8
Pete Cooper2cd35962018-12-18 20:33:00 +0000153// CHECK: call i8* @llvm.objc.initWeak
154// CHECK-NOT: call void @llvm.objc.copyWeak
John McCall460ce582015-10-22 18:38:17 +0000155// CHECK: call void @use_block
Pete Cooper2cd35962018-12-18 20:33:00 +0000156// CHECK: call void @llvm.objc.destroyWeak
John McCall460ce582015-10-22 18:38:17 +0000157
158// CHECK-LABEL: define internal void @__Block_byref_object_copy
Pete Cooper2cd35962018-12-18 20:33:00 +0000159// CHECK: call void @llvm.objc.moveWeak
John McCall460ce582015-10-22 18:38:17 +0000160
161// CHECK-LABEL: define internal void @__Block_byref_object_dispose
Pete Cooper2cd35962018-12-18 20:33:00 +0000162// CHECK: call void @llvm.objc.destroyWeak
John McCall00b2bbb2015-11-19 02:28:03 +0000163
164// CHECK-LABEL: define void @test9_baseline()
Akira Hatanaka9978da32018-08-10 15:09:24 +0000165// CHECK: define linkonce_odr hidden void @__copy_helper
166// CHECK: define linkonce_odr hidden void @__destroy_helper
John McCall00b2bbb2015-11-19 02:28:03 +0000167void test9_baseline(void) {
168 Foo *p = get_object();
169 use_block(^{ [p run]; });
170}
171
172// CHECK-LABEL: define void @test9()
Akira Hatanaka9978da32018-08-10 15:09:24 +0000173// CHECK-NOT: define linkonce_odr hidden void @__copy_helper
174// CHECK-NOT: define linkonce_odr hidden void @__destroy_helper
John McCall00b2bbb2015-11-19 02:28:03 +0000175// CHECK: define void @test9_fin()
176void test9(void) {
177 __unsafe_unretained Foo *p = get_object();
178 use_block(^{ [p run]; });
179}
180void test9_fin() {}
181
182// CHECK-LABEL: define void @test10()
Akira Hatanaka9978da32018-08-10 15:09:24 +0000183// CHECK-NOT: define linkonce_odr hidden void @__copy_helper
184// CHECK-NOT: define linkonce_odr hidden void @__destroy_helper
John McCall00b2bbb2015-11-19 02:28:03 +0000185// CHECK: define void @test10_fin()
186void test10(void) {
187 typedef __unsafe_unretained Foo *UnsafeFooPtr;
188 UnsafeFooPtr p = get_object();
189 use_block(^{ [p run]; });
190}
191void test10_fin() {}