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 27declare void @f(i32 %p, i32* %l) 28declare i1 @getbool() 29declare i32 @__CxxFrameHandler3(...) 30 31define i32 @try_catch_catch() personality i32 (...)* @__CxxFrameHandler3 { 32entry: 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 38catch.dispatch: ; preds = %entry 39 %cs = catchswitch within none [label %handler1, label %handler2] unwind to caller 40 41handler1: 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 47handler2: 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 52try.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 221define i32 @branch_to_normal_dest() personality i32 (...)* @__CxxFrameHandler3 { 222entry: 223 invoke void @f(i32 1, i32* null) 224 to label %try.cont unwind label %catch.dispatch 225 226catch.dispatch: 227 %cs1 = catchswitch within none [label %catch] unwind to caller 228 229catch: 230 %cp1 = catchpad within %cs1 [i8* null, i32 64, i8* null] 231 br label %loop 232 233loop: 234 %V = call i1 @getbool() [ "funclet"(token %cp1) ] 235 br i1 %V, label %loop, label %catch.done 236 237catch.done: 238 catchret from %cp1 to label %try.cont 239 240try.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