1 // RUN: %clang_cc1 -triple loongarch64 -target-feature +f -target-feature +d -target-abi lp64d \
2 // RUN: -emit-llvm %s -o - | FileCheck %s
3
4 /// This test checks the calling convention of the lp64d ABI.
5
6 #include <stddef.h>
7 #include <stdint.h>
8
9 /// Part 0: C Data Types and Alignment.
10
11 /// `char` datatype is signed by default.
12 /// In most cases, the unsigned integer data types are zero-extended when stored
13 /// in general-purpose register, and the signed integer data types are
14 /// sign-extended. However, in the LP64D ABI, unsigned 32-bit types, such as
15 /// unsigned int, are stored in general-purpose registers as proper sign
16 /// extensions of their 32-bit values.
17
18 // CHECK-LABEL: define{{.*}} zeroext i1 @check_bool()
check_bool()19 _Bool check_bool() { return 0; }
20
21 // CHECK-LABEL: define{{.*}} signext i8 @check_char()
check_char()22 char check_char() { return 0; }
23
24 // CHECK-LABEL: define{{.*}} signext i16 @check_short()
check_short()25 short check_short() { return 0; }
26
27 // CHECK-LABEL: define{{.*}} signext i32 @check_int()
check_int()28 int check_int() { return 0; }
29
30 // CHECK-LABEL: define{{.*}} i64 @check_long()
check_long()31 long check_long() { return 0; }
32
33 // CHECK-LABEL: define{{.*}} i64 @check_longlong()
check_longlong()34 long long check_longlong() { return 0; }
35
36 // CHECK-LABEL: define{{.*}} zeroext i8 @check_uchar()
check_uchar()37 unsigned char check_uchar() { return 0; }
38
39 // CHECK-LABEL: define{{.*}} zeroext i16 @check_ushort()
check_ushort()40 unsigned short check_ushort() { return 0; }
41
42 // CHECK-LABEL: define{{.*}} signext i32 @check_uint()
check_uint()43 unsigned int check_uint() { return 0; }
44
45 // CHECK-LABEL: define{{.*}} i64 @check_ulong()
check_ulong()46 unsigned long check_ulong() { return 0; }
47
48 // CHECK-LABEL: define{{.*}} i64 @check_ulonglong()
check_ulonglong()49 unsigned long long check_ulonglong() { return 0; }
50
51 // CHECK-LABEL: define{{.*}} float @check_float()
check_float()52 float check_float() { return 0; }
53
54 // CHECK-LABEL: define{{.*}} double @check_double()
check_double()55 double check_double() { return 0; }
56
57 // CHECK-LABEL: define{{.*}} fp128 @check_longdouble()
check_longdouble()58 long double check_longdouble() { return 0; }
59
60 /// Part 1: Scalar arguments and return value.
61
62 /// 1. 1 < WOA <= GRLEN
63 /// a. Argument is passed in a single argument register, or on the stack by
64 /// value if none is available.
65 /// i. If the argument is floating-point type, the argument is passed in FAR. if
66 /// no FAR is available, it’s passed in GAR. If no GAR is available, it’s
67 /// passed on the stack. When passed in registers or on the stack,
68 /// floating-point types narrower than GRLEN bits are widened to GRLEN bits,
69 /// with the upper bits undefined.
70 /// ii. If the argument is integer or pointer type, the argument is passed in
71 /// GAR. If no GAR is available, it’s passed on the stack. When passed in
72 /// registers or on the stack, the unsigned integer scalars narrower than GRLEN
73 /// bits are zero-extended to GRLEN bits, and the signed integer scalars are
74 /// sign-extended.
75 /// 2. GRLEN < WOA ≤ 2 × GRLEN
76 /// a. The argument is passed in a pair of GAR, with the low-order GRLEN bits in
77 /// the lower-numbered register and the high-order GRLEN bits in the
78 /// higher-numbered register. If exactly one register is available, the
79 /// low-order GRLEN bits are passed in the register and the high-order GRLEN
80 /// bits are passed on the stack. If no GAR is available, it’s passed on the
81 /// stack.
82
83 /// Note that most of these conventions are handled by the backend, so here we
84 /// only check the correctness of argument (or return value)'s sign/zero
85 /// extension attribute.
86
87 // CHECK-LABEL: define{{.*}} signext i32 @f_scalar(i1 noundef zeroext %a, i8 noundef signext %b, i8 noundef zeroext %c, i16 noundef signext %d, i16 noundef zeroext %e, i32 noundef signext %f, i32 noundef signext %g, i64 noundef %h, i1 noundef zeroext %i, i8 noundef signext %j, i8 noundef zeroext %k, i16 noundef signext %l, i16 noundef zeroext %m, i32 noundef signext %n, i32 noundef signext %o, i64 noundef %p)
f_scalar(_Bool a,int8_t b,uint8_t c,int16_t d,uint16_t e,int32_t f,uint32_t g,int64_t h,_Bool i,int8_t j,uint8_t k,int16_t l,uint16_t m,int32_t n,uint32_t o,int64_t p)88 int f_scalar(_Bool a, int8_t b, uint8_t c, int16_t d, uint16_t e, int32_t f,
89 uint32_t g, int64_t h, _Bool i, int8_t j, uint8_t k, int16_t l,
90 uint16_t m, int32_t n, uint32_t o, int64_t p) {
91 return 0;
92 }
93
94 /// Part 2: Structure arguments and return value.
95
96 /// Empty structures are ignored by C compilers which support them as a
97 /// non-standard extension(same as union arguments and return values). Bits
98 /// unused due to padding, and bits past the end of a structure whose size in
99 /// bits is not divisible by GRLEN, are undefined. And the layout of the
100 /// structure on the stack is consistent with that in memory.
101
102 /// Check empty structs are ignored.
103
104 struct empty_s {};
105
106 // CHECK-LABEL: define{{.*}} void @f_empty_s()
f_empty_s(struct empty_s x)107 struct empty_s f_empty_s(struct empty_s x) {
108 return x;
109 }
110
111 /// 1. 0 < WOA ≤ GRLEN
112 /// a. The structure has only fixed-point members. If there is an available GAR,
113 /// the structure is passed through the GAR by value passing; If no GAR is
114 /// available, it’s passed on the stack.
115
116 struct i16x4_s {
117 int16_t a, b, c, d;
118 };
119
120 // CHECK-LABEL: define{{.*}} i64 @f_i16x4_s(i64 %x.coerce)
f_i16x4_s(struct i16x4_s x)121 struct i16x4_s f_i16x4_s(struct i16x4_s x) {
122 return x;
123 }
124
125 /// b. The structure has only floating-point members:
126 /// i. One floating-point member. The argument is passed in a FAR; If no FAR is
127 /// available, the value is passed in a GAR; if no GAR is available, the value
128 /// is passed on the stack.
129
130 struct f32x1_s {
131 float a;
132 };
133
134 struct f64x1_s {
135 double a;
136 };
137
138 // CHECK-LABEL: define{{.*}} float @f_f32x1_s(float %0)
f_f32x1_s(struct f32x1_s x)139 struct f32x1_s f_f32x1_s(struct f32x1_s x) {
140 return x;
141 }
142
143 // CHECK-LABEL: define{{.*}} double @f_f64x1_s(double %0)
f_f64x1_s(struct f64x1_s x)144 struct f64x1_s f_f64x1_s(struct f64x1_s x) {
145 return x;
146 }
147
148 /// ii. Two floating-point members. The argument is passed in a pair of
149 /// available FAR, with the low-order float member bits in the lower-numbered
150 /// FAR and the high-order float member bits in the higher-numbered FAR. If the
151 /// number of available FAR is less than 2, it’s passed in a GAR, and passed on
152 /// the stack if no GAR is available.
153
154 struct f32x2_s {
155 float a, b;
156 };
157
158 // CHECK-LABEL: define{{.*}} { float, float } @f_f32x2_s(float %0, float %1)
f_f32x2_s(struct f32x2_s x)159 struct f32x2_s f_f32x2_s(struct f32x2_s x) {
160 return x;
161 }
162
163 /// c. The structure has both fixed-point and floating-point members, i.e. the
164 /// structure has one float member and...
165 /// i. Multiple fixed-point members. If there are available GAR, the structure
166 /// is passed in a GAR, and passed on the stack if no GAR is available.
167
168 struct f32x1_i16x2_s {
169 float a;
170 int16_t b, c;
171 };
172
173 // CHECK-LABEL: define{{.*}} i64 @f_f32x1_i16x2_s(i64 %x.coerce)
f_f32x1_i16x2_s(struct f32x1_i16x2_s x)174 struct f32x1_i16x2_s f_f32x1_i16x2_s(struct f32x1_i16x2_s x) {
175 return x;
176 }
177
178 /// ii. Only one fixed-point member. If one FAR and one GAR are available, the
179 /// floating-point member of the structure is passed in the FAR, and the integer
180 /// member of the structure is passed in the GAR; If no floating-point register
181 /// but one GAR is available, it’s passed in GAR; If no GAR is available, it’s
182 /// passed on the stack.
183
184 struct f32x1_i32x1_s {
185 float a;
186 int32_t b;
187 };
188
189 // CHECK-LABEL: define{{.*}} { float, i32 } @f_f32x1_i32x1_s(float %0, i32 %1)
f_f32x1_i32x1_s(struct f32x1_i32x1_s x)190 struct f32x1_i32x1_s f_f32x1_i32x1_s(struct f32x1_i32x1_s x) {
191 return x;
192 }
193
194 /// 2. GRLEN < WOA ≤ 2 × GRLEN
195 /// a. Only fixed-point members.
196 /// i. The argument is passed in a pair of available GAR, with the low-order
197 /// bits in the lower-numbered GAR and the high-order bits in the
198 /// higher-numbered GAR. If only one GAR is available, the low-order bits are in
199 /// the GAR and the high-order bits are on the stack, and passed on the stack if
200 /// no GAR is available.
201
202 struct i64x2_s {
203 int64_t a, b;
204 };
205
206 // CHECK-LABEL: define{{.*}} [2 x i64] @f_i64x2_s([2 x i64] %x.coerce)
f_i64x2_s(struct i64x2_s x)207 struct i64x2_s f_i64x2_s(struct i64x2_s x) {
208 return x;
209 }
210
211 /// b. Only floating-point members.
212 /// i. The structure has one long double member or one double member and two
213 /// adjacent float members or 3-4 float members. The argument is passed in a
214 /// pair of available GAR, with the low-order bits in the lower-numbered GAR and
215 /// the high-order bits in the higher-numbered GAR. If only one GAR is
216 /// available, the low-order bits are in the GAR and the high-order bits are on
217 /// the stack, and passed on the stack if no GAR is available.
218
219 struct f128x1_s {
220 long double a;
221 };
222
223 // CHECK-LABEL: define{{.*}} i128 @f_f128x1_s(i128 %x.coerce)
f_f128x1_s(struct f128x1_s x)224 struct f128x1_s f_f128x1_s(struct f128x1_s x) {
225 return x;
226 }
227
228 struct f64x1_f32x2_s {
229 double a;
230 float b, c;
231 };
232
233 // CHECK-LABEL: define{{.*}} [2 x i64] @f_f64x1_f32x2_s([2 x i64] %x.coerce)
f_f64x1_f32x2_s(struct f64x1_f32x2_s x)234 struct f64x1_f32x2_s f_f64x1_f32x2_s(struct f64x1_f32x2_s x) {
235 return x;
236 }
237
238 struct f32x3_s {
239 float a, b, c;
240 };
241
242 // CHECK-LABEL: define{{.*}} [2 x i64] @f_f32x3_s([2 x i64] %x.coerce)
f_f32x3_s(struct f32x3_s x)243 struct f32x3_s f_f32x3_s(struct f32x3_s x) {
244 return x;
245 }
246
247 struct f32x4_s {
248 float a, b, c, d;
249 };
250
251 // CHECK-LABEL: define{{.*}} [2 x i64] @f_f32x4_s([2 x i64] %x.coerce)
f_f32x4_s(struct f32x4_s x)252 struct f32x4_s f_f32x4_s(struct f32x4_s x) {
253 return x;
254 }
255
256 /// ii. The structure with two double members is passed in a pair of available
257 /// FARs. If no a pair of available FARs, it’s passed in GARs. A structure with
258 /// one double member and one float member is same.
259
260 struct f64x2_s {
261 double a, b;
262 };
263
264 // CHECK-LABEL: define{{.*}} { double, double } @f_f64x2_s(double %0, double %1)
f_f64x2_s(struct f64x2_s x)265 struct f64x2_s f_f64x2_s(struct f64x2_s x) {
266 return x;
267 }
268
269 /// c. Both fixed-point and floating-point members.
270 /// i. The structure has one double member and only one fixed-point member.
271 /// A. If one FAR and one GAR are available, the floating-point member of the
272 /// structure is passed in the FAR, and the integer member of the structure is
273 /// passed in the GAR; If no floating-point registers but two GARs are
274 /// available, it’s passed in the two GARs; If only one GAR is available, the
275 /// low-order bits are in the GAR and the high-order bits are on the stack; And
276 /// it’s passed on the stack if no GAR is available.
277
278 struct f64x1_i64x1_s {
279 double a;
280 int64_t b;
281 };
282
283 // CHECK-LABEL: define{{.*}} { double, i64 } @f_f64x1_i64x1_s(double %0, i64 %1)
f_f64x1_i64x1_s(struct f64x1_i64x1_s x)284 struct f64x1_i64x1_s f_f64x1_i64x1_s(struct f64x1_i64x1_s x) {
285 return x;
286 }
287
288 /// ii. Others
289 /// A. The argument is passed in a pair of available GAR, with the low-order
290 /// bits in the lower-numbered GAR and the high-order bits in the
291 /// higher-numbered GAR. If only one GAR is available, the low-order bits are in
292 /// the GAR and the high-order bits are on the stack, and passed on the stack if
293 /// no GAR is available.
294
295 struct f64x1_i32x2_s {
296 double a;
297 int32_t b, c;
298 };
299
300 // CHECK-LABEL: define{{.*}} [2 x i64] @f_f64x1_i32x2_s([2 x i64] %x.coerce)
f_f64x1_i32x2_s(struct f64x1_i32x2_s x)301 struct f64x1_i32x2_s f_f64x1_i32x2_s(struct f64x1_i32x2_s x) {
302 return x;
303 }
304
305 struct f32x2_i32x2_s {
306 float a, b;
307 int32_t c, d;
308 };
309
310 // CHECK-LABEL: define{{.*}} [2 x i64] @f_f32x2_i32x2_s([2 x i64] %x.coerce)
f_f32x2_i32x2_s(struct f32x2_i32x2_s x)311 struct f32x2_i32x2_s f_f32x2_i32x2_s(struct f32x2_i32x2_s x) {
312 return x;
313 }
314
315 /// 3. WOA > 2 × GRLEN
316 /// a. It’s passed by reference and are replaced in the argument list with the
317 /// address. If there is an available GAR, the reference is passed in the GAR,
318 /// and passed on the stack if no GAR is available.
319
320 struct i64x4_s {
321 int64_t a, b, c, d;
322 };
323
324 // CHECK-LABEL: define{{.*}} void @f_i64x4_s(ptr{{.*}} sret(%struct.i64x4_s) align 8 %agg.result, ptr{{.*}} %x)
f_i64x4_s(struct i64x4_s x)325 struct i64x4_s f_i64x4_s(struct i64x4_s x) {
326 return x;
327 }
328
329 struct f64x4_s {
330 double a, b, c, d;
331 };
332
333 // CHECK-LABEL: define{{.*}} void @f_f64x4_s(ptr{{.*}} sret(%struct.f64x4_s) align 8 %agg.result, ptr{{.*}} %x)
f_f64x4_s(struct f64x4_s x)334 struct f64x4_s f_f64x4_s(struct f64x4_s x) {
335 return x;
336 }
337
338 /// Part 3: Union arguments and return value.
339
340 /// Check empty unions are ignored.
341
342 union empty_u {};
343
344 // CHECK-LABEL: define{{.*}} void @f_empty_u()
f_empty_u(union empty_u x)345 union empty_u f_empty_u(union empty_u x) {
346 return x;
347 }
348
349 /// Union is passed in GAR or stack.
350 /// 1. 0 < WOA ≤ GRLEN
351 /// a. The argument is passed in a GAR, or on the stack by value if no GAR is
352 /// available.
353
354 union i32_f32_u {
355 int32_t a;
356 float b;
357 };
358
359 // CHECK-LABEL: define{{.*}} i64 @f_i32_f32_u(i64 %x.coerce)
f_i32_f32_u(union i32_f32_u x)360 union i32_f32_u f_i32_f32_u(union i32_f32_u x) {
361 return x;
362 }
363
364 union i64_f64_u {
365 int64_t a;
366 double b;
367 };
368
369 // CHECK-LABEL: define{{.*}} i64 @f_i64_f64_u(i64 %x.coerce)
f_i64_f64_u(union i64_f64_u x)370 union i64_f64_u f_i64_f64_u(union i64_f64_u x) {
371 return x;
372 }
373
374 /// 2. GRLEN < WOA ≤ 2 × GRLEN
375 /// a. The argument is passed in a pair of available GAR, with the low-order
376 /// bits in the lower-numbered GAR and the high-order bits in the
377 /// higher-numbered GAR. If only one GAR is available, the low-order bits are in
378 /// the GAR and the high-order bits are on the stack. The arguments are passed
379 /// on the stack when no GAR is available.
380
381 union i128_f128_u {
382 __int128_t a;
383 long double b;
384 };
385
386 // CHECK-LABEL: define{{.*}} i128 @f_i128_f128_u(i128 %x.coerce)
f_i128_f128_u(union i128_f128_u x)387 union i128_f128_u f_i128_f128_u(union i128_f128_u x) {
388 return x;
389 }
390
391 /// 3. WOA > 2 × GRLEN
392 /// a. It’s passed by reference and are replaced in the argument list with the
393 /// address. If there is an available GAR, the reference is passed in the GAR,
394 /// and passed on the stack if no GAR is available.
395
396 union i64_arr3_u {
397 int64_t a[3];
398 };
399
400 // CHECK-LABEL: define{{.*}} void @f_i64_arr3_u(ptr{{.*}} sret(%union.i64_arr3_u) align 8 %agg.result, ptr{{.*}} %x)
f_i64_arr3_u(union i64_arr3_u x)401 union i64_arr3_u f_i64_arr3_u(union i64_arr3_u x) {
402 return x;
403 }
404
405 /// Part 4: Complex number arguments and return value.
406
407 /// A complex floating-point number, or a structure containing just one complex
408 /// floating-point number, is passed as though it were a structure containing
409 /// two floating-point reals.
410
411 // CHECK-LABEL: define{{.*}} { float, float } @f_floatcomplex(float noundef %x.coerce0, float noundef %x.coerce1)
f_floatcomplex(float __complex__ x)412 float __complex__ f_floatcomplex(float __complex__ x) { return x; }
413
414 // CHECK-LABEL: define{{.*}} { double, double } @f_doublecomplex(double noundef %x.coerce0, double noundef %x.coerce1)
f_doublecomplex(double __complex__ x)415 double __complex__ f_doublecomplex(double __complex__ x) { return x; }
416
417 struct floatcomplex_s {
418 float __complex__ c;
419 };
420 // CHECK-LABEL: define{{.*}} { float, float } @f_floatcomplex_s(float %0, float %1)
f_floatcomplex_s(struct floatcomplex_s x)421 struct floatcomplex_s f_floatcomplex_s(struct floatcomplex_s x) {
422 return x;
423 }
424
425 struct doublecomplex_s {
426 double __complex__ c;
427 };
428 // CHECK-LABEL: define{{.*}} { double, double } @f_doublecomplex_s(double %0, double %1)
f_doublecomplex_s(struct doublecomplex_s x)429 struct doublecomplex_s f_doublecomplex_s(struct doublecomplex_s x) {
430 return x;
431 }
432
433 /// Part 5: Variadic arguments.
434
435 /// Variadic arguments are passed in GARs in the same manner as named arguments.
436
437 int f_va_callee(int, ...);
438
439 // CHECK-LABEL: define{{.*}} void @f_va_caller()
440 // CHECK: call signext i32 (i32, ...) @f_va_callee(i32 noundef signext 1, i32 noundef signext 2, i64 noundef 3, double noundef 4.000000e+00, double noundef 5.000000e+00, i64 {{.*}}, [2 x i64] {{.*}})
f_va_caller(void)441 void f_va_caller(void) {
442 f_va_callee(1, 2, 3LL, 4.0f, 5.0, (struct i16x4_s){6, 7, 8, 9},
443 (struct i64x2_s){10, 11});
444 }
445
446 // CHECK-LABEL: @f_va_int(
447 // CHECK-NEXT: entry:
448 // CHECK-NEXT: [[FMT_ADDR:%.*]] = alloca ptr, align 8
449 // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 8
450 // CHECK-NEXT: [[V:%.*]] = alloca i32, align 4
451 // CHECK-NEXT: store ptr [[FMT:%.*]], ptr [[FMT_ADDR]], align 8
452 // CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]])
453 // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 8
454 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8
455 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 8
456 // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARGP_CUR]], align 8
457 // CHECK-NEXT: store i32 [[TMP0]], ptr [[V]], align 4
458 // CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]])
459 // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[V]], align 4
460 // CHECK-NEXT: ret i32 [[TMP1]]
f_va_int(char * fmt,...)461 int f_va_int(char *fmt, ...) {
462 __builtin_va_list va;
463 __builtin_va_start(va, fmt);
464 int v = __builtin_va_arg(va, int);
465 __builtin_va_end(va);
466 return v;
467 }
468
469 /// Part 6. Structures with zero size fields (bitfields or arrays).
470
471 /// Check that zero size fields in structure are ignored.
472 /// Note that this rule is not explicitly documented in ABI spec but it matches
473 /// GCC's behavior.
474
475 struct f64x2_zsfs_s {
476 double a;
477 int : 0;
478 __int128_t : 0;
479 int b[0];
480 __int128_t c[0];
481 double d;
482 };
483
484 // CHECK-LABEL: define{{.*}} { double, double } @f_f64x2_zsfs_s(double %0, double %1)
f_f64x2_zsfs_s(struct f64x2_zsfs_s x)485 struct f64x2_zsfs_s f_f64x2_zsfs_s(struct f64x2_zsfs_s x) {
486 return x;
487 }
488
489