1*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -mtriple=i686-win32 | FileCheck %s 2*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -mtriple=i686-win32 -O0 | FileCheck %s 3*9880d681SAndroid Build Coastguard Worker 4*9880d681SAndroid Build Coastguard Worker; IR simplified from the following C++ snippet compiled for i686-windows-msvc: 5*9880d681SAndroid Build Coastguard Worker 6*9880d681SAndroid Build Coastguard Worker; struct A { A(); ~A(); int a; }; 7*9880d681SAndroid Build Coastguard Worker; 8*9880d681SAndroid Build Coastguard Worker; struct B { 9*9880d681SAndroid Build Coastguard Worker; virtual int f(int); 10*9880d681SAndroid Build Coastguard Worker; virtual int g(A, int, A); 11*9880d681SAndroid Build Coastguard Worker; virtual void h(A, int, A); 12*9880d681SAndroid Build Coastguard Worker; virtual A i(A, int, A); 13*9880d681SAndroid Build Coastguard Worker; virtual A j(int); 14*9880d681SAndroid Build Coastguard Worker; }; 15*9880d681SAndroid Build Coastguard Worker; 16*9880d681SAndroid Build Coastguard Worker; int (B::*mp_f)(int) = &B::f; 17*9880d681SAndroid Build Coastguard Worker; int (B::*mp_g)(A, int, A) = &B::g; 18*9880d681SAndroid Build Coastguard Worker; void (B::*mp_h)(A, int, A) = &B::h; 19*9880d681SAndroid Build Coastguard Worker; A (B::*mp_i)(A, int, A) = &B::i; 20*9880d681SAndroid Build Coastguard Worker; A (B::*mp_j)(int) = &B::j; 21*9880d681SAndroid Build Coastguard Worker 22*9880d681SAndroid Build Coastguard Worker; Each member pointer creates a thunk. The ones with inalloca are required to 23*9880d681SAndroid Build Coastguard Worker; tail calls by the ABI, even at O0. 24*9880d681SAndroid Build Coastguard Worker 25*9880d681SAndroid Build Coastguard Worker%struct.B = type { i32 (...)** } 26*9880d681SAndroid Build Coastguard Worker%struct.A = type { i32 } 27*9880d681SAndroid Build Coastguard Worker 28*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: f_thunk: 29*9880d681SAndroid Build Coastguard Worker; CHECK: jmpl 30*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: ret 31*9880d681SAndroid Build Coastguard Workerdefine x86_thiscallcc i32 @f_thunk(%struct.B* %this, i32) { 32*9880d681SAndroid Build Coastguard Workerentry: 33*9880d681SAndroid Build Coastguard Worker %1 = bitcast %struct.B* %this to i32 (%struct.B*, i32)*** 34*9880d681SAndroid Build Coastguard Worker %vtable = load i32 (%struct.B*, i32)**, i32 (%struct.B*, i32)*** %1 35*9880d681SAndroid Build Coastguard Worker %2 = load i32 (%struct.B*, i32)*, i32 (%struct.B*, i32)** %vtable 36*9880d681SAndroid Build Coastguard Worker %3 = musttail call x86_thiscallcc i32 %2(%struct.B* %this, i32 %0) 37*9880d681SAndroid Build Coastguard Worker ret i32 %3 38*9880d681SAndroid Build Coastguard Worker} 39*9880d681SAndroid Build Coastguard Worker 40*9880d681SAndroid Build Coastguard Worker; Inalloca thunks shouldn't require any stores to the stack. 41*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: g_thunk: 42*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}} 43*9880d681SAndroid Build Coastguard Worker; CHECK: jmpl 44*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: ret 45*9880d681SAndroid Build Coastguard Workerdefine x86_thiscallcc i32 @g_thunk(%struct.B* %this, <{ %struct.A, i32, %struct.A }>* inalloca) { 46*9880d681SAndroid Build Coastguard Workerentry: 47*9880d681SAndroid Build Coastguard Worker %1 = bitcast %struct.B* %this to i32 (%struct.B*, <{ %struct.A, i32, %struct.A }>*)*** 48*9880d681SAndroid Build Coastguard Worker %vtable = load i32 (%struct.B*, <{ %struct.A, i32, %struct.A }>*)**, i32 (%struct.B*, <{ %struct.A, i32, %struct.A }>*)*** %1 49*9880d681SAndroid Build Coastguard Worker %vfn = getelementptr inbounds i32 (%struct.B*, <{ %struct.A, i32, %struct.A }>*)*, i32 (%struct.B*, <{ %struct.A, i32, %struct.A }>*)** %vtable, i32 1 50*9880d681SAndroid Build Coastguard Worker %2 = load i32 (%struct.B*, <{ %struct.A, i32, %struct.A }>*)*, i32 (%struct.B*, <{ %struct.A, i32, %struct.A }>*)** %vfn 51*9880d681SAndroid Build Coastguard Worker %3 = musttail call x86_thiscallcc i32 %2(%struct.B* %this, <{ %struct.A, i32, %struct.A }>* inalloca %0) 52*9880d681SAndroid Build Coastguard Worker ret i32 %3 53*9880d681SAndroid Build Coastguard Worker} 54*9880d681SAndroid Build Coastguard Worker 55*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: h_thunk: 56*9880d681SAndroid Build Coastguard Worker; CHECK: jmpl 57*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}} 58*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: ret 59*9880d681SAndroid Build Coastguard Workerdefine x86_thiscallcc void @h_thunk(%struct.B* %this, <{ %struct.A, i32, %struct.A }>* inalloca) { 60*9880d681SAndroid Build Coastguard Workerentry: 61*9880d681SAndroid Build Coastguard Worker %1 = bitcast %struct.B* %this to void (%struct.B*, <{ %struct.A, i32, %struct.A }>*)*** 62*9880d681SAndroid Build Coastguard Worker %vtable = load void (%struct.B*, <{ %struct.A, i32, %struct.A }>*)**, void (%struct.B*, <{ %struct.A, i32, %struct.A }>*)*** %1 63*9880d681SAndroid Build Coastguard Worker %vfn = getelementptr inbounds void (%struct.B*, <{ %struct.A, i32, %struct.A }>*)*, void (%struct.B*, <{ %struct.A, i32, %struct.A }>*)** %vtable, i32 2 64*9880d681SAndroid Build Coastguard Worker %2 = load void (%struct.B*, <{ %struct.A, i32, %struct.A }>*)*, void (%struct.B*, <{ %struct.A, i32, %struct.A }>*)** %vfn 65*9880d681SAndroid Build Coastguard Worker musttail call x86_thiscallcc void %2(%struct.B* %this, <{ %struct.A, i32, %struct.A }>* inalloca %0) 66*9880d681SAndroid Build Coastguard Worker ret void 67*9880d681SAndroid Build Coastguard Worker} 68*9880d681SAndroid Build Coastguard Worker 69*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: i_thunk: 70*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}} 71*9880d681SAndroid Build Coastguard Worker; CHECK: jmpl 72*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: ret 73*9880d681SAndroid Build Coastguard Workerdefine x86_thiscallcc %struct.A* @i_thunk(%struct.B* %this, <{ %struct.A*, %struct.A, i32, %struct.A }>* inalloca) { 74*9880d681SAndroid Build Coastguard Workerentry: 75*9880d681SAndroid Build Coastguard Worker %1 = bitcast %struct.B* %this to %struct.A* (%struct.B*, <{ %struct.A*, %struct.A, i32, %struct.A }>*)*** 76*9880d681SAndroid Build Coastguard Worker %vtable = load %struct.A* (%struct.B*, <{ %struct.A*, %struct.A, i32, %struct.A }>*)**, %struct.A* (%struct.B*, <{ %struct.A*, %struct.A, i32, %struct.A }>*)*** %1 77*9880d681SAndroid Build Coastguard Worker %vfn = getelementptr inbounds %struct.A* (%struct.B*, <{ %struct.A*, %struct.A, i32, %struct.A }>*)*, %struct.A* (%struct.B*, <{ %struct.A*, %struct.A, i32, %struct.A }>*)** %vtable, i32 3 78*9880d681SAndroid Build Coastguard Worker %2 = load %struct.A* (%struct.B*, <{ %struct.A*, %struct.A, i32, %struct.A }>*)*, %struct.A* (%struct.B*, <{ %struct.A*, %struct.A, i32, %struct.A }>*)** %vfn 79*9880d681SAndroid Build Coastguard Worker %3 = musttail call x86_thiscallcc %struct.A* %2(%struct.B* %this, <{ %struct.A*, %struct.A, i32, %struct.A }>* inalloca %0) 80*9880d681SAndroid Build Coastguard Worker ret %struct.A* %3 81*9880d681SAndroid Build Coastguard Worker} 82*9880d681SAndroid Build Coastguard Worker 83*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: j_thunk: 84*9880d681SAndroid Build Coastguard Worker; CHECK: jmpl 85*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: ret 86*9880d681SAndroid Build Coastguard Workerdefine x86_thiscallcc void @j_thunk(%struct.A* noalias sret %agg.result, %struct.B* %this, i32) { 87*9880d681SAndroid Build Coastguard Workerentry: 88*9880d681SAndroid Build Coastguard Worker %1 = bitcast %struct.B* %this to void (%struct.A*, %struct.B*, i32)*** 89*9880d681SAndroid Build Coastguard Worker %vtable = load void (%struct.A*, %struct.B*, i32)**, void (%struct.A*, %struct.B*, i32)*** %1 90*9880d681SAndroid Build Coastguard Worker %vfn = getelementptr inbounds void (%struct.A*, %struct.B*, i32)*, void (%struct.A*, %struct.B*, i32)** %vtable, i32 4 91*9880d681SAndroid Build Coastguard Worker %2 = load void (%struct.A*, %struct.B*, i32)*, void (%struct.A*, %struct.B*, i32)** %vfn 92*9880d681SAndroid Build Coastguard Worker musttail call x86_thiscallcc void %2(%struct.A* sret %agg.result, %struct.B* %this, i32 %0) 93*9880d681SAndroid Build Coastguard Worker ret void 94*9880d681SAndroid Build Coastguard Worker} 95*9880d681SAndroid Build Coastguard Worker 96*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: _stdcall_thunk@8: 97*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}} 98*9880d681SAndroid Build Coastguard Worker; CHECK: jmpl 99*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: ret 100*9880d681SAndroid Build Coastguard Workerdefine x86_stdcallcc i32 @stdcall_thunk(<{ %struct.B*, %struct.A }>* inalloca) { 101*9880d681SAndroid Build Coastguard Workerentry: 102*9880d681SAndroid Build Coastguard Worker %this_ptr = getelementptr inbounds <{ %struct.B*, %struct.A }>, <{ %struct.B*, %struct.A }>* %0, i32 0, i32 0 103*9880d681SAndroid Build Coastguard Worker %this = load %struct.B*, %struct.B** %this_ptr 104*9880d681SAndroid Build Coastguard Worker %1 = bitcast %struct.B* %this to i32 (<{ %struct.B*, %struct.A }>*)*** 105*9880d681SAndroid Build Coastguard Worker %vtable = load i32 (<{ %struct.B*, %struct.A }>*)**, i32 (<{ %struct.B*, %struct.A }>*)*** %1 106*9880d681SAndroid Build Coastguard Worker %vfn = getelementptr inbounds i32 (<{ %struct.B*, %struct.A }>*)*, i32 (<{ %struct.B*, %struct.A }>*)** %vtable, i32 1 107*9880d681SAndroid Build Coastguard Worker %2 = load i32 (<{ %struct.B*, %struct.A }>*)*, i32 (<{ %struct.B*, %struct.A }>*)** %vfn 108*9880d681SAndroid Build Coastguard Worker %3 = musttail call x86_stdcallcc i32 %2(<{ %struct.B*, %struct.A }>* inalloca %0) 109*9880d681SAndroid Build Coastguard Worker ret i32 %3 110*9880d681SAndroid Build Coastguard Worker} 111*9880d681SAndroid Build Coastguard Worker 112*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @fastcall_thunk@8: 113*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}} 114*9880d681SAndroid Build Coastguard Worker; CHECK: jmpl 115*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: ret 116*9880d681SAndroid Build Coastguard Workerdefine x86_fastcallcc i32 @fastcall_thunk(%struct.B* inreg %this, <{ %struct.A }>* inalloca) { 117*9880d681SAndroid Build Coastguard Workerentry: 118*9880d681SAndroid Build Coastguard Worker %1 = bitcast %struct.B* %this to i32 (%struct.B*, <{ %struct.A }>*)*** 119*9880d681SAndroid Build Coastguard Worker %vtable = load i32 (%struct.B*, <{ %struct.A }>*)**, i32 (%struct.B*, <{ %struct.A }>*)*** %1 120*9880d681SAndroid Build Coastguard Worker %vfn = getelementptr inbounds i32 (%struct.B*, <{ %struct.A }>*)*, i32 (%struct.B*, <{ %struct.A }>*)** %vtable, i32 1 121*9880d681SAndroid Build Coastguard Worker %2 = load i32 (%struct.B*, <{ %struct.A }>*)*, i32 (%struct.B*, <{ %struct.A }>*)** %vfn 122*9880d681SAndroid Build Coastguard Worker %3 = musttail call x86_fastcallcc i32 %2(%struct.B* inreg %this, <{ %struct.A }>* inalloca %0) 123*9880d681SAndroid Build Coastguard Worker ret i32 %3 124*9880d681SAndroid Build Coastguard Worker} 125