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