11; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility %s | FileCheck %s
22
33target datalayout = "e-p:64:64"
4- target triple = "x86_64-unknown-linux-gnu"
54
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. For this particular file, the intention is to only
7+ ;; look at constants placed before the vtable, but with the next change, this
8+ ;; would place the original i32s after the vtable due to extra padding needed to
9+ ;; preserve alignment. Making them i16s allows them to stay at the beginning of
10+ ;; the vtable. There are other tests where there's a mix of constants before and
11+ ;; after the vtable but for this file we just want everything before the vtable.
12+ ; CHECK: [[VT1DATA:@[^ ]*]] = private constant { [8 x i8], [3 x ptr], [0 x i8] } { [8 x i8] c"\00\00\00\00\00\03\00\02", [3 x ptr] [ptr @vf0i1, ptr @vf1i1, ptr @vf1i16], [0 x i8] zeroinitializer }, section "vt1sec", !type [[T8:![0-9]+]]
713@vt1 = constant [3 x ptr ] [
814ptr @vf0i1 ,
915ptr @vf1i1 ,
10- ptr @vf1i32
16+ ptr @vf1i16
1117], section "vt1sec" , !type !0
1218
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]]
19+ ; CHECK: [[VT2DATA:@[^ ]*]] = private constant { [8 x i8], [3 x ptr], [0 x i8] } { [8 x i8] c"\00\00\00\00\00\04\ 00\01", [3 x ptr] [ptr @vf1i1, ptr @vf0i1, ptr @vf2i16 ], [0 x i8] zeroinitializer }, !type [[T8]]
1420@vt2 = constant [3 x ptr ] [
1521ptr @vf1i1 ,
1622ptr @vf0i1 ,
17- ptr @vf2i32
23+ ptr @vf2i16
1824], !type !0
1925
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]+]]
26+ ; CHECK: [[VT3DATA:@[^ ]*]] = private constant { [4 x i8], [3 x ptr], [0 x i8] } { [4 x i8] c"\00\05 \00\02", [3 x ptr] [ptr @vf0i1, ptr @vf1i1, ptr @vf3i16 ], [0 x i8] zeroinitializer }, align 2 , !type [[T5:![0-9]+]]
2127@vt3 = constant [3 x ptr ] [
2228ptr @vf0i1 ,
2329ptr @vf1i1 ,
24- ptr @vf3i32
25- ], align 1 , !type !0
30+ ptr @vf3i16
31+ ], align 2 , !type !0
2632
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]+]]
33+ ; 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\00\06\ 00\01", [3 x ptr] [ptr @vf1i1, ptr @vf0i1, ptr @vf4i16 ], [0 x i8] zeroinitializer }, align 16, !type [[T16:![0-9]+]]
2834@vt4 = constant [3 x ptr ] [
2935ptr @vf1i1 ,
3036ptr @vf0i1 ,
31- ptr @vf4i32
37+ ptr @vf4i16
3238], align 16 , !type !0
3339
3440; CHECK: @vt5 = {{.*}}, !type [[T0:![0-9]+]]
@@ -38,10 +44,35 @@ ptr @__cxa_pure_virtual,
3844ptr @__cxa_pure_virtual
3945], !type !0
4046
47+ ;; Test relative vtables
48+ ; CHECK: [[VT6RELDATA:@[^ ]*]] = private constant { [4 x i8], [3 x i32], [0 x i8] } { [4 x i8] c"\00\00\03\00", [3 x i32] [
49+ ; CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf0i1 to i64), i64 ptrtoint (ptr @vt6_rel to i64)) to i32),
50+ ; CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf1i1 to i64), i64 ptrtoint (ptr @vt6_rel to i64)) to i32),
51+ ; CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf1i16 to i64), i64 ptrtoint (ptr @vt6_rel to i64)) to i32)
52+ ; CHECK-SAME: ], [0 x i8] zeroinitializer }, !type [[TREL:![0-9]+]]
53+ @vt6_rel = constant [3 x i32 ] [
54+ i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf0i1 to i64 ), i64 ptrtoint (ptr @vt6_rel to i64 )) to i32 ),
55+ i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf1i1 to i64 ), i64 ptrtoint (ptr @vt6_rel to i64 )) to i32 ),
56+ i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf1i16 to i64 ), i64 ptrtoint (ptr @vt6_rel to i64 )) to i32 )
57+ ], !type !2
58+
59+ ; CHECK: [[VT7RELDATA:@[^ ]*]] = private constant { [4 x i8], [3 x i32], [0 x i8] } { [4 x i8] c"\00\00\04\00", [3 x i32] [
60+ ; CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf1i1 to i64), i64 ptrtoint (ptr @vt7_rel to i64)) to i32),
61+ ; CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf0i1 to i64), i64 ptrtoint (ptr @vt7_rel to i64)) to i32),
62+ ; CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf2i16 to i64), i64 ptrtoint (ptr @vt7_rel to i64)) to i32)
63+ ; CHECK-SAME: ], [0 x i8] zeroinitializer }, !type [[TREL]]
64+ @vt7_rel = constant [3 x i32 ] [
65+ i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf1i1 to i64 ), i64 ptrtoint (ptr @vt7_rel to i64 )) to i32 ),
66+ i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf0i1 to i64 ), i64 ptrtoint (ptr @vt7_rel to i64 )) to i32 ),
67+ i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf2i16 to i64 ), i64 ptrtoint (ptr @vt7_rel to i64 )) to i32 )
68+ ], !type !2
69+
4170; CHECK: @vt1 = alias [3 x ptr], getelementptr inbounds ({ [8 x i8], [3 x ptr], [0 x i8] }, ptr [[VT1DATA]], i32 0, i32 1)
4271; 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)
72+ ; CHECK: @vt3 = alias [3 x ptr], getelementptr inbounds ({ [4 x i8], [3 x ptr], [0 x i8] }, ptr [[VT3DATA]], i32 0, i32 1)
4473; CHECK: @vt4 = alias [3 x ptr], getelementptr inbounds ({ [16 x i8], [3 x ptr], [0 x i8] }, ptr [[VT4DATA]], i32 0, i32 1)
74+ ; CHECK: @vt6_rel = alias [3 x i32], getelementptr inbounds ({ [4 x i8], [3 x i32], [0 x i8] }, ptr [[VT6RELDATA]], i32 0, i32 1)
75+ ; CHECK: @vt7_rel = alias [3 x i32], getelementptr inbounds ({ [4 x i8], [3 x i32], [0 x i8] }, ptr [[VT7RELDATA]], i32 0, i32 1)
4576
4677define i1 @vf0i1 (ptr %this ) readnone {
4778 ret i1 0
@@ -51,20 +82,20 @@ define i1 @vf1i1(ptr %this) readnone {
5182 ret i1 1
5283}
5384
54- define i32 @vf1i32 (ptr %this ) readnone {
55- ret i32 1
85+ define i16 @vf1i16 (ptr %this ) readnone {
86+ ret i16 3
5687}
5788
58- define i32 @vf2i32 (ptr %this ) readnone {
59- ret i32 2
89+ define i16 @vf2i16 (ptr %this ) readnone {
90+ ret i16 4
6091}
6192
62- define i32 @vf3i32 (ptr %this ) readnone {
63- ret i32 3
93+ define i16 @vf3i16 (ptr %this ) readnone {
94+ ret i16 5
6495}
6596
66- define i32 @vf4i32 (ptr %this ) readnone {
67- ret i32 4
97+ define i16 @vf4i16 (ptr %this ) readnone {
98+ ret i16 6
6899}
69100
70101; CHECK: define i1 @call1(
@@ -87,7 +118,7 @@ define i1 @call2(ptr %obj) {
87118 %vtable = load ptr , ptr %obj
88119 %p = call i1 @llvm.type.test (ptr %vtable , metadata !"typeid" )
89120 call void @llvm.assume (i1 %p )
90- %fptrptr = getelementptr [3 x ptr ], ptr %vtable , i32 0 , i32 1
121+ %fptrptr = getelementptr [3 x ptr ], ptr %vtable , i16 0 , i16 1
91122 %fptr = load ptr , ptr %fptrptr
92123 ; CHECK: [[VTGEP2:%[^ ]*]] = getelementptr i8, ptr %vtable, i32 -1
93124 ; CHECK: [[VTLOAD2:%[^ ]*]] = load i8, ptr [[VTGEP2]]
@@ -98,27 +129,68 @@ define i1 @call2(ptr %obj) {
98129 ret i1 %result
99130}
100131
101- ; CHECK: define i32 @call3(
102- define i32 @call3 (ptr %obj ) {
132+ ; CHECK: define i16 @call3(
133+ define i16 @call3 (ptr %obj ) {
103134 %vtable = load ptr , ptr %obj
104135 %p = call i1 @llvm.type.test (ptr %vtable , metadata !"typeid" )
105136 call void @llvm.assume (i1 %p )
106- %fptrptr = getelementptr [3 x ptr ], ptr %vtable , i32 0 , i32 2
137+ %fptrptr = getelementptr [3 x ptr ], ptr %vtable , i16 0 , i16 2
107138 %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
139+ ; CHECK: [[VTGEP3:%[^ ]*]] = getelementptr i8, ptr %vtable, i32 -3
140+ ; CHECK: [[VTLOAD3:%[^ ]*]] = load i16, ptr [[VTGEP3]]
141+ %result = call i16 %fptr (ptr %obj )
142+ ; CHECK: ret i16 [[VTLOAD3]]
143+ ret i16 %result
144+ }
145+
146+ ; CHECK: define i1 @call1_rel(
147+ define i1 @call1_rel (ptr %obj ) {
148+ %vtable = load ptr , ptr %obj
149+ %p = call i1 @llvm.type.test (ptr %vtable , metadata !"typeid3" )
150+ call void @llvm.assume (i1 %p )
151+ %fptr = call ptr @llvm.load.relative.i32 (ptr %vtable , i32 0 )
152+ %result = call i1 %fptr (ptr %obj )
153+ ret i1 %result
154+ ; CHECK: [[RES:%[^ ]*]] = icmp eq ptr %vtable, @vt7_rel
155+ ; CHECK: ret i1 [[RES]]
156+ }
157+
158+ ; CHECK: define i1 @call2_rel(
159+ define i1 @call2_rel (ptr %obj ) {
160+ %vtable = load ptr , ptr %obj
161+ %p = call i1 @llvm.type.test (ptr %vtable , metadata !"typeid3" )
162+ call void @llvm.assume (i1 %p )
163+ %fptr = call ptr @llvm.load.relative.i32 (ptr %vtable , i32 4 )
164+ %result = call i1 %fptr (ptr %obj )
165+ ret i1 %result
166+ ; CHECK: [[RES:%[^ ]*]] = icmp eq ptr %vtable, @vt6_rel
167+ ; CHECK: ret i1 [[RES]]
168+ }
169+
170+ ; CHECK: define i16 @call3_rel(
171+ define i16 @call3_rel (ptr %obj ) {
172+ %vtable = load ptr , ptr %obj
173+ %p = call i1 @llvm.type.test (ptr %vtable , metadata !"typeid3" )
174+ call void @llvm.assume (i1 %p )
175+ %fptr = call ptr @llvm.load.relative.i32 (ptr %vtable , i32 8 )
176+ ; CHECK: [[VTGEP3:%[^ ]*]] = getelementptr i8, ptr %vtable, i32 -2
177+ ; CHECK: [[VTLOAD3:%[^ ]*]] = load i16, ptr [[VTGEP3]]
178+ %result = call i16 %fptr (ptr %obj )
179+ ; CHECK: ret i16 [[VTLOAD3]]
180+ ret i16 %result
113181}
114182
115183declare i1 @llvm.type.test (ptr , metadata )
116184declare void @llvm.assume (i1 )
117185declare void @__cxa_pure_virtual ()
186+ declare ptr @llvm.load.relative.i32 (ptr , i32 )
118187
119188; CHECK: [[T8]] = !{i32 8, !"typeid"}
120- ; CHECK: [[T5]] = !{i32 5 , !"typeid"}
189+ ; CHECK: [[T5]] = !{i32 4 , !"typeid"}
121190; CHECK: [[T16]] = !{i32 16, !"typeid"}
122191; CHECK: [[T0]] = !{i32 0, !"typeid"}
192+ ; CHECK: [[TREL]] = !{i32 4, !"typeid3"}
123193
124194!0 = !{i32 0 , !"typeid" }
195+ !1 = !{i32 0 , !"typeid2" }
196+ !2 = !{i32 0 , !"typeid3" }
0 commit comments