1 ; RUN: llc -verify-machineinstrs -mtriple=i686-pc-windows-msvc < %s | FileCheck --check-prefix=X86 %s 2 ; RUN: llc -verify-machineinstrs -mtriple=x86_64-pc-windows-msvc < %s | FileCheck --check-prefix=X64 %s 3 4 ; Loosely based on IR for this C++ source code: 5 ; void f(int p); 6 ; int main() { 7 ; try { 8 ; f(1); 9 ; } catch (int e) { 10 ; f(e); 11 ; } catch (...) { 12 ; f(3); 13 ; } 14 ; } 15 16 %rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] } 17 %eh.CatchableType = type { i32, i8*, i32, i32, i32, i32, i8* } 18 %eh.CatchableTypeArray.1 = type { i32, [1 x %eh.CatchableType*] } 19 %eh.ThrowInfo = type { i32, i8*, i8*, i8* } 20 21 $"\01??_R0H@8" = comdat any 22 23 @"\01??_7type_info@@6B@" = external constant i8* 24 @"\01??_R0H@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }, comdat 25 26 27 declare void @f(i32 %p, i32* %l) 28 declare i1 @getbool() 29 declare i32 @__CxxFrameHandler3(...) 30 31 define i32 @try_catch_catch() personality i32 (...)* @__CxxFrameHandler3 { 32 entry: 33 %e.addr = alloca i32 34 %local = alloca i32 35 invoke void @f(i32 1, i32* %local) 36 to label %try.cont unwind label %catch.dispatch 37 38 catch.dispatch: ; preds = %entry 39 %cs = catchswitch within none [label %handler1, label %handler2] unwind to caller 40 41 handler1: 42 %h1 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i32* %e.addr] 43 %e = load i32, i32* %e.addr 44 call void @f(i32 %e, i32* %local) [ "funclet"(token %h1) ] 45 catchret from %h1 to label %try.cont 46 47 handler2: 48 %h2 = catchpad within %cs [i8* null, i32 64, i8* null] 49 call void @f(i32 3, i32* %local) [ "funclet"(token %h2) ] 50 catchret from %h2 to label %try.cont 51 52 try.cont: 53 ret i32 0 54 } 55 56 ; X86-LABEL: _try_catch_catch: 57 ; X86: movl %esp, -[[sp_offset:[0-9]+]](%ebp) 58 ; X86: movl $0, -{{[0-9]+}}(%ebp) 59 ; X86: leal -[[local_offs:[0-9]+]](%ebp), %[[addr_reg:[a-z]+]] 60 ; X86-DAG: movl %[[addr_reg]], 4(%esp) 61 ; X86-DAG: movl $1, (%esp) 62 ; X86: calll _f 63 ; X86: [[contbb:LBB0_[0-9]+]]: # %try.cont 64 ; X86: retl 65 66 ; X86: [[restorebb1:LBB0_[0-9]+]]: # Block address taken 67 ; X86-NEXT: # %handler1 68 ; X86-NEXT: addl $12, %ebp 69 ; X86: jmp [[contbb]] 70 71 ; FIXME: These should be de-duplicated. 72 ; X86: [[restorebb2:LBB0_[0-9]+]]: # Block address taken 73 ; X86-NEXT: # %handler2 74 ; X86-NEXT: addl $12, %ebp 75 ; X86: jmp [[contbb]] 76 77 ; X86: "?catch$[[catch1bb:[0-9]+]]@?0?try_catch_catch@4HA": 78 ; X86: LBB0_[[catch1bb]]: # %handler1{{$}} 79 ; X86: pushl %ebp 80 ; X86: subl $8, %esp 81 ; X86: addl $12, %ebp 82 ; X86: movl %esp, -[[sp_offset]](%ebp) 83 ; X86-DAG: movl -32(%ebp), %[[e_reg:[a-z]+]] 84 ; X86-DAG: leal -[[local_offs]](%ebp), %[[addr_reg:[a-z]+]] 85 ; X86-DAG: movl $1, -{{[0-9]+}}(%ebp) 86 ; X86-DAG: movl %[[addr_reg]], 4(%esp) 87 ; X86-DAG: movl %[[e_reg]], (%esp) 88 ; X86: calll _f 89 ; X86-NEXT: movl $[[restorebb1]], %eax 90 ; X86-NEXT: addl $8, %esp 91 ; X86-NEXT: popl %ebp 92 ; X86-NEXT: retl 93 94 ; X86: "?catch$[[catch2bb:[0-9]+]]@?0?try_catch_catch@4HA": 95 ; X86: LBB0_[[catch2bb]]: # %handler2{{$}} 96 ; X86: pushl %ebp 97 ; X86: subl $8, %esp 98 ; X86: addl $12, %ebp 99 ; X86: movl %esp, -[[sp_offset]](%ebp) 100 ; X86-DAG: leal -[[local_offs]](%ebp), %[[addr_reg:[a-z]+]] 101 ; X86-DAG: movl $1, -{{[0-9]+}}(%ebp) 102 ; X86-DAG: movl %[[addr_reg]], 4(%esp) 103 ; X86-DAG: movl $3, (%esp) 104 ; X86: calll _f 105 ; X86-NEXT: movl $[[restorebb2]], %eax 106 ; X86-NEXT: addl $8, %esp 107 ; X86-NEXT: popl %ebp 108 ; X86-NEXT: retl 109 110 ; X86: L__ehtable$try_catch_catch: 111 ; X86: $handlerMap$0$try_catch_catch: 112 ; X86-NEXT: .long 0 113 ; X86-NEXT: .long "??_R0H@8" 114 ; X86-NEXT: .long -20 115 ; X86-NEXT: .long "?catch$[[catch1bb]]@?0?try_catch_catch@4HA" 116 ; X86-NEXT: .long 64 117 ; X86-NEXT: .long 0 118 ; X86-NEXT: .long 0 119 ; X86-NEXT: .long "?catch$[[catch2bb]]@?0?try_catch_catch@4HA" 120 121 ; X64-LABEL: try_catch_catch: 122 ; X64: Lfunc_begin0: 123 ; X64: pushq %rbp 124 ; X64: .seh_pushreg 5 125 ; X64: subq $48, %rsp 126 ; X64: .seh_stackalloc 48 127 ; X64: leaq 48(%rsp), %rbp 128 ; X64: .seh_setframe 5, 48 129 ; X64: .seh_endprologue 130 ; X64: movq $-2, -8(%rbp) 131 ; X64: .Ltmp0 132 ; X64-DAG: leaq -[[local_offs:[0-9]+]](%rbp), %rdx 133 ; X64-DAG: movl $1, %ecx 134 ; X64: callq f 135 ; X64: [[contbb:\.LBB0_[0-9]+]]: # Block address taken 136 ; X64-NEXT: # %try.cont 137 ; X64: addq $48, %rsp 138 ; X64: popq %rbp 139 ; X64: retq 140 141 ; X64: "?catch$[[catch1bb:[0-9]+]]@?0?try_catch_catch@4HA": 142 ; X64: LBB0_[[catch1bb]]: # %handler1{{$}} 143 ; X64: movq %rdx, 16(%rsp) 144 ; X64: pushq %rbp 145 ; X64: .seh_pushreg 5 146 ; X64: subq $32, %rsp 147 ; X64: .seh_stackalloc 32 148 ; X64: leaq 48(%rdx), %rbp 149 ; X64: .seh_endprologue 150 ; X64-DAG: leaq -[[local_offs]](%rbp), %rdx 151 ; X64-DAG: movl -12(%rbp), %ecx 152 ; X64: callq f 153 ; X64: leaq [[contbb]](%rip), %rax 154 ; X64-NEXT: addq $32, %rsp 155 ; X64-NEXT: popq %rbp 156 ; X64-NEXT: retq 157 158 ; X64: "?catch$[[catch2bb:[0-9]+]]@?0?try_catch_catch@4HA": 159 ; X64: LBB0_[[catch2bb]]: # %handler2{{$}} 160 ; X64: movq %rdx, 16(%rsp) 161 ; X64: pushq %rbp 162 ; X64: .seh_pushreg 5 163 ; X64: subq $32, %rsp 164 ; X64: .seh_stackalloc 32 165 ; X64: leaq 48(%rdx), %rbp 166 ; X64: .seh_endprologue 167 ; X64-DAG: leaq -[[local_offs]](%rbp), %rdx 168 ; X64-DAG: movl $3, %ecx 169 ; X64: callq f 170 ; X64: leaq [[contbb]](%rip), %rax 171 ; X64-NEXT: addq $32, %rsp 172 ; X64-NEXT: popq %rbp 173 ; X64-NEXT: retq 174 175 ; X64: $cppxdata$try_catch_catch: 176 ; X64-NEXT: .long 429065506 177 ; X64-NEXT: .long 2 178 ; X64-NEXT: .long ($stateUnwindMap$try_catch_catch)@IMGREL 179 ; X64-NEXT: .long 1 180 ; X64-NEXT: .long ($tryMap$try_catch_catch)@IMGREL 181 ; X64-NEXT: .long 5 182 ; X64-NEXT: .long ($ip2state$try_catch_catch)@IMGREL 183 ; X64-NEXT: .long 40 184 ; X64-NEXT: .long 0 185 ; X64-NEXT: .long 1 186 187 ; X64: $tryMap$try_catch_catch: 188 ; X64-NEXT: .long 0 189 ; X64-NEXT: .long 0 190 ; X64-NEXT: .long 1 191 ; X64-NEXT: .long 2 192 ; X64-NEXT: .long ($handlerMap$0$try_catch_catch)@IMGREL 193 194 ; X64: $handlerMap$0$try_catch_catch: 195 ; X64-NEXT: .long 0 196 ; X64-NEXT: .long "??_R0H@8"@IMGREL 197 ; X64-NEXT: .long 36 198 ; X64-NEXT: .long "?catch$[[catch1bb]]@?0?try_catch_catch@4HA"@IMGREL 199 ; X64-NEXT: .long 56 200 ; X64-NEXT: .long 64 201 ; X64-NEXT: .long 0 202 ; X64-NEXT: .long 0 203 ; X64-NEXT: .long "?catch$[[catch2bb]]@?0?try_catch_catch@4HA"@IMGREL 204 ; X64-NEXT: .long 56 205 206 ; X64: $ip2state$try_catch_catch: 207 ; X64-NEXT: .long .Lfunc_begin0@IMGREL 208 ; X64-NEXT: .long -1 209 ; X64-NEXT: .long .Ltmp0@IMGREL+1 210 ; X64-NEXT: .long 0 211 ; X64-NEXT: .long .Ltmp1@IMGREL+1 212 ; X64-NEXT: .long -1 213 ; X64-NEXT: .long "?catch$[[catch1bb]]@?0?try_catch_catch@4HA"@IMGREL 214 ; X64-NEXT: .long 1 215 ; X64-NEXT: .long "?catch$[[catch2bb]]@?0?try_catch_catch@4HA"@IMGREL 216 ; X64-NEXT: .long 1 217 218 219 define i32 @branch_to_normal_dest() personality i32 (...)* @__CxxFrameHandler3 { 220 entry: 221 invoke void @f(i32 1, i32* null) 222 to label %try.cont unwind label %catch.dispatch 223 224 catch.dispatch: 225 %cs1 = catchswitch within none [label %catch] unwind to caller 226 227 catch: 228 %cp1 = catchpad within %cs1 [i8* null, i32 64, i8* null] 229 br label %loop 230 231 loop: 232 %V = call i1 @getbool() [ "funclet"(token %cp1) ] 233 br i1 %V, label %loop, label %catch.done 234 235 catch.done: 236 catchret from %cp1 to label %try.cont 237 238 try.cont: 239 ret i32 0 240 } 241 242 ; X86-LABEL: _branch_to_normal_dest: 243 ; X86: calll _f 244 245 ; X86: [[contbb:LBB1_[0-9]+]]: # %try.cont 246 ; X86: retl 247 248 ; X86: [[restorebb:LBB1_[0-9]+]]: # Block address taken 249 ; X86-NEXT: # %catch.done 250 ; X86-NEXT: addl $12, %ebp 251 ; X86: jmp [[contbb]] 252 253 ; X86: "?catch$[[catchbb:[0-9]+]]@?0?branch_to_normal_dest@4HA": 254 ; X86: LBB1_[[catchbb]]: # %catch{{$}} 255 ; X86: pushl %ebp 256 ; X86: subl $8, %esp 257 ; X86: addl $12, %ebp 258 ; X86: LBB1_[[loopbb:[0-9]+]]: # %loop 259 ; X86: movl $1, -16(%ebp) 260 ; X86: calll _getbool 261 ; X86: testb $1, %al 262 ; X86: jne LBB1_[[loopbb]] 263 ; X86: # %catch.done 264 ; X86-NEXT: movl $[[restorebb]], %eax 265 ; X86-NEXT: addl $8, %esp 266 ; X86-NEXT: popl %ebp 267 ; X86-NEXT: retl 268 269 ; X86: L__ehtable$branch_to_normal_dest: 270 ; X86: $handlerMap$0$branch_to_normal_dest: 271 ; X86-NEXT: .long 64 272 ; X86-NEXT: .long 0 273 ; X86-NEXT: .long 0 274 ; X86-NEXT: .long "?catch$[[catchbb]]@?0?branch_to_normal_dest@4HA" 275 276 ; X64-LABEL: branch_to_normal_dest: 277 ; X64: # %entry 278 ; X64: pushq %rbp 279 ; X64: .seh_pushreg 5 280 ; X64: subq $48, %rsp 281 ; X64: .seh_stackalloc 48 282 ; X64: leaq 48(%rsp), %rbp 283 ; X64: .seh_setframe 5, 48 284 ; X64: .seh_endprologue 285 ; X64: .Ltmp[[before_call:[0-9]+]]: 286 ; X64: callq f 287 ; X64: .Ltmp[[after_call:[0-9]+]]: 288 ; X64: [[contbb:\.LBB1_[0-9]+]]: # Block address taken 289 ; X64-NEXT: # %try.cont 290 ; X64: addq $48, %rsp 291 ; X64: popq %rbp 292 ; X64: retq 293 294 ; X64: "?catch$[[catchbb:[0-9]+]]@?0?branch_to_normal_dest@4HA": 295 ; X64: LBB1_[[catchbb]]: # %catch{{$}} 296 ; X64: movq %rdx, 16(%rsp) 297 ; X64: pushq %rbp 298 ; X64: .seh_pushreg 5 299 ; X64: subq $32, %rsp 300 ; X64: .seh_stackalloc 32 301 ; X64: leaq 48(%rdx), %rbp 302 ; X64: .seh_endprologue 303 ; X64: .LBB1_[[normal_dest_bb:[0-9]+]]: # %loop 304 ; X64: callq getbool 305 ; X64: testb $1, %al 306 ; X64: jne .LBB1_[[normal_dest_bb]] 307 ; X64: # %catch.done 308 ; X64: leaq [[contbb]](%rip), %rax 309 ; X64-NEXT: addq $32, %rsp 310 ; X64-NEXT: popq %rbp 311 ; X64-NEXT: retq 312 313 ; X64-LABEL: $cppxdata$branch_to_normal_dest: 314 ; X64-NEXT: .long 429065506 315 ; X64-NEXT: .long 2 316 ; X64-NEXT: .long ($stateUnwindMap$branch_to_normal_dest)@IMGREL 317 ; X64-NEXT: .long 1 318 ; X64-NEXT: .long ($tryMap$branch_to_normal_dest)@IMGREL 319 ; X64-NEXT: .long 4 320 ; X64-NEXT: .long ($ip2state$branch_to_normal_dest)@IMGREL 321 ; X64-NEXT: .long 40 322 ; X64-NEXT: .long 0 323 ; X64-NEXT: .long 1 324 325 ; X64-LABEL: $stateUnwindMap$branch_to_normal_dest: 326 ; X64-NEXT: .long -1 327 ; X64-NEXT: .long 0 328 ; X64-NEXT: .long -1 329 ; X64-NEXT: .long 0 330 331 ; X64-LABEL: $tryMap$branch_to_normal_dest: 332 ; X64-NEXT: .long 0 333 ; X64-NEXT: .long 0 334 ; X64-NEXT: .long 1 335 ; X64-NEXT: .long 1 336 ; X64-NEXT: .long ($handlerMap$0$branch_to_normal_dest)@IMGREL 337 338 ; X64-LABEL: $handlerMap$0$branch_to_normal_dest: 339 ; X64-NEXT: .long 64 340 ; X64-NEXT: .long 0 341 ; X64-NEXT: .long 0 342 ; X64-NEXT: .long "?catch$[[catchbb]]@?0?branch_to_normal_dest@4HA"@IMGREL 343 ; X64-NEXT: .long 56 344 345 ; X64-LABEL: $ip2state$branch_to_normal_dest: 346 ; X64-NEXT: .long .Lfunc_begin1@IMGREL 347 ; X64-NEXT: .long -1 348 ; X64-NEXT: .long .Ltmp[[before_call]]@IMGREL+1 349 ; X64-NEXT: .long 0 350 ; X64-NEXT: .long .Ltmp[[after_call]]@IMGREL+1 351 ; X64-NEXT: .long -1 352 ; X64-NEXT: .long "?catch$[[catchbb]]@?0?branch_to_normal_dest@4HA"@IMGREL 353 ; X64-NEXT: .long 1 354