xref: /minix3/external/bsd/llvm/dist/clang/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc // RUN: %clang_cc1 %s -fno-rtti -triple=i686-pc-win32 -emit-llvm -o - | FileCheck --check-prefix=CHECK32 %s
2*0a6a1f1dSLionel Sambuc // RUN: %clang_cc1 %s -fno-rtti -triple=x86_64-pc-win32 -emit-llvm -o - | FileCheck --check-prefix=CHECK64 %s
3*0a6a1f1dSLionel Sambuc 
4*0a6a1f1dSLionel Sambuc namespace byval_thunk {
5*0a6a1f1dSLionel Sambuc struct Agg {
6*0a6a1f1dSLionel Sambuc   Agg();
7*0a6a1f1dSLionel Sambuc   Agg(const Agg &);
8*0a6a1f1dSLionel Sambuc   ~Agg();
9*0a6a1f1dSLionel Sambuc   int x;
10*0a6a1f1dSLionel Sambuc };
11*0a6a1f1dSLionel Sambuc 
12*0a6a1f1dSLionel Sambuc struct A { virtual void foo(Agg x); };
13*0a6a1f1dSLionel Sambuc struct B { virtual void foo(Agg x); };
14*0a6a1f1dSLionel Sambuc struct C : A, B { C(); virtual void foo(Agg x); };
C()15*0a6a1f1dSLionel Sambuc C::C() {} // force emission
16*0a6a1f1dSLionel Sambuc 
17*0a6a1f1dSLionel Sambuc // CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01?foo@C@byval_thunk@@W3AEXUAgg@2@@Z"
18*0a6a1f1dSLionel Sambuc // CHECK32:             (%"struct.byval_thunk::C"* %this, <{ %"struct.byval_thunk::Agg" }>* inalloca)
19*0a6a1f1dSLionel Sambuc // CHECK32:   getelementptr i8* %{{.*}}, i32 -4
20*0a6a1f1dSLionel Sambuc // CHECK32:   musttail call x86_thiscallcc void @"\01?foo@C@byval_thunk@@UAEXUAgg@2@@Z"
21*0a6a1f1dSLionel Sambuc // CHECK32:       (%"struct.byval_thunk::C"* %{{.*}}, <{ %"struct.byval_thunk::Agg" }>* inalloca %0)
22*0a6a1f1dSLionel Sambuc // CHECK32-NEXT: ret void
23*0a6a1f1dSLionel Sambuc 
24*0a6a1f1dSLionel Sambuc // CHECK64-LABEL: define linkonce_odr void @"\01?foo@C@byval_thunk@@W7EAAXUAgg@2@@Z"
25*0a6a1f1dSLionel Sambuc // CHECK64:             (%"struct.byval_thunk::C"* %this, %"struct.byval_thunk::Agg"* %x)
26*0a6a1f1dSLionel Sambuc // CHECK64:   getelementptr i8* %{{.*}}, i32 -8
27*0a6a1f1dSLionel Sambuc // CHECK64:   call void @"\01?foo@C@byval_thunk@@UEAAXUAgg@2@@Z"
28*0a6a1f1dSLionel Sambuc // CHECK64:       (%"struct.byval_thunk::C"* %{{.*}}, %"struct.byval_thunk::Agg"* %x)
29*0a6a1f1dSLionel Sambuc // CHECK64-NOT: call
30*0a6a1f1dSLionel Sambuc // CHECK64:   ret void
31*0a6a1f1dSLionel Sambuc }
32*0a6a1f1dSLionel Sambuc 
33*0a6a1f1dSLionel Sambuc namespace stdcall_thunk {
34*0a6a1f1dSLionel Sambuc struct Agg {
35*0a6a1f1dSLionel Sambuc   Agg();
36*0a6a1f1dSLionel Sambuc   Agg(const Agg &);
37*0a6a1f1dSLionel Sambuc   ~Agg();
38*0a6a1f1dSLionel Sambuc   int x;
39*0a6a1f1dSLionel Sambuc };
40*0a6a1f1dSLionel Sambuc 
41*0a6a1f1dSLionel Sambuc struct A { virtual void __stdcall foo(Agg x); };
42*0a6a1f1dSLionel Sambuc struct B { virtual void __stdcall foo(Agg x); };
43*0a6a1f1dSLionel Sambuc struct C : A, B { C(); virtual void __stdcall foo(Agg x); };
C()44*0a6a1f1dSLionel Sambuc C::C() {} // force emission
45*0a6a1f1dSLionel Sambuc 
46*0a6a1f1dSLionel Sambuc // CHECK32-LABEL: define linkonce_odr x86_stdcallcc void @"\01?foo@C@stdcall_thunk@@W3AGXUAgg@2@@Z"
47*0a6a1f1dSLionel Sambuc // CHECK32:             (<{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>* inalloca)
48*0a6a1f1dSLionel Sambuc // CHECK32:   %[[this_slot:[^ ]*]] = getelementptr inbounds <{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>* %0, i32 0, i32 0
49*0a6a1f1dSLionel Sambuc // CHECK32:   load %"struct.stdcall_thunk::C"** %[[this_slot]]
50*0a6a1f1dSLionel Sambuc // CHECK32:   getelementptr i8* %{{.*}}, i32 -4
51*0a6a1f1dSLionel Sambuc // CHECK32:   store %"struct.stdcall_thunk::C"* %{{.*}}, %"struct.stdcall_thunk::C"** %[[this_slot]]
52*0a6a1f1dSLionel Sambuc // CHECK32:   musttail call x86_stdcallcc void @"\01?foo@C@stdcall_thunk@@UAGXUAgg@2@@Z"
53*0a6a1f1dSLionel Sambuc // CHECK32:       (<{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>*  inalloca %0)
54*0a6a1f1dSLionel Sambuc // CHECK32-NEXT: ret void
55*0a6a1f1dSLionel Sambuc 
56*0a6a1f1dSLionel Sambuc // CHECK64-LABEL: define linkonce_odr void @"\01?foo@C@stdcall_thunk@@W7EAAXUAgg@2@@Z"
57*0a6a1f1dSLionel Sambuc // CHECK64:             (%"struct.stdcall_thunk::C"* %this, %"struct.stdcall_thunk::Agg"* %x)
58*0a6a1f1dSLionel Sambuc // CHECK64:   getelementptr i8* %{{.*}}, i32 -8
59*0a6a1f1dSLionel Sambuc // CHECK64:   call void @"\01?foo@C@stdcall_thunk@@UEAAXUAgg@2@@Z"
60*0a6a1f1dSLionel Sambuc // CHECK64:       (%"struct.stdcall_thunk::C"* %{{.*}}, %"struct.stdcall_thunk::Agg"* %x)
61*0a6a1f1dSLionel Sambuc // CHECK64-NOT: call
62*0a6a1f1dSLionel Sambuc // CHECK64:   ret void
63*0a6a1f1dSLionel Sambuc }
64*0a6a1f1dSLionel Sambuc 
65*0a6a1f1dSLionel Sambuc namespace sret_thunk {
66*0a6a1f1dSLionel Sambuc struct Agg {
67*0a6a1f1dSLionel Sambuc   Agg();
68*0a6a1f1dSLionel Sambuc   Agg(const Agg &);
69*0a6a1f1dSLionel Sambuc   ~Agg();
70*0a6a1f1dSLionel Sambuc   int x;
71*0a6a1f1dSLionel Sambuc };
72*0a6a1f1dSLionel Sambuc 
73*0a6a1f1dSLionel Sambuc struct A { virtual Agg __cdecl foo(Agg x); };
74*0a6a1f1dSLionel Sambuc struct B { virtual Agg __cdecl foo(Agg x); };
75*0a6a1f1dSLionel Sambuc struct C : A, B { C(); virtual Agg __cdecl foo(Agg x); };
C()76*0a6a1f1dSLionel Sambuc C::C() {} // force emission
77*0a6a1f1dSLionel Sambuc 
78*0a6a1f1dSLionel Sambuc // CHECK32-LABEL: define linkonce_odr %"struct.sret_thunk::Agg"* @"\01?foo@C@sret_thunk@@W3AA?AUAgg@2@U32@@Z"
79*0a6a1f1dSLionel Sambuc // CHECK32:             (<{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>* inalloca)
80*0a6a1f1dSLionel Sambuc // CHECK32:   %[[this_slot:[^ ]*]] = getelementptr inbounds <{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>* %0, i32 0, i32 0
81*0a6a1f1dSLionel Sambuc // CHECK32:   load %"struct.sret_thunk::C"** %[[this_slot]]
82*0a6a1f1dSLionel Sambuc // CHECK32:   getelementptr i8* %{{.*}}, i32 -4
83*0a6a1f1dSLionel Sambuc // CHECK32:   store %"struct.sret_thunk::C"* %{{.*}}, %"struct.sret_thunk::C"** %[[this_slot]]
84*0a6a1f1dSLionel Sambuc // CHECK32:   %[[rv:[^ ]*]] = musttail call %"struct.sret_thunk::Agg"* @"\01?foo@C@sret_thunk@@UAA?AUAgg@2@U32@@Z"
85*0a6a1f1dSLionel Sambuc // CHECK32:       (<{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>*  inalloca %0)
86*0a6a1f1dSLionel Sambuc // CHECK32-NEXT: ret %"struct.sret_thunk::Agg"* %[[rv]]
87*0a6a1f1dSLionel Sambuc 
88*0a6a1f1dSLionel Sambuc // CHECK64-LABEL: define linkonce_odr void @"\01?foo@C@sret_thunk@@W7EAA?AUAgg@2@U32@@Z"
89*0a6a1f1dSLionel Sambuc // CHECK64:             (%"struct.sret_thunk::C"* %this, %"struct.sret_thunk::Agg"* noalias sret %agg.result, %"struct.sret_thunk::Agg"* %x)
90*0a6a1f1dSLionel Sambuc // CHECK64:   getelementptr i8* %{{.*}}, i32 -8
91*0a6a1f1dSLionel Sambuc // CHECK64:   call void @"\01?foo@C@sret_thunk@@UEAA?AUAgg@2@U32@@Z"
92*0a6a1f1dSLionel Sambuc // CHECK64:       (%"struct.sret_thunk::C"* %{{.*}}, %"struct.sret_thunk::Agg"* sret %agg.result, %"struct.sret_thunk::Agg"* %x)
93*0a6a1f1dSLionel Sambuc // CHECK64-NOT: call
94*0a6a1f1dSLionel Sambuc // CHECK64:   ret void
95*0a6a1f1dSLionel Sambuc }
96*0a6a1f1dSLionel Sambuc 
97*0a6a1f1dSLionel Sambuc #if 0
98*0a6a1f1dSLionel Sambuc // FIXME: When we extend LLVM IR to allow forwarding of varargs through musttail
99*0a6a1f1dSLionel Sambuc // calls, use this test.
100*0a6a1f1dSLionel Sambuc namespace variadic_thunk {
101*0a6a1f1dSLionel Sambuc struct Agg {
102*0a6a1f1dSLionel Sambuc   Agg();
103*0a6a1f1dSLionel Sambuc   Agg(const Agg &);
104*0a6a1f1dSLionel Sambuc   ~Agg();
105*0a6a1f1dSLionel Sambuc   int x;
106*0a6a1f1dSLionel Sambuc };
107*0a6a1f1dSLionel Sambuc 
108*0a6a1f1dSLionel Sambuc struct A { virtual void foo(Agg x, ...); };
109*0a6a1f1dSLionel Sambuc struct B { virtual void foo(Agg x, ...); };
110*0a6a1f1dSLionel Sambuc struct C : A, B { C(); virtual void foo(Agg x, ...); };
111*0a6a1f1dSLionel Sambuc C::C() {} // force emission
112*0a6a1f1dSLionel Sambuc }
113*0a6a1f1dSLionel Sambuc #endif
114