xref: /aosp_15_r20/external/clang/test/CodeGenCXX/microsoft-abi-thunks.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 >%t 2>&1
2*67e74705SXin Li // RUN: FileCheck --check-prefix=MANGLING %s < %t
3*67e74705SXin Li // RUN: FileCheck --check-prefix=XMANGLING %s < %t
4*67e74705SXin Li // RUN: FileCheck --check-prefix=CODEGEN %s < %t
5*67e74705SXin Li // RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 2>&1 | FileCheck --check-prefix=MANGLING-X64 %s
6*67e74705SXin Li 
7*67e74705SXin Li void foo(void *);
8*67e74705SXin Li 
9*67e74705SXin Li struct A {
10*67e74705SXin Li   virtual ~A();
11*67e74705SXin Li   virtual void public_f();
12*67e74705SXin Li   // Make sure we don't emit unneeded thunks:
13*67e74705SXin Li   // XMANGLING-NOT: @"\01?public_f@A@@QAEXXZ"
14*67e74705SXin Li  protected:
15*67e74705SXin Li   virtual void protected_f();
16*67e74705SXin Li  private:
17*67e74705SXin Li   virtual void private_f();
18*67e74705SXin Li };
19*67e74705SXin Li 
20*67e74705SXin Li struct B {
21*67e74705SXin Li   virtual ~B();
22*67e74705SXin Li   virtual void public_f();
23*67e74705SXin Li  protected:
24*67e74705SXin Li   virtual void protected_f();
25*67e74705SXin Li  private:
26*67e74705SXin Li   virtual void private_f();
27*67e74705SXin Li };
28*67e74705SXin Li 
29*67e74705SXin Li 
30*67e74705SXin Li struct C : A, B {
31*67e74705SXin Li   C();
32*67e74705SXin Li 
33*67e74705SXin Li   virtual ~C();
34*67e74705SXin Li   // MANGLING-DAG: declare {{.*}} @"\01??1C@@UAE@XZ"({{.*}})
35*67e74705SXin Li   // MANGLING-DAG: define {{.*}} @"\01??_GC@@UAEPAXI@Z"({{.*}})
36*67e74705SXin Li   // MANGLING-DAG: define {{.*}} @"\01??_EC@@W3AEPAXI@Z"({{.*}}) {{.*}} comdat
37*67e74705SXin Li   // MANGLING-X64-DAG: declare {{.*}} @"\01??1C@@UEAA@XZ"({{.*}})
38*67e74705SXin Li   // MANGLING-X64-DAG: define {{.*}} @"\01??_GC@@UEAAPEAXI@Z"({{.*}})
39*67e74705SXin Li   // MANGLING-X64-DAG: define {{.*}} @"\01??_EC@@W7EAAPEAXI@Z"({{.*}}) {{.*}} comdat
40*67e74705SXin Li 
41*67e74705SXin Li   // Overrides public_f() of two subobjects with distinct vfptrs, thus needs a thunk.
42*67e74705SXin Li   virtual void public_f();
43*67e74705SXin Li   // MANGLING-DAG: @"\01?public_f@C@@UAEXXZ"
44*67e74705SXin Li   // MANGLING-DAG: @"\01?public_f@C@@W3AEXXZ"
45*67e74705SXin Li   // MANGLING-X64-DAG: @"\01?public_f@C@@UEAAXXZ"
46*67e74705SXin Li   // MANGLING-X64-DAG: @"\01?public_f@C@@W7EAAXXZ"
47*67e74705SXin Li  protected:
48*67e74705SXin Li   virtual void protected_f();
49*67e74705SXin Li   // MANGLING-DAG: @"\01?protected_f@C@@MAEXXZ"
50*67e74705SXin Li   // MANGLING-DAG: @"\01?protected_f@C@@O3AEXXZ"
51*67e74705SXin Li   // MANGLING-X64-DAG: @"\01?protected_f@C@@MEAAXXZ"
52*67e74705SXin Li   // MANGLING-X64-DAG: @"\01?protected_f@C@@O7EAAXXZ"
53*67e74705SXin Li 
54*67e74705SXin Li  private:
55*67e74705SXin Li   virtual void private_f();
56*67e74705SXin Li   // MANGLING-DAG: @"\01?private_f@C@@EAEXXZ"
57*67e74705SXin Li   // MANGLING-DAG: @"\01?private_f@C@@G3AEXXZ"
58*67e74705SXin Li   // MANGLING-X64-DAG: @"\01?private_f@C@@EEAAXXZ"
59*67e74705SXin Li   // MANGLING-X64-DAG: @"\01?private_f@C@@G7EAAXXZ"
60*67e74705SXin Li };
61*67e74705SXin Li 
C()62*67e74705SXin Li C::C() {}  // Emits vftable and forces thunk generation.
63*67e74705SXin Li 
64*67e74705SXin Li // CODEGEN-LABEL: define linkonce_odr x86_thiscallcc i8* @"\01??_EC@@W3AEPAXI@Z"(%struct.C* %this, i32 %should_call_delete) {{.*}} comdat
65*67e74705SXin Li // CODEGEN:   getelementptr i8, i8* {{.*}}, i32 -4
66*67e74705SXin Li // FIXME: should actually call _EC, not _GC.
67*67e74705SXin Li // CODEGEN:   call x86_thiscallcc i8* @"\01??_GC@@UAEPAXI@Z"
68*67e74705SXin Li // CODEGEN: ret
69*67e74705SXin Li 
70*67e74705SXin Li // CODEGEN-LABEL: define linkonce_odr x86_thiscallcc void @"\01?public_f@C@@W3AEXXZ"(%struct.C*
71*67e74705SXin Li // CODEGEN:   getelementptr i8, i8* {{.*}}, i32 -4
72*67e74705SXin Li // CODEGEN:   call x86_thiscallcc void @"\01?public_f@C@@UAEXXZ"(%struct.C*
73*67e74705SXin Li // CODEGEN: ret
74*67e74705SXin Li 
zoo(C * obj)75*67e74705SXin Li void zoo(C* obj) {
76*67e74705SXin Li   delete obj;
77*67e74705SXin Li }
78*67e74705SXin Li 
79*67e74705SXin Li struct D {
80*67e74705SXin Li   virtual B* goo();
81*67e74705SXin Li };
82*67e74705SXin Li 
83*67e74705SXin Li struct E : D {
84*67e74705SXin Li   E();
85*67e74705SXin Li   virtual C* goo();
86*67e74705SXin Li   // MANGLING-DAG: @"\01?goo@E@@UAEPAUC@@XZ"
87*67e74705SXin Li   // MANGLING-DAG: @"\01?goo@E@@QAEPAUB@@XZ"
88*67e74705SXin Li   // MANGLING-X64-DAG: @"\01?goo@E@@UEAAPEAUC@@XZ"
89*67e74705SXin Li   // MANGLING-X64-DAG: @"\01?goo@E@@QEAAPEAUB@@XZ"
90*67e74705SXin Li };
91*67e74705SXin Li 
E()92*67e74705SXin Li E::E() {}  // Emits vftable and forces thunk generation.
93*67e74705SXin Li 
94*67e74705SXin Li // CODEGEN-LABEL: define weak_odr x86_thiscallcc %struct.C* @"\01?goo@E@@QAEPAUB@@XZ"{{.*}} comdat
95*67e74705SXin Li // CODEGEN:   call x86_thiscallcc %struct.C* @"\01?goo@E@@UAEPAUC@@XZ"
96*67e74705SXin Li // CODEGEN:   getelementptr inbounds i8, i8* {{.*}}, i32 4
97*67e74705SXin Li // CODEGEN: ret
98*67e74705SXin Li 
99*67e74705SXin Li struct F : virtual A, virtual B {
100*67e74705SXin Li   virtual void own_method();
101*67e74705SXin Li   virtual ~F();
102*67e74705SXin Li };
103*67e74705SXin Li 
104*67e74705SXin Li F f;  // Just make sure we don't crash, e.g. mangling the complete dtor.
105*67e74705SXin Li 
106*67e74705SXin Li struct G : C { };
107*67e74705SXin Li 
108*67e74705SXin Li struct H : E {
109*67e74705SXin Li   virtual G* goo();
110*67e74705SXin Li   // MANGLING-DAG: @"\01?goo@H@@UAEPAUG@@XZ"
111*67e74705SXin Li   // MANGLING-DAG: @"\01?goo@H@@QAEPAUB@@XZ"
112*67e74705SXin Li   // MANGLING-DAG: @"\01?goo@H@@QAEPAUC@@XZ"
113*67e74705SXin Li   // MANGLING-X64-DAG: @"\01?goo@H@@UEAAPEAUG@@XZ"
114*67e74705SXin Li   // MANGLING-X64-DAG: @"\01?goo@H@@QEAAPEAUB@@XZ"
115*67e74705SXin Li   // MANGLING-X64-DAG: @"\01?goo@H@@QEAAPEAUC@@XZ"
116*67e74705SXin Li };
117*67e74705SXin Li 
118*67e74705SXin Li H h;
119*67e74705SXin Li 
120*67e74705SXin Li struct I : D {
121*67e74705SXin Li   I();
122*67e74705SXin Li   virtual F* goo();
123*67e74705SXin Li };
124*67e74705SXin Li 
I()125*67e74705SXin Li I::I() {}  // Emits vftable and forces thunk generation.
126*67e74705SXin Li 
127*67e74705SXin Li // CODEGEN-LABEL: define weak_odr x86_thiscallcc %struct.{{[BF]}}* @"\01?goo@I@@QAEPAUB@@XZ"{{.*}} comdat
128*67e74705SXin Li // CODEGEN: %[[ORIG_RET:.*]] = call x86_thiscallcc %struct.F* @"\01?goo@I@@UAEPAUF@@XZ"
129*67e74705SXin Li // CODEGEN: %[[ORIG_RET_i8:.*]] = bitcast %struct.F* %[[ORIG_RET]] to i8*
130*67e74705SXin Li // CODEGEN: %[[VBPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[ORIG_RET_i8]], i32 4
131*67e74705SXin Li // CODEGEN: %[[VBPTR:.*]] = bitcast i8* %[[VBPTR_i8]] to i32**
132*67e74705SXin Li // CODEGEN: %[[VBTABLE:.*]] = load i32*, i32** %[[VBPTR]]
133*67e74705SXin Li // CODEGEN: %[[VBASE_OFFSET_PTR:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 2
134*67e74705SXin Li // CODEGEN: %[[VBASE_OFFSET:.*]] = load i32, i32* %[[VBASE_OFFSET_PTR]]
135*67e74705SXin Li // CODEGEN: %[[RES_i8:.*]] = getelementptr inbounds i8, i8* %[[VBPTR_i8]], i32 %[[VBASE_OFFSET]]
136*67e74705SXin Li // CODEGEN: %[[RES:.*]] = bitcast i8* %[[RES_i8]] to %struct.F*
137*67e74705SXin Li // CODEGEN: phi %struct.F* {{.*}} %[[RES]]
138*67e74705SXin Li // CODEGEN: ret %struct.{{[BF]}}*
139*67e74705SXin Li 
140*67e74705SXin Li namespace CrashOnThunksForAttributedType {
141*67e74705SXin Li // We used to crash on this because the type of foo is an AttributedType, not
142*67e74705SXin Li // FunctionType, and we had to look through the sugar.
143*67e74705SXin Li struct A {
144*67e74705SXin Li   virtual void __stdcall foo();
145*67e74705SXin Li };
146*67e74705SXin Li struct B {
147*67e74705SXin Li   virtual void __stdcall foo();
148*67e74705SXin Li };
149*67e74705SXin Li struct C : A, B {
150*67e74705SXin Li   virtual void __stdcall foo();
151*67e74705SXin Li };
152*67e74705SXin Li C c;
153*67e74705SXin Li }
154*67e74705SXin Li 
155*67e74705SXin Li namespace {
156*67e74705SXin Li struct E : D {
157*67e74705SXin Li   E();
158*67e74705SXin Li   virtual C* goo();
159*67e74705SXin Li };
E()160*67e74705SXin Li E::E() {}
161*67e74705SXin Li E e;
162*67e74705SXin Li // Class with internal linkage has internal linkage thunks.
163*67e74705SXin Li // CODEGEN: define internal x86_thiscallcc %struct.C* @"\01?goo@E@?A@@QAEPAUB@@XZ"
164*67e74705SXin Li }
165