blob: dd9b88b0234d09fa27e93c673082f5d9ede9811e [file] [log] [blame]
Akira Hatanaka02914dc2018-02-05 20:23:22 +00001// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc -fobjc-weak -fobjc-runtime-has-weak -emit-llvm -o - %s | FileCheck %s
2// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc -fobjc-weak -fobjc-runtime-has-weak -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s
Akira Hatanakafcbe17c2018-03-28 21:13:14 +00003// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc -fobjc-weak -fobjc-runtime-has-weak -emit-llvm -o - -DTRIVIALABI %s | FileCheck %s
4// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc -fobjc-weak -fobjc-runtime-has-weak -fclang-abi-compat=4.0 -emit-llvm -o - -DTRIVIALABI %s | FileCheck %s
5
6// Check that structs consisting solely of __strong or __weak pointer fields are
7// destructed in the callee function and structs consisting solely of __strong
8// pointer fields are passed directly.
Akira Hatanaka02914dc2018-02-05 20:23:22 +00009
10// CHECK: %[[STRUCT_STRONGWEAK:.*]] = type { i8*, i8* }
Akira Hatanakae6313ac2018-04-09 22:48:22 +000011// CHECK: %[[STRUCT_CONTAINSSTRONGWEAK:.*]] = type { %[[STRUCT_STRONGWEAK]] }
12// CHECK: %[[STRUCT_DERIVEDSTRONGWEAK:.*]] = type { %[[STRUCT_STRONGWEAK]] }
Akira Hatanaka02914dc2018-02-05 20:23:22 +000013// CHECK: %[[STRUCT_STRONG:.*]] = type { i8* }
14// CHECK: %[[STRUCT_S:.*]] = type { i8* }
Akira Hatanakafcbe17c2018-03-28 21:13:14 +000015// CHECK: %[[STRUCT_CONTAINSNONTRIVIAL:.*]] = type { %{{.*}}, i8* }
Akira Hatanaka02914dc2018-02-05 20:23:22 +000016
Akira Hatanakafcbe17c2018-03-28 21:13:14 +000017#ifdef TRIVIALABI
Akira Hatanaka02914dc2018-02-05 20:23:22 +000018struct __attribute__((trivial_abi)) StrongWeak {
Akira Hatanakafcbe17c2018-03-28 21:13:14 +000019#else
20struct StrongWeak {
21#endif
Akira Hatanaka02914dc2018-02-05 20:23:22 +000022 id fstrong;
23 __weak id fweak;
24};
25
Akira Hatanakafcbe17c2018-03-28 21:13:14 +000026#ifdef TRIVIALABI
Akira Hatanakae6313ac2018-04-09 22:48:22 +000027struct __attribute__((trivial_abi)) ContainsStrongWeak {
28#else
29struct ContainsStrongWeak {
30#endif
31 StrongWeak sw;
32};
33
34#ifdef TRIVIALABI
35struct __attribute__((trivial_abi)) DerivedStrongWeak : StrongWeak {
36#else
37struct DerivedStrongWeak : StrongWeak {
38#endif
39};
40
41#ifdef TRIVIALABI
Akira Hatanaka02914dc2018-02-05 20:23:22 +000042struct __attribute__((trivial_abi)) Strong {
Akira Hatanakafcbe17c2018-03-28 21:13:14 +000043#else
44struct Strong {
45#endif
Akira Hatanaka02914dc2018-02-05 20:23:22 +000046 id fstrong;
47};
48
49template<class T>
Akira Hatanakafcbe17c2018-03-28 21:13:14 +000050#ifdef TRIVIALABI
Akira Hatanaka02914dc2018-02-05 20:23:22 +000051struct __attribute__((trivial_abi)) S {
Akira Hatanakafcbe17c2018-03-28 21:13:14 +000052#else
53struct S {
54#endif
Akira Hatanaka02914dc2018-02-05 20:23:22 +000055 T a;
56};
57
Akira Hatanakafcbe17c2018-03-28 21:13:14 +000058struct NonTrivial {
59 NonTrivial();
60 NonTrivial(const NonTrivial &);
61 ~NonTrivial();
62 int *a;
63};
64
65// This struct is not passed directly nor destructed in the callee because f0
66// has type NonTrivial.
67struct ContainsNonTrivial {
68 NonTrivial f0;
69 id f1;
70};
71
Akira Hatanaka02914dc2018-02-05 20:23:22 +000072// CHECK: define void @_Z19testParamStrongWeak10StrongWeak(%[[STRUCT_STRONGWEAK]]* %{{.*}})
Akira Hatanakafcbe17c2018-03-28 21:13:14 +000073// CHECK: call %struct.StrongWeak* @_ZN10StrongWeakD1Ev(
74// CHECK-NEXT: ret void
Akira Hatanaka02914dc2018-02-05 20:23:22 +000075
76void testParamStrongWeak(StrongWeak a) {
77}
78
79// CHECK: define void @_Z18testCallStrongWeakP10StrongWeak(%[[STRUCT_STRONGWEAK]]* %[[A:.*]])
80// CHECK: %[[A_ADDR:.*]] = alloca %[[STRUCT_STRONGWEAK]]*, align 8
81// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONGWEAK]], align 8
82// CHECK: store %[[STRUCT_STRONGWEAK]]* %[[A]], %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8
83// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONGWEAK]]*, %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8
84// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONGWEAK]]* @_ZN10StrongWeakC1ERKS_(%[[STRUCT_STRONGWEAK]]* %[[AGG_TMP]], %[[STRUCT_STRONGWEAK]]* dereferenceable(16) %[[V0]])
85// CHECK: call void @_Z19testParamStrongWeak10StrongWeak(%[[STRUCT_STRONGWEAK]]* %[[AGG_TMP]])
Akira Hatanakafcbe17c2018-03-28 21:13:14 +000086// CHECK-NOT: call
Akira Hatanaka02914dc2018-02-05 20:23:22 +000087// CHECK: ret void
88
89void testCallStrongWeak(StrongWeak *a) {
90 testParamStrongWeak(*a);
91}
92
93// CHECK: define void @_Z20testReturnStrongWeakP10StrongWeak(%[[STRUCT_STRONGWEAK:.*]]* noalias sret %[[AGG_RESULT:.*]], %[[STRUCT_STRONGWEAK]]* %[[A:.*]])
94// CHECK: %[[A_ADDR:.*]] = alloca %[[STRUCT_STRONGWEAK]]*, align 8
95// CHECK: store %[[STRUCT_STRONGWEAK]]* %[[A]], %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8
96// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONGWEAK]]*, %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8
97// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONGWEAK]]* @_ZN10StrongWeakC1ERKS_(%[[STRUCT_STRONGWEAK]]* %[[AGG_RESULT]], %[[STRUCT_STRONGWEAK]]* dereferenceable(16) %[[V0]])
98// CHECK: ret void
99
100StrongWeak testReturnStrongWeak(StrongWeak *a) {
101 return *a;
102}
103
Akira Hatanakae6313ac2018-04-09 22:48:22 +0000104// CHECK: define void @_Z27testParamContainsStrongWeak18ContainsStrongWeak(%[[STRUCT_CONTAINSSTRONGWEAK]]* %[[A:.*]])
105// CHECK: call %[[STRUCT_CONTAINSSTRONGWEAK]]* @_ZN18ContainsStrongWeakD1Ev(%[[STRUCT_CONTAINSSTRONGWEAK]]* %[[A]])
106
107void testParamContainsStrongWeak(ContainsStrongWeak a) {
108}
109
110// CHECK: define void @_Z26testParamDerivedStrongWeak17DerivedStrongWeak(%[[STRUCT_DERIVEDSTRONGWEAK]]* %[[A:.*]])
111// CHECK: call %[[STRUCT_DERIVEDSTRONGWEAK]]* @_ZN17DerivedStrongWeakD1Ev(%[[STRUCT_DERIVEDSTRONGWEAK]]* %[[A]])
112
113void testParamDerivedStrongWeak(DerivedStrongWeak a) {
114}
115
Akira Hatanaka02914dc2018-02-05 20:23:22 +0000116// CHECK: define void @_Z15testParamStrong6Strong(i64 %[[A_COERCE:.*]])
117// CHECK: %[[A:.*]] = alloca %[[STRUCT_STRONG]], align 8
118// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[A]], i32 0, i32 0
119// CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[A_COERCE]] to i8*
120// CHECK: store i8* %[[COERCE_VAL_IP]], i8** %[[COERCE_DIVE]], align 8
121// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONG]]* @_ZN6StrongD1Ev(%[[STRUCT_STRONG]]* %[[A]])
122// CHECK: ret void
123
124// CHECK: define linkonce_odr %[[STRUCT_STRONG]]* @_ZN6StrongD1Ev(
125
126void testParamStrong(Strong a) {
127}
128
129// CHECK: define void @_Z14testCallStrongP6Strong(%[[STRUCT_STRONG]]* %[[A:.*]])
130// CHECK: %[[A_ADDR:.*]] = alloca %[[STRUCT_STRONG]]*, align 8
131// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONG]], align 8
132// CHECK: store %[[STRUCT_STRONG]]* %[[A]], %[[STRUCT_STRONG]]** %[[A_ADDR]], align 8
133// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONG]]*, %[[STRUCT_STRONG]]** %[[A_ADDR]], align 8
134// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONG]]* @_ZN6StrongC1ERKS_(%[[STRUCT_STRONG]]* %[[AGG_TMP]], %[[STRUCT_STRONG]]* dereferenceable(8) %[[V0]])
135// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[AGG_TMP]], i32 0, i32 0
136// CHECK: %[[V1:.*]] = load i8*, i8** %[[COERCE_DIVE]], align 8
137// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i8* %[[V1]] to i64
138// CHECK: call void @_Z15testParamStrong6Strong(i64 %[[COERCE_VAL_PI]])
139// CHECK: ret void
140
141void testCallStrong(Strong *a) {
142 testParamStrong(*a);
143}
144
145// CHECK: define i64 @_Z16testReturnStrongP6Strong(%[[STRUCT_STRONG]]* %[[A:.*]])
Akira Hatanaka02914dc2018-02-05 20:23:22 +0000146// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_STRONG]], align 8
147// CHECK: %[[A_ADDR:.*]] = alloca %[[STRUCT_STRONG]]*, align 8
148// CHECK: store %[[STRUCT_STRONG]]* %[[A]], %[[STRUCT_STRONG]]** %[[A_ADDR]], align 8
149// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONG]]*, %[[STRUCT_STRONG]]** %[[A_ADDR]], align 8
150// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONG]]* @_ZN6StrongC1ERKS_(%[[STRUCT_STRONG]]* %[[RETVAL]], %[[STRUCT_STRONG]]* dereferenceable(8) %[[V0]])
151// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[RETVAL]], i32 0, i32 0
152// CHECK: %[[V1:.*]] = load i8*, i8** %[[COERCE_DIVE]], align 8
153// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i8* %[[V1]] to i64
154// CHECK: ret i64 %[[COERCE_VAL_PI]]
155
156Strong testReturnStrong(Strong *a) {
157 return *a;
158}
159
160// CHECK: define void @_Z21testParamWeakTemplate1SIU6__weakP11objc_objectE(%[[STRUCT_S]]* %{{.*}})
Akira Hatanakafcbe17c2018-03-28 21:13:14 +0000161// CHECK: call %struct.S* @_ZN1SIU6__weakP11objc_objectED1Ev(
162// CHECK-NEXT: ret void
163
164void testParamWeakTemplate(S<__weak id> a) {
165}
166
167// CHECK: define void @_Z27testParamContainsNonTrivial18ContainsNonTrivial(%[[STRUCT_CONTAINSNONTRIVIAL]]* %{{.*}})
Akira Hatanaka02914dc2018-02-05 20:23:22 +0000168// CHECK-NOT: call
169// CHECK: ret void
170
Akira Hatanakafcbe17c2018-03-28 21:13:14 +0000171void testParamContainsNonTrivial(ContainsNonTrivial a) {
172}
173
174// CHECK: define void @_Z26testCallContainsNonTrivialP18ContainsNonTrivial(
175// CHECK: call void @_Z27testParamContainsNonTrivial18ContainsNonTrivial(%[[STRUCT_CONTAINSNONTRIVIAL]]* %{{.*}})
176// CHECK: call %struct.ContainsNonTrivial* @_ZN18ContainsNonTrivialD1Ev(%[[STRUCT_CONTAINSNONTRIVIAL]]* %{{.*}})
177
178void testCallContainsNonTrivial(ContainsNonTrivial *a) {
179 testParamContainsNonTrivial(*a);
Akira Hatanaka02914dc2018-02-05 20:23:22 +0000180}