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 |
3 | |
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 } |
8 | |
9 | struct __attribute__((trivial_abi)) Small { |
10 | int *p; |
11 | Small(); |
12 | ~Small(); |
13 | Small(const Small &) noexcept; |
14 | Small &operator=(const Small &); |
15 | }; |
16 | |
17 | struct __attribute__((trivial_abi)) Large { |
18 | int *p; |
19 | int a[128]; |
20 | Large(); |
21 | ~Large(); |
22 | Large(const Large &) noexcept; |
23 | Large &operator=(const Large &); |
24 | }; |
25 | |
26 | struct Trivial { |
27 | int a; |
28 | }; |
29 | |
30 | struct NonTrivial { |
31 | NonTrivial(); |
32 | ~NonTrivial(); |
33 | int a; |
34 | }; |
35 | |
36 | struct HasTrivial { |
37 | Small s; |
38 | Trivial m; |
39 | }; |
40 | |
41 | struct HasNonTrivial { |
42 | Small s; |
43 | NonTrivial m; |
44 | }; |
45 | |
46 | // CHECK: define void @_Z14testParamSmall5Small(i64 %[[A_COERCE:.*]]) |
47 | // CHECK: %[[A:.*]] = alloca %[[STRUCT_SMALL]], align 8 |
48 | // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[A]], i32 0, i32 0 |
49 | // CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[A_COERCE]] to i32* |
50 | // CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8 |
51 | // CHECK: %[[CALL:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[A]]) |
52 | // CHECK: ret void |
53 | // CHECK: } |
54 | |
55 | void testParamSmall(Small a) noexcept { |
56 | } |
57 | |
58 | // CHECK: define i64 @_Z15testReturnSmallv() |
59 | // CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8 |
60 | // CHECK: %[[CALL:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[RETVAL]]) |
61 | // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[RETVAL]], i32 0, i32 0 |
62 | // CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE]], align 8 |
63 | // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V0]] to i64 |
64 | // CHECK: ret i64 %[[COERCE_VAL_PI]] |
65 | // CHECK: } |
66 | |
67 | Small testReturnSmall() { |
68 | Small t; |
69 | return t; |
70 | } |
71 | |
72 | // CHECK: define void @_Z14testCallSmall0v() |
73 | // CHECK: %[[T:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8 |
74 | // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL]], align 8 |
75 | // CHECK: %[[CALL:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[T]]) |
76 | // CHECK: %[[CALL1:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallC1ERKS_(%[[STRUCT_SMALL]]* %[[AGG_TMP]], %[[STRUCT_SMALL]]* dereferenceable(8) %[[T]]) |
77 | // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0 |
78 | // CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE]], align 8 |
79 | // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V0]] to i64 |
80 | // CHECK: call void @_Z14testParamSmall5Small(i64 %[[COERCE_VAL_PI]]) |
81 | // CHECK: %[[CALL2:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[T]]) |
82 | // CHECK: ret void |
83 | // CHECK: } |
84 | |
85 | void testCallSmall0() { |
86 | Small t; |
87 | testParamSmall(t); |
88 | } |
89 | |
90 | // CHECK: define void @_Z14testCallSmall1v() |
91 | // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8 |
92 | // CHECK: %[[CALL:.*]] = call i64 @_Z15testReturnSmallv() |
93 | // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0 |
94 | // CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to i32* |
95 | // CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8 |
96 | // CHECK: %[[COERCE_DIVE1:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0 |
97 | // CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE1]], align 8 |
98 | // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V0]] to i64 |
99 | // CHECK: call void @_Z14testParamSmall5Small(i64 %[[COERCE_VAL_PI]]) |
100 | // CHECK: ret void |
101 | // CHECK: } |
102 | |
103 | void testCallSmall1() { |
104 | testParamSmall(testReturnSmall()); |
105 | } |
106 | |
107 | // CHECK: define void @_Z16testIgnoredSmallv() |
108 | // CHECK: %[[AGG_TMP_ENSURED:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8 |
109 | // CHECK: %[[CALL:.*]] = call i64 @_Z15testReturnSmallv() |
110 | // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP_ENSURED]], i32 0, i32 0 |
111 | // CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to i32* |
112 | // CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8 |
113 | // CHECK: %[[CALL1:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP_ENSURED]]) |
114 | // CHECK: ret void |
115 | // CHECK: } |
116 | |
117 | void testIgnoredSmall() { |
118 | testReturnSmall(); |
119 | } |
120 | |
121 | // CHECK: define void @_Z14testParamLarge5Large(%[[STRUCT_LARGE:.*]]* %[[A:.*]]) |
122 | // CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[A]]) |
123 | // CHECK: ret void |
124 | // CHECK: } |
125 | |
126 | void testParamLarge(Large a) noexcept { |
127 | } |
128 | |
129 | // CHECK: define void @_Z15testReturnLargev(%[[STRUCT_LARGE:.*]]* noalias sret %[[AGG_RESULT:.*]]) |
130 | // CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[AGG_RESULT]]) |
131 | // CHECK: ret void |
132 | // CHECK: } |
133 | |
134 | Large testReturnLarge() { |
135 | Large t; |
136 | return t; |
137 | } |
138 | |
139 | // CHECK: define void @_Z14testCallLarge0v() |
140 | // CHECK: %[[T:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8 |
141 | // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE]], align 8 |
142 | // CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[T]]) |
143 | // CHECK: %[[CALL1:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeC1ERKS_(%[[STRUCT_LARGE]]* %[[AGG_TMP]], %[[STRUCT_LARGE]]* dereferenceable(520) %[[T]]) |
144 | // CHECK: call void @_Z14testParamLarge5Large(%[[STRUCT_LARGE]]* %[[AGG_TMP]]) |
145 | // CHECK: %[[CALL2:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[T]]) |
146 | // CHECK: ret void |
147 | // CHECK: } |
148 | |
149 | void testCallLarge0() { |
150 | Large t; |
151 | testParamLarge(t); |
152 | } |
153 | |
154 | // CHECK: define void @_Z14testCallLarge1v() |
155 | // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8 |
156 | // CHECK: call void @_Z15testReturnLargev(%[[STRUCT_LARGE]]* sret %[[AGG_TMP]]) |
157 | // CHECK: call void @_Z14testParamLarge5Large(%[[STRUCT_LARGE]]* %[[AGG_TMP]]) |
158 | // CHECK: ret void |
159 | // CHECK: } |
160 | |
161 | void testCallLarge1() { |
162 | testParamLarge(testReturnLarge()); |
163 | } |
164 | |
165 | // CHECK: define void @_Z16testIgnoredLargev() |
166 | // CHECK: %[[AGG_TMP_ENSURED:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8 |
167 | // CHECK: call void @_Z15testReturnLargev(%[[STRUCT_LARGE]]* sret %[[AGG_TMP_ENSURED]]) |
168 | // CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP_ENSURED]]) |
169 | // CHECK: ret void |
170 | // CHECK: } |
171 | |
172 | void testIgnoredLarge() { |
173 | testReturnLarge(); |
174 | } |
175 | |
176 | // CHECK: define i64 @_Z20testReturnHasTrivialv() |
177 | // CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_TRIVIAL:.*]], align 4 |
178 | // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_TRIVIAL]], %[[STRUCT_TRIVIAL]]* %[[RETVAL]], i32 0, i32 0 |
179 | // CHECK: %[[V0:.*]] = load i32, i32* %[[COERCE_DIVE]], align 4 |
180 | // CHECK: %[[COERCE_VAL_II:.*]] = zext i32 %[[V0]] to i64 |
181 | // CHECK: ret i64 %[[COERCE_VAL_II]] |
182 | // CHECK: } |
183 | |
184 | Trivial testReturnHasTrivial() { |
185 | Trivial t; |
186 | return t; |
187 | } |
188 | |
189 | // CHECK: define void @_Z23testReturnHasNonTrivialv(%[[STRUCT_NONTRIVIAL:.*]]* noalias sret %[[AGG_RESULT:.*]]) |
190 | // CHECK: %[[CALL:.*]] = call %[[STRUCT_NONTRIVIAL]]* @_ZN10NonTrivialC1Ev(%[[STRUCT_NONTRIVIAL]]* %[[AGG_RESULT]]) |
191 | // CHECK: ret void |
192 | // CHECK: } |
193 | |
194 | NonTrivial testReturnHasNonTrivial() { |
195 | NonTrivial t; |
196 | return t; |
197 | } |
198 | |
199 | // CHECK: define void @_Z18testExceptionSmallv() |
200 | // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL]], align 8 |
201 | // CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_SMALL]], align 8 |
202 | // CHECK: call %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP]]) |
203 | // CHECK: invoke %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP1]]) |
204 | |
205 | // CHECK: call void @_Z20calleeExceptionSmall5SmallS_(i64 %{{.*}}, i64 %{{.*}}) |
206 | // CHECK-NEXT: ret void |
207 | |
208 | // CHECK: landingpad { i8*, i32 } |
209 | // CHECK: call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP]]) |
210 | // CHECK: br |
211 | |
212 | // CHECK: resume { i8*, i32 } |
213 | |
214 | void calleeExceptionSmall(Small, Small); |
215 | |
216 | void testExceptionSmall() { |
217 | calleeExceptionSmall(Small(), Small()); |
218 | } |
219 | |
220 | // CHECK: define void @_Z18testExceptionLargev() |
221 | // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE]], align 8 |
222 | // CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_LARGE]], align 8 |
223 | // CHECK: call %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP]]) |
224 | // CHECK: invoke %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP1]]) |
225 | |
226 | // CHECK: call void @_Z20calleeExceptionLarge5LargeS_(%[[STRUCT_LARGE]]* %[[AGG_TMP]], %[[STRUCT_LARGE]]* %[[AGG_TMP1]]) |
227 | // CHECK-NEXT: ret void |
228 | |
229 | // CHECK: landingpad { i8*, i32 } |
230 | // CHECK: call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP]]) |
231 | // CHECK: br |
232 | |
233 | // CHECK: resume { i8*, i32 } |
234 | |
235 | void calleeExceptionLarge(Large, Large); |
236 | |
237 | void testExceptionLarge() { |
238 | calleeExceptionLarge(Large(), Large()); |
239 | } |
240 | |