1 ; RUN: llc -verify-machineinstrs < %s -mtriple=i686-win32 | FileCheck %s
2 ; RUN: llc -verify-machineinstrs < %s -mtriple=i686-win32 -O0 | FileCheck %s
4 ; IR simplified from the following C++ snippet compiled for i686-windows-msvc:
6 ; struct A { A(); ~A(); int a; };
10 ; virtual int g(A, int, A);
11 ; virtual void h(A, int, A);
12 ; virtual A i(A, int, A);
16 ; int (B::*mp_f)(int) = &B::f;
17 ; int (B::*mp_g)(A, int, A) = &B::g;
18 ; void (B::*mp_h)(A, int, A) = &B::h;
19 ; A (B::*mp_i)(A, int, A) = &B::i;
20 ; A (B::*mp_j)(int) = &B::j;
22 ; Each member pointer creates a thunk. The ones with inalloca are required to
23 ; tail calls by the ABI, even at O0.
25 %struct.B = type { ptr }
26 %struct.A = type { i32 }
28 ; CHECK-LABEL: f_thunk:
31 define x86_thiscallcc i32 @f_thunk(ptr %this, i32) {
33 %vtable = load ptr, ptr %this
34 %1 = load ptr, ptr %vtable
35 %2 = musttail call x86_thiscallcc i32 %1(ptr %this, i32 %0)
39 ; Inalloca thunks shouldn't require any stores to the stack.
40 ; CHECK-LABEL: g_thunk:
41 ; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}
44 define x86_thiscallcc i32 @g_thunk(ptr %this, ptr inalloca(<{ %struct.A, i32, %struct.A }>)) {
46 %vtable = load ptr, ptr %this
47 %vfn = getelementptr inbounds ptr, ptr %vtable, i32 1
48 %1 = load ptr, ptr %vfn
49 %2 = musttail call x86_thiscallcc i32 %1(ptr %this, ptr inalloca(<{ %struct.A, i32, %struct.A }>) %0)
53 ; Preallocated thunks shouldn't require any stores to the stack.
54 ; CHECK-LABEL: g_thunk_preallocated:
55 ; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}
58 define x86_thiscallcc i32 @g_thunk_preallocated(ptr %this, ptr preallocated(<{ %struct.A, i32, %struct.A }>)) {
60 %vtable = load ptr, ptr %this
61 %vfn = getelementptr inbounds ptr, ptr %vtable, i32 1
62 %1 = load ptr, ptr %vfn
63 %2 = musttail call x86_thiscallcc i32 %1(ptr %this, ptr preallocated(<{ %struct.A, i32, %struct.A }>) %0)
67 ; CHECK-LABEL: h_thunk:
69 ; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}
71 define x86_thiscallcc void @h_thunk(ptr %this, ptr inalloca(<{ %struct.A, i32, %struct.A }>)) {
73 %vtable = load ptr, ptr %this
74 %vfn = getelementptr inbounds ptr, ptr %vtable, i32 2
75 %1 = load ptr, ptr %vfn
76 musttail call x86_thiscallcc void %1(ptr %this, ptr inalloca(<{ %struct.A, i32, %struct.A }>) %0)
80 ; CHECK-LABEL: h_thunk_preallocated:
82 ; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}
84 define x86_thiscallcc void @h_thunk_preallocated(ptr %this, ptr preallocated(<{ %struct.A, i32, %struct.A }>)) {
86 %vtable = load ptr, ptr %this
87 %vfn = getelementptr inbounds ptr, ptr %vtable, i32 2
88 %1 = load ptr, ptr %vfn
89 musttail call x86_thiscallcc void %1(ptr %this, ptr preallocated(<{ %struct.A, i32, %struct.A }>) %0)
93 ; CHECK-LABEL: i_thunk:
94 ; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}
97 define x86_thiscallcc ptr @i_thunk(ptr %this, ptr inalloca(<{ ptr, %struct.A, i32, %struct.A }>)) {
99 %vtable = load ptr, ptr %this
100 %vfn = getelementptr inbounds ptr, ptr %vtable, i32 3
101 %1 = load ptr, ptr %vfn
102 %2 = musttail call x86_thiscallcc ptr %1(ptr %this, ptr inalloca(<{ ptr, %struct.A, i32, %struct.A }>) %0)
106 ; CHECK-LABEL: i_thunk_preallocated:
107 ; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}
110 define x86_thiscallcc ptr @i_thunk_preallocated(ptr %this, ptr preallocated(<{ ptr, %struct.A, i32, %struct.A }>)) {
112 %vtable = load ptr, ptr %this
113 %vfn = getelementptr inbounds ptr, ptr %vtable, i32 3
114 %1 = load ptr, ptr %vfn
115 %2 = musttail call x86_thiscallcc ptr %1(ptr %this, ptr preallocated(<{ ptr, %struct.A, i32, %struct.A }>) %0)
119 ; CHECK-LABEL: j_thunk:
122 define x86_thiscallcc void @j_thunk(ptr noalias sret(%struct.A) %agg.result, ptr %this, i32) {
124 %vtable = load ptr, ptr %this
125 %vfn = getelementptr inbounds ptr, ptr %vtable, i32 4
126 %1 = load ptr, ptr %vfn
127 musttail call x86_thiscallcc void %1(ptr sret(%struct.A) %agg.result, ptr %this, i32 %0)
131 ; CHECK-LABEL: _stdcall_thunk@8:
132 ; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}
135 define x86_stdcallcc i32 @stdcall_thunk(ptr inalloca(<{ ptr, %struct.A }>)) {
137 %this_ptr = getelementptr inbounds <{ ptr, %struct.A }>, ptr %0, i32 0, i32 0
138 %this = load ptr, ptr %this_ptr
139 %vtable = load ptr, ptr %this
140 %vfn = getelementptr inbounds ptr, ptr %vtable, i32 1
141 %1 = load ptr, ptr %vfn
142 %2 = musttail call x86_stdcallcc i32 %1(ptr inalloca(<{ ptr, %struct.A }>) %0)
146 ; CHECK-LABEL: _stdcall_thunk_preallocated@8:
147 ; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}
150 define x86_stdcallcc i32 @stdcall_thunk_preallocated(ptr preallocated(<{ ptr, %struct.A }>)) {
152 %this_ptr = getelementptr inbounds <{ ptr, %struct.A }>, ptr %0, i32 0, i32 0
153 %this = load ptr, ptr %this_ptr
154 %vtable = load ptr, ptr %this
155 %vfn = getelementptr inbounds ptr, ptr %vtable, i32 1
156 %1 = load ptr, ptr %vfn
157 %2 = musttail call x86_stdcallcc i32 %1(ptr preallocated(<{ ptr, %struct.A }>) %0)
161 ; CHECK-LABEL: @fastcall_thunk@8:
162 ; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}
165 define x86_fastcallcc i32 @fastcall_thunk(ptr inreg %this, ptr inalloca(<{ %struct.A }>)) {
167 %vtable = load ptr, ptr %this
168 %vfn = getelementptr inbounds ptr, ptr %vtable, i32 1
169 %1 = load ptr, ptr %vfn
170 %2 = musttail call x86_fastcallcc i32 %1(ptr inreg %this, ptr inalloca(<{ %struct.A }>) %0)
174 ; CHECK-LABEL: @fastcall_thunk_preallocated@8:
175 ; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}
178 define x86_fastcallcc i32 @fastcall_thunk_preallocated(ptr inreg %this, ptr preallocated(<{ %struct.A }>)) {
180 %vtable = load ptr, ptr %this
181 %vfn = getelementptr inbounds ptr, ptr %vtable, i32 1
182 %1 = load ptr, ptr %vfn
183 %2 = musttail call x86_fastcallcc i32 %1(ptr inreg %this, ptr preallocated(<{ %struct.A }>) %0)