Dan Gohman | 7d7409e | 2017-02-28 23:37:04 +0000 | [diff] [blame] | 1 | ; RUN: llc < %s -asm-verbose=false -disable-wasm-explicit-locals | FileCheck %s --check-prefix=TYPEINFONAME |
| 2 | ; RUN: llc < %s -asm-verbose=false -disable-wasm-explicit-locals | FileCheck %s --check-prefix=VTABLE |
| 3 | ; RUN: llc < %s -asm-verbose=false -disable-wasm-explicit-locals | FileCheck %s --check-prefix=TYPEINFO |
JF Bastien | 374ea4b | 2015-12-19 18:55:18 +0000 | [diff] [blame] | 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 | |
Dan Gohman | 0c6f5ac | 2016-01-07 03:19:23 +0000 | [diff] [blame] | 14 | target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" |
Dan Gohman | 7d7409e | 2017-02-28 23:37:04 +0000 | [diff] [blame] | 15 | target triple = "wasm32-unknown-unknown-wasm" |
JF Bastien | 374ea4b | 2015-12-19 18:55:18 +0000 | [diff] [blame] | 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 |
Dan Gohman | 7d7409e | 2017-02-28 23:37:04 +0000 | [diff] [blame] | 39 | ; VTABLE-NEXT: .section .data.rel.ro._ZTV1A, |
JF Bastien | 374ea4b | 2015-12-19 18:55:18 +0000 | [diff] [blame] | 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 |
Dan Gohman | 7d7409e | 2017-02-28 23:37:04 +0000 | [diff] [blame] | 50 | ; VTABLE-NEXT: .section .data.rel.ro._ZTV1B, |
JF Bastien | 374ea4b | 2015-12-19 18:55:18 +0000 | [diff] [blame] | 51 | ; VTABLE-NEXT: .globl _ZTV1B |
| 52 | ; VTABLE-LABEL: _ZTV1B: |
| 53 | ; VTABLE-NEXT: .int32 0 |
| 54 | ; VTABLE-NEXT: .int32 _ZTI1B |
| 55 | ; VTABLE-NEXT: .int32 _ZN1AD2Ev |
| 56 | ; VTABLE-NEXT: .int32 _ZN1BD0Ev |
| 57 | ; VTABLE-NEXT: .int32 _ZN1B3fooEv |
| 58 | ; VTABLE-NEXT: .size _ZTV1B, 20 |
| 59 | @_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 |
| 60 | ; VTABLE: .type _ZTV1C,@object |
Dan Gohman | 7d7409e | 2017-02-28 23:37:04 +0000 | [diff] [blame] | 61 | ; VTABLE-NEXT: .section .data.rel.ro._ZTV1C, |
JF Bastien | 374ea4b | 2015-12-19 18:55:18 +0000 | [diff] [blame] | 62 | ; VTABLE-NEXT: .globl _ZTV1C |
| 63 | ; VTABLE-LABEL: _ZTV1C: |
| 64 | ; VTABLE-NEXT: .int32 0 |
| 65 | ; VTABLE-NEXT: .int32 _ZTI1C |
| 66 | ; VTABLE-NEXT: .int32 _ZN1AD2Ev |
| 67 | ; VTABLE-NEXT: .int32 _ZN1CD0Ev |
| 68 | ; VTABLE-NEXT: .int32 _ZN1C3fooEv |
| 69 | ; VTABLE-NEXT: .size _ZTV1C, 20 |
| 70 | @_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 |
| 71 | ; VTABLE: .type _ZTV1D,@object |
Dan Gohman | 7d7409e | 2017-02-28 23:37:04 +0000 | [diff] [blame] | 72 | ; VTABLE-NEXT: .section .data.rel.ro._ZTV1D, |
JF Bastien | 374ea4b | 2015-12-19 18:55:18 +0000 | [diff] [blame] | 73 | ; VTABLE-NEXT: .globl _ZTV1D |
| 74 | ; VTABLE-LABEL: _ZTV1D: |
| 75 | ; VTABLE-NEXT: .int32 0 |
| 76 | ; VTABLE-NEXT: .int32 _ZTI1D |
| 77 | ; VTABLE-NEXT: .int32 _ZN1AD2Ev |
| 78 | ; VTABLE-NEXT: .int32 _ZN1DD0Ev |
| 79 | ; VTABLE-NEXT: .int32 _ZN1D3fooEv |
| 80 | ; VTABLE-NEXT: .size _ZTV1D, 20 |
| 81 | @_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 |
| 82 | |
| 83 | ; TYPEINFO: .type _ZTI1A,@object |
| 84 | ; TYPEINFO: .globl _ZTI1A |
| 85 | ; TYPEINFO-LABEL: _ZTI1A: |
| 86 | ; TYPEINFO-NEXT: .int32 _ZTVN10__cxxabiv117__class_type_infoE+8 |
| 87 | ; TYPEINFO-NEXT: .int32 _ZTS1A |
| 88 | ; TYPEINFO-NEXT: .size _ZTI1A, 8 |
| 89 | @_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) } |
| 90 | ; TYPEINFO: .type _ZTI1B,@object |
| 91 | ; TYPEINFO: .globl _ZTI1B |
| 92 | ; TYPEINFO-LABEL: _ZTI1B: |
| 93 | ; TYPEINFO-NEXT: .int32 _ZTVN10__cxxabiv120__si_class_type_infoE+8 |
| 94 | ; TYPEINFO-NEXT: .int32 _ZTS1B |
| 95 | ; TYPEINFO-NEXT: .int32 _ZTI1A |
| 96 | ; TYPEINFO-NEXT: .size _ZTI1B, 12 |
| 97 | @_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*) } |
| 98 | ; TYPEINFO: .type _ZTI1C,@object |
| 99 | ; TYPEINFO: .globl _ZTI1C |
| 100 | ; TYPEINFO-LABEL: _ZTI1C: |
| 101 | ; TYPEINFO-NEXT: .int32 _ZTVN10__cxxabiv120__si_class_type_infoE+8 |
| 102 | ; TYPEINFO-NEXT: .int32 _ZTS1C |
| 103 | ; TYPEINFO-NEXT: .int32 _ZTI1A |
| 104 | ; TYPEINFO-NEXT: .size _ZTI1C, 12 |
| 105 | @_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*) } |
| 106 | ; TYPEINFO: .type _ZTI1D,@object |
| 107 | ; TYPEINFO: .globl _ZTI1D |
| 108 | ; TYPEINFO-LABEL: _ZTI1D: |
| 109 | ; TYPEINFO-NEXT: .int32 _ZTVN10__cxxabiv120__si_class_type_infoE+8 |
| 110 | ; TYPEINFO-NEXT: .int32 _ZTS1D |
| 111 | ; TYPEINFO-NEXT: .int32 _ZTI1B |
| 112 | ; TYPEINFO-NEXT: .size _ZTI1D, 12 |
| 113 | @_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*) } |
| 114 | |
| 115 | @g = global i32 0, align 4 |
| 116 | |
| 117 | define void @_ZN1A3fooEv(%struct.A* %this) { |
| 118 | entry: |
| 119 | store i32 2, i32* @g, align 4 |
| 120 | ret void |
| 121 | } |
| 122 | |
| 123 | define void @_ZN1B3fooEv(%struct.B* %this) { |
| 124 | entry: |
| 125 | store i32 4, i32* @g, align 4 |
| 126 | ret void |
| 127 | } |
| 128 | |
| 129 | define void @_ZN1C3fooEv(%struct.C* %this) { |
| 130 | entry: |
| 131 | store i32 6, i32* @g, align 4 |
| 132 | ret void |
| 133 | } |
| 134 | |
| 135 | define void @_ZN1D3fooEv(%struct.D* %this) { |
| 136 | entry: |
| 137 | store i32 8, i32* @g, align 4 |
| 138 | ret void |
| 139 | } |
| 140 | |
| 141 | define linkonce_odr void @_ZN1AD0Ev(%struct.A* %this) { |
| 142 | entry: |
| 143 | %0 = bitcast %struct.A* %this to i8* |
| 144 | tail call void @_ZdlPv(i8* %0) |
| 145 | ret void |
| 146 | } |
| 147 | |
| 148 | define linkonce_odr void @_ZN1BD0Ev(%struct.B* %this) { |
| 149 | entry: |
| 150 | %0 = bitcast %struct.B* %this to i8* |
| 151 | tail call void @_ZdlPv(i8* %0) |
| 152 | ret void |
| 153 | } |
| 154 | |
| 155 | define linkonce_odr void @_ZN1CD0Ev(%struct.C* %this) { |
| 156 | entry: |
| 157 | %0 = bitcast %struct.C* %this to i8* |
| 158 | tail call void @_ZdlPv(i8* %0) |
| 159 | ret void |
| 160 | } |
| 161 | |
| 162 | define linkonce_odr %struct.A* @_ZN1AD2Ev(%struct.A* returned %this) { |
| 163 | entry: |
| 164 | ret %struct.A* %this |
| 165 | } |
| 166 | |
| 167 | define linkonce_odr void @_ZN1DD0Ev(%struct.D* %this) { |
| 168 | entry: |
| 169 | %0 = bitcast %struct.D* %this to i8* |
| 170 | tail call void @_ZdlPv(i8* %0) |
| 171 | ret void |
| 172 | } |
| 173 | |
| 174 | declare void @_ZdlPv(i8*) |