186 lines · plain
1; RUN: llc -verify-machineinstrs < %s -mtriple=i686-win32 | FileCheck %s2; RUN: llc -verify-machineinstrs < %s -mtriple=i686-win32 -O0 | FileCheck %s3 4; IR simplified from the following C++ snippet compiled for i686-windows-msvc:5 6; struct A { A(); ~A(); int a; };7;8; struct B {9; virtual int f(int);10; virtual int g(A, int, A);11; virtual void h(A, int, A);12; virtual A i(A, int, A);13; virtual A j(int);14; };15;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;21 22; Each member pointer creates a thunk. The ones with inalloca are required to23; tail calls by the ABI, even at O0.24 25%struct.B = type { ptr }26%struct.A = type { i32 }27 28; CHECK-LABEL: f_thunk:29; CHECK: jmpl30; CHECK-NOT: ret31define x86_thiscallcc i32 @f_thunk(ptr %this, i32) {32entry:33 %vtable = load ptr, ptr %this34 %1 = load ptr, ptr %vtable35 %2 = musttail call x86_thiscallcc i32 %1(ptr %this, i32 %0)36 ret i32 %237}38 39; Inalloca thunks shouldn't require any stores to the stack.40; CHECK-LABEL: g_thunk:41; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}42; CHECK: jmpl43; CHECK-NOT: ret44define x86_thiscallcc i32 @g_thunk(ptr %this, ptr inalloca(<{ %struct.A, i32, %struct.A }>)) {45entry:46 %vtable = load ptr, ptr %this47 %vfn = getelementptr inbounds ptr, ptr %vtable, i32 148 %1 = load ptr, ptr %vfn49 %2 = musttail call x86_thiscallcc i32 %1(ptr %this, ptr inalloca(<{ %struct.A, i32, %struct.A }>) %0)50 ret i32 %251}52 53; Preallocated thunks shouldn't require any stores to the stack.54; CHECK-LABEL: g_thunk_preallocated:55; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}56; CHECK: jmpl57; CHECK-NOT: ret58define x86_thiscallcc i32 @g_thunk_preallocated(ptr %this, ptr preallocated(<{ %struct.A, i32, %struct.A }>)) {59entry:60 %vtable = load ptr, ptr %this61 %vfn = getelementptr inbounds ptr, ptr %vtable, i32 162 %1 = load ptr, ptr %vfn63 %2 = musttail call x86_thiscallcc i32 %1(ptr %this, ptr preallocated(<{ %struct.A, i32, %struct.A }>) %0)64 ret i32 %265}66 67; CHECK-LABEL: h_thunk:68; CHECK: jmpl69; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}70; CHECK-NOT: ret71define x86_thiscallcc void @h_thunk(ptr %this, ptr inalloca(<{ %struct.A, i32, %struct.A }>)) {72entry:73 %vtable = load ptr, ptr %this74 %vfn = getelementptr inbounds ptr, ptr %vtable, i32 275 %1 = load ptr, ptr %vfn76 musttail call x86_thiscallcc void %1(ptr %this, ptr inalloca(<{ %struct.A, i32, %struct.A }>) %0)77 ret void78}79 80; CHECK-LABEL: h_thunk_preallocated:81; CHECK: jmpl82; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}83; CHECK-NOT: ret84define x86_thiscallcc void @h_thunk_preallocated(ptr %this, ptr preallocated(<{ %struct.A, i32, %struct.A }>)) {85entry:86 %vtable = load ptr, ptr %this87 %vfn = getelementptr inbounds ptr, ptr %vtable, i32 288 %1 = load ptr, ptr %vfn89 musttail call x86_thiscallcc void %1(ptr %this, ptr preallocated(<{ %struct.A, i32, %struct.A }>) %0)90 ret void91}92 93; CHECK-LABEL: i_thunk:94; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}95; CHECK: jmpl96; CHECK-NOT: ret97define x86_thiscallcc ptr @i_thunk(ptr %this, ptr inalloca(<{ ptr, %struct.A, i32, %struct.A }>)) {98entry:99 %vtable = load ptr, ptr %this100 %vfn = getelementptr inbounds ptr, ptr %vtable, i32 3101 %1 = load ptr, ptr %vfn102 %2 = musttail call x86_thiscallcc ptr %1(ptr %this, ptr inalloca(<{ ptr, %struct.A, i32, %struct.A }>) %0)103 ret ptr %2104}105 106; CHECK-LABEL: i_thunk_preallocated:107; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}108; CHECK: jmpl109; CHECK-NOT: ret110define x86_thiscallcc ptr @i_thunk_preallocated(ptr %this, ptr preallocated(<{ ptr, %struct.A, i32, %struct.A }>)) {111entry:112 %vtable = load ptr, ptr %this113 %vfn = getelementptr inbounds ptr, ptr %vtable, i32 3114 %1 = load ptr, ptr %vfn115 %2 = musttail call x86_thiscallcc ptr %1(ptr %this, ptr preallocated(<{ ptr, %struct.A, i32, %struct.A }>) %0)116 ret ptr %2117}118 119; CHECK-LABEL: j_thunk:120; CHECK: jmpl121; CHECK-NOT: ret122define x86_thiscallcc void @j_thunk(ptr noalias sret(%struct.A) %agg.result, ptr %this, i32) {123entry:124 %vtable = load ptr, ptr %this125 %vfn = getelementptr inbounds ptr, ptr %vtable, i32 4126 %1 = load ptr, ptr %vfn127 musttail call x86_thiscallcc void %1(ptr sret(%struct.A) %agg.result, ptr %this, i32 %0)128 ret void129}130 131; CHECK-LABEL: _stdcall_thunk@8:132; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}133; CHECK: jmpl134; CHECK-NOT: ret135define x86_stdcallcc i32 @stdcall_thunk(ptr inalloca(<{ ptr, %struct.A }>)) {136entry:137 %this_ptr = getelementptr inbounds <{ ptr, %struct.A }>, ptr %0, i32 0, i32 0138 %this = load ptr, ptr %this_ptr139 %vtable = load ptr, ptr %this140 %vfn = getelementptr inbounds ptr, ptr %vtable, i32 1141 %1 = load ptr, ptr %vfn142 %2 = musttail call x86_stdcallcc i32 %1(ptr inalloca(<{ ptr, %struct.A }>) %0)143 ret i32 %2144}145 146; CHECK-LABEL: _stdcall_thunk_preallocated@8:147; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}148; CHECK: jmpl149; CHECK-NOT: ret150define x86_stdcallcc i32 @stdcall_thunk_preallocated(ptr preallocated(<{ ptr, %struct.A }>)) {151entry:152 %this_ptr = getelementptr inbounds <{ ptr, %struct.A }>, ptr %0, i32 0, i32 0153 %this = load ptr, ptr %this_ptr154 %vtable = load ptr, ptr %this155 %vfn = getelementptr inbounds ptr, ptr %vtable, i32 1156 %1 = load ptr, ptr %vfn157 %2 = musttail call x86_stdcallcc i32 %1(ptr preallocated(<{ ptr, %struct.A }>) %0)158 ret i32 %2159}160 161; CHECK-LABEL: @fastcall_thunk@8:162; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}163; CHECK: jmpl164; CHECK-NOT: ret165define x86_fastcallcc i32 @fastcall_thunk(ptr inreg %this, ptr inalloca(<{ %struct.A }>)) {166entry:167 %vtable = load ptr, ptr %this168 %vfn = getelementptr inbounds ptr, ptr %vtable, i32 1169 %1 = load ptr, ptr %vfn170 %2 = musttail call x86_fastcallcc i32 %1(ptr inreg %this, ptr inalloca(<{ %struct.A }>) %0)171 ret i32 %2172}173 174; CHECK-LABEL: @fastcall_thunk_preallocated@8:175; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}176; CHECK: jmpl177; CHECK-NOT: ret178define x86_fastcallcc i32 @fastcall_thunk_preallocated(ptr inreg %this, ptr preallocated(<{ %struct.A }>)) {179entry:180 %vtable = load ptr, ptr %this181 %vfn = getelementptr inbounds ptr, ptr %vtable, i32 1182 %1 = load ptr, ptr %vfn183 %2 = musttail call x86_fastcallcc i32 %1(ptr inreg %this, ptr preallocated(<{ %struct.A }>) %0)184 ret i32 %2185}186