1; RUN: llc -mtriple=x86_64-windows-msvc < %s | FileCheck %s 2 3target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" 4target triple = "x86_64-pc-windows-msvc" 5 6%eh.ThrowInfo = type { i32, i32, i32, i32 } 7%rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] } 8 9@"\01??_7type_info@@6B@" = external constant i8* 10@"\01??_R0H@8" = internal global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" } 11 12declare void @llvm.trap() 13 14define void @test1(i1 %B) personality i32 (...)* @__CxxFrameHandler3 { 15entry: 16 invoke void @g() 17 to label %unreachable unwind label %catch.dispatch 18 19catch.dispatch: 20 %cs1 = catchswitch within none [label %catch] unwind to caller 21 22catch: 23 %cp = catchpad within %cs1 [i8* null, i32 64, i8* null] 24 br label %catch.loop 25 26catch.loop: 27 br i1 %B, label %catchret, label %catch.loop 28 29catchret: 30 catchret from %cp to label %try.cont 31 32try.cont: 33 ret void 34 35unreachable: 36 call void @llvm.trap() 37 unreachable 38} 39 40; CHECK-LABEL: test1: 41 42; The entry funclet contains %entry and %try.cont 43; CHECK: # %entry 44; CHECK: # %try.cont 45; CHECK: retq 46 47; The catch funclet contains %catch and %catchret 48; CHECK: # %catch{{$}} 49; CHECK: # %catchret 50; CHECK: retq 51 52declare void @g() 53 54 55define i32 @test2(i1 %B) personality i32 (...)* @__CxxFrameHandler3 { 56entry: 57 invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) #1 58 to label %unreachable unwind label %catch.dispatch 59 60catch.dispatch: ; preds = %entry 61 %cs1 = catchswitch within none [label %catch] unwind to caller 62 63catch: ; preds = %catch.dispatch 64 %0 = catchpad within %cs1 [i8* null, i32 64, i8* null] 65 invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) #1 ["funclet"(token %0)] 66 to label %unreachable unwind label %catch.dispatch.1 67 68catch.dispatch.1: ; preds = %catch 69 %cs2 = catchswitch within %0 [label %catch.3] unwind to caller 70 71catch.3: ; preds = %catch.dispatch.1 72 %1 = catchpad within %cs2 [i8* null, i32 64, i8* null] 73 catchret from %1 to label %try.cont 74 75try.cont: ; preds = %catch.3 76 catchret from %0 to label %try.cont.5 77 78try.cont.5: ; preds = %try.cont 79 ret i32 0 80 81unreachable: ; preds = %catch, %entry 82 call void @llvm.trap() 83 unreachable 84} 85 86; CHECK-LABEL: test2: 87 88; The parent function contains %entry and %try.cont.5 89; CHECK: .seh_proc 90; CHECK: # %entry 91; CHECK: # %try.cont.5 92; CHECK: retq 93 94; The inner catch funclet contains %catch.3 95; CHECK: .seh_proc 96; CHECK: # %catch.3{{$}} 97; CHECK: retq 98 99; The outer catch funclet contains %catch 100; CHECK: .seh_proc 101; CHECK: # %catch{{$}} 102; CHECK: callq _CxxThrowException 103; CHECK: # %unreachable 104; CHECK: ud2 105 106 107define void @test3(i1 %V) #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { 108entry: 109 invoke void @g() 110 to label %try.cont unwind label %catch.dispatch 111 112catch.dispatch: ; preds = %entry 113 %cs1 = catchswitch within none [label %catch.2] unwind label %catch.dispatch.1 114 115catch.2: ; preds = %catch.dispatch 116 %0 = catchpad within %cs1 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null] 117 tail call void @exit(i32 0) #2 [ "funclet"(token %0) ] 118 unreachable 119 120catch.dispatch.1: ; preds = %catch.dispatch 121 %cs2 = catchswitch within none [label %catch] unwind to caller 122 123catch: ; preds = %catch.dispatch.1 124 %1 = catchpad within %cs2 [i8* null, i32 64, i8* null] 125 tail call void @exit(i32 0) #2 [ "funclet"(token %1) ] 126 unreachable 127 128try.cont: ; preds = %entry 129 br i1 %V, label %exit_one, label %exit_two 130 131exit_one: 132 tail call void @g() 133 call void @llvm.trap() 134 unreachable 135 136exit_two: 137 tail call void @g() 138 call void @llvm.trap() 139 unreachable 140} 141 142; CHECK-LABEL: test3: 143 144; The entry funclet contains %entry and %try.cont 145; CHECK: # %entry 146; CHECK: # %try.cont 147; CHECK: callq g 148; CHECK-NOT: # exit_one 149; CHECK-NOT: # exit_two 150; CHECK: ud2 151 152; The catch(...) funclet contains %catch.2 153; CHECK: # %catch.2{{$}} 154; CHECK: callq exit 155; CHECK-NEXT: int3 156 157; The catch(int) funclet contains %catch 158; CHECK: # %catch{{$}} 159; CHECK: callq exit 160; CHECK-NEXT: int3 161 162declare void @exit(i32) noreturn nounwind 163declare void @_CxxThrowException(i8*, %eh.ThrowInfo*) 164declare i32 @__CxxFrameHandler3(...) 165