xref: /aosp_15_r20/external/llvm/test/CodeGen/X86/tailcall-msvc-conventions.ll (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker; RUN: llc -mtriple=i686-unknown-linux-gnu -O1 < %s | FileCheck %s
2*9880d681SAndroid Build Coastguard Worker; RUN: llc -mtriple=i686-unknown-linux-gnu -O0 < %s | FileCheck %s
3*9880d681SAndroid Build Coastguard Worker
4*9880d681SAndroid Build Coastguard Worker; The MSVC family of x86 calling conventions makes tail calls really tricky.
5*9880d681SAndroid Build Coastguard Worker; Tests of all the various combinations should live here.
6*9880d681SAndroid Build Coastguard Worker
7*9880d681SAndroid Build Coastguard Workerdeclare i32 @cdecl_i32()
8*9880d681SAndroid Build Coastguard Workerdeclare void @cdecl_void()
9*9880d681SAndroid Build Coastguard Worker
10*9880d681SAndroid Build Coastguard Worker; Don't allow tail calling these cdecl functions, because we need to clear the
11*9880d681SAndroid Build Coastguard Worker; incoming stack arguments for these argument-clearing conventions.
12*9880d681SAndroid Build Coastguard Worker
13*9880d681SAndroid Build Coastguard Workerdefine x86_thiscallcc void @thiscall_cdecl_notail(i32 %a, i32 %b, i32 %c) {
14*9880d681SAndroid Build Coastguard Worker  tail call void @cdecl_void()
15*9880d681SAndroid Build Coastguard Worker  ret void
16*9880d681SAndroid Build Coastguard Worker}
17*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: thiscall_cdecl_notail
18*9880d681SAndroid Build Coastguard Worker; CHECK: calll cdecl_void
19*9880d681SAndroid Build Coastguard Worker; CHECK: retl $8
20*9880d681SAndroid Build Coastguard Worker
21*9880d681SAndroid Build Coastguard Workerdefine x86_stdcallcc void @stdcall_cdecl_notail(i32 %a, i32 %b, i32 %c) {
22*9880d681SAndroid Build Coastguard Worker  tail call void @cdecl_void()
23*9880d681SAndroid Build Coastguard Worker  ret void
24*9880d681SAndroid Build Coastguard Worker}
25*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: stdcall_cdecl_notail
26*9880d681SAndroid Build Coastguard Worker; CHECK: calll cdecl_void
27*9880d681SAndroid Build Coastguard Worker; CHECK: retl $12
28*9880d681SAndroid Build Coastguard Worker
29*9880d681SAndroid Build Coastguard Workerdefine x86_vectorcallcc void @vectorcall_cdecl_notail(i32 inreg %a, i32 inreg %b, i32 %c) {
30*9880d681SAndroid Build Coastguard Worker  tail call void @cdecl_void()
31*9880d681SAndroid Build Coastguard Worker  ret void
32*9880d681SAndroid Build Coastguard Worker}
33*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: vectorcall_cdecl_notail
34*9880d681SAndroid Build Coastguard Worker; CHECK: calll cdecl_void
35*9880d681SAndroid Build Coastguard Worker; CHECK: retl $4
36*9880d681SAndroid Build Coastguard Worker
37*9880d681SAndroid Build Coastguard Workerdefine x86_fastcallcc void @fastcall_cdecl_notail(i32 inreg %a, i32 inreg %b, i32 %c) {
38*9880d681SAndroid Build Coastguard Worker  tail call void @cdecl_void()
39*9880d681SAndroid Build Coastguard Worker  ret void
40*9880d681SAndroid Build Coastguard Worker}
41*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: fastcall_cdecl_notail
42*9880d681SAndroid Build Coastguard Worker; CHECK: calll cdecl_void
43*9880d681SAndroid Build Coastguard Worker; CHECK: retl $4
44*9880d681SAndroid Build Coastguard Worker
45*9880d681SAndroid Build Coastguard Worker
46*9880d681SAndroid Build Coastguard Worker; Tail call to/from callee pop functions can work under the right circumstances:
47*9880d681SAndroid Build Coastguard Worker
48*9880d681SAndroid Build Coastguard Workerdeclare x86_thiscallcc void @no_args_method(i8*)
49*9880d681SAndroid Build Coastguard Workerdeclare x86_thiscallcc void @one_arg_method(i8*, i32)
50*9880d681SAndroid Build Coastguard Workerdeclare x86_thiscallcc void @two_args_method(i8*, i32, i32)
51*9880d681SAndroid Build Coastguard Workerdeclare void @ccall_func()
52*9880d681SAndroid Build Coastguard Workerdeclare void @ccall_func1(i32)
53*9880d681SAndroid Build Coastguard Worker
54*9880d681SAndroid Build Coastguard Workerdefine x86_thiscallcc void @thiscall_thiscall_tail(i8* %this) {
55*9880d681SAndroid Build Coastguard Workerentry:
56*9880d681SAndroid Build Coastguard Worker  tail call x86_thiscallcc void @no_args_method(i8* %this)
57*9880d681SAndroid Build Coastguard Worker  ret void
58*9880d681SAndroid Build Coastguard Worker}
59*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: thiscall_thiscall_tail:
60*9880d681SAndroid Build Coastguard Worker; CHECK: jmp no_args_method
61*9880d681SAndroid Build Coastguard Worker
62*9880d681SAndroid Build Coastguard Workerdefine x86_thiscallcc void @thiscall_thiscall_tail2(i8* %this, i32 %a, i32 %b) {
63*9880d681SAndroid Build Coastguard Workerentry:
64*9880d681SAndroid Build Coastguard Worker  tail call x86_thiscallcc void @two_args_method(i8* %this, i32 %a, i32 %b)
65*9880d681SAndroid Build Coastguard Worker  ret void
66*9880d681SAndroid Build Coastguard Worker}
67*9880d681SAndroid Build Coastguard Worker; @two_args_method will take care of popping %a and %b from the stack for us.
68*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: thiscall_thiscall_tail2:
69*9880d681SAndroid Build Coastguard Worker; CHECK: jmp two_args_method
70*9880d681SAndroid Build Coastguard Worker
71*9880d681SAndroid Build Coastguard Workerdefine x86_thiscallcc void @thiscall_thiscall_notail(i8* %this, i32 %a, i32 %b, i32 %x) {
72*9880d681SAndroid Build Coastguard Workerentry:
73*9880d681SAndroid Build Coastguard Worker  tail call x86_thiscallcc void @two_args_method(i8* %this, i32 %a, i32 %b)
74*9880d681SAndroid Build Coastguard Worker  ret void
75*9880d681SAndroid Build Coastguard Worker}
76*9880d681SAndroid Build Coastguard Worker; @two_args_method would not pop %x.
77*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: thiscall_thiscall_notail:
78*9880d681SAndroid Build Coastguard Worker; CHECK: calll two_args_method
79*9880d681SAndroid Build Coastguard Worker; CHECK: retl $12
80*9880d681SAndroid Build Coastguard Worker
81*9880d681SAndroid Build Coastguard Workerdefine x86_thiscallcc void @thiscall_thiscall_notail2(i8* %this, i32 %a) {
82*9880d681SAndroid Build Coastguard Workerentry:
83*9880d681SAndroid Build Coastguard Worker  tail call x86_thiscallcc void @no_args_method(i8* %this)
84*9880d681SAndroid Build Coastguard Worker  ret void
85*9880d681SAndroid Build Coastguard Worker}
86*9880d681SAndroid Build Coastguard Worker; @no_args_method would not pop %x for us. Make sure this is checked even
87*9880d681SAndroid Build Coastguard Worker; when there are no arguments to the call.
88*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: thiscall_thiscall_notail2:
89*9880d681SAndroid Build Coastguard Worker; CHECK: calll no_args_method
90*9880d681SAndroid Build Coastguard Worker; CHECK: retl $4
91*9880d681SAndroid Build Coastguard Worker
92*9880d681SAndroid Build Coastguard Workerdefine void @ccall_thiscall_tail(i8* %x) {
93*9880d681SAndroid Build Coastguard Workerentry:
94*9880d681SAndroid Build Coastguard Worker  tail call x86_thiscallcc void @no_args_method(i8* %x)
95*9880d681SAndroid Build Coastguard Worker  ret void
96*9880d681SAndroid Build Coastguard Worker}
97*9880d681SAndroid Build Coastguard Worker; Tail calling from ccall to thiscall works.
98*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: ccall_thiscall_tail:
99*9880d681SAndroid Build Coastguard Worker; CHECK: jmp no_args_method
100*9880d681SAndroid Build Coastguard Worker
101*9880d681SAndroid Build Coastguard Workerdefine void @ccall_thiscall_notail(i8* %x, i32 %y) {
102*9880d681SAndroid Build Coastguard Workerentry:
103*9880d681SAndroid Build Coastguard Worker  tail call x86_thiscallcc void @one_arg_method(i8* %x, i32 %y);
104*9880d681SAndroid Build Coastguard Worker  ret void
105*9880d681SAndroid Build Coastguard Worker}
106*9880d681SAndroid Build Coastguard Worker; @one_arg_method would pop %y off the stack.
107*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: ccall_thiscall_notail:
108*9880d681SAndroid Build Coastguard Worker; CHECK: calll one_arg_method
109*9880d681SAndroid Build Coastguard Worker
110*9880d681SAndroid Build Coastguard Workerdefine x86_thiscallcc void @thiscall_ccall_tail(i8* %this) {
111*9880d681SAndroid Build Coastguard Workerentry:
112*9880d681SAndroid Build Coastguard Worker  tail call void @ccall_func()
113*9880d681SAndroid Build Coastguard Worker  ret void
114*9880d681SAndroid Build Coastguard Worker}
115*9880d681SAndroid Build Coastguard Worker; Tail call from thiscall to ccall works if no arguments need popping.
116*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: thiscall_ccall_tail:
117*9880d681SAndroid Build Coastguard Worker; CHECK: jmp ccall_func
118*9880d681SAndroid Build Coastguard Worker
119*9880d681SAndroid Build Coastguard Workerdefine x86_thiscallcc void @thiscall_ccall_notail(i8* %this, i32 %x) {
120*9880d681SAndroid Build Coastguard Workerentry:
121*9880d681SAndroid Build Coastguard Worker  tail call void @ccall_func1(i32 %x)
122*9880d681SAndroid Build Coastguard Worker  ret void
123*9880d681SAndroid Build Coastguard Worker}
124*9880d681SAndroid Build Coastguard Worker; No tail call: %x needs to be popped.
125*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: thiscall_ccall_notail:
126*9880d681SAndroid Build Coastguard Worker; CHECK: calll ccall_func1
127*9880d681SAndroid Build Coastguard Worker; CHECK: retl $4
128*9880d681SAndroid Build Coastguard Worker
129*9880d681SAndroid Build Coastguard Worker%S = type { i32 (...)** }
130*9880d681SAndroid Build Coastguard Workerdefine x86_thiscallcc void @tailcall_through_pointer(%S* %this, i32 %a) {
131*9880d681SAndroid Build Coastguard Workerentry:
132*9880d681SAndroid Build Coastguard Worker  %0 = bitcast %S* %this to void (%S*, i32)***
133*9880d681SAndroid Build Coastguard Worker  %vtable = load void (%S*, i32)**, void (%S*, i32)*** %0
134*9880d681SAndroid Build Coastguard Worker  %1 = load void (%S*, i32)*, void (%S*, i32)** %vtable
135*9880d681SAndroid Build Coastguard Worker  tail call x86_thiscallcc void %1(%S* %this, i32 %a)
136*9880d681SAndroid Build Coastguard Worker  ret void
137*9880d681SAndroid Build Coastguard Worker}
138*9880d681SAndroid Build Coastguard Worker; Tail calling works through function pointers too.
139*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: tailcall_through_pointer:
140*9880d681SAndroid Build Coastguard Worker; CHECK: jmpl
141*9880d681SAndroid Build Coastguard Worker
142*9880d681SAndroid Build Coastguard Workerdefine x86_stdcallcc void @stdcall_cdecl_tail() {
143*9880d681SAndroid Build Coastguard Worker  tail call void @ccall_func()
144*9880d681SAndroid Build Coastguard Worker  ret void
145*9880d681SAndroid Build Coastguard Worker}
146*9880d681SAndroid Build Coastguard Worker; stdcall to cdecl works if no arguments need popping.
147*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: stdcall_cdecl_tail
148*9880d681SAndroid Build Coastguard Worker; CHECK: jmp ccall_func
149*9880d681SAndroid Build Coastguard Worker
150*9880d681SAndroid Build Coastguard Workerdefine x86_vectorcallcc void @vectorcall_cdecl_tail(i32 inreg %a, i32 inreg %b) {
151*9880d681SAndroid Build Coastguard Worker  tail call void @ccall_func()
152*9880d681SAndroid Build Coastguard Worker  ret void
153*9880d681SAndroid Build Coastguard Worker}
154*9880d681SAndroid Build Coastguard Worker; vectorcall to cdecl works if no arguments need popping.
155*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: vectorcall_cdecl_tail
156*9880d681SAndroid Build Coastguard Worker; CHECK: jmp ccall_func
157*9880d681SAndroid Build Coastguard Worker
158*9880d681SAndroid Build Coastguard Workerdefine x86_fastcallcc void @fastcall_cdecl_tail(i32 inreg %a, i32 inreg %b) {
159*9880d681SAndroid Build Coastguard Worker  tail call void @ccall_func()
160*9880d681SAndroid Build Coastguard Worker  ret void
161*9880d681SAndroid Build Coastguard Worker}
162*9880d681SAndroid Build Coastguard Worker; fastcall to cdecl works if no arguments need popping.
163*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: fastcall_cdecl_tail
164*9880d681SAndroid Build Coastguard Worker; CHECK: jmp ccall_func
165*9880d681SAndroid Build Coastguard Worker
166*9880d681SAndroid Build Coastguard Workerdefine x86_stdcallcc void @stdcall_thiscall_notail(i8* %this, i32 %a, i32 %b) {
167*9880d681SAndroid Build Coastguard Worker  tail call x86_thiscallcc void @two_args_method(i8* %this, i32 %a, i32 %b)
168*9880d681SAndroid Build Coastguard Worker  ret void
169*9880d681SAndroid Build Coastguard Worker}
170*9880d681SAndroid Build Coastguard Worker; two_args_method will not pop %this.
171*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: stdcall_thiscall_notail
172*9880d681SAndroid Build Coastguard Worker; CHECK: calll two_args_method
173*9880d681SAndroid Build Coastguard Worker
174*9880d681SAndroid Build Coastguard Workerdefine x86_stdcallcc void @stdcall_thiscall_tail(i32 %a, i32 %b) {
175*9880d681SAndroid Build Coastguard Worker  tail call x86_thiscallcc void @two_args_method(i8* null, i32 %a, i32 %b)
176*9880d681SAndroid Build Coastguard Worker  ret void
177*9880d681SAndroid Build Coastguard Worker}
178*9880d681SAndroid Build Coastguard Worker; The callee pop amounts match up.
179*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: stdcall_thiscall_tail
180*9880d681SAndroid Build Coastguard Worker; CHECK: jmp two_args_method
181*9880d681SAndroid Build Coastguard Worker
182*9880d681SAndroid Build Coastguard Workerdeclare x86_fastcallcc void @fastcall2(i32 inreg %a, i32 inreg %b)
183*9880d681SAndroid Build Coastguard Workerdefine void @cdecl_fastcall_tail(i32 %a, i32 %b) {
184*9880d681SAndroid Build Coastguard Worker  tail call x86_fastcallcc void @fastcall2(i32 %a, i32 %b)
185*9880d681SAndroid Build Coastguard Worker  ret void
186*9880d681SAndroid Build Coastguard Worker}
187*9880d681SAndroid Build Coastguard Worker; fastcall2 won't pop anything.
188*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: cdecl_fastcall_tail
189*9880d681SAndroid Build Coastguard Worker; CHECK: jmp fastcall2
190