1
1
; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility %s | FileCheck %s
2
2
3
3
target datalayout = "e-p:64:64"
4
- target triple = "x86_64-unknown-linux-gnu"
5
4
6
- ; CHECK: [[VT1DATA:@[^ ]*]] = private constant { [8 x i8], [3 x ptr], [0 x i8] } { [8 x i8] c"\00\00\00\01\00\00\00\02", [3 x ptr] [ptr @vf0i1, ptr @vf1i1, ptr @vf1i32], [0 x i8] zeroinitializer }, section "vt1sec", !type [[T8:![0-9]+]]
5
+ ;; Note that i16 is used here such that we can ensure all constants for "typeid"
6
+ ;; can come before the vtable.
7
+ ; CHECK: [[VT1DATA:@[^ ]*]] = private constant { [8 x i8], [3 x ptr], [0 x i8] } { [8 x i8] c"\00\00\00\00\03\00\00\02", [3 x ptr] [ptr @vf0i1, ptr @vf1i1, ptr @vf1i16], [0 x i8] zeroinitializer }, section "vt1sec", !type [[T8:![0-9]+]]
7
8
@vt1 = constant [3 x ptr ] [
8
9
ptr @vf0i1 ,
9
10
ptr @vf1i1 ,
10
- ptr @vf1i32
11
+ ptr @vf1i16
11
12
], section "vt1sec" , !type !0
12
13
13
- ; CHECK: [[VT2DATA:@[^ ]*]] = private constant { [8 x i8], [3 x ptr], [0 x i8] } { [8 x i8] c"\00\00\00\02\ 00\00\00\01", [3 x ptr] [ptr @vf1i1, ptr @vf0i1, ptr @vf2i32 ], [0 x i8] zeroinitializer }, !type [[T8]]
14
+ ; CHECK: [[VT2DATA:@[^ ]*]] = private constant { [8 x i8], [3 x ptr], [0 x i8] } { [8 x i8] c"\00\00\00\00\04\ 00\00\01", [3 x ptr] [ptr @vf1i1, ptr @vf0i1, ptr @vf2i16 ], [0 x i8] zeroinitializer }, !type [[T8]]
14
15
@vt2 = constant [3 x ptr ] [
15
16
ptr @vf1i1 ,
16
17
ptr @vf0i1 ,
17
- ptr @vf2i32
18
+ ptr @vf2i16
18
19
], !type !0
19
20
20
- ; CHECK: [[VT3DATA:@[^ ]*]] = private constant { [5 x i8], [3 x ptr], [0 x i8] } { [5 x i8] c"\03 \00\00\00\ 02", [3 x ptr] [ptr @vf0i1, ptr @vf1i1, ptr @vf3i32 ], [0 x i8] zeroinitializer }, align 1 , !type [[T5:![0-9]+]]
21
+ ; CHECK: [[VT3DATA:@[^ ]*]] = private constant { [4 x i8], [3 x ptr], [0 x i8] } { [4 x i8] c"\05 \00\00\02", [3 x ptr] [ptr @vf0i1, ptr @vf1i1, ptr @vf3i16 ], [0 x i8] zeroinitializer }, align 2 , !type [[T5:![0-9]+]]
21
22
@vt3 = constant [3 x ptr ] [
22
23
ptr @vf0i1 ,
23
24
ptr @vf1i1 ,
24
- ptr @vf3i32
25
- ], align 1 , !type !0
25
+ ptr @vf3i16
26
+ ], align 2 , !type !0
26
27
27
- ; CHECK: [[VT4DATA:@[^ ]*]] = private constant { [16 x i8], [3 x ptr], [0 x i8] } { [16 x i8] c"\00\00\00\00\00\00\00\00\00\00\00\04\ 00\00\00\01", [3 x ptr] [ptr @vf1i1, ptr @vf0i1, ptr @vf4i32 ], [0 x i8] zeroinitializer }, align 16, !type [[T16:![0-9]+]]
28
+ ; CHECK: [[VT4DATA:@[^ ]*]] = private constant { [16 x i8], [3 x ptr], [0 x i8] } { [16 x i8] c"\00\00\00\00\00\00\00\00\00\00\00\00\06\ 00\00\01", [3 x ptr] [ptr @vf1i1, ptr @vf0i1, ptr @vf4i16 ], [0 x i8] zeroinitializer }, align 16, !type [[T16:![0-9]+]]
28
29
@vt4 = constant [3 x ptr ] [
29
30
ptr @vf1i1 ,
30
31
ptr @vf0i1 ,
31
- ptr @vf4i32
32
+ ptr @vf4i16
32
33
], align 16 , !type !0
33
34
34
35
; CHECK: @vt5 = {{.*}}, !type [[T0:![0-9]+]]
@@ -38,10 +39,35 @@ ptr @__cxa_pure_virtual,
38
39
ptr @__cxa_pure_virtual
39
40
], !type !0
40
41
42
+ ;; Test relative vtables
43
+ ; CHECK: [[VT6RELDATA:@[^ ]*]] = private constant { [4 x i8], [3 x i32], [0 x i8] } { [4 x i8] c"\00\00\03\00", [3 x i32] [
44
+ ; CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf0i1 to i64), i64 ptrtoint (ptr @vt6_rel to i64)) to i32),
45
+ ; CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf1i1 to i64), i64 ptrtoint (ptr @vt6_rel to i64)) to i32),
46
+ ; CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf1i16 to i64), i64 ptrtoint (ptr @vt6_rel to i64)) to i32)
47
+ ; CHECK-SAME: ], [0 x i8] zeroinitializer }, !type [[TREL:![0-9]+]]
48
+ @vt6_rel = constant [3 x i32 ] [
49
+ i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf0i1 to i64 ), i64 ptrtoint (ptr @vt6_rel to i64 )) to i32 ),
50
+ i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf1i1 to i64 ), i64 ptrtoint (ptr @vt6_rel to i64 )) to i32 ),
51
+ i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf1i16 to i64 ), i64 ptrtoint (ptr @vt6_rel to i64 )) to i32 )
52
+ ], !type !2
53
+
54
+ ; CHECK: [[VT7RELDATA:@[^ ]*]] = private constant { [4 x i8], [3 x i32], [0 x i8] } { [4 x i8] c"\00\00\04\00", [3 x i32] [
55
+ ; CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf1i1 to i64), i64 ptrtoint (ptr @vt7_rel to i64)) to i32),
56
+ ; CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf0i1 to i64), i64 ptrtoint (ptr @vt7_rel to i64)) to i32),
57
+ ; CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf2i16 to i64), i64 ptrtoint (ptr @vt7_rel to i64)) to i32)
58
+ ; CHECK-SAME: ], [0 x i8] zeroinitializer }, !type [[TREL]]
59
+ @vt7_rel = constant [3 x i32 ] [
60
+ i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf1i1 to i64 ), i64 ptrtoint (ptr @vt7_rel to i64 )) to i32 ),
61
+ i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf0i1 to i64 ), i64 ptrtoint (ptr @vt7_rel to i64 )) to i32 ),
62
+ i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf2i16 to i64 ), i64 ptrtoint (ptr @vt7_rel to i64 )) to i32 )
63
+ ], !type !2
64
+
41
65
; CHECK: @vt1 = alias [3 x ptr], getelementptr inbounds ({ [8 x i8], [3 x ptr], [0 x i8] }, ptr [[VT1DATA]], i32 0, i32 1)
42
66
; CHECK: @vt2 = alias [3 x ptr], getelementptr inbounds ({ [8 x i8], [3 x ptr], [0 x i8] }, ptr [[VT2DATA]], i32 0, i32 1)
43
- ; CHECK: @vt3 = alias [3 x ptr], getelementptr inbounds ({ [5 x i8], [3 x ptr], [0 x i8] }, ptr [[VT3DATA]], i32 0, i32 1)
67
+ ; CHECK: @vt3 = alias [3 x ptr], getelementptr inbounds ({ [4 x i8], [3 x ptr], [0 x i8] }, ptr [[VT3DATA]], i32 0, i32 1)
44
68
; CHECK: @vt4 = alias [3 x ptr], getelementptr inbounds ({ [16 x i8], [3 x ptr], [0 x i8] }, ptr [[VT4DATA]], i32 0, i32 1)
69
+ ; CHECK: @vt6_rel = alias [3 x i32], getelementptr inbounds ({ [4 x i8], [3 x i32], [0 x i8] }, ptr [[VT6RELDATA]], i32 0, i32 1)
70
+ ; CHECK: @vt7_rel = alias [3 x i32], getelementptr inbounds ({ [4 x i8], [3 x i32], [0 x i8] }, ptr [[VT7RELDATA]], i32 0, i32 1)
45
71
46
72
define i1 @vf0i1 (ptr %this ) readnone {
47
73
ret i1 0
@@ -51,20 +77,20 @@ define i1 @vf1i1(ptr %this) readnone {
51
77
ret i1 1
52
78
}
53
79
54
- define i32 @vf1i32 (ptr %this ) readnone {
55
- ret i32 1
80
+ define i16 @vf1i16 (ptr %this ) readnone {
81
+ ret i16 3
56
82
}
57
83
58
- define i32 @vf2i32 (ptr %this ) readnone {
59
- ret i32 2
84
+ define i16 @vf2i16 (ptr %this ) readnone {
85
+ ret i16 4
60
86
}
61
87
62
- define i32 @vf3i32 (ptr %this ) readnone {
63
- ret i32 3
88
+ define i16 @vf3i16 (ptr %this ) readnone {
89
+ ret i16 5
64
90
}
65
91
66
- define i32 @vf4i32 (ptr %this ) readnone {
67
- ret i32 4
92
+ define i16 @vf4i16 (ptr %this ) readnone {
93
+ ret i16 6
68
94
}
69
95
70
96
; CHECK: define i1 @call1(
@@ -87,7 +113,7 @@ define i1 @call2(ptr %obj) {
87
113
%vtable = load ptr , ptr %obj
88
114
%p = call i1 @llvm.type.test (ptr %vtable , metadata !"typeid" )
89
115
call void @llvm.assume (i1 %p )
90
- %fptrptr = getelementptr [3 x ptr ], ptr %vtable , i32 0 , i32 1
116
+ %fptrptr = getelementptr [3 x ptr ], ptr %vtable , i16 0 , i16 1
91
117
%fptr = load ptr , ptr %fptrptr
92
118
; CHECK: [[VTGEP2:%[^ ]*]] = getelementptr i8, ptr %vtable, i32 -1
93
119
; CHECK: [[VTLOAD2:%[^ ]*]] = load i8, ptr [[VTGEP2]]
@@ -98,27 +124,68 @@ define i1 @call2(ptr %obj) {
98
124
ret i1 %result
99
125
}
100
126
101
- ; CHECK: define i32 @call3(
102
- define i32 @call3 (ptr %obj ) {
127
+ ; CHECK: define i16 @call3(
128
+ define i16 @call3 (ptr %obj ) {
103
129
%vtable = load ptr , ptr %obj
104
130
%p = call i1 @llvm.type.test (ptr %vtable , metadata !"typeid" )
105
131
call void @llvm.assume (i1 %p )
106
- %fptrptr = getelementptr [3 x ptr ], ptr %vtable , i32 0 , i32 2
132
+ %fptrptr = getelementptr [3 x ptr ], ptr %vtable , i16 0 , i16 2
107
133
%fptr = load ptr , ptr %fptrptr
108
- ; CHECK: [[VTGEP3:%[^ ]*]] = getelementptr i8, ptr %vtable, i32 -5
109
- ; CHECK: [[VTLOAD3:%[^ ]*]] = load i32, ptr [[VTGEP3]]
110
- %result = call i32 %fptr (ptr %obj )
111
- ; CHECK: ret i32 [[VTLOAD3]]
112
- ret i32 %result
134
+ ; CHECK: [[VTGEP3:%[^ ]*]] = getelementptr i8, ptr %vtable, i32 -4
135
+ ; CHECK: [[VTLOAD3:%[^ ]*]] = load i16, ptr [[VTGEP3]]
136
+ %result = call i16 %fptr (ptr %obj )
137
+ ; CHECK: ret i16 [[VTLOAD3]]
138
+ ret i16 %result
139
+ }
140
+
141
+ ; CHECK: define i1 @call1_rel(
142
+ define i1 @call1_rel (ptr %obj ) {
143
+ %vtable = load ptr , ptr %obj
144
+ %p = call i1 @llvm.type.test (ptr %vtable , metadata !"typeid3" )
145
+ call void @llvm.assume (i1 %p )
146
+ %fptr = call ptr @llvm.load.relative.i32 (ptr %vtable , i32 0 )
147
+ %result = call i1 %fptr (ptr %obj )
148
+ ret i1 %result
149
+ ; CHECK: [[RES:%[^ ]*]] = icmp eq ptr %vtable, @vt7_rel
150
+ ; CHECK: ret i1 [[RES]]
151
+ }
152
+
153
+ ; CHECK: define i1 @call2_rel(
154
+ define i1 @call2_rel (ptr %obj ) {
155
+ %vtable = load ptr , ptr %obj
156
+ %p = call i1 @llvm.type.test (ptr %vtable , metadata !"typeid3" )
157
+ call void @llvm.assume (i1 %p )
158
+ %fptr = call ptr @llvm.load.relative.i32 (ptr %vtable , i32 4 )
159
+ %result = call i1 %fptr (ptr %obj )
160
+ ret i1 %result
161
+ ; CHECK: [[RES:%[^ ]*]] = icmp eq ptr %vtable, @vt6_rel
162
+ ; CHECK: ret i1 [[RES]]
163
+ }
164
+
165
+ ; CHECK: define i16 @call3_rel(
166
+ define i16 @call3_rel (ptr %obj ) {
167
+ %vtable = load ptr , ptr %obj
168
+ %p = call i1 @llvm.type.test (ptr %vtable , metadata !"typeid3" )
169
+ call void @llvm.assume (i1 %p )
170
+ %fptr = call ptr @llvm.load.relative.i32 (ptr %vtable , i32 8 )
171
+ ; CHECK: [[VTGEP3:%[^ ]*]] = getelementptr i8, ptr %vtable, i32 -2
172
+ ; CHECK: [[VTLOAD3:%[^ ]*]] = load i16, ptr [[VTGEP3]]
173
+ %result = call i16 %fptr (ptr %obj )
174
+ ; CHECK: ret i16 [[VTLOAD3]]
175
+ ret i16 %result
113
176
}
114
177
115
178
declare i1 @llvm.type.test (ptr , metadata )
116
179
declare void @llvm.assume (i1 )
117
180
declare void @__cxa_pure_virtual ()
181
+ declare ptr @llvm.load.relative.i32 (ptr , i32 )
118
182
119
183
; CHECK: [[T8]] = !{i32 8, !"typeid"}
120
- ; CHECK: [[T5]] = !{i32 5 , !"typeid"}
184
+ ; CHECK: [[T5]] = !{i32 4 , !"typeid"}
121
185
; CHECK: [[T16]] = !{i32 16, !"typeid"}
122
186
; CHECK: [[T0]] = !{i32 0, !"typeid"}
187
+ ; CHECK: [[TREL]] = !{i32 4, !"typeid3"}
123
188
124
189
!0 = !{i32 0 , !"typeid" }
190
+ !1 = !{i32 0 , !"typeid2" }
191
+ !2 = !{i32 0 , !"typeid3" }
0 commit comments