1; RUN: llc < %s -asm-verbose=false | FileCheck %s --check-prefix=TYPEINFONAME 2; RUN: llc < %s -asm-verbose=false | FileCheck %s --check-prefix=VTABLE 3; RUN: llc < %s -asm-verbose=false | 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 datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" 15target triple = "wasm32-unknown-unknown" 16 17%struct.A = type { i32 (...)** } 18%struct.B = type { %struct.A } 19%struct.C = type { %struct.A } 20%struct.D = type { %struct.B } 21 22@_ZTVN10__cxxabiv117__class_type_infoE = external global i8* 23@_ZTVN10__cxxabiv120__si_class_type_infoE = external global i8* 24 25; TYPEINFONAME-LABEL: _ZTS1A: 26; TYPEINFONAME-NEXT: .asciz "1A" 27@_ZTS1A = constant [3 x i8] c"1A\00" 28; TYPEINFONAME-LABEL: _ZTS1B: 29; TYPEINFONAME-NEXT: .asciz "1B" 30@_ZTS1B = constant [3 x i8] c"1B\00" 31; TYPEINFONAME-LABEL: _ZTS1C: 32; TYPEINFONAME-NEXT: .asciz "1C" 33@_ZTS1C = constant [3 x i8] c"1C\00" 34; TYPEINFONAME-LABEL: _ZTS1D: 35; TYPEINFONAME-NEXT: .asciz "1D" 36@_ZTS1D = constant [3 x i8] c"1D\00" 37 38; VTABLE: .type _ZTV1A,@object 39; VTABLE-NEXT: .section .data.rel.ro,"aw",@progbits 40; VTABLE-NEXT: .globl _ZTV1A 41; VTABLE-LABEL: _ZTV1A: 42; VTABLE-NEXT: .int32 0 43; VTABLE-NEXT: .int32 _ZTI1A 44; VTABLE-NEXT: .int32 _ZN1AD2Ev 45; VTABLE-NEXT: .int32 _ZN1AD0Ev 46; VTABLE-NEXT: .int32 _ZN1A3fooEv 47; VTABLE-NEXT: .size _ZTV1A, 20 48@_ZTV1A = constant [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast (%struct.A* (%struct.A*)* @_ZN1AD2Ev to i8*), i8* bitcast (void (%struct.A*)* @_ZN1AD0Ev to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A3fooEv to i8*)], align 4 49; VTABLE: .type _ZTV1B,@object 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 i8*] [i8* null, i8* bitcast ({ i8*, i8*, i8* }* @_ZTI1B to i8*), i8* bitcast (%struct.A* (%struct.A*)* @_ZN1AD2Ev to i8*), i8* bitcast (void (%struct.B*)* @_ZN1BD0Ev to i8*), i8* bitcast (void (%struct.B*)* @_ZN1B3fooEv to i8*)], align 4 59; VTABLE: .type _ZTV1C,@object 60; VTABLE-NEXT: .globl _ZTV1C 61; VTABLE-LABEL: _ZTV1C: 62; VTABLE-NEXT: .int32 0 63; VTABLE-NEXT: .int32 _ZTI1C 64; VTABLE-NEXT: .int32 _ZN1AD2Ev 65; VTABLE-NEXT: .int32 _ZN1CD0Ev 66; VTABLE-NEXT: .int32 _ZN1C3fooEv 67; VTABLE-NEXT: .size _ZTV1C, 20 68@_ZTV1C = constant [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8*, i8* }* @_ZTI1C to i8*), i8* bitcast (%struct.A* (%struct.A*)* @_ZN1AD2Ev to i8*), i8* bitcast (void (%struct.C*)* @_ZN1CD0Ev to i8*), i8* bitcast (void (%struct.C*)* @_ZN1C3fooEv to i8*)], align 4 69; VTABLE: .type _ZTV1D,@object 70; VTABLE-NEXT: .globl _ZTV1D 71; VTABLE-LABEL: _ZTV1D: 72; VTABLE-NEXT: .int32 0 73; VTABLE-NEXT: .int32 _ZTI1D 74; VTABLE-NEXT: .int32 _ZN1AD2Ev 75; VTABLE-NEXT: .int32 _ZN1DD0Ev 76; VTABLE-NEXT: .int32 _ZN1D3fooEv 77; VTABLE-NEXT: .size _ZTV1D, 20 78@_ZTV1D = constant [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8*, i8* }* @_ZTI1D to i8*), i8* bitcast (%struct.A* (%struct.A*)* @_ZN1AD2Ev to i8*), i8* bitcast (void (%struct.D*)* @_ZN1DD0Ev to i8*), i8* bitcast (void (%struct.D*)* @_ZN1D3fooEv to i8*)], align 4 79 80; TYPEINFO: .type _ZTI1A,@object 81; TYPEINFO: .globl _ZTI1A 82; TYPEINFO-LABEL: _ZTI1A: 83; TYPEINFO-NEXT: .int32 _ZTVN10__cxxabiv117__class_type_infoE+8 84; TYPEINFO-NEXT: .int32 _ZTS1A 85; TYPEINFO-NEXT: .size _ZTI1A, 8 86@_ZTI1A = constant { i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv117__class_type_infoE, i32 2) to i8*), i8* getelementptr inbounds ([3 x i8], [3 x i8]* @_ZTS1A, i32 0, i32 0) } 87; TYPEINFO: .type _ZTI1B,@object 88; TYPEINFO: .globl _ZTI1B 89; TYPEINFO-LABEL: _ZTI1B: 90; TYPEINFO-NEXT: .int32 _ZTVN10__cxxabiv120__si_class_type_infoE+8 91; TYPEINFO-NEXT: .int32 _ZTS1B 92; TYPEINFO-NEXT: .int32 _ZTI1A 93; TYPEINFO-NEXT: .size _ZTI1B, 12 94@_ZTI1B = constant { i8*, i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv120__si_class_type_infoE, i32 2) to i8*), i8* getelementptr inbounds ([3 x i8], [3 x i8]* @_ZTS1B, i32 0, i32 0), i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*) } 95; TYPEINFO: .type _ZTI1C,@object 96; TYPEINFO: .globl _ZTI1C 97; TYPEINFO-LABEL: _ZTI1C: 98; TYPEINFO-NEXT: .int32 _ZTVN10__cxxabiv120__si_class_type_infoE+8 99; TYPEINFO-NEXT: .int32 _ZTS1C 100; TYPEINFO-NEXT: .int32 _ZTI1A 101; TYPEINFO-NEXT: .size _ZTI1C, 12 102@_ZTI1C = constant { i8*, i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv120__si_class_type_infoE, i32 2) to i8*), i8* getelementptr inbounds ([3 x i8], [3 x i8]* @_ZTS1C, i32 0, i32 0), i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*) } 103; TYPEINFO: .type _ZTI1D,@object 104; TYPEINFO: .globl _ZTI1D 105; TYPEINFO-LABEL: _ZTI1D: 106; TYPEINFO-NEXT: .int32 _ZTVN10__cxxabiv120__si_class_type_infoE+8 107; TYPEINFO-NEXT: .int32 _ZTS1D 108; TYPEINFO-NEXT: .int32 _ZTI1B 109; TYPEINFO-NEXT: .size _ZTI1D, 12 110@_ZTI1D = constant { i8*, i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv120__si_class_type_infoE, i32 2) to i8*), i8* getelementptr inbounds ([3 x i8], [3 x i8]* @_ZTS1D, i32 0, i32 0), i8* bitcast ({ i8*, i8*, i8* }* @_ZTI1B to i8*) } 111 112@g = global i32 0, align 4 113 114define void @_ZN1A3fooEv(%struct.A* %this) { 115entry: 116 store i32 2, i32* @g, align 4 117 ret void 118} 119 120define void @_ZN1B3fooEv(%struct.B* %this) { 121entry: 122 store i32 4, i32* @g, align 4 123 ret void 124} 125 126define void @_ZN1C3fooEv(%struct.C* %this) { 127entry: 128 store i32 6, i32* @g, align 4 129 ret void 130} 131 132define void @_ZN1D3fooEv(%struct.D* %this) { 133entry: 134 store i32 8, i32* @g, align 4 135 ret void 136} 137 138define linkonce_odr void @_ZN1AD0Ev(%struct.A* %this) { 139entry: 140 %0 = bitcast %struct.A* %this to i8* 141 tail call void @_ZdlPv(i8* %0) 142 ret void 143} 144 145define linkonce_odr void @_ZN1BD0Ev(%struct.B* %this) { 146entry: 147 %0 = bitcast %struct.B* %this to i8* 148 tail call void @_ZdlPv(i8* %0) 149 ret void 150} 151 152define linkonce_odr void @_ZN1CD0Ev(%struct.C* %this) { 153entry: 154 %0 = bitcast %struct.C* %this to i8* 155 tail call void @_ZdlPv(i8* %0) 156 ret void 157} 158 159define linkonce_odr %struct.A* @_ZN1AD2Ev(%struct.A* returned %this) { 160entry: 161 ret %struct.A* %this 162} 163 164define linkonce_odr void @_ZN1DD0Ev(%struct.D* %this) { 165entry: 166 %0 = bitcast %struct.D* %this to i8* 167 tail call void @_ZdlPv(i8* %0) 168 ret void 169} 170 171declare void @_ZdlPv(i8*) 172