xref: /llvm-project/llvm/test/CodeGen/WebAssembly/vtable.ll (revision 73856247eef35f5336e485dc009842a5b991c421)
1; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s --check-prefix=TYPEINFONAME
2; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s --check-prefix=VTABLE
3; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s --check-prefix=TYPEINFO
4
5; Test that simple vtables assemble as expected.
6;
7; The class hierarchy is:
8;   struct A;
9;   struct B : public A;
10;   struct C : public A;
11;   struct D : public B;
12; Each with a virtual dtor and method foo.
13
14target triple = "wasm32-unknown-unknown"
15
16%struct.A = type { ptr }
17%struct.B = type { %struct.A }
18%struct.C = type { %struct.A }
19%struct.D = type { %struct.B }
20
21@_ZTVN10__cxxabiv117__class_type_infoE = external global ptr
22@_ZTVN10__cxxabiv120__si_class_type_infoE = external global ptr
23
24; TYPEINFONAME-LABEL: _ZTS1A:
25; TYPEINFONAME-NEXT: .asciz "1A"
26@_ZTS1A = constant [3 x i8] c"1A\00"
27; TYPEINFONAME-LABEL: _ZTS1B:
28; TYPEINFONAME-NEXT: .asciz "1B"
29@_ZTS1B = constant [3 x i8] c"1B\00"
30; TYPEINFONAME-LABEL: _ZTS1C:
31; TYPEINFONAME-NEXT: .asciz "1C"
32@_ZTS1C = constant [3 x i8] c"1C\00"
33; TYPEINFONAME-LABEL: _ZTS1D:
34; TYPEINFONAME-NEXT: .asciz "1D"
35@_ZTS1D = constant [3 x i8] c"1D\00"
36
37; VTABLE:       .type _ZTV1A,@object
38; VTABLE-NEXT:  .section .rodata._ZTV1A,
39; VTABLE-NEXT:  .globl _ZTV1A
40; VTABLE-LABEL: _ZTV1A:
41; VTABLE-NEXT:  .int32 0
42; VTABLE-NEXT:  .int32 _ZTI1A
43; VTABLE-NEXT:  .int32 _ZN1AD2Ev
44; VTABLE-NEXT:  .int32 _ZN1AD0Ev
45; VTABLE-NEXT:  .int32 _ZN1A3fooEv
46; VTABLE-NEXT:  .size _ZTV1A, 20
47@_ZTV1A = constant [5 x ptr] [ptr null, ptr @_ZTI1A, ptr @_ZN1AD2Ev, ptr @_ZN1AD0Ev, ptr @_ZN1A3fooEv], align 4
48; VTABLE:       .type _ZTV1B,@object
49; VTABLE-NEXT:  .section .rodata._ZTV1B,
50; VTABLE-NEXT:  .globl _ZTV1B
51; VTABLE-LABEL: _ZTV1B:
52; VTABLE-NEXT:  .int32 0
53; VTABLE-NEXT:  .int32 _ZTI1B
54; VTABLE-NEXT:  .int32 _ZN1AD2Ev
55; VTABLE-NEXT:  .int32 _ZN1BD0Ev
56; VTABLE-NEXT:  .int32 _ZN1B3fooEv
57; VTABLE-NEXT:  .size _ZTV1B, 20
58@_ZTV1B = constant [5 x ptr] [ptr null, ptr @_ZTI1B, ptr @_ZN1AD2Ev, ptr @_ZN1BD0Ev, ptr @_ZN1B3fooEv], align 4
59; VTABLE:       .type _ZTV1C,@object
60; VTABLE-NEXT:  .section .rodata._ZTV1C,
61; VTABLE-NEXT:  .globl _ZTV1C
62; VTABLE-LABEL: _ZTV1C:
63; VTABLE-NEXT:  .int32 0
64; VTABLE-NEXT:  .int32 _ZTI1C
65; VTABLE-NEXT:  .int32 _ZN1AD2Ev
66; VTABLE-NEXT:  .int32 _ZN1CD0Ev
67; VTABLE-NEXT:  .int32 _ZN1C3fooEv
68; VTABLE-NEXT:  .size _ZTV1C, 20
69@_ZTV1C = constant [5 x ptr] [ptr null, ptr @_ZTI1C, ptr @_ZN1AD2Ev, ptr @_ZN1CD0Ev, ptr @_ZN1C3fooEv], align 4
70; VTABLE:       .type _ZTV1D,@object
71; VTABLE-NEXT:  .section .rodata._ZTV1D,
72; VTABLE-NEXT:  .globl _ZTV1D
73; VTABLE-LABEL: _ZTV1D:
74; VTABLE-NEXT:  .int32 0
75; VTABLE-NEXT:  .int32 _ZTI1D
76; VTABLE-NEXT:  .int32 _ZN1AD2Ev
77; VTABLE-NEXT:  .int32 _ZN1DD0Ev
78; VTABLE-NEXT:  .int32 _ZN1D3fooEv
79; VTABLE-NEXT:  .size _ZTV1D, 20
80@_ZTV1D = constant [5 x ptr] [ptr null, ptr @_ZTI1D, ptr @_ZN1AD2Ev, ptr @_ZN1DD0Ev, ptr @_ZN1D3fooEv], align 4
81
82; TYPEINFO:       .type _ZTI1A,@object
83; TYPEINFO:       .globl _ZTI1A
84; TYPEINFO-LABEL: _ZTI1A:
85; TYPEINFO-NEXT:  .int32 _ZTVN10__cxxabiv117__class_type_infoE+8
86; TYPEINFO-NEXT:  .int32 _ZTS1A
87; TYPEINFO-NEXT:  .size _ZTI1A, 8
88@_ZTI1A = constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i32 2), ptr @_ZTS1A }
89; TYPEINFO:       .type _ZTI1B,@object
90; TYPEINFO:       .globl _ZTI1B
91; TYPEINFO-LABEL: _ZTI1B:
92; TYPEINFO-NEXT:  .int32 _ZTVN10__cxxabiv120__si_class_type_infoE+8
93; TYPEINFO-NEXT:  .int32 _ZTS1B
94; TYPEINFO-NEXT:  .int32 _ZTI1A
95; TYPEINFO-NEXT:  .size _ZTI1B, 12
96@_ZTI1B = constant { ptr, ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv120__si_class_type_infoE, i32 2), ptr @_ZTS1B, ptr @_ZTI1A }
97; TYPEINFO:       .type _ZTI1C,@object
98; TYPEINFO:       .globl _ZTI1C
99; TYPEINFO-LABEL: _ZTI1C:
100; TYPEINFO-NEXT:  .int32 _ZTVN10__cxxabiv120__si_class_type_infoE+8
101; TYPEINFO-NEXT:  .int32 _ZTS1C
102; TYPEINFO-NEXT:  .int32 _ZTI1A
103; TYPEINFO-NEXT:  .size _ZTI1C, 12
104@_ZTI1C = constant { ptr, ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv120__si_class_type_infoE, i32 2), ptr @_ZTS1C, ptr @_ZTI1A }
105; TYPEINFO:       .type _ZTI1D,@object
106; TYPEINFO:       .globl _ZTI1D
107; TYPEINFO-LABEL: _ZTI1D:
108; TYPEINFO-NEXT:  .int32 _ZTVN10__cxxabiv120__si_class_type_infoE+8
109; TYPEINFO-NEXT:  .int32 _ZTS1D
110; TYPEINFO-NEXT:  .int32 _ZTI1B
111; TYPEINFO-NEXT:  .size _ZTI1D, 12
112@_ZTI1D = constant { ptr, ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv120__si_class_type_infoE, i32 2), ptr @_ZTS1D, ptr @_ZTI1B }
113
114@g = global i32 0, align 4
115
116define void @_ZN1A3fooEv(ptr %this) {
117entry:
118  store i32 2, ptr @g, align 4
119  ret void
120}
121
122define void @_ZN1B3fooEv(ptr %this) {
123entry:
124  store i32 4, ptr @g, align 4
125  ret void
126}
127
128define void @_ZN1C3fooEv(ptr %this) {
129entry:
130  store i32 6, ptr @g, align 4
131  ret void
132}
133
134define void @_ZN1D3fooEv(ptr %this) {
135entry:
136  store i32 8, ptr @g, align 4
137  ret void
138}
139
140define linkonce_odr void @_ZN1AD0Ev(ptr %this) {
141entry:
142  tail call void @_ZdlPv(ptr %this)
143  ret void
144}
145
146define linkonce_odr void @_ZN1BD0Ev(ptr %this) {
147entry:
148  tail call void @_ZdlPv(ptr %this)
149  ret void
150}
151
152define linkonce_odr void @_ZN1CD0Ev(ptr %this) {
153entry:
154  tail call void @_ZdlPv(ptr %this)
155  ret void
156}
157
158define linkonce_odr ptr @_ZN1AD2Ev(ptr returned %this) {
159entry:
160  ret ptr %this
161}
162
163define linkonce_odr void @_ZN1DD0Ev(ptr %this) {
164entry:
165  tail call void @_ZdlPv(ptr %this)
166  ret void
167}
168
169declare void @_ZdlPv(ptr)
170