1 // RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fcxx-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s
2 // RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fcxx-exceptions -fexceptions -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s
4 // CHECK: %[[STRUCT_SMALL:.*]] = type { i32* }
5 // CHECK: %[[STRUCT_LARGE:.*]] = type { i32*, [128 x i32] }
6 // CHECK: %[[STRUCT_TRIVIAL:.*]] = type { i32 }
7 // CHECK: %[[STRUCT_NONTRIVIAL:.*]] = type { i32 }
9 struct __attribute__((trivial_abi
)) Small
{
13 Small(const Small
&) noexcept
;
14 Small
&operator=(const Small
&);
17 struct __attribute__((trivial_abi
)) Large
{
22 Large(const Large
&) noexcept
;
23 Large
&operator=(const Large
&);
41 struct HasNonTrivial
{
58 // CHECK-LABEL: define{{.*}} i64 @_ZThn8_N2D02m0Ev(
59 // CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_SMALL]], align 8
60 // CHECK: %[[CALL:.*]] = tail call i64 @_ZN2D02m0Ev(
61 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[RETVAL]], i32 0, i32 0
62 // CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to i32*
63 // CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8
64 // CHECK: %[[COERCE_DIVE2:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[RETVAL]], i32 0, i32 0
65 // CHECK: %[[V3:.*]] = load i32*, i32** %[[COERCE_DIVE2]], align 8
66 // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V3]] to i64
67 // CHECK: ret i64 %[[COERCE_VAL_PI]]
69 Small
D0::m0() { return {}; }
71 // CHECK: define{{.*}} void @_Z14testParamSmall5Small(i64 %[[A_COERCE:.*]])
72 // CHECK: %[[A:.*]] = alloca %[[STRUCT_SMALL]], align 8
73 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[A]], i32 0, i32 0
74 // CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[A_COERCE]] to i32*
75 // CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8
76 // CHECK: %[[CALL:.*]] = call noundef %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* {{[^,]*}} %[[A]])
80 void testParamSmall(Small a
) noexcept
{
83 // CHECK: define{{.*}} i64 @_Z15testReturnSmallv()
84 // CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8
85 // CHECK: %[[CALL:.*]] = call noundef %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* {{[^,]*}} %[[RETVAL]])
86 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[RETVAL]], i32 0, i32 0
87 // CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE]], align 8
88 // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V0]] to i64
89 // CHECK: ret i64 %[[COERCE_VAL_PI]]
92 Small
testReturnSmall() {
97 // CHECK: define{{.*}} void @_Z14testCallSmall0v()
98 // CHECK: %[[T:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8
99 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL]], align 8
100 // CHECK: %[[CALL:.*]] = call noundef %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* {{[^,]*}} %[[T]])
101 // CHECK: %[[CALL1:.*]] = call noundef %[[STRUCT_SMALL]]* @_ZN5SmallC1ERKS_(%[[STRUCT_SMALL]]* {{[^,]*}} %[[AGG_TMP]], %[[STRUCT_SMALL]]* noundef nonnull align 8 dereferenceable(8) %[[T]])
102 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0
103 // CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE]], align 8
104 // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V0]] to i64
105 // CHECK: call void @_Z14testParamSmall5Small(i64 %[[COERCE_VAL_PI]])
106 // CHECK: %[[CALL2:.*]] = call noundef %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* {{[^,]*}} %[[T]])
110 void testCallSmall0() {
115 // CHECK: define{{.*}} void @_Z14testCallSmall1v()
116 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8
117 // CHECK: %[[CALL:.*]] = call i64 @_Z15testReturnSmallv()
118 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0
119 // CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to i32*
120 // CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8
121 // CHECK: %[[COERCE_DIVE1:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0
122 // CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE1]], align 8
123 // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V0]] to i64
124 // CHECK: call void @_Z14testParamSmall5Small(i64 %[[COERCE_VAL_PI]])
128 void testCallSmall1() {
129 testParamSmall(testReturnSmall());
132 // CHECK: define{{.*}} void @_Z16testIgnoredSmallv()
133 // CHECK: %[[AGG_TMP_ENSURED:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8
134 // CHECK: %[[CALL:.*]] = call i64 @_Z15testReturnSmallv()
135 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP_ENSURED]], i32 0, i32 0
136 // CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to i32*
137 // CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8
138 // CHECK: %[[CALL1:.*]] = call noundef %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* {{[^,]*}} %[[AGG_TMP_ENSURED]])
142 void testIgnoredSmall() {
146 // CHECK: define{{.*}} void @_Z14testParamLarge5Large(%[[STRUCT_LARGE:.*]]* noundef %[[A:.*]])
147 // CHECK: %[[CALL:.*]] = call noundef %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* {{[^,]*}} %[[A]])
151 void testParamLarge(Large a
) noexcept
{
154 // CHECK: define{{.*}} void @_Z15testReturnLargev(%[[STRUCT_LARGE:.*]]* noalias sret(%[[STRUCT_LARGE]]) align 8 %[[AGG_RESULT:.*]])
155 // CHECK: %[[CALL:.*]] = call noundef %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* {{[^,]*}} %[[AGG_RESULT]])
159 Large
testReturnLarge() {
164 // CHECK: define{{.*}} void @_Z14testCallLarge0v()
165 // CHECK: %[[T:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8
166 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE]], align 8
167 // CHECK: %[[CALL:.*]] = call noundef %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* {{[^,]*}} %[[T]])
168 // CHECK: %[[CALL1:.*]] = call noundef %[[STRUCT_LARGE]]* @_ZN5LargeC1ERKS_(%[[STRUCT_LARGE]]* {{[^,]*}} %[[AGG_TMP]], %[[STRUCT_LARGE]]* noundef nonnull align 8 dereferenceable(520) %[[T]])
169 // CHECK: call void @_Z14testParamLarge5Large(%[[STRUCT_LARGE]]* noundef %[[AGG_TMP]])
170 // CHECK: %[[CALL2:.*]] = call noundef %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* {{[^,]*}} %[[T]])
174 void testCallLarge0() {
179 // CHECK: define{{.*}} void @_Z14testCallLarge1v()
180 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8
181 // CHECK: call void @_Z15testReturnLargev(%[[STRUCT_LARGE]]* sret(%[[STRUCT_LARGE]]) align 8 %[[AGG_TMP]])
182 // CHECK: call void @_Z14testParamLarge5Large(%[[STRUCT_LARGE]]* noundef %[[AGG_TMP]])
186 void testCallLarge1() {
187 testParamLarge(testReturnLarge());
190 // CHECK: define{{.*}} void @_Z16testIgnoredLargev()
191 // CHECK: %[[AGG_TMP_ENSURED:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8
192 // CHECK: call void @_Z15testReturnLargev(%[[STRUCT_LARGE]]* sret(%[[STRUCT_LARGE]]) align 8 %[[AGG_TMP_ENSURED]])
193 // CHECK: %[[CALL:.*]] = call noundef %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* {{[^,]*}} %[[AGG_TMP_ENSURED]])
197 void testIgnoredLarge() {
201 // CHECK: define{{.*}} i32 @_Z20testReturnHasTrivialv()
202 // CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_TRIVIAL:.*]], align 4
203 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_TRIVIAL]], %[[STRUCT_TRIVIAL]]* %[[RETVAL]], i32 0, i32 0
204 // CHECK: %[[V0:.*]] = load i32, i32* %[[COERCE_DIVE]], align 4
205 // CHECK: ret i32 %[[V0]]
208 Trivial
testReturnHasTrivial() {
213 // CHECK: define{{.*}} void @_Z23testReturnHasNonTrivialv(%[[STRUCT_NONTRIVIAL:.*]]* noalias sret(%[[STRUCT_NONTRIVIAL]]) align 4 %[[AGG_RESULT:.*]])
214 // CHECK: %[[CALL:.*]] = call noundef %[[STRUCT_NONTRIVIAL]]* @_ZN10NonTrivialC1Ev(%[[STRUCT_NONTRIVIAL]]* {{[^,]*}} %[[AGG_RESULT]])
218 NonTrivial
testReturnHasNonTrivial() {
223 // CHECK: define{{.*}} void @_Z18testExceptionSmallv()
224 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL]], align 8
225 // CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_SMALL]], align 8
226 // CHECK: call noundef %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* {{[^,]*}} %[[AGG_TMP]])
227 // CHECK: invoke noundef %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* {{[^,]*}} %[[AGG_TMP1]])
229 // CHECK: call void @_Z20calleeExceptionSmall5SmallS_(i64 %{{.*}}, i64 %{{.*}})
230 // CHECK-NEXT: ret void
232 // CHECK: landingpad { i8*, i32 }
233 // CHECK: call noundef %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* {{[^,]*}} %[[AGG_TMP]])
236 // CHECK: resume { i8*, i32 }
238 void calleeExceptionSmall(Small
, Small
);
240 void testExceptionSmall() {
241 calleeExceptionSmall(Small(), Small());
244 // CHECK: define{{.*}} void @_Z18testExceptionLargev()
245 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE]], align 8
246 // CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_LARGE]], align 8
247 // CHECK: call noundef %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* {{[^,]*}} %[[AGG_TMP]])
248 // CHECK: invoke noundef %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* {{[^,]*}} %[[AGG_TMP1]])
250 // CHECK: call void @_Z20calleeExceptionLarge5LargeS_(%[[STRUCT_LARGE]]* noundef %[[AGG_TMP]], %[[STRUCT_LARGE]]* noundef %[[AGG_TMP1]])
251 // CHECK-NEXT: ret void
253 // CHECK: landingpad { i8*, i32 }
254 // CHECK: call noundef %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* {{[^,]*}} %[[AGG_TMP]])
257 // CHECK: resume { i8*, i32 }
259 void calleeExceptionLarge(Large
, Large
);
261 void testExceptionLarge() {
262 calleeExceptionLarge(Large(), Large());
267 // CHECK: define{{.*}} @"_ZN3$_08__invokeEv"()
268 // CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_SMALL]], align 8
269 // CHECK: %[[COERCE:.*]] = alloca %[[STRUCT_SMALL]], align 8
270 // CHECK: %[[CALL:.*]] = call{{.*}} @"_ZNK3$_0clEv"
271 // CHECK: %[[COERCEDIVE:.*]] = getelementptr{{.*}} %[[COERCE]]
272 // CHECK: %[[COERCEVALIP:.*]] = inttoptr{{.*}} %[[CALL]]
273 // CHECK: %[[RETVALP:.*]] = bitcast %[[STRUCT_SMALL]]* %[[RETVAL]]
274 // CHECK: %[[COERCEP:.*]] = bitcast %[[STRUCT_SMALL]]* %[[COERCE]]
275 // CHECK: call {{.*}}memcpy{{.*}} %[[RETVALP]]{{.*}} %[[COERCEP]]
276 // CHECK: %[[COERCEDIVE1:.*]] = getelementptr{{.*}} %[[RETVAL]]
277 // CHECK: %[[TMP:.*]] = load{{.*}} %[[COERCEDIVE1]]
278 // CHECK: %[[COERCEVALPI:.*]] = ptrtoint{{.*}} %[[TMP]]
279 // CHECK: ret{{.*}} %[[COERCEVALPI]]
281 Small (*fp
)() = []() -> Small
{ return Small(); };