1## This test reproduces the case where C++ exception handling is used and split 2## function optimization is enabled. In particular, function foo is splitted 3## to two fragments: 4## foo: contains 2 try blocks, which invokes bar to throw exception 5## foo.cold.1: contains 2 corresponding catch blocks (landing pad) 6## 7## Similar to split jump table, split landing pad target to different fragment. 8## This test is written to ensure BOLT safely handle these targets, e.g., by 9## marking them as non-simple. 10## 11## Steps to write this test: 12## - Create a copy of Inputs/src/unreachable.cpp 13## - Simplify bar(), focus on throw an exception 14## - Create the second switch case in foo() to have multiple landing pads 15## - Compile with clang++ to .s 16## - Move landing pad code from foo to foo.cold.1 17## - Ensure that all landing pads can be reached normally 18## 19## Additional details: 20## .gcc_except_table specify the landing pads for try blocks 21## LPStart = 255 (omit), which means LPStart = foo start 22## Landing pads .Ltmp2 and .Ltmp5 in call site record are offset to foo start. 23 24 25# REQUIRES: system-linux 26# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o 27# RUN: %clang++ %cxxflags %t.o -o %t.exe -Wl,-q 28# RUN: llvm-bolt -v=3 %t.exe -o %t.out 2>&1 | FileCheck %s 29 30# CHECK: BOLT-WARNING: Ignoring foo 31# CHECK: BOLT-WARNING: Ignoring foo.cold.1 32# CHECK: BOLT-WARNING: skipped 2 functions due to cold fragments 33 34 .text 35 .globl bar # -- Begin function bar 36 .p2align 4, 0x90 37 .type bar,@function 38bar: # @bar 39 .cfi_startproc 40# %bb.0: # %entry 41 pushq %rbp 42 .cfi_def_cfa_offset 16 43 .cfi_offset %rbp, -16 44 movq %rsp, %rbp 45 .cfi_def_cfa_register %rbp 46 subq $16, %rsp 47 movq %rdi, -8(%rbp) 48 cmpq $34, -8(%rbp) 49 jne .LBB0_2 50# %bb.1: # %if.then 51 movl $4, %edi 52 callq __cxa_allocate_exception@PLT 53 movq %rax, %rdi 54 movl $0, (%rdi) 55 movq _ZTIi@GOTPCREL(%rip), %rsi 56 xorl %eax, %eax 57 movl %eax, %edx 58 callq __cxa_throw@PLT 59.LBB0_2: # %if.else 60 movl $8, %edi 61 callq __cxa_allocate_exception@PLT 62 movq %rax, %rdi 63 movq $0, (%rdi) 64 movq _ZTIDn@GOTPCREL(%rip), %rsi 65 xorl %eax, %eax 66 movl %eax, %edx 67 callq __cxa_throw@PLT 68.Lfunc_end0: 69 .size bar, .Lfunc_end0-bar 70 .cfi_endproc 71 # -- End function 72 .globl foo # -- Begin function foo 73 .p2align 4, 0x90 74 .type foo,@function 75foo: # @foo 76.Lfunc_begin0: 77 .cfi_startproc 78 .cfi_personality 155, DW.ref.__gxx_personality_v0 79 .cfi_lsda 27, .Lexception0 80# %bb.0: # %entry 81 pushq %rbp 82 .cfi_def_cfa_offset 16 83 .cfi_offset %rbp, -16 84 movq %rsp, %rbp 85 .cfi_def_cfa_register %rbp 86 subq $48, %rsp 87 movq %rdi, -16(%rbp) 88 movq -16(%rbp), %rdi 89.Ltmp0: 90 callq bar 91.Ltmp1: 92 jmp .LBB1_1 93.LBB1_1: # %invoke.cont 94 jmp .LBB1_5 95.LBB1_5: # %try.cont 96 movq -16(%rbp), %rdi 97 addq $34, %rdi 98.Ltmp3: 99 callq bar 100.Ltmp4: 101 jmp .LBB1_6 102.LBB1_6: # %invoke.cont2 103 jmp .LBB1_10 104.LBB1_10: # %try.cont8 105 movq $0, -8(%rbp) 106.LBB1_11: # %return 107 movq -8(%rbp), %rax 108 addq $48, %rsp 109 popq %rbp 110 .cfi_def_cfa %rsp, 8 111 retq 112.LBB1_12: # %eh.resume 113 .cfi_def_cfa %rbp, 16 114 movq -24(%rbp), %rdi 115 callq _Unwind_Resume@PLT 116.Lfunc_end1: 117 .size foo, .Lfunc_end1-foo 118 .cfi_endproc 119 .section .gcc_except_table,"a",@progbits 120 .p2align 2 121GCC_except_table1: 122.Lexception0: 123 .byte 255 # @LPStart Encoding = omit 124 .byte 155 # @TType Encoding = indirect pcrel sdata4 125 .uleb128 .Lttbase0-.Lttbaseref0 126.Lttbaseref0: 127 .byte 1 # Call site Encoding = uleb128 128 .uleb128 .Lcst_end0-.Lcst_begin0 129.Lcst_begin0: 130 .uleb128 .Ltmp0-.Lfunc_begin0 # >> Call Site 1 << 131 .uleb128 .Ltmp1-.Ltmp0 # Call between .Ltmp0 and .Ltmp1 132 .uleb128 .Ltmp2-.Lfunc_begin0 # jumps to .Ltmp2 133 .byte 1 # On action: 1 134 .uleb128 .Ltmp1-.Lfunc_begin0 # >> Call Site 2 << 135 .uleb128 .Ltmp3-.Ltmp1 # Call between .Ltmp1 and .Ltmp3 136 .byte 0 # has no landing pad 137 .byte 0 # On action: cleanup 138 .uleb128 .Ltmp3-.Lfunc_begin0 # >> Call Site 3 << 139 .uleb128 .Ltmp4-.Ltmp3 # Call between .Ltmp3 and .Ltmp4 140 .uleb128 .Ltmp5-.Lfunc_begin0 # jumps to .Ltmp5 141 .byte 1 # On action: 1 142 .uleb128 .Ltmp4-.Lfunc_begin0 # >> Call Site 4 << 143 .uleb128 .Lfunc_end1-.Ltmp4 # Call between .Ltmp4 and .Lfunc_end1 144 .byte 0 # has no landing pad 145 .byte 0 # On action: cleanup 146.Lcst_end0: 147 .byte 1 # >> Action Record 1 << 148 # Catch TypeInfo 1 149 .byte 0 # No further actions 150 .p2align 2 151 # >> Catch TypeInfos << 152.Ltmp6: # TypeInfo 1 153 .long .L_ZTIi.DW.stub-.Ltmp6 154.Lttbase0: 155 .p2align 2 156 # -- End function 157 158 159 .text 160 .globl foo.cold.1 # -- Begin function foo.cold.1 161 .p2align 4, 0x90 162 .type foo.cold.1,@function 163foo.cold.1: # @foo.cold.1 164.Lfunc_begin3: 165 .cfi_startproc 166.Ltmp2: 167 movq %rax, %rcx 168 movl %edx, %eax 169 movq %rcx, -24(%rbp) 170 movl %eax, -28(%rbp) 171# %bb.3: # %catch.dispatch 172 movl -28(%rbp), %eax 173 movl $1, %ecx 174 cmpl %ecx, %eax 175 jne .LBB1_12 176# %bb.4: # %catch 177 movq -24(%rbp), %rdi 178 callq __cxa_begin_catch@PLT 179 movl (%rax), %eax 180 movl %eax, -32(%rbp) 181 movq $0, -8(%rbp) 182 callq __cxa_end_catch@PLT 183 jmp .LBB1_11 184.Ltmp5: 185 movq %rax, %rcx 186 movl %edx, %eax 187 movq %rcx, -24(%rbp) 188 movl %eax, -28(%rbp) 189# %bb.8: # %catch.dispatch3 190 movl -28(%rbp), %eax 191 movl $1, %ecx 192 cmpl %ecx, %eax 193 jne .LBB1_12 194# %bb.9: # %catch6 195 movq -24(%rbp), %rdi 196 callq __cxa_begin_catch@PLT 197 movl (%rax), %eax 198 movl %eax, -36(%rbp) 199 movq $0, -8(%rbp) 200 callq __cxa_end_catch@PLT 201 jmp .LBB1_11 202.Lfunc_end3: 203 .size foo.cold.1, .Lfunc_end3-foo.cold.1 204 .cfi_endproc 205 206 207 .text 208 .globl main # -- Begin function main 209 .p2align 4, 0x90 210 .type main,@function 211main: # @main 212 .cfi_startproc 213# %bb.0: # %entry 214 pushq %rbp 215 .cfi_def_cfa_offset 16 216 .cfi_offset %rbp, -16 217 movq %rsp, %rbp 218 .cfi_def_cfa_register %rbp 219 subq $16, %rsp 220 movl $0, -4(%rbp) 221 movl %edi, -8(%rbp) 222 movq %rsi, -16(%rbp) 223 xorl %eax, %eax 224 movl %eax, %edi 225 callq foo 226 # kill: def $eax killed $eax killed $rax 227 addq $16, %rsp 228 popq %rbp 229 .cfi_def_cfa %rsp, 8 230 retq 231.Lfunc_end2: 232 .size main, .Lfunc_end2-main 233 .cfi_endproc 234 # -- End function 235 .data 236 .p2align 3 237.L_ZTIi.DW.stub: 238 .quad _ZTIi 239 .hidden DW.ref.__gxx_personality_v0 240 .weak DW.ref.__gxx_personality_v0 241 .section .data.DW.ref.__gxx_personality_v0,"aGw",@progbits,DW.ref.__gxx_personality_v0,comdat 242 .p2align 3 243 .type DW.ref.__gxx_personality_v0,@object 244 .size DW.ref.__gxx_personality_v0, 8 245DW.ref.__gxx_personality_v0: 246 .quad __gxx_personality_v0 247 .section ".note.GNU-stack","",@progbits 248 .addrsig 249 .addrsig_sym bar 250 .addrsig_sym __cxa_allocate_exception 251 .addrsig_sym __cxa_throw 252 .addrsig_sym foo 253 .addrsig_sym __gxx_personality_v0 254 .addrsig_sym __cxa_begin_catch 255 .addrsig_sym __cxa_end_catch 256 .addrsig_sym _Unwind_Resume 257 .addrsig_sym _ZTIi 258 .addrsig_sym _ZTIDn 259 .addrsig_sym foo.cold.1 260 .addrsig_sym __cxa_begin_catch 261 .addrsig_sym __cxa_end_catch 262