xref: /aosp_15_r20/external/llvm/test/CodeGen/WebAssembly/varargs.ll (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -verify-machineinstrs | FileCheck %s
2*9880d681SAndroid Build Coastguard Worker
3*9880d681SAndroid Build Coastguard Worker; Test varargs constructs.
4*9880d681SAndroid Build Coastguard Worker
5*9880d681SAndroid Build Coastguard Workertarget datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
6*9880d681SAndroid Build Coastguard Workertarget triple = "wasm32-unknown-unknown"
7*9880d681SAndroid Build Coastguard Worker
8*9880d681SAndroid Build Coastguard Worker; Test va_start.
9*9880d681SAndroid Build Coastguard Worker
10*9880d681SAndroid Build Coastguard Worker; TODO: Test va_start.
11*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: start:
12*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .param i32, i32
13*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: __stack_pointer
14*9880d681SAndroid Build Coastguard Workerdefine void @start(i8** %ap, ...) {
15*9880d681SAndroid Build Coastguard Workerentry:
16*9880d681SAndroid Build Coastguard Worker  %0 = bitcast i8** %ap to i8*
17*9880d681SAndroid Build Coastguard Worker; Store the second argument (the hidden vararg buffer pointer) into ap
18*9880d681SAndroid Build Coastguard Worker; CHECK: i32.store $drop=, 0($0), $1
19*9880d681SAndroid Build Coastguard Worker  call void @llvm.va_start(i8* %0)
20*9880d681SAndroid Build Coastguard Worker  ret void
21*9880d681SAndroid Build Coastguard Worker}
22*9880d681SAndroid Build Coastguard Worker
23*9880d681SAndroid Build Coastguard Worker; Test va_end.
24*9880d681SAndroid Build Coastguard Worker
25*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: end:
26*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .param i32{{$}}
27*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: return{{$}}
28*9880d681SAndroid Build Coastguard Workerdefine void @end(i8** %ap) {
29*9880d681SAndroid Build Coastguard Workerentry:
30*9880d681SAndroid Build Coastguard Worker  %0 = bitcast i8** %ap to i8*
31*9880d681SAndroid Build Coastguard Worker  call void @llvm.va_end(i8* %0)
32*9880d681SAndroid Build Coastguard Worker  ret void
33*9880d681SAndroid Build Coastguard Worker}
34*9880d681SAndroid Build Coastguard Worker
35*9880d681SAndroid Build Coastguard Worker; Test va_copy.
36*9880d681SAndroid Build Coastguard Worker
37*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: copy:
38*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .param i32, i32{{$}}
39*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: i32.load  $push0=, 0($1){{$}}
40*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: i32.store $drop=, 0($0), $pop0{{$}}
41*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: return{{$}}
42*9880d681SAndroid Build Coastguard Workerdefine void @copy(i8** %ap, i8** %bp) {
43*9880d681SAndroid Build Coastguard Workerentry:
44*9880d681SAndroid Build Coastguard Worker  %0 = bitcast i8** %ap to i8*
45*9880d681SAndroid Build Coastguard Worker  %1 = bitcast i8** %bp to i8*
46*9880d681SAndroid Build Coastguard Worker  call void @llvm.va_copy(i8* %0, i8* %1)
47*9880d681SAndroid Build Coastguard Worker  ret void
48*9880d681SAndroid Build Coastguard Worker}
49*9880d681SAndroid Build Coastguard Worker
50*9880d681SAndroid Build Coastguard Worker; Test va_arg with an i8 argument.
51*9880d681SAndroid Build Coastguard Worker
52*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: arg_i8:
53*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .param     i32{{$}}
54*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .result    i32{{$}}
55*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .local     i32{{$}}
56*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: i32.load   $push[[NUM0:[0-9]+]]=, 0($0){{$}}
57*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: tee_local  $push[[NUM1:[0-9]+]]=, $1=, $pop[[NUM0]]{{$}}
58*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: i32.const  $push[[NUM2:[0-9]+]]=, 4{{$}}
59*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: i32.add    $push[[NUM3:[0-9]+]]=, $pop[[NUM1]], $pop[[NUM2]]{{$}}
60*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: i32.store  $drop=, 0($0), $pop[[NUM3]]{{$}}
61*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: i32.load   $push[[NUM4:[0-9]+]]=, 0($1){{$}}
62*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: return     $pop[[NUM4]]{{$}}
63*9880d681SAndroid Build Coastguard Workerdefine i8 @arg_i8(i8** %ap) {
64*9880d681SAndroid Build Coastguard Workerentry:
65*9880d681SAndroid Build Coastguard Worker  %t = va_arg i8** %ap, i8
66*9880d681SAndroid Build Coastguard Worker  ret i8 %t
67*9880d681SAndroid Build Coastguard Worker}
68*9880d681SAndroid Build Coastguard Worker
69*9880d681SAndroid Build Coastguard Worker; Test va_arg with an i32 argument.
70*9880d681SAndroid Build Coastguard Worker
71*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: arg_i32:
72*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .param     i32{{$}}
73*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .result    i32{{$}}
74*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .local     i32{{$}}
75*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: i32.load   $push[[NUM0:[0-9]+]]=, 0($0){{$}}
76*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: i32.const  $push[[NUM1:[0-9]+]]=, 3{{$}}
77*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: i32.add    $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $pop[[NUM1]]{{$}}
78*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: i32.const  $push[[NUM3:[0-9]+]]=, -4{{$}}
79*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: i32.and    $push[[NUM4:[0-9]+]]=, $pop[[NUM2]], $pop[[NUM3]]{{$}}
80*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: tee_local  $push[[NUM5:[0-9]+]]=, $1=, $pop[[NUM4]]{{$}}
81*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: i32.const  $push[[NUM6:[0-9]+]]=, 4{{$}}
82*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: i32.add    $push[[NUM7:[0-9]+]]=, $pop[[NUM5]], $pop[[NUM6]]{{$}}
83*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: i32.store  $drop=, 0($0), $pop[[NUM7]]{{$}}
84*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: i32.load   $push[[NUM8:[0-9]+]]=, 0($1){{$}}
85*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: return     $pop[[NUM8]]{{$}}
86*9880d681SAndroid Build Coastguard Workerdefine i32 @arg_i32(i8** %ap) {
87*9880d681SAndroid Build Coastguard Workerentry:
88*9880d681SAndroid Build Coastguard Worker  %t = va_arg i8** %ap, i32
89*9880d681SAndroid Build Coastguard Worker  ret i32 %t
90*9880d681SAndroid Build Coastguard Worker}
91*9880d681SAndroid Build Coastguard Worker
92*9880d681SAndroid Build Coastguard Worker; Test va_arg with an i128 argument.
93*9880d681SAndroid Build Coastguard Worker
94*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: arg_i128:
95*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .param i32, i32{{$}}
96*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .local
97*9880d681SAndroid Build Coastguard Worker; CHECK: i32.and
98*9880d681SAndroid Build Coastguard Worker; CHECK: i64.load
99*9880d681SAndroid Build Coastguard Worker; CHECK: i64.load
100*9880d681SAndroid Build Coastguard Worker; CHECK: return{{$}}
101*9880d681SAndroid Build Coastguard Workerdefine i128 @arg_i128(i8** %ap) {
102*9880d681SAndroid Build Coastguard Workerentry:
103*9880d681SAndroid Build Coastguard Worker  %t = va_arg i8** %ap, i128
104*9880d681SAndroid Build Coastguard Worker  ret i128 %t
105*9880d681SAndroid Build Coastguard Worker}
106*9880d681SAndroid Build Coastguard Worker
107*9880d681SAndroid Build Coastguard Worker; Test a varargs call with no actual arguments.
108*9880d681SAndroid Build Coastguard Worker
109*9880d681SAndroid Build Coastguard Workerdeclare void @callee(...)
110*9880d681SAndroid Build Coastguard Worker
111*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: caller_none:
112*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: i32.const $push0=, 0
113*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: call callee@FUNCTION, $pop0
114*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: return{{$}}
115*9880d681SAndroid Build Coastguard Workerdefine void @caller_none() {
116*9880d681SAndroid Build Coastguard Worker  call void (...) @callee()
117*9880d681SAndroid Build Coastguard Worker  ret void
118*9880d681SAndroid Build Coastguard Worker}
119*9880d681SAndroid Build Coastguard Worker
120*9880d681SAndroid Build Coastguard Worker; Test a varargs call with some actual arguments.
121*9880d681SAndroid Build Coastguard Worker; Note that the store of 2.0 is converted to an i64 store; this optimization
122*9880d681SAndroid Build Coastguard Worker; is not needed on WebAssembly, but there isn't currently a convenient hook for
123*9880d681SAndroid Build Coastguard Worker; disabling it.
124*9880d681SAndroid Build Coastguard Worker
125*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: caller_some
126*9880d681SAndroid Build Coastguard Worker; CHECK: i32.store
127*9880d681SAndroid Build Coastguard Worker; CHECK: i64.store
128*9880d681SAndroid Build Coastguard Workerdefine void @caller_some() {
129*9880d681SAndroid Build Coastguard Worker  call void (...) @callee(i32 0, double 2.0)
130*9880d681SAndroid Build Coastguard Worker  ret void
131*9880d681SAndroid Build Coastguard Worker}
132*9880d681SAndroid Build Coastguard Worker
133*9880d681SAndroid Build Coastguard Worker; Test a va_start call in a non-entry block
134*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: startbb:
135*9880d681SAndroid Build Coastguard Worker; CHECK: .param i32, i32, i32
136*9880d681SAndroid Build Coastguard Workerdefine void @startbb(i1 %cond, i8** %ap, ...) {
137*9880d681SAndroid Build Coastguard Workerentry:
138*9880d681SAndroid Build Coastguard Worker  br i1 %cond, label %bb0, label %bb1
139*9880d681SAndroid Build Coastguard Workerbb0:
140*9880d681SAndroid Build Coastguard Worker  ret void
141*9880d681SAndroid Build Coastguard Workerbb1:
142*9880d681SAndroid Build Coastguard Worker  %0 = bitcast i8** %ap to i8*
143*9880d681SAndroid Build Coastguard Worker; Store the second argument (the hidden vararg buffer pointer) into ap
144*9880d681SAndroid Build Coastguard Worker; CHECK: i32.store $drop=, 0($1), $2
145*9880d681SAndroid Build Coastguard Worker  call void @llvm.va_start(i8* %0)
146*9880d681SAndroid Build Coastguard Worker  ret void
147*9880d681SAndroid Build Coastguard Worker}
148*9880d681SAndroid Build Coastguard Worker
149*9880d681SAndroid Build Coastguard Worker
150*9880d681SAndroid Build Coastguard Workerdeclare void @llvm.va_start(i8*)
151*9880d681SAndroid Build Coastguard Workerdeclare void @llvm.va_end(i8*)
152*9880d681SAndroid Build Coastguard Workerdeclare void @llvm.va_copy(i8*, i8*)
153