## This test reproduces the case where C++ exception handling is used and split
## function optimization is enabled. In particular, function foo is splitted
## to two fragments:
## foo: contains 2 try blocks, which invokes bar to throw exception
## foo.cold.1: contains 2 corresponding catch blocks (landing pad)
##
## Similar to split jump table, split landing pad target to different fragment.
## This test is written to ensure BOLT safely handle these targets, e.g., by
## marking them as non-simple.
##
## Steps to write this test:
## - Create a copy of Inputs/src/unreachable.cpp
## - Simplify bar(), focus on throw an exception
## - Create the second switch case in foo() to have multiple landing pads
## - Compile with clang++ to .s
## - Move landing pad code from foo to foo.cold.1
## - Ensure that all landing pads can be reached normally
##
## Additional details:
## .gcc_except_table specify the landing pads for try blocks
## LPStart = 255 (omit), which means LPStart = foo start
## Landing pads .Ltmp2 and .Ltmp5 in call site record are offset to foo start.
# REQUIRES: system-linux
# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o
# RUN: %clang++ %cxxflags %t.o -o %t.exe -Wl,-q
# RUN: llvm-bolt -v=3 %t.exe -o %t.out 2>&1 | FileCheck %s
# CHECK: BOLT-WARNING: Ignoring foo
# CHECK: BOLT-WARNING: Ignoring foo.cold.1
# CHECK: BOLT-WARNING: skipped 2 functions due to cold fragments
.text
.globl bar # -- Begin function bar
.p2align 4, 0x90
.type bar,@function
bar: # @bar
.cfi_startproc
# %bb.0: # %entry
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq $16, %rsp
movq %rdi, -8(%rbp)
cmpq $34, -8(%rbp)
jne .LBB0_2
# %bb.1: # %if.then
movl $4, %edi
callq __cxa_allocate_exception@PLT
movq %rax, %rdi
movl $0, (%rdi)
movq _ZTIi@GOTPCREL(%rip), %rsi
xorl %eax, %eax
movl %eax, %edx
callq __cxa_throw@PLT
.LBB0_2: # %if.else
movl $8, %edi
callq __cxa_allocate_exception@PLT
movq %rax, %rdi
movq $0, (%rdi)
movq _ZTIDn@GOTPCREL(%rip), %rsi
xorl %eax, %eax
movl %eax, %edx
callq __cxa_throw@PLT
.Lfunc_end0:
.size bar, .Lfunc_end0-bar
.cfi_endproc
# -- End function
.globl foo # -- Begin function foo
.p2align 4, 0x90
.type foo,@function
foo: # @foo
.Lfunc_begin0:
.cfi_startproc
.cfi_personality 155, DW.ref.__gxx_personality_v0
.cfi_lsda 27, .Lexception0
# %bb.0: # %entry
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq $48, %rsp
movq %rdi, -16(%rbp)
movq -16(%rbp), %rdi
.Ltmp0:
callq bar
.Ltmp1:
jmp .LBB1_1
.LBB1_1: # %invoke.cont
jmp .LBB1_5
.LBB1_5: # %try.cont
movq -16(%rbp), %rdi
addq $34, %rdi
.Ltmp3:
callq bar
.Ltmp4:
jmp .LBB1_6
.LBB1_6: # %invoke.cont2
jmp .LBB1_10
.LBB1_10: # %try.cont8
movq $0, -8(%rbp)
.LBB1_11: # %return
movq -8(%rbp), %rax
addq $48, %rsp
popq %rbp
.cfi_def_cfa %rsp, 8
retq
.LBB1_12: # %eh.resume
.cfi_def_cfa %rbp, 16
movq -24(%rbp), %rdi
callq _Unwind_Resume@PLT
.Lfunc_end1:
.size foo, .Lfunc_end1-foo
.cfi_endproc
.section .gcc_except_table,"a",@progbits
.p2align 2
GCC_except_table1:
.Lexception0:
.byte 255 # @LPStart Encoding = omit
.byte 155 # @TType Encoding = indirect pcrel sdata4
.uleb128 .Lttbase0-.Lttbaseref0
.Lttbaseref0:
.byte 1 # Call site Encoding = uleb128
.uleb128 .Lcst_end0-.Lcst_begin0
.Lcst_begin0:
.uleb128 .Ltmp0-.Lfunc_begin0 # >> Call Site 1 <<
.uleb128 .Ltmp1-.Ltmp0 # Call between .Ltmp0 and .Ltmp1
.uleb128 .Ltmp2-.Lfunc_begin0 # jumps to .Ltmp2
.byte 1 # On action: 1
.uleb128 .Ltmp1-.Lfunc_begin0 # >> Call Site 2 <<
.uleb128 .Ltmp3-.Ltmp1 # Call between .Ltmp1 and .Ltmp3
.byte 0 # has no landing pad
.byte 0 # On action: cleanup
.uleb128 .Ltmp3-.Lfunc_begin0 # >> Call Site 3 <<
.uleb128 .Ltmp4-.Ltmp3 # Call between .Ltmp3 and .Ltmp4
.uleb128 .Ltmp5-.Lfunc_begin0 # jumps to .Ltmp5
.byte 1 # On action: 1
.uleb128 .Ltmp4-.Lfunc_begin0 # >> Call Site 4 <<
.uleb128 .Lfunc_end1-.Ltmp4 # Call between .Ltmp4 and .Lfunc_end1
.byte 0 # has no landing pad
.byte 0 # On action: cleanup
.Lcst_end0:
.byte 1 # >> Action Record 1 <<
# Catch TypeInfo 1
.byte 0 # No further actions
.p2align 2
# >> Catch TypeInfos <<
.Ltmp6: # TypeInfo 1
.long .L_ZTIi.DW.stub-.Ltmp6
.Lttbase0:
.p2align 2
# -- End function
.text
.globl foo.cold.1 # -- Begin function foo.cold.1
.p2align 4, 0x90
.type foo.cold.1,@function
foo.cold.1: # @foo.cold.1
.Lfunc_begin3:
.cfi_startproc
.Ltmp2:
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -24(%rbp)
movl %eax, -28(%rbp)
# %bb.3: # %catch.dispatch
movl -28(%rbp), %eax
movl $1, %ecx
cmpl %ecx, %eax
jne .LBB1_12
# %bb.4: # %catch
movq -24(%rbp), %rdi
callq __cxa_begin_catch@PLT
movl (%rax), %eax
movl %eax, -32(%rbp)
movq $0, -8(%rbp)
callq __cxa_end_catch@PLT
jmp .LBB1_11
.Ltmp5:
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -24(%rbp)
movl %eax, -28(%rbp)
# %bb.8: # %catch.dispatch3
movl -28(%rbp), %eax
movl $1, %ecx
cmpl %ecx, %eax
jne .LBB1_12
# %bb.9: # %catch6
movq -24(%rbp), %rdi
callq __cxa_begin_catch@PLT
movl (%rax), %eax
movl %eax, -36(%rbp)
movq $0, -8(%rbp)
callq __cxa_end_catch@PLT
jmp .LBB1_11
.Lfunc_end3:
.size foo.cold.1, .Lfunc_end3-foo.cold.1
.cfi_endproc
.text
.globl main # -- Begin function main
.p2align 4, 0x90
.type main,@function
main: # @main
.cfi_startproc
# %bb.0: # %entry
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq $16, %rsp
movl $0, -4(%rbp)
movl %edi, -8(%rbp)
movq %rsi, -16(%rbp)
xorl %eax, %eax
movl %eax, %edi
callq foo
# kill: def $eax killed $eax killed $rax
addq $16, %rsp
popq %rbp
.cfi_def_cfa %rsp, 8
retq
.Lfunc_end2:
.size main, .Lfunc_end2-main
.cfi_endproc
# -- End function
.data
.p2align 3
.L_ZTIi.DW.stub:
.quad _ZTIi
.hidden DW.ref.__gxx_personality_v0
.weak DW.ref.__gxx_personality_v0
.section .data.DW.ref.__gxx_personality_v0,"aGw",@progbits,DW.ref.__gxx_personality_v0,comdat
.p2align 3
.type DW.ref.__gxx_personality_v0,@object
.size DW.ref.__gxx_personality_v0, 8
DW.ref.__gxx_personality_v0:
.quad __gxx_personality_v0
.section ".note.GNU-stack","",@progbits
.addrsig
.addrsig_sym bar
.addrsig_sym __cxa_allocate_exception
.addrsig_sym __cxa_throw
.addrsig_sym foo
.addrsig_sym __gxx_personality_v0
.addrsig_sym __cxa_begin_catch
.addrsig_sym __cxa_end_catch
.addrsig_sym _Unwind_Resume
.addrsig_sym _ZTIi
.addrsig_sym _ZTIDn
.addrsig_sym foo.cold.1
.addrsig_sym __cxa_begin_catch
.addrsig_sym __cxa_end_catch