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 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: 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 219define i32 @branch_to_normal_dest() personality i32 (...)* @__CxxFrameHandler3 { 220entry: 221 invoke void @f(i32 1, i32* null) 222 to label %try.cont unwind label %catch.dispatch 223 224catch.dispatch: 225 %cs1 = catchswitch within none [label %catch] unwind to caller 226 227catch: 228 %cp1 = catchpad within %cs1 [i8* null, i32 64, i8* null] 229 br label %loop 230 231loop: 232 %V = call i1 @getbool() [ "funclet"(token %cp1) ] 233 br i1 %V, label %loop, label %catch.done 234 235catch.done: 236 catchret from %cp1 to label %try.cont 237 238try.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