xref: /aosp_15_r20/external/clang/test/CodeGen/wasm-varargs.c (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 -triple wasm32-unknown-unknown -o - -emit-llvm %s | FileCheck %s
2*67e74705SXin Li 
3*67e74705SXin Li #include <stdarg.h>
4*67e74705SXin Li 
test_i32(char * fmt,...)5*67e74705SXin Li int test_i32(char *fmt, ...) {
6*67e74705SXin Li   va_list va;
7*67e74705SXin Li 
8*67e74705SXin Li   va_start(va, fmt);
9*67e74705SXin Li   int v = va_arg(va, int);
10*67e74705SXin Li   va_end(va);
11*67e74705SXin Li 
12*67e74705SXin Li   return v;
13*67e74705SXin Li }
14*67e74705SXin Li 
15*67e74705SXin Li // CHECK-LABEL: define i32 @test_i32(i8*{{.*}} %fmt, ...) {{.*}} {
16*67e74705SXin Li // CHECK:   [[FMT_ADDR:%[^,=]+]] = alloca i8*, align 4
17*67e74705SXin Li // CHECK:   [[VA:%[^,=]+]] = alloca i8*, align 4
18*67e74705SXin Li // CHECK:   [[V:%[^,=]+]] = alloca i32, align 4
19*67e74705SXin Li // CHECK:   store i8* %fmt, i8** [[FMT_ADDR]], align 4
20*67e74705SXin Li // CHECK:   [[VA1:%[^,=]+]] = bitcast i8** [[VA]] to i8*
21*67e74705SXin Li // CHECK:   call void @llvm.va_start(i8* [[VA1]])
22*67e74705SXin Li // CHECK:   [[ARGP_CUR:%[^,=]+]] = load i8*, i8** [[VA]], align 4
23*67e74705SXin Li // CHECK:   [[ARGP_NEXT:%[^,=]+]] = getelementptr inbounds i8, i8* [[ARGP_CUR]], i32 4
24*67e74705SXin Li // CHECK:   store i8* [[ARGP_NEXT]], i8** [[VA]], align 4
25*67e74705SXin Li // CHECK:   [[R3:%[^,=]+]] = bitcast i8* [[ARGP_CUR]] to i32*
26*67e74705SXin Li // CHECK:   [[R4:%[^,=]+]] = load i32, i32* [[R3]], align 4
27*67e74705SXin Li // CHECK:   store i32 [[R4]], i32* [[V]], align 4
28*67e74705SXin Li // CHECK:   [[VA2:%[^,=]+]] = bitcast i8** [[VA]] to i8*
29*67e74705SXin Li // CHECK:   call void @llvm.va_end(i8* [[VA2]])
30*67e74705SXin Li // CHECK:   [[R5:%[^,=]+]] = load i32, i32* [[V]], align 4
31*67e74705SXin Li // CHECK:   ret i32 [[R5]]
32*67e74705SXin Li // CHECK: }
33*67e74705SXin Li 
test_i64(char * fmt,...)34*67e74705SXin Li long long test_i64(char *fmt, ...) {
35*67e74705SXin Li   va_list va;
36*67e74705SXin Li 
37*67e74705SXin Li   va_start(va, fmt);
38*67e74705SXin Li   long long v = va_arg(va, long long);
39*67e74705SXin Li   va_end(va);
40*67e74705SXin Li 
41*67e74705SXin Li   return v;
42*67e74705SXin Li }
43*67e74705SXin Li 
44*67e74705SXin Li // CHECK-LABEL: define i64 @test_i64(i8*{{.*}} %fmt, ...) {{.*}} {
45*67e74705SXin Li // CHECK:   [[FMT_ADDR:%[^,=]+]] = alloca i8*, align 4
46*67e74705SXin Li // CHECK:   [[VA:%[^,=]+]] = alloca i8*, align 4
47*67e74705SXin Li // CHECK:   [[V:%[^,=]+]] = alloca i64, align 8
48*67e74705SXin Li // CHECK:   store i8* %fmt, i8** [[FMT_ADDR]], align 4
49*67e74705SXin Li // CHECK:   [[VA1:%[^,=]+]] = bitcast i8** [[VA]] to i8*
50*67e74705SXin Li // CHECK:   call void @llvm.va_start(i8* [[VA1]])
51*67e74705SXin Li // CHECK:   [[ARGP_CUR:%[^,=]+]] = load i8*, i8** [[VA]], align 4
52*67e74705SXin Li // CHECK:   [[R0:%[^,=]+]] = ptrtoint i8* [[ARGP_CUR]] to i32
53*67e74705SXin Li // CHECK:   [[R1:%[^,=]+]] = add i32 [[R0]], 7
54*67e74705SXin Li // CHECK:   [[R2:%[^,=]+]] = and i32 [[R1]], -8
55*67e74705SXin Li // CHECK:   [[ARGP_CUR_ALIGNED:%[^,=]+]] = inttoptr i32 [[R2]] to i8*
56*67e74705SXin Li // CHECK:   [[ARGP_NEXT:%[^,=]+]] = getelementptr inbounds i8, i8* [[ARGP_CUR_ALIGNED]], i32 8
57*67e74705SXin Li // CHECK:   store i8* [[ARGP_NEXT]], i8** [[VA]], align 4
58*67e74705SXin Li // CHECK:   [[R3:%[^,=]+]] = bitcast i8* [[ARGP_CUR_ALIGNED]] to i64*
59*67e74705SXin Li // CHECK:   [[R4:%[^,=]+]] = load i64, i64* [[R3]], align 8
60*67e74705SXin Li // CHECK:   store i64 [[R4]], i64* [[V]], align 8
61*67e74705SXin Li // CHECK:   [[VA2:%[^,=]+]] = bitcast i8** [[VA]] to i8*
62*67e74705SXin Li // CHECK:   call void @llvm.va_end(i8* [[VA2]])
63*67e74705SXin Li // CHECK:   [[R5:%[^,=]+]] = load i64, i64* [[V]], align 8
64*67e74705SXin Li // CHECK:   ret i64 [[R5]]
65*67e74705SXin Li // CHECK: }
66*67e74705SXin Li 
67*67e74705SXin Li struct S {
68*67e74705SXin Li     int x;
69*67e74705SXin Li     int y;
70*67e74705SXin Li     int z;
71*67e74705SXin Li };
72*67e74705SXin Li 
test_struct(char * fmt,...)73*67e74705SXin Li struct S test_struct(char *fmt, ...) {
74*67e74705SXin Li   va_list va;
75*67e74705SXin Li 
76*67e74705SXin Li   va_start(va, fmt);
77*67e74705SXin Li   struct S v = va_arg(va, struct S);
78*67e74705SXin Li   va_end(va);
79*67e74705SXin Li 
80*67e74705SXin Li   return v;
81*67e74705SXin Li }
82*67e74705SXin Li 
83*67e74705SXin Li // CHECK: define void @test_struct([[STRUCT_S:%[^,=]+]]*{{.*}} noalias sret %agg.result, i8*{{.*}} %fmt, ...) {{.*}} {
84*67e74705SXin Li // CHECK:   [[FMT_ADDR:%[^,=]+]] = alloca i8*, align 4
85*67e74705SXin Li // CHECK:   [[VA:%[^,=]+]] = alloca i8*, align 4
86*67e74705SXin Li // CHECK:   [[V:%[^,=]+]] = alloca [[STRUCT_S]], align 4
87*67e74705SXin Li // CHECK:   store i8* %fmt, i8** [[FMT_ADDR]], align 4
88*67e74705SXin Li // CHECK:   [[VA1:%[^,=]+]] = bitcast i8** [[VA]] to i8*
89*67e74705SXin Li // CHECK:   call void @llvm.va_start(i8* [[VA1]])
90*67e74705SXin Li // CHECK:   [[ARGP_CUR:%[^,=]+]] = load i8*, i8** [[VA]], align 4
91*67e74705SXin Li // CHECK:   [[ARGP_NEXT:%[^,=]+]] = getelementptr inbounds i8, i8* [[ARGP_CUR]], i32 12
92*67e74705SXin Li // CHECK:   store i8* [[ARGP_NEXT]], i8** [[VA]], align 4
93*67e74705SXin Li // CHECK:   [[R3:%[^,=]+]] = bitcast i8* [[ARGP_CUR]] to [[STRUCT_S]]*
94*67e74705SXin Li // CHECK:   [[R4:%[^,=]+]] = bitcast [[STRUCT_S]]* [[V]] to i8*
95*67e74705SXin Li // CHECK:   [[R5:%[^,=]+]] = bitcast [[STRUCT_S]]* [[R3]] to i8*
96*67e74705SXin Li // CHECK:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[R4]], i8* [[R5]], i32 12, i32 4, i1 false)
97*67e74705SXin Li // CHECK:   [[VA2:%[^,=]+]] = bitcast i8** [[VA]] to i8*
98*67e74705SXin Li // CHECK:   call void @llvm.va_end(i8* [[VA2]])
99*67e74705SXin Li // CHECK:   [[R6:%[^,=]+]] = bitcast [[STRUCT_S]]* %agg.result to i8*
100*67e74705SXin Li // CHECK:   [[R7:%[^,=]+]] = bitcast [[STRUCT_S]]* [[V]] to i8*
101*67e74705SXin Li // CHECK:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[R6]], i8* [[R7]], i32 12, i32 4, i1 false)
102*67e74705SXin Li // CHECK:   ret void
103*67e74705SXin Li // CHECK: }
104