1 // RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-llvm -o - %s | FileCheck -check-prefix=ARM64 -check-prefix=COMMON %s
2 // RUN: %clang_cc1 -triple thumbv7-apple-ios10 -fobjc-arc -fblocks -fobjc-runtime=ios-10.0 -emit-llvm -o - %s | FileCheck -check-prefix=COMMON %s
3 // RUN: %clang_cc1 -triple x86_64-apple-macosx10.13 -fobjc-arc -fblocks -fobjc-runtime=macosx-10.13.0 -emit-llvm -o - %s | FileCheck -check-prefix=COMMON %s
4 // RUN: %clang_cc1 -triple i386-apple-macosx10.13.0 -fobjc-arc -fblocks -fobjc-runtime=macosx-fragile-10.13.0 -emit-llvm -o - %s | FileCheck -check-prefix=COMMON %s
6 typedef void (^BlockTy)(void);
8 // COMMON: %[[STRUCT_WEAK:.*]] = type { i32, ptr }
16 void calleeWeak(Weak);
18 // ARM64: define{{.*}} void @test_constructor_destructor_Weak()
19 // ARM64: %[[T:.*]] = alloca %[[STRUCT_WEAK]], align 8
20 // ARM64: call void @__default_constructor_8_w8(ptr %[[T]])
21 // ARM64: call void @__destructor_8_w8(ptr %[[T]])
24 // ARM64: define linkonce_odr hidden void @__default_constructor_8_w8(ptr noundef %[[DST:.*]])
25 // ARM64: %[[DST_ADDR:.*]] = alloca ptr, align 8
26 // ARM64: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8
27 // ARM64: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8
28 // ARM64: %[[V2:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 8
29 // ARM64: call void @llvm.memset.p0.i64(ptr align 8 %[[V2]], i8 0, i64 8, i1 false)
31 // ARM64: define linkonce_odr hidden void @__destructor_8_w8(ptr noundef %[[DST:.*]])
32 // ARM64: %[[DST_ADDR:.*]] = alloca ptr, align 8
33 // ARM64: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8
34 // ARM64: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8
35 // ARM64: %[[V2:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 8
36 // ARM64: call void @llvm.objc.destroyWeak(ptr %[[V2]])
42 void test_constructor_destructor_Weak(void) {
46 // ARM64: define{{.*}} void @test_copy_constructor_Weak(ptr noundef %{{.*}})
47 // ARM64: call void @__copy_constructor_8_8_t0w4_w8(ptr %{{.*}}, ptr %{{.*}})
48 // ARM64: call void @__destructor_8_w8(ptr %{{.*}})
50 // ARM64: define linkonce_odr hidden void @__copy_constructor_8_8_t0w4_w8(ptr noundef %[[DST:.*]], ptr noundef %[[SRC:.*]])
51 // ARM64: %[[DST_ADDR:.*]] = alloca ptr, align 8
52 // ARM64: %[[SRC_ADDR:.*]] = alloca ptr, align 8
53 // ARM64: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8
54 // ARM64: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8
55 // ARM64: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8
56 // ARM64: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8
57 // ARM64: %[[V4:.*]] = load i32, ptr %[[V1]], align 8
58 // ARM64: store i32 %[[V4]], ptr %[[V0]], align 8
59 // ARM64: %[[V6:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 8
60 // ARM64: %[[V9:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 8
61 // ARM64: call void @llvm.objc.copyWeak(ptr %[[V6]], ptr %[[V9]])
63 void test_copy_constructor_Weak(Weak *s) {
67 // ARM64: define{{.*}} void @test_copy_assignment_Weak(ptr noundef %{{.*}}, ptr noundef %{{.*}})
68 // ARM64: call void @__copy_assignment_8_8_t0w4_w8(ptr %{{.*}}, ptr %{{.*}})
70 // ARM64: define linkonce_odr hidden void @__copy_assignment_8_8_t0w4_w8(ptr noundef %[[DST:.*]], ptr noundef %[[SRC:.*]])
71 // ARM64: %[[DST_ADDR:.*]] = alloca ptr, align 8
72 // ARM64: %[[SRC_ADDR:.*]] = alloca ptr, align 8
73 // ARM64: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8
74 // ARM64: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8
75 // ARM64: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8
76 // ARM64: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8
77 // ARM64: %[[V4:.*]] = load i32, ptr %[[V1]], align 8
78 // ARM64: store i32 %[[V4]], ptr %[[V0]], align 8
79 // ARM64: %[[V6:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 8
80 // ARM64: %[[V9:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 8
81 // ARM64: %[[V11:.*]] = call ptr @llvm.objc.loadWeakRetained(ptr %[[V9]])
82 // ARM64: %[[V12:.*]] = call ptr @llvm.objc.storeWeak(ptr %[[V6]], ptr %[[V11]])
83 // ARM64: call void @llvm.objc.release(ptr %[[V11]])
85 void test_copy_assignment_Weak(Weak *d, Weak *s) {
89 // ARM64: define internal void @__Block_byref_object_copy_(ptr noundef %0, ptr noundef %1)
90 // ARM64: call void @__move_constructor_8_8_t0w4_w8(ptr %{{.*}}, ptr %{{.*}})
92 // ARM64: define linkonce_odr hidden void @__move_constructor_8_8_t0w4_w8(ptr noundef %[[DST:.*]], ptr noundef %[[SRC:.*]])
93 // ARM64: %[[DST_ADDR:.*]] = alloca ptr, align 8
94 // ARM64: %[[SRC_ADDR:.*]] = alloca ptr, align 8
95 // ARM64: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8
96 // ARM64: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8
97 // ARM64: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8
98 // ARM64: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8
99 // ARM64: %[[V4:.*]] = load i32, ptr %[[V1]], align 8
100 // ARM64: store i32 %[[V4]], ptr %[[V0]], align 8
101 // ARM64: %[[V6:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 8
102 // ARM64: %[[V9:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 8
103 // ARM64: call void @llvm.objc.moveWeak(ptr %[[V6]], ptr %[[V9]])
105 void test_move_constructor_Weak(void) {
107 BlockTy b = ^{ (void)t; };
110 // ARM64: define{{.*}} void @test_move_assignment_Weak(ptr noundef %{{.*}})
111 // ARM64: call void @__move_assignment_8_8_t0w4_w8(ptr %{{.*}}, ptr %{{.*}})
113 // ARM64: define linkonce_odr hidden void @__move_assignment_8_8_t0w4_w8(ptr noundef %[[DST:.*]], ptr noundef %[[SRC:.*]])
114 // ARM64: %[[DST_ADDR:.*]] = alloca ptr, align 8
115 // ARM64: %[[SRC_ADDR:.*]] = alloca ptr, align 8
116 // ARM64: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8
117 // ARM64: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8
118 // ARM64: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8
119 // ARM64: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8
120 // ARM64: %[[V4:.*]] = load i32, ptr %[[V1]], align 8
121 // ARM64: store i32 %[[V4]], ptr %[[V0]], align 8
122 // ARM64: %[[V6:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 8
123 // ARM64: %[[V9:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 8
124 // ARM64: %[[V11:.*]] = call ptr @llvm.objc.loadWeakRetained(ptr %[[V9]])
125 // ARM64: %[[V12:.*]] = call ptr @llvm.objc.storeWeak(ptr %[[V6]], ptr %[[V11]])
126 // ARM64: call void @llvm.objc.destroyWeak(ptr %[[V9]])
127 // ARM64: call void @llvm.objc.release(ptr %[[V11]])
129 void test_move_assignment_Weak(Weak *p) {
133 // COMMON: define{{.*}} void @test_parameter_Weak(ptr noundef %[[A:.*]])
134 // COMMON: call void @__destructor_{{.*}}(ptr %[[A]])
136 void test_parameter_Weak(Weak a) {
139 // COMMON: define{{.*}} void @test_argument_Weak(ptr noundef %[[A:.*]])
140 // COMMON: %[[A_ADDR:.*]] = alloca ptr
141 // COMMON: %[[AGG_TMP:.*]] = alloca %[[STRUCT_WEAK]]
142 // COMMON: store ptr %[[A]], ptr %[[A_ADDR]]
143 // COMMON: %[[V0:.*]] = load ptr, ptr %[[A_ADDR]]
144 // COMMON: call void @__copy_constructor_{{.*}}(ptr %[[AGG_TMP]], ptr %[[V0]])
145 // COMMON: call void @calleeWeak(ptr noundef %[[AGG_TMP]])
148 void test_argument_Weak(Weak *a) {
152 // COMMON: define{{.*}} void @test_return_Weak(ptr noalias sret(%[[STRUCT_WEAK]]) align {{.*}} %[[AGG_RESULT:.*]], ptr noundef %[[A:.*]])
153 // COMMON: %[[A_ADDR:.*]] = alloca ptr
154 // COMMON: store ptr %[[A]], ptr %[[A_ADDR]]
155 // COMMON: %[[V0:.*]] = load ptr, ptr %[[A_ADDR]]
156 // COMMON: call void @__copy_constructor_{{.*}}(ptr %[[AGG_RESULT]], ptr %[[V0]])
159 Weak test_return_Weak(Weak *a) {
163 // COMMON-LABEL: define{{.*}} void @test_null_receiver(
164 // COMMON: %[[AGG_TMP:.*]] = alloca %[[STRUCT_WEAK]]
167 // COMMON: call void @objc_msgSend({{.*}}, ptr noundef %[[AGG_TMP]])
170 // COMMON: call void @__destructor_{{.*}}(ptr %[[AGG_TMP]])
173 void test_null_receiver(C *c) {