[clang] Implement lifetime analysis for lifetime_capture_by(X) (#115921)
[llvm-project.git] / clang / test / CodeGen / arm64_32-vaarg.c
blob3f1f4443436da15fa588e3067bd617a400d6ecc9
1 // RUN: %clang_cc1 -triple arm64_32-apple-ios7.0 -target-abi darwinpcs -emit-llvm -o - -O1 -ffreestanding %s | FileCheck %s
3 #include <stdarg.h>
5 typedef struct {
6 int a;
7 } OneInt;
9 // No realignment should be needed here: slot size is 4 bytes.
10 int test_int(OneInt input, va_list *mylist) {
11 // CHECK-LABEL: define{{.*}} i32 @test_int(i32 %input
12 // CHECK: [[START:%.*]] = load ptr, ptr %mylist
13 // CHECK: [[NEXT:%.*]] = getelementptr inbounds i8, ptr [[START]], i32 4
14 // CHECK: store ptr [[NEXT]], ptr %mylist
16 // CHECK: [[RES:%.*]] = load i32, ptr [[START]]
17 // CHECK: ret i32 [[RES]]
19 return va_arg(*mylist, OneInt).a;
23 typedef struct {
24 long long a;
25 } OneLongLong;
27 // Minimum slot size is 4 bytes, so address needs rounding up to multiple of 8.
28 long long test_longlong(OneLongLong input, va_list *mylist) {
29 // CHECK-LABEL: define{{.*}} i64 @test_longlong(i64 %input
30 // CHECK: [[STARTPTR:%.*]] = load ptr, ptr %mylist
31 // CHECK: [[ALIGN_TMP:%.+]] = getelementptr inbounds i8, ptr [[STARTPTR]], i32 7
32 // CHECK: [[ALIGNED_ADDR:%.+]] = tail call align 8 ptr @llvm.ptrmask.p0.i32(ptr nonnull [[ALIGN_TMP]], i32 -8)
33 // CHECK: [[NEXT:%.*]] = getelementptr inbounds i8, ptr [[ALIGNED_ADDR]], i32 8
34 // CHECK: store ptr [[NEXT]], ptr %mylist
36 // CHECK: [[RES:%.*]] = load i64, ptr [[ALIGNED_ADDR]]
37 // CHECK: ret i64 [[RES]]
39 return va_arg(*mylist, OneLongLong).a;
43 typedef struct {
44 float arr[4];
45 } HFA;
47 // HFAs take priority over passing large structs indirectly.
48 float test_hfa(va_list *mylist) {
49 // CHECK-LABEL: define{{.*}} float @test_hfa
50 // CHECK: [[START:%.*]] = load ptr, ptr %mylist
52 // CHECK: [[NEXT:%.*]] = getelementptr inbounds i8, ptr [[START]], i32 16
53 // CHECK: store ptr [[NEXT]], ptr %mylist
55 // CHECK: [[RES:%.*]] = load float, ptr [[START]]
56 // CHECK: ret float [[RES]]
58 return va_arg(*mylist, HFA).arr[0];
61 // armv7k does not return HFAs normally for variadic functions, so we must match
62 // that.
63 HFA test_hfa_return(int n, ...) {
64 // CHECK-LABEL: define{{.*}} [2 x i64] @test_hfa_return
65 HFA h = {0};
66 return h;
69 typedef struct {
70 long long a, b;
71 char c;
72 } BigStruct;
74 // Structs bigger than 16 bytes are passed indirectly: a pointer is placed on
75 // the stack.
76 long long test_bigstruct(BigStruct input, va_list *mylist) {
77 // CHECK-LABEL: define{{.*}} i64 @test_bigstruct(ptr
78 // CHECK: [[START:%.*]] = load ptr, ptr %mylist
79 // CHECK: [[NEXT:%.*]] = getelementptr inbounds i8, ptr [[START]], i32 4
80 // CHECK: store ptr [[NEXT]], ptr %mylist
82 // CHECK: [[ADDR:%.*]] = load ptr, ptr [[START]]
83 // CHECK: [[RES:%.*]] = load i64, ptr [[ADDR]]
84 // CHECK: ret i64 [[RES]]
86 return va_arg(*mylist, BigStruct).a;
89 typedef struct {
90 short arr[3];
91 } ThreeShorts;
93 // Slot sizes are 4-bytes on arm64_32, so structs with less than 32-bit
94 // alignment must be passed via "[N x i32]" to be correctly allocated in the
95 // backend.
96 short test_threeshorts(ThreeShorts input, va_list *mylist) {
97 // CHECK-LABEL: define{{.*}} signext i16 @test_threeshorts([2 x i32] %input
99 // CHECK: [[START:%.*]] = load ptr, ptr %mylist
100 // CHECK: [[NEXT:%.*]] = getelementptr inbounds i8, ptr [[START]], i32 8
101 // CHECK: store ptr [[NEXT]], ptr %mylist
103 // CHECK: [[RES:%.*]] = load i16, ptr [[START]]
104 // CHECK: ret i16 [[RES]]
106 return va_arg(*mylist, ThreeShorts).arr[0];