169 lines
5.4 KiB
LLVM
169 lines
5.4 KiB
LLVM
; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s --check-prefix=TYPEINFONAME
|
|
; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s --check-prefix=VTABLE
|
|
; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s --check-prefix=TYPEINFO
|
|
|
|
; Test that simple vtables assemble as expected.
|
|
;
|
|
; The class hierarchy is:
|
|
; struct A;
|
|
; struct B : public A;
|
|
; struct C : public A;
|
|
; struct D : public B;
|
|
; Each with a virtual dtor and method foo.
|
|
|
|
target triple = "wasm32-unknown-unknown"
|
|
|
|
%struct.A = type { ptr }
|
|
%struct.B = type { %struct.A }
|
|
%struct.C = type { %struct.A }
|
|
%struct.D = type { %struct.B }
|
|
|
|
@_ZTVN10__cxxabiv117__class_type_infoE = external global ptr
|
|
@_ZTVN10__cxxabiv120__si_class_type_infoE = external global ptr
|
|
|
|
; TYPEINFONAME-LABEL: _ZTS1A:
|
|
; TYPEINFONAME-NEXT: .asciz "1A"
|
|
@_ZTS1A = constant [3 x i8] c"1A\00"
|
|
; TYPEINFONAME-LABEL: _ZTS1B:
|
|
; TYPEINFONAME-NEXT: .asciz "1B"
|
|
@_ZTS1B = constant [3 x i8] c"1B\00"
|
|
; TYPEINFONAME-LABEL: _ZTS1C:
|
|
; TYPEINFONAME-NEXT: .asciz "1C"
|
|
@_ZTS1C = constant [3 x i8] c"1C\00"
|
|
; TYPEINFONAME-LABEL: _ZTS1D:
|
|
; TYPEINFONAME-NEXT: .asciz "1D"
|
|
@_ZTS1D = constant [3 x i8] c"1D\00"
|
|
|
|
; VTABLE: .type _ZTV1A,@object
|
|
; VTABLE-NEXT: .section .rodata._ZTV1A,
|
|
; VTABLE-NEXT: .globl _ZTV1A
|
|
; VTABLE-LABEL: _ZTV1A:
|
|
; VTABLE-NEXT: .int32 0
|
|
; VTABLE-NEXT: .int32 _ZTI1A
|
|
; VTABLE-NEXT: .int32 _ZN1AD2Ev
|
|
; VTABLE-NEXT: .int32 _ZN1AD0Ev
|
|
; VTABLE-NEXT: .int32 _ZN1A3fooEv
|
|
; VTABLE-NEXT: .size _ZTV1A, 20
|
|
@_ZTV1A = constant [5 x ptr] [ptr null, ptr @_ZTI1A, ptr @_ZN1AD2Ev, ptr @_ZN1AD0Ev, ptr @_ZN1A3fooEv], align 4
|
|
; VTABLE: .type _ZTV1B,@object
|
|
; VTABLE-NEXT: .section .rodata._ZTV1B,
|
|
; VTABLE-NEXT: .globl _ZTV1B
|
|
; VTABLE-LABEL: _ZTV1B:
|
|
; VTABLE-NEXT: .int32 0
|
|
; VTABLE-NEXT: .int32 _ZTI1B
|
|
; VTABLE-NEXT: .int32 _ZN1AD2Ev
|
|
; VTABLE-NEXT: .int32 _ZN1BD0Ev
|
|
; VTABLE-NEXT: .int32 _ZN1B3fooEv
|
|
; VTABLE-NEXT: .size _ZTV1B, 20
|
|
@_ZTV1B = constant [5 x ptr] [ptr null, ptr @_ZTI1B, ptr @_ZN1AD2Ev, ptr @_ZN1BD0Ev, ptr @_ZN1B3fooEv], align 4
|
|
; VTABLE: .type _ZTV1C,@object
|
|
; VTABLE-NEXT: .section .rodata._ZTV1C,
|
|
; VTABLE-NEXT: .globl _ZTV1C
|
|
; VTABLE-LABEL: _ZTV1C:
|
|
; VTABLE-NEXT: .int32 0
|
|
; VTABLE-NEXT: .int32 _ZTI1C
|
|
; VTABLE-NEXT: .int32 _ZN1AD2Ev
|
|
; VTABLE-NEXT: .int32 _ZN1CD0Ev
|
|
; VTABLE-NEXT: .int32 _ZN1C3fooEv
|
|
; VTABLE-NEXT: .size _ZTV1C, 20
|
|
@_ZTV1C = constant [5 x ptr] [ptr null, ptr @_ZTI1C, ptr @_ZN1AD2Ev, ptr @_ZN1CD0Ev, ptr @_ZN1C3fooEv], align 4
|
|
; VTABLE: .type _ZTV1D,@object
|
|
; VTABLE-NEXT: .section .rodata._ZTV1D,
|
|
; VTABLE-NEXT: .globl _ZTV1D
|
|
; VTABLE-LABEL: _ZTV1D:
|
|
; VTABLE-NEXT: .int32 0
|
|
; VTABLE-NEXT: .int32 _ZTI1D
|
|
; VTABLE-NEXT: .int32 _ZN1AD2Ev
|
|
; VTABLE-NEXT: .int32 _ZN1DD0Ev
|
|
; VTABLE-NEXT: .int32 _ZN1D3fooEv
|
|
; VTABLE-NEXT: .size _ZTV1D, 20
|
|
@_ZTV1D = constant [5 x ptr] [ptr null, ptr @_ZTI1D, ptr @_ZN1AD2Ev, ptr @_ZN1DD0Ev, ptr @_ZN1D3fooEv], align 4
|
|
|
|
; TYPEINFO: .type _ZTI1A,@object
|
|
; TYPEINFO: .globl _ZTI1A
|
|
; TYPEINFO-LABEL: _ZTI1A:
|
|
; TYPEINFO-NEXT: .int32 _ZTVN10__cxxabiv117__class_type_infoE+8
|
|
; TYPEINFO-NEXT: .int32 _ZTS1A
|
|
; TYPEINFO-NEXT: .size _ZTI1A, 8
|
|
@_ZTI1A = constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i32 2), ptr @_ZTS1A }
|
|
; TYPEINFO: .type _ZTI1B,@object
|
|
; TYPEINFO: .globl _ZTI1B
|
|
; TYPEINFO-LABEL: _ZTI1B:
|
|
; TYPEINFO-NEXT: .int32 _ZTVN10__cxxabiv120__si_class_type_infoE+8
|
|
; TYPEINFO-NEXT: .int32 _ZTS1B
|
|
; TYPEINFO-NEXT: .int32 _ZTI1A
|
|
; TYPEINFO-NEXT: .size _ZTI1B, 12
|
|
@_ZTI1B = constant { ptr, ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv120__si_class_type_infoE, i32 2), ptr @_ZTS1B, ptr @_ZTI1A }
|
|
; TYPEINFO: .type _ZTI1C,@object
|
|
; TYPEINFO: .globl _ZTI1C
|
|
; TYPEINFO-LABEL: _ZTI1C:
|
|
; TYPEINFO-NEXT: .int32 _ZTVN10__cxxabiv120__si_class_type_infoE+8
|
|
; TYPEINFO-NEXT: .int32 _ZTS1C
|
|
; TYPEINFO-NEXT: .int32 _ZTI1A
|
|
; TYPEINFO-NEXT: .size _ZTI1C, 12
|
|
@_ZTI1C = constant { ptr, ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv120__si_class_type_infoE, i32 2), ptr @_ZTS1C, ptr @_ZTI1A }
|
|
; TYPEINFO: .type _ZTI1D,@object
|
|
; TYPEINFO: .globl _ZTI1D
|
|
; TYPEINFO-LABEL: _ZTI1D:
|
|
; TYPEINFO-NEXT: .int32 _ZTVN10__cxxabiv120__si_class_type_infoE+8
|
|
; TYPEINFO-NEXT: .int32 _ZTS1D
|
|
; TYPEINFO-NEXT: .int32 _ZTI1B
|
|
; TYPEINFO-NEXT: .size _ZTI1D, 12
|
|
@_ZTI1D = constant { ptr, ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv120__si_class_type_infoE, i32 2), ptr @_ZTS1D, ptr @_ZTI1B }
|
|
|
|
@g = global i32 0, align 4
|
|
|
|
define void @_ZN1A3fooEv(ptr %this) {
|
|
entry:
|
|
store i32 2, ptr @g, align 4
|
|
ret void
|
|
}
|
|
|
|
define void @_ZN1B3fooEv(ptr %this) {
|
|
entry:
|
|
store i32 4, ptr @g, align 4
|
|
ret void
|
|
}
|
|
|
|
define void @_ZN1C3fooEv(ptr %this) {
|
|
entry:
|
|
store i32 6, ptr @g, align 4
|
|
ret void
|
|
}
|
|
|
|
define void @_ZN1D3fooEv(ptr %this) {
|
|
entry:
|
|
store i32 8, ptr @g, align 4
|
|
ret void
|
|
}
|
|
|
|
define linkonce_odr void @_ZN1AD0Ev(ptr %this) {
|
|
entry:
|
|
tail call void @_ZdlPv(ptr %this)
|
|
ret void
|
|
}
|
|
|
|
define linkonce_odr void @_ZN1BD0Ev(ptr %this) {
|
|
entry:
|
|
tail call void @_ZdlPv(ptr %this)
|
|
ret void
|
|
}
|
|
|
|
define linkonce_odr void @_ZN1CD0Ev(ptr %this) {
|
|
entry:
|
|
tail call void @_ZdlPv(ptr %this)
|
|
ret void
|
|
}
|
|
|
|
define linkonce_odr ptr @_ZN1AD2Ev(ptr returned %this) {
|
|
entry:
|
|
ret ptr %this
|
|
}
|
|
|
|
define linkonce_odr void @_ZN1DD0Ev(ptr %this) {
|
|
entry:
|
|
tail call void @_ZdlPv(ptr %this)
|
|
ret void
|
|
}
|
|
|
|
declare void @_ZdlPv(ptr)
|