xref: /llvm-project/bolt/test/runtime/X86/jt-confusion.s (revision 43d0891d3bb1fc40ff5dcea91c28d1582978caff)
1# REQUIRES: system-linux
2
3# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o
4# RUN: llvm-strip --strip-unneeded %t.o
5# RUN: %clang %cflags -no-pie -nostartfiles -nostdlib -lc %t.o -o %t.exe -Wl,-q
6
7# RUN: llvm-bolt %t.exe -o %t.exe.bolt --relocs=1 --lite=0
8
9# RUN: %t.exe.bolt
10
11## Check that BOLT's jump table detection diffrentiates between
12## __builtin_unreachable() targets and function pointers.
13
14## The test case was built from the following two source files and
15## modiffied for standalone build. main became _start, etc.
16## $ $(CC) a.c -O1 -S -o a.s
17## $ $(CC) b.c -O0 -S -o b.s
18
19## a.c:
20
21## typedef int (*fptr)(int);
22## void check_fptr(fptr, int);
23##
24## int foo(int a) {
25##   check_fptr(foo, 0);
26##   switch (a) {
27##   default:
28##     __builtin_unreachable();
29##   case 0:
30##     return 3;
31##   case 1:
32##     return 5;
33##   case 2:
34##     return 7;
35##   case 3:
36##     return 11;
37##   case 4:
38##     return 13;
39##   case 5:
40##     return 17;
41##   }
42##   return 0;
43## }
44##
45## int main(int argc) {
46##   check_fptr(main, 1);
47##   return foo(argc);
48## }
49##
50## const fptr funcs[2] = {foo, main};
51
52## b.c.:
53
54## typedef int (*fptr)(int);
55## extern const fptr funcs[2];
56##
57## #define assert(C) { if (!(C)) (*(unsigned long long *)0) = 0; }
58## void check_fptr(fptr f, int i) {
59##   assert(f == funcs[i]);
60## }
61
62
63	.text
64	.globl	foo
65	.type	foo, @function
66foo:
67.LFB0:
68	.cfi_startproc
69	pushq	%rbx
70	.cfi_def_cfa_offset 16
71	.cfi_offset 3, -16
72	movl	%edi, %ebx
73	movl	$0, %esi
74	movl	$foo, %edi
75	call	check_fptr
76	movl	%ebx, %ebx
77	jmp	*.L4(,%rbx,8)
78.L8:
79	movl	$5, %eax
80	jmp	.L1
81.L7:
82	movl	$7, %eax
83	jmp	.L1
84.L6:
85	movl	$11, %eax
86	jmp	.L1
87.L5:
88	movl	$13, %eax
89	jmp	.L1
90.L3:
91	movl	$17, %eax
92	jmp	.L1
93.L10:
94	movl	$3, %eax
95.L1:
96	popq	%rbx
97	.cfi_def_cfa_offset 8
98	ret
99	.cfi_endproc
100.LFE0:
101	.size	foo, .-foo
102	.globl	_start
103	.type	_start, @function
104_start:
105.LFB1:
106	.cfi_startproc
107	pushq	%rbx
108	.cfi_def_cfa_offset 16
109	.cfi_offset 3, -16
110	movl	%edi, %ebx
111	movl	$1, %esi
112	movl	$_start, %edi
113	call	check_fptr
114	movl	$1, %edi
115	call	foo
116	popq	%rbx
117	.cfi_def_cfa_offset 8
118  callq exit@PLT
119	.cfi_endproc
120.LFE1:
121	.size	_start, .-_start
122	.globl	check_fptr
123	.type	check_fptr, @function
124check_fptr:
125.LFB2:
126	.cfi_startproc
127	pushq	%rbp
128	.cfi_def_cfa_offset 16
129	.cfi_offset 6, -16
130	movq	%rsp, %rbp
131	.cfi_def_cfa_register 6
132	movq	%rdi, -8(%rbp)
133	movl	%esi, -12(%rbp)
134	movl	-12(%rbp), %eax
135	cltq
136	movq	funcs(,%rax,8), %rax
137	cmpq	%rax, -8(%rbp)
138	je	.L33
139	movl	$0, %eax
140	movq	$0, (%rax)
141.L33:
142	nop
143	popq	%rbp
144	.cfi_def_cfa 7, 8
145	ret
146	.cfi_endproc
147
148	.section	.rodata
149	.align 8
150	.align 4
151.L4:
152	.quad	.L10
153	.quad	.L8
154	.quad	.L7
155	.quad	.L6
156	.quad	.L5
157	.quad	.L3
158
159	.globl	funcs
160	.type	funcs, @object
161	.size	funcs, 16
162funcs:
163	.quad	foo
164	.quad	_start
165