1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
| ; RUN: opt -lowertypetests -S %s | FileCheck --check-prefix=FULL %s
; RUN: opt -lowertypetests -lowertypetests-summary-action=import -lowertypetests-read-summary=%p/Inputs/cfi-direct-call1.yaml -S %s | FileCheck --check-prefix=THIN %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux"
define hidden i32 @local_func1() !type !3 !type !4 {
ret i32 11
}
define hidden i32 @local_func2() !type !3 !type !4 {
ret i32 22
}
define hidden i32 @local_func3(i32 %i) local_unnamed_addr !type !5 !type !6 {
entry:
%add = add nsw i32 %i, 44
ret i32 %add
}
declare !type !3 !type !4 extern_weak i32 @extern_weak()
declare !type !3 !type !4 i32 @extern_decl()
declare i1 @llvm.type.test(i8*, metadata)
define hidden i32 @main(i32 %argc) {
entry:
%cmp.i = icmp sgt i32 %argc, 1
%fptr1 = select i1 %cmp.i, i32 ()* @local_func1, i32 ()* @local_func2
%fptr2 = select i1 %cmp.i, i32 ()* @extern_weak, i32 ()* @extern_decl
%0 = bitcast i32 ()* %fptr1 to i8*
%1 = tail call i1 @llvm.type.test(i8* nonnull %0, metadata !"_ZTSFivE")
%call2 = tail call i32 %fptr1()
%2 = bitcast i32 ()* %fptr2 to i8*
%3 = tail call i1 @llvm.type.test(i8* %2, metadata !"_ZTSFivE")
%call4 = tail call i32 %fptr2()
%call5 = tail call i32 @extern_decl()
%call7 = tail call i32 @extern_weak()
%call6 = tail call i32 @local_func1()
%call8 = tail call i32 @local_func3(i32 4)
ret i32 12
}
!3 = !{i64 0, !"_ZTSFivE"}
!4 = !{i64 0, !"_ZTSFivE.generalized"}
!5 = !{i64 0, !"_ZTSFiiE"}
!6 = !{i64 0, !"_ZTSFiiE.generalized"}
; Make sure local_func1 and local_func2 have been renamed to <name>.cfi
; FULL: define hidden i32 @local_func1.cfi()
; FULL: define hidden i32 @local_func2.cfi()
; There are no indirect calls of local_func3 type, it should not be renamed
; FULL: define hidden i32 @local_func3(i32 %i)
; Indirect references to local_func1 and local_func2 must to through jump table
; FULL: %fptr1 = select i1 %cmp.i, i32 ()* @local_func1, i32 ()* @local_func2
; Indirect references to extern_weak and extern_decl must go through jump table
; FULL: %fptr2 = select i1 %cmp.i, i32 ()* select (i1 icmp ne (i32 ()* @extern_weak, i32 ()* null), i32 ()* bitcast ([8 x i8]* getelementptr inbounds ([4 x [8 x i8]], [4 x [8 x i8]]* bitcast (void ()* @.cfi.jumptable to [4 x [8 x i8]]*), i64 0, i64 2) to i32 ()*), i32 ()* null), i32 ()* bitcast ([8 x i8]* getelementptr inbounds ([4 x [8 x i8]], [4 x [8 x i8]]* bitcast (void ()* @.cfi.jumptable to [4 x [8 x i8]]*), i64 0, i64 3) to i32 ()*)
; Direct calls to extern_weak and extern_decl should go to original names
; FULL: %call5 = tail call i32 @extern_decl()
; FULL: %call7 = tail call i32 @extern_weak()
; Direct call to local_func1 should to the renamed version
; FULL: %call6 = tail call i32 @local_func1.cfi()
; local_func3 hasn't been renamed, direct call should go to the original name
; FULL: %call8 = tail call i32 @local_func3(i32 4)
; Check which jump table entries are created
; FULL: define private void @.cfi.jumptable(){{.*}}
; FULL-NEXT: entry:
; FULL-NEXT: call void asm{{.*}}local_func1.cfi{{.*}}local_func2.cfi{{.*}}extern_weak{{.*}}extern_decl
; Make sure all local functions have been renamed to <name>.cfi
; THIN: define hidden i32 @local_func1.cfi()
; THIN: define hidden i32 @local_func2.cfi()
; THIN: define hidden i32 @local_func3.cfi(i32 %i){{.*}}
; Indirect references to local_func1 and local_func2 must to through jump table
; THIN: %fptr1 = select i1 %cmp.i, i32 ()* @local_func1, i32 ()* @local_func2
; Indirect references to extern_weak and extern_decl must go through jump table
; THIN: %fptr2 = select i1 %cmp.i, i32 ()* select (i1 icmp ne (i32 ()* @extern_weak, i32 ()* null), i32 ()* @extern_weak.cfi_jt, i32 ()* null), i32 ()* @extern_decl.cfi_jt
; Direct calls to extern_weak and extern_decl should go to original names
; THIN: %call5 = tail call i32 @extern_decl()
; THIN: %call7 = tail call i32 @extern_weak()
; Direct call to local_func1 should to the renamed version
; THIN: %call6 = tail call i32 @local_func1.cfi()
; THIN: %call8 = tail call i32 @local_func3.cfi(i32 4)
|