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