xref: /aosp_15_r20/external/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o - | FileCheck %s
2*67e74705SXin Li 
3*67e74705SXin Li // For now, just make sure x86_64 doesn't crash.
4*67e74705SXin Li // RUN: %clang_cc1 %s -fno-rtti -triple=x86_64-pc-win32 -emit-llvm -o %t
5*67e74705SXin Li 
6*67e74705SXin Li struct A {
7*67e74705SXin Li   virtual void f();
8*67e74705SXin Li };
9*67e74705SXin Li 
10*67e74705SXin Li struct B {
11*67e74705SXin Li   virtual void f();
12*67e74705SXin Li };
13*67e74705SXin Li 
14*67e74705SXin Li struct C : A, B {};
15*67e74705SXin Li 
16*67e74705SXin Li struct D : virtual C {
17*67e74705SXin Li   D();
18*67e74705SXin Li   ~D();
19*67e74705SXin Li   virtual void f();
20*67e74705SXin Li   void g();
21*67e74705SXin Li   int xxx;
22*67e74705SXin Li };
23*67e74705SXin Li 
D()24*67e74705SXin Li D::D() {}  // Forces vftable emission.
25*67e74705SXin Li 
26*67e74705SXin Li // CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01?f@D@@$4PPPPPPPM@A@AEXXZ"
27*67e74705SXin Li // CHECK: %[[ECX:.*]] = load %struct.D*, %struct.D** %{{.*}}
28*67e74705SXin Li // CHECK: %[[ECX_i8:.*]] = bitcast %struct.D* %[[ECX]] to i8*
29*67e74705SXin Li // CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr inbounds i8, i8* %[[ECX_i8]], i32 -4
30*67e74705SXin Li // CHECK: %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_PTR_i8]] to i32*
31*67e74705SXin Li // CHECK: %[[VTORDISP:.*]] = load i32, i32* %[[VTORDISP_PTR]]
32*67e74705SXin Li // CHECK: %[[VTORDISP_NEG:.*]] = sub i32 0, %[[VTORDISP]]
33*67e74705SXin Li // CHECK: %[[ADJUSTED_i8:.*]] = getelementptr i8, i8* %[[ECX_i8]], i32 %[[VTORDISP_NEG]]
34*67e74705SXin Li // CHECK: call x86_thiscallcc void @"\01?f@D@@UAEXXZ"(i8* %[[ADJUSTED_i8]])
35*67e74705SXin Li // CHECK: ret void
36*67e74705SXin Li 
37*67e74705SXin Li // CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01?f@D@@$4PPPPPPPI@3AEXXZ"
38*67e74705SXin Li // CHECK: %[[ECX:.*]] = load %struct.D*, %struct.D** %{{.*}}
39*67e74705SXin Li // CHECK: %[[ECX_i8:.*]] = bitcast %struct.D* %[[ECX]] to i8*
40*67e74705SXin Li // CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr inbounds i8, i8* %[[ECX_i8]], i32 -8
41*67e74705SXin Li // CHECK: %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_PTR_i8]] to i32*
42*67e74705SXin Li // CHECK: %[[VTORDISP:.*]] = load i32, i32* %[[VTORDISP_PTR]]
43*67e74705SXin Li // CHECK: %[[VTORDISP_NEG:.*]] = sub i32 0, %[[VTORDISP]]
44*67e74705SXin Li // CHECK: %[[VTORDISP_ADJUSTED_i8:.*]] = getelementptr i8, i8* %[[ECX_i8]], i32 %[[VTORDISP_NEG]]
45*67e74705SXin Li // CHECK: %[[ADJUSTED_i8:.*]] = getelementptr i8, i8* %[[VTORDISP_ADJUSTED_i8]], i32 -4
46*67e74705SXin Li // CHECK: call x86_thiscallcc void @"\01?f@D@@UAEXXZ"(i8* %[[ADJUSTED_i8]])
47*67e74705SXin Li // CHECK: ret void
48*67e74705SXin Li 
49*67e74705SXin Li struct E : virtual A {
50*67e74705SXin Li   virtual void f();
51*67e74705SXin Li   ~E();
52*67e74705SXin Li };
53*67e74705SXin Li 
54*67e74705SXin Li struct F {
55*67e74705SXin Li   virtual void z();
56*67e74705SXin Li };
57*67e74705SXin Li 
58*67e74705SXin Li struct G : virtual F, virtual E {
59*67e74705SXin Li   int ggg;
60*67e74705SXin Li   G();
61*67e74705SXin Li   ~G();
62*67e74705SXin Li };
63*67e74705SXin Li 
G()64*67e74705SXin Li G::G() {}  // Forces vftable emission.
65*67e74705SXin Li 
66*67e74705SXin Li // CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01?f@E@@$R4BA@M@PPPPPPPM@7AEXXZ"(i8*)
67*67e74705SXin Li // CHECK: %[[ECX:.*]] = load %struct.E*, %struct.E** %{{.*}}
68*67e74705SXin Li // CHECK: %[[ECX_i8:.*]] = bitcast %struct.E* %[[ECX]] to i8*
69*67e74705SXin Li // CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr inbounds i8, i8* %[[ECX_i8]], i32 -4
70*67e74705SXin Li // CHECK: %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_PTR_i8]] to i32*
71*67e74705SXin Li // CHECK: %[[VTORDISP:.*]] = load i32, i32* %[[VTORDISP_PTR]]
72*67e74705SXin Li // CHECK: %[[VTORDISP_NEG:.*]] = sub i32 0, %[[VTORDISP]]
73*67e74705SXin Li // CHECK: %[[VTORDISP_ADJUSTED_i8:.*]] = getelementptr i8, i8* %[[ECX_i8]], i32 %[[VTORDISP_NEG]]
74*67e74705SXin Li // CHECK: %[[VBPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[VTORDISP_ADJUSTED_i8]], i32 -16
75*67e74705SXin Li // CHECK: %[[VBPTR:.*]] = bitcast i8* %[[VBPTR_i8]] to i32**
76*67e74705SXin Li // CHECK: %[[VBTABLE:.*]] = load i32*, i32** %[[VBPTR]]
77*67e74705SXin Li // CHECK: %[[VBOFFSET_PTR:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 3
78*67e74705SXin Li // CHECK: %[[VBASE_OFFSET:.*]] = load i32, i32* %[[VBOFFSET_PTR]]
79*67e74705SXin Li // CHECK: %[[VBASE:.*]] = getelementptr inbounds i8, i8* %[[VBPTR_i8]], i32 %[[VBASE_OFFSET]]
80*67e74705SXin Li // CHECK: %[[ARG_i8:.*]] = getelementptr i8, i8* %[[VBASE]], i32 8
81*67e74705SXin Li // CHECK: call x86_thiscallcc void @"\01?f@E@@UAEXXZ"(i8* %[[ARG_i8]])
82*67e74705SXin Li // CHECK: ret void
83