# REQUIRES: system-linux # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags -no-pie -nostartfiles -nostdlib -lc %t.o -o %t.exe -Wl,-q # RUN: llvm-bolt %t.exe -o %t.exe.bolt --relocs=1 --lite=0 # RUN: %t.exe.bolt ## Check that BOLT's jump table detection diffrentiates between ## __builtin_unreachable() targets and function pointers. ## The test case was built from the following two source files and ## modiffied for standalone build. main became _start, etc. ## $ $(CC) a.c -O1 -S -o a.s ## $ $(CC) b.c -O0 -S -o b.s ## a.c: ## typedef int (*fptr)(int); ## void check_fptr(fptr, int); ## ## int foo(int a) { ## check_fptr(foo, 0); ## switch (a) { ## default: ## __builtin_unreachable(); ## case 0: ## return 3; ## case 1: ## return 5; ## case 2: ## return 7; ## case 3: ## return 11; ## case 4: ## return 13; ## case 5: ## return 17; ## } ## return 0; ## } ## ## int main(int argc) { ## check_fptr(main, 1); ## return foo(argc); ## } ## ## const fptr funcs[2] = {foo, main}; ## b.c.: ## typedef int (*fptr)(int); ## extern const fptr funcs[2]; ## ## #define assert(C) { if (!(C)) (*(unsigned long long *)0) = 0; } ## void check_fptr(fptr f, int i) { ## assert(f == funcs[i]); ## } .text .globl foo .type foo, @function foo: .LFB0: .cfi_startproc pushq %rbx .cfi_def_cfa_offset 16 .cfi_offset 3, -16 movl %edi, %ebx movl $0, %esi movl $foo, %edi call check_fptr movl %ebx, %ebx jmp *.L4(,%rbx,8) .L8: movl $5, %eax jmp .L1 .L7: movl $7, %eax jmp .L1 .L6: movl $11, %eax jmp .L1 .L5: movl $13, %eax jmp .L1 .L3: movl $17, %eax jmp .L1 .L10: movl $3, %eax .L1: popq %rbx .cfi_def_cfa_offset 8 ret .cfi_endproc .LFE0: .size foo, .-foo .globl _start .type _start, @function _start: .LFB1: .cfi_startproc pushq %rbx .cfi_def_cfa_offset 16 .cfi_offset 3, -16 movl %edi, %ebx movl $1, %esi movl $_start, %edi call check_fptr movl $1, %edi call foo popq %rbx .cfi_def_cfa_offset 8 callq exit@PLT .cfi_endproc .LFE1: .size _start, .-_start .globl check_fptr .type check_fptr, @function check_fptr: .LFB2: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movq %rdi, -8(%rbp) movl %esi, -12(%rbp) movl -12(%rbp), %eax cltq movq funcs(,%rax,8), %rax cmpq %rax, -8(%rbp) je .L33 movl $0, %eax movq $0, (%rax) .L33: nop popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .section .rodata .align 8 .align 4 .L4: .quad .L10 .quad .L8 .quad .L7 .quad .L6 .quad .L5 .quad .L3 .globl funcs .type funcs, @object .size funcs, 16 funcs: .quad foo .quad _start