[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
diff --git a/llvm/test/CodeGen/X86/branchfolding-catchpads.ll b/llvm/test/CodeGen/X86/branchfolding-catchpads.ll
index 21c7818..0468b3c 100644
--- a/llvm/test/CodeGen/X86/branchfolding-catchpads.ll
+++ b/llvm/test/CodeGen/X86/branchfolding-catchpads.ll
@@ -19,24 +19,18 @@
to label %cleanup unwind label %catch.dispatch
catch.dispatch:
- catchpad [i8* null, i32 8, i8* null]
- to label %catch unwind label %catch.dispatch.2
+ %cs = catchswitch within none [ label %catch, label %catch.2 ] unwind to caller
catch:
- invoke void @throw() noreturn
- to label %unreachable unwind label %catchendblock
-
-catch.dispatch.2:
- catchpad [i8* null, i32 64, i8* null]
- to label %catch.2 unwind label %catchendblock
+ catchpad within %cs [i8* null, i32 8, i8* null]
+ call void @throw() noreturn
+ br label %unreachable
catch.2:
+ catchpad within %cs [i8* null, i32 64, i8* null]
store i8 1, i8* %b
- invoke void @throw() noreturn
- to label %unreachable unwind label %catchendblock
-
-catchendblock:
- catchendpad unwind to caller
+ call void @throw() noreturn
+ br label %unreachable
cleanup:
%retval = phi i16 [ %call1, %if.then ], [ %call2, %if.else ]
@@ -67,31 +61,22 @@
to label %cleanup unwind label %catch.dispatch
catch.dispatch:
- catchpad [i8* null, i32 8, i8* null]
- to label %catch unwind label %catch.dispatch.2
+ %cs = catchswitch within none [ label %catch, label %catch.2, label %catch.3 ] unwind to caller
catch:
- invoke void @throw() noreturn
- to label %unreachable unwind label %catchendblock
-
-catch.dispatch.2:
- %c2 = catchpad [i8* null, i32 32, i8* null]
- to label %catch.2 unwind label %catch.dispatch.3
+ catchpad within %cs [i8* null, i32 8, i8* null]
+ call void @throw() noreturn
+ br label %unreachable
catch.2:
+ %c2 = catchpad within %cs [i8* null, i32 32, i8* null]
store i8 1, i8* %b
- catchret %c2 to label %cleanup
-
-catch.dispatch.3:
- %c3 = catchpad [i8* null, i32 64, i8* null]
- to label %catch.3 unwind label %catchendblock
+ catchret from %c2 to label %cleanup
catch.3:
+ %c3 = catchpad within %cs [i8* null, i32 64, i8* null]
store i8 2, i8* %b
- catchret %c3 to label %cleanup
-
-catchendblock:
- catchendpad unwind to caller
+ catchret from %c3 to label %cleanup
cleanup:
%retval = phi i16 [ %call1, %if.then ], [ %call2, %if.else ], [ -1, %catch.2 ], [ -1, %catch.3 ]
diff --git a/llvm/test/CodeGen/X86/catchpad-realign-savexmm.ll b/llvm/test/CodeGen/X86/catchpad-realign-savexmm.ll
index 267c693..1160101 100644
--- a/llvm/test/CodeGen/X86/catchpad-realign-savexmm.ll
+++ b/llvm/test/CodeGen/X86/catchpad-realign-savexmm.ll
@@ -14,19 +14,17 @@
%v1 = fadd double %v, 1.0
store double %v1, double* @fp_global
invoke void @g()
- to label %return unwind label %catch
+ to label %return unwind label %catch.dispatch
return:
ret void
-catch:
- %p = catchpad [i8* null, i32 64, i8* null]
- to label %catchit unwind label %endpad
+catch.dispatch:
+ %cs1 = catchswitch within none [label %catch] unwind to caller
-catchit:
- catchret %p to label %return
-endpad:
- catchendpad unwind to caller
+catch:
+ %p = catchpad within %cs1 [i8* null, i32 64, i8* null]
+ catchret from %p to label %return
}
; CHECK: f: # @f
diff --git a/llvm/test/CodeGen/X86/catchpad-regmask.ll b/llvm/test/CodeGen/X86/catchpad-regmask.ll
index fe3a238..0d436f6 100644
--- a/llvm/test/CodeGen/X86/catchpad-regmask.ll
+++ b/llvm/test/CodeGen/X86/catchpad-regmask.ll
@@ -41,14 +41,14 @@
to label %unreachable unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %0 = catchpad [i8* null, i32 64, i8* null]
- to label %catch unwind label %catchendblock
+ %cs1 = catchswitch within none [label %catch] unwind to caller
catch: ; preds = %catch.dispatch
+ %0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
%idxprom1 = sext i32 %idx2 to i64
%arrayidx2 = getelementptr inbounds [4 x i32], [4 x i32]* @array, i64 0, i64 %idxprom1
store i32 222, i32* %arrayidx2, align 4, !tbaa !2
- catchret %0 to label %try.cont
+ catchret from %0 to label %try.cont
try.cont: ; preds = %catch
%idxprom3 = sext i32 %idx3 to i64
@@ -56,9 +56,6 @@
store i32 333, i32* %arrayidx4, align 4, !tbaa !2
ret void
-catchendblock: ; preds = %catch.dispatch
- catchendpad unwind to caller
-
unreachable: ; preds = %entry
unreachable
}
@@ -98,20 +95,17 @@
to label %unreachable unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %0 = catchpad [i8* null, i32 64, i8* null]
- to label %catch unwind label %catchendblock
+ %cs1 = catchswitch within none [label %catch] unwind to caller
catch: ; preds = %catch.dispatch
+ %0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
store i32 222, i32* @imported, align 4, !tbaa !2
- catchret %0 to label %try.cont
+ catchret from %0 to label %try.cont
try.cont: ; preds = %catch
store i32 333, i32* @imported, align 4, !tbaa !2
ret void
-catchendblock: ; preds = %catch.dispatch
- catchendpad unwind to caller
-
unreachable: ; preds = %entry
unreachable
}
diff --git a/llvm/test/CodeGen/X86/catchpad-weight.ll b/llvm/test/CodeGen/X86/catchpad-weight.ll
index e8b4168..1abcd03 100644
--- a/llvm/test/CodeGen/X86/catchpad-weight.ll
+++ b/llvm/test/CodeGen/X86/catchpad-weight.ll
@@ -2,7 +2,7 @@
; Check if the edge weight to the catchpad is calculated correctly.
-; CHECK: Successors according to CFG: BB#3(0x7ffff100 / 0x80000000 = 100.00%) BB#1(0x00000800 / 0x80000000 = 0.00%) BB#4(0x00000400 / 0x80000000 = 0.00%) BB#6(0x00000200 / 0x80000000 = 0.00%) BB#8(0x00000100 / 0x80000000 = 0.00%)
+; CHECK: Successors according to CFG: BB#2(0x7ffff100 / 0x80000000 = 100.00%) BB#1(0x00000800 / 0x80000000 = 0.00%) BB#3(0x00000400 / 0x80000000 = 0.00%) BB#4(0x00000200 / 0x80000000 = 0.00%) BB#5(0x00000100 / 0x80000000 = 0.00%)
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64--windows-msvc18.0.0"
@@ -31,11 +31,11 @@
to label %try.cont unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %1 = catchpad [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 0, i8* null]
- to label %catch.5 unwind label %catch.dispatch.1
+ %cs1 = catchswitch within none [label %catch.5] unwind label %catch.dispatch.1
catch.5: ; preds = %catch.dispatch
- catchret %1 to label %try.cont
+ %1 = catchpad within %cs1 [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 0, i8* null]
+ catchret from %1 to label %try.cont
try.cont: ; preds = %entry, %catch, %catch.3, %catch.5
call void @"\01??1HasDtor@@QEAA@XZ"(%struct.HasDtor* nonnull %o) #4
@@ -43,26 +43,23 @@
ret i32 0
catch.dispatch.1: ; preds = %catch.dispatch
- %2 = catchpad [%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8", i32 0, i8* null]
- to label %catch.3 unwind label %catch.dispatch.2
+ %cs2 = catchswitch within none [label %catch.3] unwind label %catch.dispatch.2
catch.3: ; preds = %catch.dispatch.1
- catchret %2 to label %try.cont
+ %2 = catchpad within %cs2 [%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8", i32 0, i8* null]
+ catchret from %2 to label %try.cont
catch.dispatch.2: ; preds = %catch.dispatch.1
- %3 = catchpad [%rtti.TypeDescriptor7* @"\01??_R0?AUC@@@8", i32 0, i8* null]
- to label %catch unwind label %catchendblock
+ %cs3 = catchswitch within none [label %catch] unwind label %ehcleanup
catch: ; preds = %catch.dispatch.2
- catchret %3 to label %try.cont
-
-catchendblock: ; preds = %catch.dispatch.2
- catchendpad unwind label %ehcleanup
+ %3 = catchpad within %cs3 [%rtti.TypeDescriptor7* @"\01??_R0?AUC@@@8", i32 0, i8* null]
+ catchret from %3 to label %try.cont
ehcleanup: ; preds = %catchendblock
- %4 = cleanuppad []
+ %4 = cleanuppad within none []
call void @"\01??1HasDtor@@QEAA@XZ"(%struct.HasDtor* nonnull %o) #4
- cleanupret %4 unwind to caller
+ cleanupret from %4 unwind to caller
}
; Function Attrs: nounwind argmemonly
diff --git a/llvm/test/CodeGen/X86/catchret-empty-fallthrough.ll b/llvm/test/CodeGen/X86/catchret-empty-fallthrough.ll
index 3b3b3f5..585f7bc 100644
--- a/llvm/test/CodeGen/X86/catchret-empty-fallthrough.ll
+++ b/llvm/test/CodeGen/X86/catchret-empty-fallthrough.ll
@@ -19,14 +19,11 @@
to label %fallthrough unwind label %dispatch
dispatch: ; preds = %try
- %0 = catchpad [i8* null]
- to label %catch unwind label %catchendblock.i.i
+ %cs1 = catchswitch within none [label %catch] unwind to caller
catch: ; preds = %dispatch
- catchret %0 to label %return
-
-catchendblock.i.i: ; preds = %dispatch
- catchendpad unwind to caller
+ %0 = catchpad within %cs1 [i8* null]
+ catchret from %0 to label %return
fallthrough: ; preds = %try
unreachable
diff --git a/llvm/test/CodeGen/X86/catchret-fallthrough.ll b/llvm/test/CodeGen/X86/catchret-fallthrough.ll
index f732566..6a94b29 100644
--- a/llvm/test/CodeGen/X86/catchret-fallthrough.ll
+++ b/llvm/test/CodeGen/X86/catchret-fallthrough.ll
@@ -18,14 +18,11 @@
to label %invoke.cont.3 unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %0 = catchpad [i8* null, i32 64, i8* null]
- to label %catch unwind label %catchendblock
+ %cs1 = catchswitch within none [label %catch] unwind to caller
catch: ; preds = %catch.dispatch
- catchret %0 to label %nrvo.skipdtor
-
-catchendblock: ; preds = %catch, %catch.dispatch
- catchendpad unwind to caller
+ %0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
+ catchret from %0 to label %nrvo.skipdtor
invoke.cont.3: ; preds = %entry
store i32 123, i32* @some_global
diff --git a/llvm/test/CodeGen/X86/cleanuppad-inalloca.ll b/llvm/test/CodeGen/X86/cleanuppad-inalloca.ll
index 8858f37..294ef3a 100644
--- a/llvm/test/CodeGen/X86/cleanuppad-inalloca.ll
+++ b/llvm/test/CodeGen/X86/cleanuppad-inalloca.ll
@@ -29,9 +29,9 @@
ret void
ehcleanup: ; preds = %entry
- %2 = cleanuppad []
+ %2 = cleanuppad within none []
call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %0)
- cleanupret %2 unwind to caller
+ cleanupret from %2 unwind to caller
}
; CHECK: _passes_two:
diff --git a/llvm/test/CodeGen/X86/cleanuppad-large-codemodel.ll b/llvm/test/CodeGen/X86/cleanuppad-large-codemodel.ll
index df866f9..e32cdbe 100644
--- a/llvm/test/CodeGen/X86/cleanuppad-large-codemodel.ll
+++ b/llvm/test/CodeGen/X86/cleanuppad-large-codemodel.ll
@@ -9,9 +9,9 @@
invoke void @bar()
to label %exit unwind label %cleanup
cleanup:
- %c = cleanuppad []
+ %c = cleanuppad within none []
call void @bar()
- cleanupret %c unwind to caller
+ cleanupret from %c unwind to caller
exit:
ret void
}
diff --git a/llvm/test/CodeGen/X86/cleanuppad-realign.ll b/llvm/test/CodeGen/X86/cleanuppad-realign.ll
index a19cf26..d322932 100644
--- a/llvm/test/CodeGen/X86/cleanuppad-realign.ll
+++ b/llvm/test/CodeGen/X86/cleanuppad-realign.ll
@@ -17,9 +17,9 @@
ret void
ehcleanup: ; preds = %entry
- %0 = cleanuppad []
+ %0 = cleanuppad within none []
call void @Dtor(i64* %o)
- cleanupret %0 unwind to caller
+ cleanupret from %0 unwind to caller
}
; X86-LABEL: _realigned_cleanup: # @realigned_cleanup
diff --git a/llvm/test/CodeGen/X86/funclet-layout.ll b/llvm/test/CodeGen/X86/funclet-layout.ll
index 053d484..b5972df 100644
--- a/llvm/test/CodeGen/X86/funclet-layout.ll
+++ b/llvm/test/CodeGen/X86/funclet-layout.ll
@@ -15,21 +15,21 @@
to label %unreachable unwind label %catch.dispatch
catch.dispatch:
- %cp = catchpad [i8* null, i32 64, i8* null]
- to label %catch unwind label %catchendblock
+ %cs1 = catchswitch within none [label %catch] unwind to caller
catch:
- br i1 %B, label %catchret, label %catch
+ %cp = catchpad within %cs1 [i8* null, i32 64, i8* null]
+ br label %catch.loop
+
+catch.loop:
+ br i1 %B, label %catchret, label %catch.loop
catchret:
- catchret %cp to label %try.cont
+ catchret from %cp to label %try.cont
try.cont:
ret void
-catchendblock:
- catchendpad unwind to caller
-
unreachable:
unreachable
}
@@ -55,54 +55,50 @@
to label %unreachable unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %0 = catchpad [i8* null, i32 64, i8* null]
- to label %catch unwind label %catchendblock
+ %cs1 = catchswitch within none [label %catch] unwind to caller
catch: ; preds = %catch.dispatch
+ %0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) #1
to label %unreachable unwind label %catch.dispatch.1
catch.dispatch.1: ; preds = %catch
- %1 = catchpad [i8* null, i32 64, i8* null]
- to label %catch.3 unwind label %catchendblock.2
+ %cs2 = catchswitch within %0 [label %catch.3] unwind to caller
catch.3: ; preds = %catch.dispatch.1
- catchret %1 to label %try.cont
+ %1 = catchpad within %cs2 [i8* null, i32 64, i8* null]
+ catchret from %1 to label %try.cont
try.cont: ; preds = %catch.3
- catchret %0 to label %try.cont.5
+ catchret from %0 to label %try.cont.5
try.cont.5: ; preds = %try.cont
ret i32 0
-catchendblock.2: ; preds = %catch.dispatch.1
- catchendpad unwind label %catchendblock
-
-catchendblock: ; preds = %catchendblock.2, %catch.dispatch
- catchendpad unwind to caller
-
unreachable: ; preds = %catch, %entry
unreachable
-
}
; CHECK-LABEL: test2:
-; The entry funclet contains %entry and %try.cont.5
+; The parent function contains %entry and %try.cont.5
+; CHECK: .seh_proc
; CHECK: # %entry
; CHECK: # %try.cont.5
; CHECK: retq
-; The outer catch funclet contains %catch.dispatch
-; CHECK: # %catch.dispatch{{$}}
+; The inner catch funclet contains %catch.3
+; CHECK: .seh_proc
+; CHECK: # %catch.3{{$}}
+; CHECK: retq
+
+; The outer catch funclet contains %catch
+; CHECK: .seh_proc
+; CHECK: # %catch{{$}}
; CHECK: callq _CxxThrowException
; CHECK: # %unreachable
; CHECK: ud2
-; The inner catch funclet contains %catch.dispatch.1
-; CHECK: # %catch.dispatch.1
-; CHECK: retq
-
define void @test3(i1 %V) #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
entry:
@@ -110,24 +106,21 @@
to label %try.cont unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %0 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
- to label %catch.2 unwind label %catch.dispatch.1
+ %cs1 = catchswitch within none [label %catch.2] unwind label %catch.dispatch.1
catch.2: ; preds = %catch.dispatch
+ %0 = catchpad within %cs1 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
tail call void @exit(i32 0) #2
unreachable
catch.dispatch.1: ; preds = %catch.dispatch
- %1 = catchpad [i8* null, i32 64, i8* null]
- to label %catch unwind label %catchendblock
+ %cs2 = catchswitch within none [label %catch] unwind to caller
catch: ; preds = %catch.dispatch.1
+ %1 = catchpad within %cs2 [i8* null, i32 64, i8* null]
tail call void @exit(i32 0) #2
unreachable
-catchendblock: ; preds = %catch.dispatch.1
- catchendpad unwind to caller
-
try.cont: ; preds = %entry
br i1 %V, label %exit_one, label %exit_two
@@ -150,13 +143,13 @@
; CHECK-NOT: # exit_two
; CHECK: ud2
-; The catch(...) funclet contains %catch.dispatch
-; CHECK: # %catch.dispatch{{$}}
+; The catch(...) funclet contains %catch.2
+; CHECK: # %catch.2{{$}}
; CHECK: callq exit
; CHECK: ud2
-; The catch(int) funclet contains %catch.dispatch.1
-; CHECK: # %catch.dispatch.1
+; The catch(int) funclet contains %catch
+; CHECK: # %catch{{$}}
; CHECK: callq exit
; CHECK: ud2
diff --git a/llvm/test/CodeGen/X86/late-address-taken.ll b/llvm/test/CodeGen/X86/late-address-taken.ll
index 8f85393..f98c535 100644
--- a/llvm/test/CodeGen/X86/late-address-taken.ll
+++ b/llvm/test/CodeGen/X86/late-address-taken.ll
@@ -22,19 +22,17 @@
invoke void @f()
to label %exit unwind label %catch.pad
catch.pad:
- %catch = catchpad [i32 33554467]
- to label %catch.body unwind label %catch.end
+ %cs1 = catchswitch within none [label %catch.body] unwind to caller
catch.body:
- catchret %catch to label %exit
-catch.end:
- catchendpad unwind to caller
+ %catch = catchpad within %cs1 [i32 33554467]
+ catchret from %catch to label %exit
exit:
ret void
}
; CHECK-LABEL: catchret: # @catchret
; CHECK: [[Exit:^[^ :]+]]: # Block address taken
; CHECK-NEXT: # %exit
-; CHECK: # %catch.pad
+; CHECK: # %catch.body
; CHECK: .seh_endprolog
; CHECK: leaq [[Exit]](%rip), %rax
; CHECK: retq # CATCHRET
diff --git a/llvm/test/CodeGen/X86/seh-catch-all-win32.ll b/llvm/test/CodeGen/X86/seh-catch-all-win32.ll
index 5d9d503..69afb1b 100644
--- a/llvm/test/CodeGen/X86/seh-catch-all-win32.ll
+++ b/llvm/test/CodeGen/X86/seh-catch-all-win32.ll
@@ -22,16 +22,13 @@
to label %__try.cont unwind label %lpad
lpad: ; preds = %entry
- %p = catchpad [i8* bitcast (i32 ()* @"filt$main" to i8*)]
- to label %__except unwind label %endpad
+ %cs1 = catchswitch within none [label %__except] unwind to caller
__except: ; preds = %lpad
+ %p = catchpad within %cs1 [i8* bitcast (i32 ()* @"filt$main" to i8*)]
%code = load i32, i32* %__exceptioncode, align 4
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i32 0, i32 0), i32 %code) #4
- catchret %p to label %__try.cont
-
-endpad: ; preds = %lpad
- catchendpad unwind to caller
+ catchret from %p to label %__try.cont
__try.cont: ; preds = %entry, %__except
ret i32 0
@@ -73,7 +70,7 @@
; CHECK: popl %edi
; CHECK: popl %ebx
; CHECK: retl
-; CHECK: LBB0_[[lpbb:[0-9]+]]: # %lpad{{$}}
+; CHECK: LBB0_[[lpbb:[0-9]+]]: # %__except{{$}}
; stackrestore
; CHECK: movl -24(%ebp), %esp
; EH state -1
diff --git a/llvm/test/CodeGen/X86/seh-catch-all.ll b/llvm/test/CodeGen/X86/seh-catch-all.ll
index aa1b6e0..4463485 100644
--- a/llvm/test/CodeGen/X86/seh-catch-all.ll
+++ b/llvm/test/CodeGen/X86/seh-catch-all.ll
@@ -16,16 +16,13 @@
ret i32 0
lpad:
- %p = catchpad [i8* null, i32 64, i8* null]
- to label %catchall unwind label %endpad
+ %cs1 = catchswitch within none [label %catchall] unwind to caller
catchall:
+ %p = catchpad within %cs1 [i8* null, i32 64, i8* null]
%code = call i32 @llvm.eh.exceptioncode(token %p)
call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i64 0, i64 0), i32 %code)
- catchret %p to label %__try.cont
-
-endpad:
- catchendpad unwind to caller
+ catchret from %p to label %__try.cont
}
; Check that we can get the exception code from eax to the printf.
@@ -33,7 +30,7 @@
; CHECK-LABEL: main:
; CHECK: callq crash
; CHECK: retq
-; CHECK: .LBB0_2: # %lpad
+; CHECK: .LBB0_2: # %catchall
; CHECK: leaq str(%rip), %rcx
; CHECK: movl %eax, %edx
; CHECK: callq printf
diff --git a/llvm/test/CodeGen/X86/seh-catchpad.ll b/llvm/test/CodeGen/X86/seh-catchpad.ll
index 895dba8..a8be4ec 100644
--- a/llvm/test/CodeGen/X86/seh-catchpad.ll
+++ b/llvm/test/CodeGen/X86/seh-catchpad.ll
@@ -45,13 +45,6 @@
%call = invoke i32 @do_div(i32 1, i32 0) #4
to label %__try.cont.12 unwind label %catch.dispatch
-catch.dispatch: ; preds = %entry
- %0 = catchpad [i8* null]
- to label %__except unwind label %catchendblock
-
-__except: ; preds = %catch.dispatch
- catchret %0 to label %__except.2
-
__except.2: ; preds = %__except
%call4 = invoke i32 @do_div(i32 1, i32 0) #4
to label %invoke.cont.3 unwind label %ehcleanup
@@ -60,24 +53,6 @@
invoke fastcc void @"\01?fin$0@0@main@@"() #4
to label %__try.cont.12 unwind label %catch.dispatch.7
-catchendblock: ; preds = %catch.dispatch
- catchendpad unwind label %catch.dispatch.7
-
-ehcleanup: ; preds = %__except.2
- %1 = cleanuppad []
- invoke fastcc void @"\01?fin$0@0@main@@"() #4
- to label %invoke.cont.6 unwind label %ehcleanup.end
-
-invoke.cont.6: ; preds = %ehcleanup
- cleanupret %1 unwind label %catch.dispatch.7
-
-catch.dispatch.7: ; preds = %invoke.cont.3, %invoke.cont.6, %ehcleanup.end, %catchendblock
- %2 = catchpad [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@main@@" to i8*)]
- to label %__except.ret unwind label %catchendblock.8
-
-__except.ret: ; preds = %catch.dispatch.7
- catchret %2 to label %__except.9
-
__except.9: ; preds = %__except.ret
%call11 = tail call i32 @puts(i8* nonnull getelementptr inbounds ([7 x i8], [7 x i8]* @"\01??_C@_06IBDBCMGJ@caught?$AA@", i64 0, i64 0))
br label %__try.cont.12
@@ -85,11 +60,27 @@
__try.cont.12: ; preds = %invoke.cont.3, %entry, %__except.9
ret i32 0
-catchendblock.8: ; preds = %catch.dispatch.7
- catchendpad unwind to caller
+catch.dispatch: ; preds = %entry
+ %cs1 = catchswitch within none [label %__except] unwind label %catch.dispatch.7
-ehcleanup.end: ; preds = %ehcleanup
- cleanupendpad %1 unwind label %catch.dispatch.7
+__except: ; preds = %catch.dispatch
+ %cp1 = catchpad within %cs1 [i8* null]
+ catchret from %cp1 to label %__except.2
+
+ehcleanup: ; preds = %__except.2
+ %cp2 = cleanuppad within none []
+ invoke fastcc void @"\01?fin$0@0@main@@"() #4
+ to label %invoke.cont.6 unwind label %catch.dispatch.7
+
+invoke.cont.6: ; preds = %ehcleanup
+ cleanupret from %cp2 unwind label %catch.dispatch.7
+
+catch.dispatch.7:
+ %cs2 = catchswitch within none [label %__except.ret] unwind to caller
+
+__except.ret: ; preds = %catch.dispatch.7
+ %cp3 = catchpad within %cs2 [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@main@@" to i8*)]
+ catchret from %cp3 to label %__except.9
}
; CHECK: main: # @main
@@ -112,7 +103,7 @@
; CHECK: addq $32, %rsp
; CHECK: popq %rbp
; CHECK: retq
-; CHECK: .LBB1_[[except1bb:[0-9]+]]: # %catch.dispatch
+; CHECK: .LBB1_[[except1bb:[0-9]+]]: # %__except
; CHECK: .Ltmp2:
; CHECK: movl $1, %ecx
; CHECK: xorl %edx, %edx
@@ -120,7 +111,7 @@
; CHECK: .Ltmp3:
; CHECK: callq "?fin$0@0@main@@"
; CHECK: jmp .LBB1_[[epilogue]]
-; CHECK: .LBB1_[[except2bb:[0-9]+]]: # %catch.dispatch.7
+; CHECK: .LBB1_[[except2bb:[0-9]+]]: # %__except.ret
; CHECK: leaq "??_C@_06IBDBCMGJ@caught?$AA@"(%rip), %rcx
; CHECK: callq puts
; CHECK: jmp .LBB1_[[epilogue]]
@@ -143,18 +134,18 @@
; CHECK-NEXT: .long .Ltmp2@IMGREL+1
; CHECK-NEXT: .long .Ltmp3@IMGREL+1
; CHECK-NEXT: .long "?filt$0@0@main@@"@IMGREL
-; CHECK-NEXT: .long .LBB1_5@IMGREL
+; CHECK-NEXT: .long .LBB1_3@IMGREL
; CHECK-NEXT: .long .Ltmp6@IMGREL+1
; CHECK-NEXT: .long .Ltmp7@IMGREL+1
; CHECK-NEXT: .long "?filt$0@0@main@@"@IMGREL
-; CHECK-NEXT: .long .LBB1_5@IMGREL
+; CHECK-NEXT: .long .LBB1_3@IMGREL
; CHECK-NEXT: .Llsda_end0:
; CHECK: .text
; CHECK: .seh_endproc
-; CHECK: "?dtor$3@?0?main@4HA":
-; CHECK: .seh_proc "?dtor$3@?0?main@4HA"
+; CHECK: "?dtor$[[finbb]]@?0?main@4HA":
+; CHECK: .seh_proc "?dtor$[[finbb]]@?0?main@4HA"
; CHECK: .seh_handler __C_specific_handler, @unwind, @except
; CHECK: .LBB1_[[finbb]]: # %ehcleanup
; CHECK: movq %rdx, 16(%rsp)
diff --git a/llvm/test/CodeGen/X86/seh-except-finally.ll b/llvm/test/CodeGen/X86/seh-except-finally.ll
index 7acb802..b252b5b 100644
--- a/llvm/test/CodeGen/X86/seh-except-finally.ll
+++ b/llvm/test/CodeGen/X86/seh-except-finally.ll
@@ -49,37 +49,24 @@
br label %__try.cont
__finally: ; preds = %entry
- %cleanuppad = cleanuppad []
+ %cleanuppad = cleanuppad within none []
%locals = call i8* @llvm.localaddress()
invoke void @"\01?fin$0@0@use_both@@"(i1 zeroext true, i8* %locals) #5
- to label %invoke.cont3 unwind label %cleanupendpad
+ to label %invoke.cont3 unwind label %catch.dispatch
invoke.cont3: ; preds = %__finally
- cleanupret %cleanuppad unwind label %catch.dispatch
-
-cleanupendpad:
- cleanupendpad %cleanuppad unwind label %catch.dispatch
+ cleanupret from %cleanuppad unwind label %catch.dispatch
catch.dispatch: ; preds = %invoke.cont3, %lpad1
- %catchpad = catchpad [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_both@@" to i8*)]
- to label %__except unwind label %catchendpad
+ %cs1 = catchswitch within none [label %__except] unwind to caller
__except: ; preds = %catch.dispatch
+ %catchpad = catchpad within %cs1 [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_both@@" to i8*)]
%call = call i32 @puts(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @"\01??_C@_08MLCMLGHM@__except?$AA@", i32 0, i32 0))
- catchret %catchpad to label %__try.cont
-
-catchendpad:
- catchendpad unwind to caller
+ catchret from %catchpad to label %__try.cont
__try.cont: ; preds = %__except, %invoke.cont2
ret void
-
-eh.resume: ; preds = %catch.dispatch
- %exn = load i8*, i8** %exn.slot
- %sel4 = load i32, i32* %ehselector.slot
- %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn, 0
- %lpad.val5 = insertvalue { i8*, i32 } %lpad.val, i32 %sel4, 1
- resume { i8*, i32 } %lpad.val5
}
; CHECK-LABEL: use_both:
diff --git a/llvm/test/CodeGen/X86/seh-exception-code.ll b/llvm/test/CodeGen/X86/seh-exception-code.ll
index e481a8e..20e1544 100644
--- a/llvm/test/CodeGen/X86/seh-exception-code.ll
+++ b/llvm/test/CodeGen/X86/seh-exception-code.ll
@@ -14,11 +14,11 @@
to label %__try.cont unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %pad = catchpad [i8* null]
- to label %__except unwind label %catchendblock
+ %cs = catchswitch within none [label %__except] unwind to caller
__except: ; preds = %catch.dispatch
- catchret %pad to label %__except.1
+ %pad = catchpad within %cs [i8* null]
+ catchret from %pad to label %__except.1
__except.1: ; preds = %__except
%code = call i32 @llvm.eh.exceptioncode(token %pad)
@@ -27,15 +27,12 @@
__try.cont: ; preds = %entry, %__except.1
ret void
-
-catchendblock: ; preds = %catch.dispatch
- catchendpad unwind to caller
}
; CHECK-LABEL: ehcode:
; CHECK: xorl %ecx, %ecx
; CHECK: callq f
-; CHECK: # %catch.dispatch
+; CHECK: # %__except
; CHECK: movl %eax, %ecx
; CHECK-NEXT: callq f
diff --git a/llvm/test/CodeGen/X86/seh-finally.ll b/llvm/test/CodeGen/X86/seh-finally.ll
index 57c2c8c..67bce81 100644
--- a/llvm/test/CodeGen/X86/seh-finally.ll
+++ b/llvm/test/CodeGen/X86/seh-finally.ll
@@ -17,15 +17,9 @@
ret i32 0
lpad: ; preds = %entry
- %p = cleanuppad []
- %call2 = invoke i32 @puts(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @str_recovered, i64 0, i64 0))
- to label %invoke.cont1 unwind label %endpad
-
-invoke.cont1: ; preds = %lpad
- cleanupret %p unwind to caller
-
-endpad: ; preds = %lpad
- cleanupendpad %p unwind to caller
+ %p = cleanuppad within none []
+ %call2 = call i32 @puts(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @str_recovered, i64 0, i64 0))
+ cleanupret from %p unwind to caller
}
; X64-LABEL: main:
diff --git a/llvm/test/CodeGen/X86/seh-safe-div-win32.ll b/llvm/test/CodeGen/X86/seh-safe-div-win32.ll
index 7f83b0c..3f88696 100644
--- a/llvm/test/CodeGen/X86/seh-safe-div-win32.ll
+++ b/llvm/test/CodeGen/X86/seh-safe-div-win32.ll
@@ -31,28 +31,22 @@
to label %__try.cont unwind label %lpad0
lpad0:
- %p0 = catchpad [i8* bitcast (i32 ()* @safe_div_filt0 to i8*)]
- to label %handler0 unwind label %endpad0
+ %cs0 = catchswitch within none [label %handler0] unwind label %lpad1
handler0:
+ %p0 = catchpad within %cs0 [i8* bitcast (i32 ()* @safe_div_filt0 to i8*)]
call void @puts(i8* getelementptr ([27 x i8], [27 x i8]* @str1, i32 0, i32 0))
store i32 -1, i32* %r, align 4
- catchret %p0 to label %__try.cont
-
-endpad0:
- catchendpad unwind label %lpad1
+ catchret from %p0 to label %__try.cont
lpad1:
- %p1 = catchpad [i8* bitcast (i32 ()* @safe_div_filt1 to i8*)]
- to label %handler1 unwind label %endpad1
+ %cs1 = catchswitch within none [label %handler1] unwind to caller
handler1:
+ %p1 = catchpad within %cs1 [i8* bitcast (i32 ()* @safe_div_filt1 to i8*)]
call void @puts(i8* getelementptr ([29 x i8], [29 x i8]* @str2, i32 0, i32 0))
store i32 -2, i32* %r, align 4
- catchret %p1 to label %__try.cont
-
-endpad1:
- catchendpad unwind to caller
+ catchret from %p1 to label %__try.cont
__try.cont:
%safe_ret = load i32, i32* %r, align 4
@@ -71,13 +65,13 @@
; Landing pad code
-; CHECK: [[lpad0:LBB0_[0-9]+]]: # %lpad0
+; CHECK: [[handler0:LBB0_[0-9]+]]: # %handler0
; Restore SP
; CHECK: movl {{.*}}(%ebp), %esp
; CHECK: calll _puts
; CHECK: jmp [[cont_bb]]
-; CHECK: [[lpad1:LBB0_[0-9]+]]: # %lpad1
+; CHECK: [[handler1:LBB0_[0-9]+]]: # %handler1
; Restore SP
; CHECK: movl {{.*}}(%ebp), %esp
; CHECK: calll _puts
@@ -87,10 +81,10 @@
; CHECK: L__ehtable$safe_div:
; CHECK-NEXT: .long -1
; CHECK-NEXT: .long _safe_div_filt1
-; CHECK-NEXT: .long [[lpad1]]
+; CHECK-NEXT: .long [[handler1]]
; CHECK-NEXT: .long 0
; CHECK-NEXT: .long _safe_div_filt0
-; CHECK-NEXT: .long [[lpad0]]
+; CHECK-NEXT: .long [[handler0]]
define void @try_body(i32* %r, i32* %n, i32* %d) {
entry:
diff --git a/llvm/test/CodeGen/X86/seh-safe-div.ll b/llvm/test/CodeGen/X86/seh-safe-div.ll
index 1c7318b..3eeeab0 100644
--- a/llvm/test/CodeGen/X86/seh-safe-div.ll
+++ b/llvm/test/CodeGen/X86/seh-safe-div.ll
@@ -30,28 +30,22 @@
to label %__try.cont unwind label %lpad0
lpad0:
- %p0 = catchpad [i8* bitcast (i32 (i8*, i8*)* @safe_div_filt0 to i8*)]
- to label %handler0 unwind label %endpad0
+ %cs0 = catchswitch within none [label %handler0] unwind label %lpad1
handler0:
+ %p0 = catchpad within %cs0 [i8* bitcast (i32 (i8*, i8*)* @safe_div_filt0 to i8*)]
call void @puts(i8* getelementptr ([27 x i8], [27 x i8]* @str1, i32 0, i32 0))
store i32 -1, i32* %r, align 4
- catchret %p0 to label %__try.cont
-
-endpad0:
- catchendpad unwind label %lpad1
+ catchret from %p0 to label %__try.cont
lpad1:
- %p1 = catchpad [i8* bitcast (i32 (i8*, i8*)* @safe_div_filt1 to i8*)]
- to label %handler1 unwind label %endpad1
+ %cs1 = catchswitch within none [label %handler1] unwind to caller
handler1:
+ %p1 = catchpad within %cs1 [i8* bitcast (i32 (i8*, i8*)* @safe_div_filt1 to i8*)]
call void @puts(i8* getelementptr ([29 x i8], [29 x i8]* @str2, i32 0, i32 0))
store i32 -2, i32* %r, align 4
- catchret %p1 to label %__try.cont
-
-endpad1:
- catchendpad unwind to caller
+ catchret from %p1 to label %__try.cont
__try.cont:
%safe_ret = load i32, i32* %r, align 4
@@ -73,12 +67,12 @@
; Landing pad code
-; CHECK: [[lpad0:\.LBB0_[0-9]+]]: # %lpad0
+; CHECK: [[handler0:\.LBB0_[0-9]+]]: # %handler0
; CHECK: callq puts
; CHECK: movl $-1, [[rloc]]
; CHECK: jmp [[cont_bb]]
-; CHECK: [[lpad1:\.LBB0_[0-9]+]]: # %lpad1
+; CHECK: [[handler1:\.LBB0_[0-9]+]]: # %handler1
; CHECK: callq puts
; CHECK: movl $-2, [[rloc]]
; CHECK: jmp [[cont_bb]]
@@ -89,11 +83,11 @@
; CHECK-NEXT: .long .Ltmp0@IMGREL+1
; CHECK-NEXT: .long .Ltmp1@IMGREL+1
; CHECK-NEXT: .long safe_div_filt0@IMGREL
-; CHECK-NEXT: .long [[lpad0]]@IMGREL
+; CHECK-NEXT: .long [[handler0]]@IMGREL
; CHECK-NEXT: .long .Ltmp0@IMGREL+1
; CHECK-NEXT: .long .Ltmp1@IMGREL+1
; CHECK-NEXT: .long safe_div_filt1@IMGREL
-; CHECK-NEXT: .long [[lpad1]]@IMGREL
+; CHECK-NEXT: .long [[handler1]]@IMGREL
; CHECK-NEXT: .Llsda_end0:
; CHECK: .text
; CHECK: .seh_endproc
diff --git a/llvm/test/CodeGen/X86/seh-stack-realign.ll b/llvm/test/CodeGen/X86/seh-stack-realign.ll
index 8494cad..880533b 100644
--- a/llvm/test/CodeGen/X86/seh-stack-realign.ll
+++ b/llvm/test/CodeGen/X86/seh-stack-realign.ll
@@ -23,16 +23,13 @@
to label %__try.cont unwind label %lpad
lpad: ; preds = %entry
- %p = catchpad [i8* bitcast (i32 ()* @"filt$main" to i8*)]
- to label %__except unwind label %endpad
+ %cs1 = catchswitch within none [label %__except] unwind to caller
__except: ; preds = %lpad
+ %p = catchpad within %cs1 [i8* bitcast (i32 ()* @"filt$main" to i8*)]
%code = load i32, i32* %__exceptioncode, align 4
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i32 0, i32 0), i32 %code) #4
- catchret %p to label %__try.cont
-
-endpad:
- catchendpad unwind to caller
+ catchret from %p to label %__try.cont
__try.cont: ; preds = %entry, %__except
ret i32 0
@@ -63,7 +60,7 @@
; CHECK: movl $0, 40(%esi)
; CHECK: calll _crash
; CHECK: retl
-; CHECK: LBB0_[[lpbb:[0-9]+]]: # %lpad
+; CHECK: LBB0_[[lpbb:[0-9]+]]: # %__except
; Restore ESP
; CHECK: movl -24(%ebp), %esp
; Restore ESI
diff --git a/llvm/test/CodeGen/X86/tail-dup-catchret.ll b/llvm/test/CodeGen/X86/tail-dup-catchret.ll
index 18682fb..3eeb24d 100644
--- a/llvm/test/CodeGen/X86/tail-dup-catchret.ll
+++ b/llvm/test/CodeGen/X86/tail-dup-catchret.ll
@@ -8,19 +8,16 @@
to label %try.cont unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %0 = catchpad [i8* null, i32 64, i8* null]
- to label %catch unwind label %catchendblock
+ %cs1 = catchswitch within none [label %catch] unwind to caller
catch: ; preds = %catch.dispatch
- catchret %0 to label %try.cont
+ %0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
+ catchret from %0 to label %try.cont
try.cont: ; preds = %entry, %catch
%b.0 = phi i1 [ false, %catch ], [ true, %entry ]
tail call void @h(i1 zeroext %b.0)
ret void
-
-catchendblock: ; preds = %catch.dispatch
- catchendpad unwind to caller
}
; CHECK-LABEL: _f:
diff --git a/llvm/test/CodeGen/X86/tail-merge-wineh.ll b/llvm/test/CodeGen/X86/tail-merge-wineh.ll
index d0f6b72..69c2fda 100644
--- a/llvm/test/CodeGen/X86/tail-merge-wineh.ll
+++ b/llvm/test/CodeGen/X86/tail-merge-wineh.ll
@@ -54,11 +54,11 @@
to label %unreachable unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %1 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
- to label %catch unwind label %catchendblock
+ %cs1 = catchswitch within none [label %catch] unwind label %catch.dispatch.7
catch: ; preds = %catch.dispatch
- catchret %1 to label %catchret.dest
+ %1 = catchpad within %cs1 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+ catchret from %1 to label %catchret.dest
catchret.dest: ; preds = %catch
br label %try.cont
@@ -70,11 +70,11 @@
to label %unreachable unwind label %catch.dispatch.2
catch.dispatch.2: ; preds = %try.cont
- %3 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
- to label %catch.4 unwind label %catchendblock.3
+ %cs2 = catchswitch within none [label %catch.4] unwind label %catch.dispatch.7
catch.4: ; preds = %catch.dispatch.2
- catchret %3 to label %catchret.dest.5
+ %3 = catchpad within %cs2 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+ catchret from %3 to label %catchret.dest.5
catchret.dest.5: ; preds = %catch.4
br label %try.cont.6
@@ -82,15 +82,12 @@
try.cont.6: ; preds = %catchret.dest.5
br label %try.cont.11
-catchendblock.3: ; preds = %catch.dispatch.2
- catchendpad unwind label %catch.dispatch.7
-
-catch.dispatch.7: ; preds = %catchendblock.3, %catchendblock
- %4 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
- to label %catch.9 unwind label %catchendblock.8
+catch.dispatch.7:
+ %cs3 = catchswitch within none [label %catch.9] unwind to caller
catch.9: ; preds = %catch.dispatch.7
- catchret %4 to label %catchret.dest.10
+ %4 = catchpad within %cs3 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+ catchret from %4 to label %catchret.dest.10
catchret.dest.10: ; preds = %catch.9
br label %try.cont.11
@@ -98,12 +95,6 @@
try.cont.11: ; preds = %catchret.dest.10, %try.cont.6
ret void
-catchendblock.8: ; preds = %catch.dispatch.7
- catchendpad unwind to caller
-
-catchendblock: ; preds = %catch.dispatch
- catchendpad unwind label %catch.dispatch.7
-
unreachable: ; preds = %try.cont, %entry
unreachable
}
diff --git a/llvm/test/CodeGen/X86/win-catchpad-csrs.ll b/llvm/test/CodeGen/X86/win-catchpad-csrs.ll
index b6b4a93..9f7a495 100644
--- a/llvm/test/CodeGen/X86/win-catchpad-csrs.ll
+++ b/llvm/test/CodeGen/X86/win-catchpad-csrs.ll
@@ -16,7 +16,7 @@
declare void @f(i32 %p)
declare i32 @__CxxFrameHandler3(...)
-define i32 @try_catch_catch() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+define i32 @try_catch_catch() personality i32 (...)* @__CxxFrameHandler3 {
entry:
%a = call i32 @getint()
%b = call i32 @getint()
@@ -26,22 +26,16 @@
invoke void @f(i32 1)
to label %try.cont unwind label %catch.dispatch
-catch.dispatch: ; preds = %entry
- %0 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
- to label %catch unwind label %catchendblock
-
-catch:
- invoke void @f(i32 2)
- to label %invoke.cont.2 unwind label %catchendblock
-
-invoke.cont.2: ; preds = %catch
- catchret %0 to label %try.cont
-
-try.cont: ; preds = %entry, %invoke.cont.2, %invoke.cont.3
+try.cont:
ret i32 0
-catchendblock: ; preds = %catch,
- catchendpad unwind to caller
+catch.dispatch:
+ %cs = catchswitch within none [label %handler1] unwind to caller
+
+handler1:
+ %h1 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+ call void @f(i32 2)
+ catchret from %h1 to label %try.cont
}
; X86-LABEL: _try_catch_catch:
@@ -71,7 +65,7 @@
; X86: jmp [[contbb]]
; X86: "?catch$[[catch1bb:[0-9]+]]@?0?try_catch_catch@4HA":
-; X86: LBB0_[[catch1bb]]: # %catch.dispatch{{$}}
+; X86: LBB0_[[catch1bb]]: # %handler1{{$}}
; X86: pushl %ebp
; X86-NOT: pushl
; X86: subl $16, %esp
@@ -120,7 +114,7 @@
; X64: retq
; X64: "?catch$[[catch1bb:[0-9]+]]@?0?try_catch_catch@4HA":
-; X64: LBB0_[[catch1bb]]: # %catch.dispatch{{$}}
+; X64: LBB0_[[catch1bb]]: # %handler1{{$}}
; X64: movq %rdx, 16(%rsp)
; X64: pushq %rbp
; X64: .seh_pushreg 5
@@ -159,18 +153,15 @@
invoke void @f(i32 1)
to label %try.cont unwind label %catch.dispatch
-catch.dispatch: ; preds = %entry
- %0 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
- to label %catch unwind label %catchendblock
+catch.dispatch:
+ %cs = catchswitch within none [label %handler1] unwind to caller
-catch:
- catchret %0 to label %try.cont
+handler1:
+ %0 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+ catchret from %0 to label %try.cont
-try.cont: ; preds = %entry, %invoke.cont.2, %invoke.cont.3
+try.cont:
ret i32 0
-
-catchendblock: ; preds = %catch,
- catchendpad unwind to caller
}
; X64-LABEL: try_one_csr:
@@ -198,7 +189,7 @@
; X64: retq
; X64: "?catch$[[catch1bb:[0-9]+]]@?0?try_one_csr@4HA":
-; X64: LBB1_[[catch1bb]]: # %catch.dispatch{{$}}
+; X64: LBB1_[[catch1bb]]: # %handler1{{$}}
; X64: movq %rdx, 16(%rsp)
; X64: pushq %rbp
; X64: .seh_pushreg 5
@@ -226,18 +217,15 @@
invoke void @f(i32 1)
to label %try.cont unwind label %catch.dispatch
-catch.dispatch: ; preds = %entry
- %0 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
- to label %catch unwind label %catchendblock
+catch.dispatch:
+ %cs = catchswitch within none [label %handler1] unwind to caller
-catch:
- catchret %0 to label %try.cont
+handler1:
+ %cp1 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+ catchret from %cp1 to label %try.cont
-try.cont: ; preds = %entry, %invoke.cont.2, %invoke.cont.3
+try.cont:
ret i32 0
-
-catchendblock: ; preds = %catch,
- catchendpad unwind to caller
}
; X64-LABEL: try_no_csr:
@@ -259,7 +247,7 @@
; X64: retq
; X64: "?catch$[[catch1bb:[0-9]+]]@?0?try_no_csr@4HA":
-; X64: LBB2_[[catch1bb]]: # %catch.dispatch{{$}}
+; X64: LBB2_[[catch1bb]]: # %handler1{{$}}
; X64: movq %rdx, 16(%rsp)
; X64: pushq %rbp
; X64: .seh_pushreg 5
diff --git a/llvm/test/CodeGen/X86/win-catchpad-nested-cxx.ll b/llvm/test/CodeGen/X86/win-catchpad-nested-cxx.ll
new file mode 100644
index 0000000..22ce7e5
--- /dev/null
+++ b/llvm/test/CodeGen/X86/win-catchpad-nested-cxx.ll
@@ -0,0 +1,105 @@
+; RUN: llc -verify-machineinstrs -mtriple=i686-pc-windows-msvc < %s \
+; RUN: | FileCheck --check-prefix=CHECK --check-prefix=X86 %s
+; RUN: llc -verify-machineinstrs -mtriple=x86_64-pc-windows-msvc < %s \
+; RUN: | FileCheck --check-prefix=CHECK --check-prefix=X64 %s
+
+; Loosely based on IR for this C++ source code:
+; void f(int p);
+; void try_in_catch() {
+; try {
+; f(1);
+; } catch (...) {
+; try {
+; f(2);
+; } catch (...) {
+; f(3);
+; }
+; }
+; }
+
+declare void @f(i32 %p)
+declare i32 @__CxxFrameHandler3(...)
+
+define i32 @try_in_catch() personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+ invoke void @f(i32 1)
+ to label %try.cont unwind label %catch.dispatch.1
+try.cont:
+ ret i32 0
+
+catch.dispatch.1:
+ %cs1 = catchswitch within none [label %handler1] unwind to caller
+handler1:
+ %h1 = catchpad within %cs1 [i8* null, i32 64, i8* null]
+ invoke void @f(i32 2)
+ to label %catchret1 unwind label %catch.dispatch.2
+catchret1:
+ catchret from %h1 to label %try.cont
+
+catch.dispatch.2:
+ %cs2 = catchswitch within %h1 [label %handler2] unwind to caller
+handler2:
+ %h2 = catchpad within %cs2 [i8* null, i32 64, i8* null]
+ call void @f(i32 3)
+ catchret from %h2 to label %catchret1
+}
+
+; X86-LABEL: L__ehtable$try_in_catch:
+; X64-LABEL: $cppxdata$try_in_catch:
+; CHECK-NEXT: .long 429065506
+; CHECK-NEXT: .long 4
+; CHECK-NEXT: .long ($stateUnwindMap$try_in_catch)
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long ($tryMap$try_in_catch)
+; ip2state num + ptr
+; X86-NEXT: .long 0
+; X86-NEXT: .long 0
+; X64-NEXT: .long 7
+; X64-NEXT: .long ($ip2state$try_in_catch)
+; unwindhelp offset
+; X64-NEXT: .long 40
+; CHECK-NEXT: .long 0
+; EHFlags
+; CHECK-NEXT: .long 1
+
+; CHECK: $tryMap$try_in_catch:
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long 3
+; CHECK-NEXT: .long 1
+; CHECK-NEXT: .long ($handlerMap$0$try_in_catch)
+; CHECK-NEXT: .long 0
+; CHECK-NEXT: .long 0
+; CHECK-NEXT: .long 3
+; CHECK-NEXT: .long 1
+; CHECK-NEXT: .long ($handlerMap$1$try_in_catch)
+
+; CHECK: $handlerMap$0$try_in_catch:
+; CHECK-NEXT: .long 64
+; CHECK-NEXT: .long 0
+; CHECK-NEXT: .long 0
+; CHECK-NEXT: .long "?catch${{[0-9]+}}@?0?try_in_catch@4HA"
+; X64-NEXT: .long 56
+
+; CHECK: $handlerMap$1$try_in_catch:
+; CHECK-NEXT: .long 64
+; CHECK-NEXT: .long 0
+; CHECK-NEXT: .long 0
+; CHECK-NEXT: .long "?catch${{[0-9]+}}@?0?try_in_catch@4HA"
+; X64-NEXT: .long 56
+
+; X64: $ip2state$try_in_catch:
+; X64-NEXT: .long .Lfunc_begin0@IMGREL
+; X64-NEXT: .long -1
+; X64-NEXT: .long .Ltmp0@IMGREL+1
+; X64-NEXT: .long 0
+; X64-NEXT: .long .Ltmp1@IMGREL+1
+; X64-NEXT: .long -1
+; X64-NEXT: .long "?catch$2@?0?try_in_catch@4HA"@IMGREL
+; X64-NEXT: .long 1
+; X64-NEXT: .long .Ltmp2@IMGREL+1
+; X64-NEXT: .long 2
+; X64-NEXT: .long .Ltmp3@IMGREL+1
+; X64-NEXT: .long 1
+; X64-NEXT: .long "?catch$4@?0?try_in_catch@4HA"@IMGREL
+; X64-NEXT: .long 3
diff --git a/llvm/test/CodeGen/X86/win-catchpad-nested.ll b/llvm/test/CodeGen/X86/win-catchpad-nested.ll
index 25adfdf..d20f9f6 100644
--- a/llvm/test/CodeGen/X86/win-catchpad-nested.ll
+++ b/llvm/test/CodeGen/X86/win-catchpad-nested.ll
@@ -7,26 +7,25 @@
define void @test1() personality void ()* @ProcessCLRException {
entry:
invoke void @f()
- to label %exit unwind label %outer.pad
-outer.pad:
- %outer = catchpad [i32 1]
- to label %outer.catch unwind label %outer.end
-outer.catch:
- invoke void @f()
- to label %outer.ret unwind label %inner.pad
-inner.pad:
- %inner = catchpad [i32 2]
- to label %inner.ret unwind label %inner.end
-inner.ret:
- catchret %inner to label %outer.ret
-inner.end:
- catchendpad unwind label %outer.end
-outer.ret:
- catchret %outer to label %exit
-outer.end:
- catchendpad unwind to caller
+ to label %exit unwind label %catch.dispatch.1
exit:
ret void
+
+catch.dispatch.1:
+ %cs1 = catchswitch within none [label %outer.catch] unwind to caller
+
+outer.catch:
+ %cp1 = catchpad within %cs1 [i32 1]
+ invoke void @f()
+ to label %outer.ret unwind label %catch.dispatch.2
+outer.ret:
+ catchret from %cp1 to label %exit
+
+catch.dispatch.2:
+ %cs2 = catchswitch within %cp1 [label %inner.catch] unwind to caller
+inner.catch:
+ %cp2 = catchpad within %cs2 [i32 2]
+ catchret from %cp2 to label %outer.ret
}
; Check the catchret targets
@@ -37,7 +36,7 @@
; CHECK-NEXT: # %outer.ret
; CHECK-NEXT: leaq [[Exit]](%rip), %rax
; CHECK: retq # CATCHRET
-; CHECK: {{^[^: ]+}}: # %inner.pad
+; CHECK: {{^[^: ]+}}: # %inner.catch
; CHECK: .seh_endprolog
; CHECK-NEXT: leaq [[OuterRet]](%rip), %rax
; CHECK: retq # CATCHRET
diff --git a/llvm/test/CodeGen/X86/win-catchpad-varargs.ll b/llvm/test/CodeGen/X86/win-catchpad-varargs.ll
index a2988a3..6508f3b 100644
--- a/llvm/test/CodeGen/X86/win-catchpad-varargs.ll
+++ b/llvm/test/CodeGen/X86/win-catchpad-varargs.ll
@@ -13,20 +13,17 @@
to label %return unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %0 = catchpad [i8* null, i32 64, i8* null]
- to label %catch unwind label %catchendblock
+ %cs1 = catchswitch within none [label %catch] unwind to caller
catch: ; preds = %catch.dispatch
+ %0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
%ap1 = bitcast i8** %ap to i8*
call void @llvm.va_start(i8* %ap1)
%argp.cur = load i8*, i8** %ap
%1 = bitcast i8* %argp.cur to i32*
%arg2 = load i32, i32* %1
call void @llvm.va_end(i8* %ap1)
- catchret %0 to label %return
-
-catchendblock: ; preds = %catch.dispatch
- catchendpad unwind to caller
+ catchret from %0 to label %return
return: ; preds = %entry, %catch
%retval.0 = phi i32 [ %arg2, %catch ], [ -1, %entry ]
diff --git a/llvm/test/CodeGen/X86/win-catchpad.ll b/llvm/test/CodeGen/X86/win-catchpad.ll
index d9c8307..5bd2504 100644
--- a/llvm/test/CodeGen/X86/win-catchpad.ll
+++ b/llvm/test/CodeGen/X86/win-catchpad.ll
@@ -28,7 +28,7 @@
declare i1 @getbool()
declare i32 @__CxxFrameHandler3(...)
-define i32 @try_catch_catch() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+define i32 @try_catch_catch() personality i32 (...)* @__CxxFrameHandler3 {
entry:
%e.addr = alloca i32
%local = alloca i32
@@ -36,33 +36,21 @@
to label %try.cont unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %0 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i32* %e.addr]
- to label %catch unwind label %catch.dispatch.2
+ %cs = catchswitch within none [label %handler1, label %handler2] unwind to caller
-catch: ; preds = %catch.dispatch
+handler1:
+ %h1 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i32* %e.addr]
%e = load i32, i32* %e.addr
- invoke void @f(i32 %e, i32* %local)
- to label %invoke.cont.2 unwind label %catchendblock
+ call void @f(i32 %e, i32* %local)
+ catchret from %h1 to label %try.cont
-invoke.cont.2: ; preds = %catch
- catchret %0 to label %try.cont
+handler2:
+ %h2 = catchpad within %cs [i8* null, i32 64, i8* null]
+ call void @f(i32 3, i32* %local)
+ catchret from %h2 to label %try.cont
-catch.dispatch.2: ; preds = %catch.dispatch
- %1 = catchpad [i8* null, i32 u0x40, i8* null]
- to label %catch.2 unwind label %catchendblock
-
-catch.2: ; preds = %catch.dispatch.2
- invoke void @f(i32 3, i32* %local)
- to label %invoke.cont.3 unwind label %catchendblock
-
-invoke.cont.3: ; preds = %catch.2
- catchret %1 to label %try.cont
-
-try.cont: ; preds = %entry, %invoke.cont.2, %invoke.cont.3
+try.cont:
ret i32 0
-
-catchendblock: ; preds = %catch, %catch.2, %catch.dispatch.2
- catchendpad unwind to caller
}
; X86-LABEL: _try_catch_catch:
@@ -76,25 +64,25 @@
; X86: retl
; X86: [[restorebb1:LBB0_[0-9]+]]: # Block address taken
-; X86-NEXT: # %invoke.cont.2
+; X86-NEXT: # %handler1
; X86-NEXT: addl $12, %ebp
; X86: jmp [[contbb]]
; FIXME: These should be de-duplicated.
; X86: [[restorebb2:LBB0_[0-9]+]]: # Block address taken
-; X86-NEXT: # %invoke.cont.3
+; X86-NEXT: # %handler2
; X86-NEXT: addl $12, %ebp
; X86: jmp [[contbb]]
; X86: "?catch$[[catch1bb:[0-9]+]]@?0?try_catch_catch@4HA":
-; X86: LBB0_[[catch1bb]]: # %catch.dispatch{{$}}
+; X86: LBB0_[[catch1bb]]: # %handler1{{$}}
; X86: pushl %ebp
; X86: subl $8, %esp
; X86: addl $12, %ebp
; X86: movl %esp, -[[sp_offset]](%ebp)
-; X86: leal -[[local_offs]](%ebp), %[[addr_reg:[a-z]+]]
-; X86: movl -32(%ebp), %[[e_reg:[a-z]+]]
-; X86: movl $1, -{{[0-9]+}}(%ebp)
+; X86-DAG: movl -32(%ebp), %[[e_reg:[a-z]+]]
+; X86-DAG: leal -[[local_offs]](%ebp), %[[addr_reg:[a-z]+]]
+; X86-DAG: movl $1, -{{[0-9]+}}(%ebp)
; X86-DAG: movl %[[addr_reg]], 4(%esp)
; X86-DAG: movl %[[e_reg]], (%esp)
; X86: calll _f
@@ -104,13 +92,13 @@
; X86-NEXT: retl
; X86: "?catch$[[catch2bb:[0-9]+]]@?0?try_catch_catch@4HA":
-; X86: LBB0_[[catch2bb]]: # %catch.dispatch.2{{$}}
+; X86: LBB0_[[catch2bb]]: # %handler2{{$}}
; X86: pushl %ebp
; X86: subl $8, %esp
; X86: addl $12, %ebp
; X86: movl %esp, -[[sp_offset]](%ebp)
-; X86: leal -[[local_offs]](%ebp), %[[addr_reg:[a-z]+]]
-; X86: movl $1, -{{[0-9]+}}(%ebp)
+; X86-DAG: leal -[[local_offs]](%ebp), %[[addr_reg:[a-z]+]]
+; X86-DAG: movl $1, -{{[0-9]+}}(%ebp)
; X86-DAG: movl %[[addr_reg]], 4(%esp)
; X86-DAG: movl $3, (%esp)
; X86: calll _f
@@ -151,7 +139,7 @@
; X64: retq
; X64: "?catch$[[catch1bb:[0-9]+]]@?0?try_catch_catch@4HA":
-; X64: LBB0_[[catch1bb]]: # %catch.dispatch{{$}}
+; X64: LBB0_[[catch1bb]]: # %handler1{{$}}
; X64: movq %rdx, 16(%rsp)
; X64: pushq %rbp
; X64: .seh_pushreg 5
@@ -159,7 +147,6 @@
; X64: .seh_stackalloc 32
; X64: leaq 48(%rdx), %rbp
; X64: .seh_endprologue
-; X64-DAG: .Ltmp4
; X64-DAG: leaq -[[local_offs]](%rbp), %rdx
; X64-DAG: movl -12(%rbp), %ecx
; X64: callq f
@@ -169,7 +156,7 @@
; X64-NEXT: retq
; X64: "?catch$[[catch2bb:[0-9]+]]@?0?try_catch_catch@4HA":
-; X64: LBB0_[[catch2bb]]: # %catch.dispatch.2{{$}}
+; X64: LBB0_[[catch2bb]]: # %handler2{{$}}
; X64: movq %rdx, 16(%rsp)
; X64: pushq %rbp
; X64: .seh_pushreg 5
@@ -180,7 +167,6 @@
; X64-DAG: leaq -[[local_offs]](%rbp), %rdx
; X64-DAG: movl $3, %ecx
; X64: callq f
-; X64: .Ltmp3
; X64: leaq [[contbb]](%rip), %rax
; X64-NEXT: addq $32, %rsp
; X64-NEXT: popq %rbp
@@ -192,7 +178,7 @@
; X64-NEXT: .long ($stateUnwindMap$try_catch_catch)@IMGREL
; X64-NEXT: .long 1
; X64-NEXT: .long ($tryMap$try_catch_catch)@IMGREL
-; X64-NEXT: .long 4
+; X64-NEXT: .long 5
; X64-NEXT: .long ($ip2state$try_catch_catch)@IMGREL
; X64-NEXT: .long 40
; X64-NEXT: .long 0
@@ -222,33 +208,35 @@
; X64-NEXT: .long -1
; X64-NEXT: .long .Ltmp0@IMGREL+1
; X64-NEXT: .long 0
-; X64-NEXT: .long .Ltmp4@IMGREL+1
-; X64-NEXT: .long 1
-; X64-NEXT: .long .Ltmp3@IMGREL+1
+; X64-NEXT: .long .Ltmp1@IMGREL+1
; X64-NEXT: .long -1
+; X64-NEXT: .long "?catch$[[catch1bb]]@?0?try_catch_catch@4HA"@IMGREL
+; X64-NEXT: .long 1
+; X64-NEXT: .long "?catch$[[catch2bb]]@?0?try_catch_catch@4HA"@IMGREL
+; X64-NEXT: .long 1
-define i32 @branch_to_normal_dest() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+define i32 @branch_to_normal_dest() personality i32 (...)* @__CxxFrameHandler3 {
entry:
invoke void @f(i32 1, i32* null)
to label %try.cont unwind label %catch.dispatch
catch.dispatch:
- %0 = catchpad [i8* null, i32 64, i8* null]
- to label %catch unwind label %catchendblock
+ %cs1 = catchswitch within none [label %catch] unwind to caller
catch:
+ %cp1 = catchpad within %cs1 [i8* null, i32 64, i8* null]
+ br label %loop
+
+loop:
%V = call i1 @getbool()
- br i1 %V, label %catch, label %catch.done
+ br i1 %V, label %loop, label %catch.done
catch.done:
- catchret %0 to label %try.cont
+ catchret from %cp1 to label %try.cont
try.cont:
ret i32 0
-
-catchendblock:
- catchendpad unwind to caller
}
; X86-LABEL: _branch_to_normal_dest:
@@ -262,17 +250,16 @@
; X86-NEXT: addl $12, %ebp
; X86: jmp [[contbb]]
-; X86: "?catch$[[catchdispbb:[0-9]+]]@?0?branch_to_normal_dest@4HA":
-; X86: LBB1_[[catchdispbb]]: # %catch.dispatch{{$}}
+; X86: "?catch$[[catchbb:[0-9]+]]@?0?branch_to_normal_dest@4HA":
+; X86: LBB1_[[catchbb]]: # %catch{{$}}
; X86: pushl %ebp
; X86: subl $8, %esp
; X86: addl $12, %ebp
-
-; X86: LBB1_[[catchbb:[0-9]+]]: # %catch
-; X86: movl $-1, -16(%ebp)
+; X86: LBB1_[[loopbb:[0-9]+]]: # %loop
+; X86: movl $1, -16(%ebp)
; X86: calll _getbool
; X86: testb $1, %al
-; X86: jne LBB1_[[catchbb]]
+; X86: jne LBB1_[[loopbb]]
; X86: # %catch.done
; X86-NEXT: movl $[[restorebb]], %eax
; X86-NEXT: addl $8, %esp
@@ -284,7 +271,7 @@
; X86-NEXT: .long 64
; X86-NEXT: .long 0
; X86-NEXT: .long 0
-; X86-NEXT: .long "?catch$[[catchdispbb]]@?0?branch_to_normal_dest@4HA"
+; X86-NEXT: .long "?catch$[[catchbb]]@?0?branch_to_normal_dest@4HA"
; X64-LABEL: branch_to_normal_dest:
; X64: # %entry
@@ -305,7 +292,7 @@
; X64: retq
; X64: "?catch$[[catchbb:[0-9]+]]@?0?branch_to_normal_dest@4HA":
-; X64: LBB1_[[catchbb]]: # %catch.dispatch{{$}}
+; X64: LBB1_[[catchbb]]: # %catch{{$}}
; X64: movq %rdx, 16(%rsp)
; X64: pushq %rbp
; X64: .seh_pushreg 5
@@ -313,7 +300,7 @@
; X64: .seh_stackalloc 32
; X64: leaq 48(%rdx), %rbp
; X64: .seh_endprologue
-; X64: .LBB1_[[normal_dest_bb:[0-9]+]]: # %catch
+; X64: .LBB1_[[normal_dest_bb:[0-9]+]]: # %loop
; X64: callq getbool
; X64: testb $1, %al
; X64: jne .LBB1_[[normal_dest_bb]]
@@ -329,7 +316,7 @@
; X64-NEXT: .long ($stateUnwindMap$branch_to_normal_dest)@IMGREL
; X64-NEXT: .long 1
; X64-NEXT: .long ($tryMap$branch_to_normal_dest)@IMGREL
-; X64-NEXT: .long 3
+; X64-NEXT: .long 4
; X64-NEXT: .long ($ip2state$branch_to_normal_dest)@IMGREL
; X64-NEXT: .long 40
; X64-NEXT: .long 0
@@ -362,3 +349,5 @@
; X64-NEXT: .long 0
; X64-NEXT: .long .Ltmp[[after_call]]@IMGREL+1
; X64-NEXT: .long -1
+; X64-NEXT: .long "?catch$[[catchbb]]@?0?branch_to_normal_dest@4HA"@IMGREL
+; X64-NEXT: .long 1
diff --git a/llvm/test/CodeGen/X86/win-cleanuppad.ll b/llvm/test/CodeGen/X86/win-cleanuppad.ll
index 27bb6e2..37090c2 100644
--- a/llvm/test/CodeGen/X86/win-cleanuppad.ll
+++ b/llvm/test/CodeGen/X86/win-cleanuppad.ll
@@ -14,9 +14,9 @@
ret void
ehcleanup: ; preds = %entry
- %0 = cleanuppad []
+ %0 = cleanuppad within none []
call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o) #2
- cleanupret %0 unwind to caller
+ cleanupret from %0 unwind to caller
}
; CHECK: simple_cleanup: # @simple_cleanup
@@ -77,14 +77,14 @@
ret void
cleanup.inner: ; preds = %invoke.cont
- %0 = cleanuppad []
+ %0 = cleanuppad within none []
call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o2) #2
- cleanupret %0 unwind label %cleanup.outer
+ cleanupret from %0 unwind label %cleanup.outer
cleanup.outer: ; preds = %invoke.cont.1, %cleanup.inner, %entry
- %1 = cleanuppad []
+ %1 = cleanuppad within none []
call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o1) #2
- cleanupret %1 unwind to caller
+ cleanupret from %1 unwind to caller
}
; X86-LABEL: _nested_cleanup:
diff --git a/llvm/test/CodeGen/X86/win-funclet-cfi.ll b/llvm/test/CodeGen/X86/win-funclet-cfi.ll
index 52589ee..95afa75 100644
--- a/llvm/test/CodeGen/X86/win-funclet-cfi.ll
+++ b/llvm/test/CodeGen/X86/win-funclet-cfi.ll
@@ -9,24 +9,21 @@
to label %unreachable unwind label %cleanupblock
cleanupblock:
- %cleanp = cleanuppad []
+ %cleanp = cleanuppad within none []
call void @g()
- cleanupret %cleanp unwind label %catch.dispatch
+ cleanupret from %cleanp unwind label %catch.dispatch
catch.dispatch:
- %cp = catchpad [i8* null, i32 64, i8* null]
- to label %catch unwind label %catchendblock
+ %cs1 = catchswitch within none [label %catch] unwind to caller
catch:
+ %cp = catchpad within %cs1 [i8* null, i32 64, i8* null]
call void @g()
- catchret %cp to label %try.cont
+ catchret from %cp to label %try.cont
try.cont:
ret void
-catchendblock:
- catchendpad unwind to caller
-
unreachable:
unreachable
}
@@ -70,7 +67,7 @@
; CHECK: "?catch$[[catch:[0-9]+]]@?0??f@@YAXXZ@4HA":
; CHECK: .seh_proc "?catch$[[catch]]@?0??f@@YAXXZ@4HA"
; CHECK-NEXT: .seh_handler __CxxFrameHandler3, @unwind, @except
-; CHECK: LBB0_[[catch]]: # %catch.dispatch{{$}}
+; CHECK: LBB0_[[catch]]: # %catch{{$}}
; Emit CFI for pushing RBP.
; CHECK: movq %rdx, 16(%rsp)
diff --git a/llvm/test/CodeGen/X86/win-mixed-ehpersonality.ll b/llvm/test/CodeGen/X86/win-mixed-ehpersonality.ll
index 9b69165..f7b6d07 100644
--- a/llvm/test/CodeGen/X86/win-mixed-ehpersonality.ll
+++ b/llvm/test/CodeGen/X86/win-mixed-ehpersonality.ll
@@ -18,12 +18,10 @@
ret i32 0
lpad:
- %p = catchpad [i8* bitcast (i32 (i8*, i8*)* @filt_g to i8*)]
- to label %catch unwind label %endpad
+ %cs = catchswitch within none [label %catch] unwind to caller
catch:
- catchret %p to label %ret1
-endpad:
- catchendpad unwind to caller
+ %p = catchpad within %cs [i8* bitcast (i32 (i8*, i8*)* @filt_g to i8*)]
+ catchret from %p to label %ret1
ret1:
ret i32 1
@@ -39,7 +37,7 @@
; CHECK: xorl %eax, %eax
; CHECK: .LBB0_[[epilogue:[0-9]+]]
; CHECK: retq
-; CHECK: # %lpad
+; CHECK: # %catch{{$}}
; CHECK: movl $1, %eax
; CHECK: jmp .LBB0_[[epilogue]]
diff --git a/llvm/test/CodeGen/X86/win32-eh-states.ll b/llvm/test/CodeGen/X86/win32-eh-states.ll
index cb7b053..fe3639b 100644
--- a/llvm/test/CodeGen/X86/win32-eh-states.ll
+++ b/llvm/test/CodeGen/X86/win32-eh-states.ll
@@ -1,4 +1,5 @@
-; RUN: llc -mtriple=i686-pc-windows-msvc < %s | FileCheck %s
+; RUN: llc -mtriple=i686-pc-windows-msvc < %s | FileCheck %s --check-prefix=X86
+; RUN: llc -mtriple=x86_64-pc-windows-msvc < %s | FileCheck %s --check-prefix=X64
; Based on this source:
; extern "C" void may_throw(int);
@@ -40,59 +41,167 @@
to label %try.cont.9 unwind label %lpad
try.cont.9: ; preds = %invoke.cont.3, %invoke.cont, %catch.7
- ; FIXME: Something about our CFG breaks TailDuplication. This empy asm blocks
- ; it so we can focus on testing the state numbering.
- call void asm sideeffect "", "~{dirflag},~{fpsr},~{flags}"()
ret void
lpad: ; preds = %catch, %entry
- %p1 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
- to label %catch unwind label %end.inner.catch
+ %cs1 = catchswitch within none [label %catch] unwind label %lpad.1
catch: ; preds = %lpad.1
+ %p1 = catchpad within %cs1 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
invoke void @may_throw(i32 3)
- to label %invoke.cont.3 unwind label %end.inner.catch
+ to label %invoke.cont.3 unwind label %lpad.1
invoke.cont.3: ; preds = %catch
- catchret %p1 to label %try.cont.9
-
-
-end.inner.catch:
- catchendpad unwind label %lpad.1
+ catchret from %p1 to label %try.cont.9
lpad.1: ; preds = %invoke.cont
- %p2 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
- to label %catch.7 unwind label %eh.resume
+ %cs2 = catchswitch within none [label %catch.7] unwind to caller
catch.7:
- invoke void @may_throw(i32 4)
- to label %invoke.cont.10 unwind label %eh.resume
-
-invoke.cont.10:
- catchret %p2 to label %try.cont.9
-
-eh.resume: ; preds = %catch.dispatch.4
- catchendpad unwind to caller
+ %p2 = catchpad within %cs2 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+ call void @may_throw(i32 4)
+ catchret from %p2 to label %try.cont.9
}
-; CHECK-LABEL: _f:
-; CHECK: movl $-1, [[state:[-0-9]+]](%ebp)
-; CHECK: movl $___ehhandler$f, {{.*}}
+; X86-LABEL: _f:
+; X86: movl $-1, [[state:[-0-9]+]](%ebp)
+; X86: movl $___ehhandler$f, {{.*}}
;
-; CHECK: movl $0, [[state]](%ebp)
-; CHECK: movl $1, (%esp)
-; CHECK: calll _may_throw
+; X86: movl $0, [[state]](%ebp)
+; X86: movl $1, (%esp)
+; X86: calll _may_throw
;
-; CHECK: movl $1, [[state]](%ebp)
-; CHECK: movl $2, (%esp)
-; CHECK: calll _may_throw
+; X86: movl $1, [[state]](%ebp)
+; X86: movl $2, (%esp)
+; X86: calll _may_throw
;
-; CHECK: movl $2, [[state]](%ebp)
-; CHECK: movl $3, (%esp)
-; CHECK: calll _may_throw
+; X86: movl $2, [[state]](%ebp)
+; X86: movl $3, (%esp)
+; X86: calll _may_throw
;
-; CHECK: movl $3, [[state]](%ebp)
-; CHECK: movl $4, (%esp)
-; CHECK: calll _may_throw
+; X86: movl $3, [[state]](%ebp)
+; X86: movl $4, (%esp)
+; X86: calll _may_throw
-; CHECK: .safeseh ___ehhandler$f
+
+; X64-LABEL: f:
+; X64-LABEL: $ip2state$f:
+; X64-NEXT: .long .Lfunc_begin0@IMGREL
+; X64-NEXT: .long -1
+; X64-NEXT: .long .Ltmp{{.*}}@IMGREL+1
+; X64-NEXT: .long 0
+; X64-NEXT: .long .Ltmp{{.*}}@IMGREL+1
+; X64-NEXT: .long 1
+; X64-NEXT: .long .Ltmp{{.*}}@IMGREL+1
+; X64-NEXT: .long -1
+; X64-NEXT: .long "?catch${{.*}}@?0?f@4HA"@IMGREL
+; X64-NEXT: .long 2
+; X64-NEXT: .long "?catch${{.*}}@?0?f@4HA"@IMGREL
+; X64-NEXT: .long 3
+
+; Based on this source:
+; extern "C" void may_throw(int);
+; struct S { ~S(); };
+; void g() {
+; S x;
+; try {
+; may_throw(-1);
+; } catch (...) {
+; may_throw(0);
+; {
+; S y;
+; may_throw(1);
+; }
+; may_throw(2);
+; }
+; }
+
+%struct.S = type { i8 }
+declare void @"\01??1S@@QEAA@XZ"(%struct.S*)
+
+define void @g() personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+ %x = alloca %struct.S, align 1
+ %y = alloca %struct.S, align 1
+ invoke void @may_throw(i32 -1)
+ to label %unreachable unwind label %catch.dispatch
+
+catch.dispatch: ; preds = %entry
+ %0 = catchswitch within none [label %catch] unwind label %ehcleanup5
+
+catch: ; preds = %catch.dispatch
+ %1 = catchpad within %0 [i8* null, i32 64, i8* null]
+ invoke void @may_throw(i32 0)
+ to label %invoke.cont unwind label %ehcleanup5
+
+invoke.cont: ; preds = %catch
+ invoke void @may_throw(i32 1)
+ to label %invoke.cont2 unwind label %ehcleanup
+
+invoke.cont2: ; preds = %invoke.cont
+ invoke void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %y)
+ to label %invoke.cont3 unwind label %ehcleanup5
+
+invoke.cont3: ; preds = %invoke.cont2
+ invoke void @may_throw(i32 2)
+ to label %invoke.cont4 unwind label %ehcleanup5
+
+invoke.cont4: ; preds = %invoke.cont3
+ catchret from %1 to label %try.cont
+
+try.cont: ; preds = %invoke.cont4
+ call void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %x)
+ ret void
+
+ehcleanup: ; preds = %invoke.cont
+ %2 = cleanuppad within %1 []
+ call void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %y)
+ cleanupret from %2 unwind label %ehcleanup5
+
+ehcleanup5: ; preds = %invoke.cont2, %invoke.cont3, %ehcleanup, %catch, %catch.dispatch
+ %3 = cleanuppad within none []
+ call void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %x)
+ cleanupret from %3 unwind to caller
+
+unreachable: ; preds = %entry
+ unreachable
+}
+
+; X86-LABEL: _g:
+; X86: movl $-1, [[state:[-0-9]+]](%ebp)
+; X86: movl $___ehhandler$g, {{.*}}
+;
+; X86: movl $1, [[state]](%ebp)
+; X86: movl $-1, (%esp)
+; X86: calll _may_throw
+;
+; X86: movl $2, [[state]](%ebp)
+; X86: movl $0, (%esp)
+; X86: calll _may_throw
+;
+; X86: movl $3, [[state]](%ebp)
+; X86: movl $1, (%esp)
+; X86: calll _may_throw
+;
+; X86: movl $2, [[state]](%ebp)
+; X86: movl $2, (%esp)
+; X86: calll _may_throw
+
+; X64-LABEL: g:
+; X64-LABEL: $ip2state$g:
+; X64-NEXT: .long .Lfunc_begin1@IMGREL
+; X64-NEXT: .long -1
+; X64-NEXT: .long .Ltmp{{.*}}@IMGREL+1
+; X64-NEXT: .long 1
+; X64-NEXT: .long .Ltmp{{.*}}@IMGREL+1
+; X64-NEXT: .long -1
+; X64-NEXT: .long "?catch${{.*}}@?0?g@4HA"@IMGREL
+; X64-NEXT: .long 2
+; X64-NEXT: .long .Ltmp{{.*}}@IMGREL+1
+; X64-NEXT: .long 3
+; X64-NEXT: .long .Ltmp{{.*}}@IMGREL+1
+; X64-NEXT: .long 2
+
+
+; X86: .safeseh ___ehhandler$f
+; X86: .safeseh ___ehhandler$g
diff --git a/llvm/test/CodeGen/X86/win32-eh.ll b/llvm/test/CodeGen/X86/win32-eh.ll
index 87926a4..73c7b48 100644
--- a/llvm/test/CodeGen/X86/win32-eh.ll
+++ b/llvm/test/CodeGen/X86/win32-eh.ll
@@ -19,12 +19,10 @@
cont:
ret void
lpad:
- %p = catchpad [i8* bitcast (i32 ()* @catchall_filt to i8*)]
- to label %catch unwind label %endpad
+ %cs = catchswitch within none [label %catch] unwind to caller
catch:
- catchret %p to label %cont
-endpad:
- catchendpad unwind to caller
+ %p = catchpad within %cs [i8* bitcast (i32 ()* @catchall_filt to i8*)]
+ catchret from %p to label %cont
}
; CHECK-LABEL: _use_except_handler3:
@@ -45,7 +43,7 @@
; CHECK: movl -28(%ebp), %[[next:[^ ,]*]]
; CHECK: movl %[[next]], %fs:0
; CHECK: retl
-; CHECK: LBB1_2: # %lpad{{$}}
+; CHECK: LBB1_2: # %catch{{$}}
; CHECK: .section .xdata,"dr"
; CHECK-LABEL: L__ehtable$use_except_handler3:
@@ -60,12 +58,10 @@
cont:
ret void
lpad:
- %p = catchpad [i8* bitcast (i32 ()* @catchall_filt to i8*)]
- to label %catch unwind label %endpad
+ %cs = catchswitch within none [label %catch] unwind to caller
catch:
- catchret %p to label %cont
-endpad:
- catchendpad unwind to caller
+ %p = catchpad within %cs [i8* bitcast (i32 ()* @catchall_filt to i8*)]
+ catchret from %p to label %cont
}
; CHECK-LABEL: _use_except_handler4:
@@ -86,7 +82,7 @@
; CHECK: movl -28(%ebp), %[[next:[^ ,]*]]
; CHECK: movl %[[next]], %fs:0
; CHECK: retl
-; CHECK: LBB2_2: # %lpad{{$}}
+; CHECK: LBB2_2: # %catch{{$}}
; CHECK: .section .xdata,"dr"
; CHECK-LABEL: L__ehtable$use_except_handler4:
@@ -105,14 +101,10 @@
ret void
catchall:
- %p = catchpad [i8* null, i32 64, i8* null]
- to label %catch unwind label %endcatch
-
+ %cs = catchswitch within none [label %catch] unwind to caller
catch:
- catchret %p to label %cont
-
-endcatch:
- catchendpad unwind to caller
+ %p = catchpad within %cs [i8* null, i32 64, i8* null]
+ catchret from %p to label %cont
}
; CHECK-LABEL: _use_CxxFrameHandler3:
diff --git a/llvm/test/CodeGen/X86/win32-seh-catchpad-realign.ll b/llvm/test/CodeGen/X86/win32-seh-catchpad-realign.ll
index 24db164..23aeea3 100644
--- a/llvm/test/CodeGen/X86/win32-seh-catchpad-realign.ll
+++ b/llvm/test/CodeGen/X86/win32-seh-catchpad-realign.ll
@@ -15,17 +15,14 @@
to label %__try.cont unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %pad = catchpad [i8* bitcast (i32 ()* @"\01?filt$0@0@realigned_try@@" to i8*)]
- to label %__except.ret unwind label %catchendblock
+ %cs1 = catchswitch within none [label %__except.ret] unwind to caller
__except.ret: ; preds = %catch.dispatch
- catchret %pad to label %__try.cont
+ %pad = catchpad within %cs1 [i8* bitcast (i32 ()* @"\01?filt$0@0@realigned_try@@" to i8*)]
+ catchret from %pad to label %__try.cont
__try.cont: ; preds = %entry, %__except.ret
ret void
-
-catchendblock: ; preds = %catch.dispatch
- catchendpad unwind to caller
}
; Function Attrs: nounwind argmemonly
@@ -69,7 +66,7 @@
; CHECK: popl %ebp
; CHECK: retl
;
-; CHECK: LBB0_1: # %catch.dispatch
+; CHECK: LBB0_1: # %__except.ret
; Restore ESP
; CHECK: movl -24(%ebp), %esp
; Recompute ESI by subtracting 60 from the end of the registration node.
diff --git a/llvm/test/CodeGen/X86/win32-seh-catchpad.ll b/llvm/test/CodeGen/X86/win32-seh-catchpad.ll
index 4e373af..88dea36 100644
--- a/llvm/test/CodeGen/X86/win32-seh-catchpad.ll
+++ b/llvm/test/CodeGen/X86/win32-seh-catchpad.ll
@@ -11,10 +11,11 @@
to label %invoke.cont unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %0 = catchpad [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)] to label %__except.ret unwind label %catchendblock
+ %cs1 = catchswitch within none [label %__except.ret] unwind to caller
__except.ret: ; preds = %catch.dispatch
- catchret %0 to label %__except
+ %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)]
+ catchret from %0 to label %__except
__except: ; preds = %__except.ret
call void @f(i32 2)
@@ -24,9 +25,6 @@
call void @f(i32 3)
ret void
-catchendblock: ; preds = %catch.dispatch
- catchendpad unwind to caller
-
invoke.cont: ; preds = %entry
br label %__try.cont
}
@@ -77,81 +75,69 @@
to label %__try.cont unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %0 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret unwind label %catchendblock
+ %cs1 = catchswitch within none [label %__except.ret] unwind label %catch.dispatch.11
__except.ret: ; preds = %catch.dispatch
- catchret %0 to label %__try.cont
+ %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
+ catchret from %0 to label %__try.cont
__try.cont: ; preds = %entry, %__except.ret
invoke void @crash() #3
to label %__try.cont.9 unwind label %catch.dispatch.5
catch.dispatch.5: ; preds = %__try.cont
- %1 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.7 unwind label %catchendblock.6
+ %cs2 = catchswitch within none [label %__except.ret.7] unwind label %catch.dispatch.11
__except.ret.7: ; preds = %catch.dispatch.5
- catchret %1 to label %__try.cont.9
+ %1 = catchpad within %cs2 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
+ catchret from %1 to label %__try.cont.9
__try.cont.9: ; preds = %__try.cont, %__except.ret.7
invoke void @crash() #3
to label %__try.cont.15 unwind label %catch.dispatch.11
catch.dispatch.11: ; preds = %catchendblock, %catchendblock.6, %__try.cont.9
- %2 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.13 unwind label %catchendblock.12
+ %cs3 = catchswitch within none [label %__except.ret.13] unwind label %catch.dispatch.17
__except.ret.13: ; preds = %catch.dispatch.11
- catchret %2 to label %__try.cont.15
+ %2 = catchpad within %cs3 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
+ catchret from %2 to label %__try.cont.15
__try.cont.15: ; preds = %__try.cont.9, %__except.ret.13
invoke void @crash() #3
to label %__try.cont.35 unwind label %catch.dispatch.17
catch.dispatch.17: ; preds = %catchendblock.12, %__try.cont.15
- %3 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.19 unwind label %catchendblock.18
+ %cs4 = catchswitch within none [label %__except.ret.19] unwind to caller
__except.ret.19: ; preds = %catch.dispatch.17
- catchret %3 to label %__except.20
+ %3 = catchpad within %cs4 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
+ catchret from %3 to label %__except.20
__except.20: ; preds = %__except.ret.19
invoke void @crash() #3
to label %__try.cont.27 unwind label %catch.dispatch.23
catch.dispatch.23: ; preds = %__except.20
- %4 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.25 unwind label %catchendblock.24
+ %cs5 = catchswitch within none [label %__except.ret.25] unwind to caller
__except.ret.25: ; preds = %catch.dispatch.23
- catchret %4 to label %__try.cont.27
+ %4 = catchpad within %cs5 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
+ catchret from %4 to label %__try.cont.27
__try.cont.27: ; preds = %__except.20, %__except.ret.25
invoke void @crash() #3
to label %__try.cont.35 unwind label %catch.dispatch.30
catch.dispatch.30: ; preds = %__try.cont.27
- %5 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.32 unwind label %catchendblock.31
+ %cs6 = catchswitch within none [label %__except.ret.32] unwind to caller
__except.ret.32: ; preds = %catch.dispatch.30
- catchret %5 to label %__try.cont.35
+ %5 = catchpad within %cs6 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
+ catchret from %5 to label %__try.cont.35
__try.cont.35: ; preds = %__try.cont.15, %__try.cont.27, %__except.ret.32
ret void
-
-catchendblock.31: ; preds = %catch.dispatch.30
- catchendpad unwind to caller
-
-catchendblock.24: ; preds = %catch.dispatch.23
- catchendpad unwind to caller
-
-catchendblock.18: ; preds = %catch.dispatch.17
- catchendpad unwind to caller
-
-catchendblock.12: ; preds = %catch.dispatch.11
- catchendpad unwind label %catch.dispatch.17
-
-catchendblock.6: ; preds = %catch.dispatch.5
- catchendpad unwind label %catch.dispatch.11
-
-catchendblock: ; preds = %catch.dispatch
- catchendpad unwind label %catch.dispatch.11
}
; This table is equivalent to the one produced by MSVC, even if it isn't in
@@ -162,19 +148,19 @@
; CHECK: .long -1
; CHECK: .long _nested_exceptions_filter_catchall
; CHECK: .long LBB
-; CHECK: .long -1
+; CHECK: .long 0
+; CHECK: .long _nested_exceptions_filter_catchall
+; CHECK: .long LBB
+; CHECK: .long 1
+; CHECK: .long _nested_exceptions_filter_catchall
+; CHECK: .long LBB
+; CHECK: .long 1
; CHECK: .long _nested_exceptions_filter_catchall
; CHECK: .long LBB
; CHECK: .long -1
; CHECK: .long _nested_exceptions_filter_catchall
; CHECK: .long LBB
-; CHECK: .long 2
-; CHECK: .long _nested_exceptions_filter_catchall
-; CHECK: .long LBB
-; CHECK: .long 3
-; CHECK: .long _nested_exceptions_filter_catchall
-; CHECK: .long LBB
-; CHECK: .long 3
+; CHECK: .long -1
; CHECK: .long _nested_exceptions_filter_catchall
; CHECK: .long LBB
@@ -203,21 +189,19 @@
to label %__except unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %0 = catchpad [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)] to label %__except.ret unwind label %catchendblock
+ %cs1 = catchswitch within none [label %__except.ret] unwind to caller
__except.ret: ; preds = %catch.dispatch
+ %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)]
call void @f(i32 2)
- catchret %0 to label %__except
+ catchret from %0 to label %__except
__except:
ret void
-
-catchendblock: ; preds = %catch.dispatch
- catchendpad unwind to caller
}
; CHECK-LABEL: _code_in_catchpad:
-; CHECK: # %catch.dispatch
+; CHECK: # %__except.ret
; CHECK-NEXT: movl -24(%ebp), %esp
; CHECK-NEXT: addl $12, %ebp
; CHECK-NEXT: movl $-1, -16(%ebp)
diff --git a/llvm/test/CodeGen/X86/win32-seh-cleanupendpad.ll b/llvm/test/CodeGen/X86/win32-seh-nested-finally.ll
similarity index 81%
rename from llvm/test/CodeGen/X86/win32-seh-cleanupendpad.ll
rename to llvm/test/CodeGen/X86/win32-seh-nested-finally.ll
index 35d9bfe..c91a142 100644
--- a/llvm/test/CodeGen/X86/win32-seh-cleanupendpad.ll
+++ b/llvm/test/CodeGen/X86/win32-seh-nested-finally.ll
@@ -17,26 +17,17 @@
ret void
ehcleanup: ; preds = %entry
- %0 = cleanuppad []
+ %0 = cleanuppad within none []
invoke void @f(i32 2) #3
- to label %invoke.cont.2 unwind label %ehcleanup.end
+ to label %invoke.cont.2 unwind label %ehcleanup.3
invoke.cont.2: ; preds = %ehcleanup
- cleanupret %0 unwind label %ehcleanup.3
-
-ehcleanup.end: ; preds = %ehcleanup
- cleanupendpad %0 unwind label %ehcleanup.3
+ cleanupret from %0 unwind label %ehcleanup.3
ehcleanup.3: ; preds = %invoke.cont.2, %ehcleanup.end, %invoke.cont
- %1 = cleanuppad []
- invoke void @f(i32 3) #3
- to label %invoke.cont.4 unwind label %ehcleanup.end.5
-
-invoke.cont.4: ; preds = %ehcleanup.3
- cleanupret %1 unwind to caller
-
-ehcleanup.end.5: ; preds = %ehcleanup.3
- cleanupendpad %1 unwind to caller
+ %1 = cleanuppad within none []
+ call void @f(i32 3) #3
+ cleanupret from %1 unwind to caller
}
declare void @f(i32) #0
diff --git a/llvm/test/CodeGen/X86/wineh-coreclr.ll b/llvm/test/CodeGen/X86/wineh-coreclr.ll
new file mode 100644
index 0000000..7bbc64e
--- /dev/null
+++ b/llvm/test/CodeGen/X86/wineh-coreclr.ll
@@ -0,0 +1,267 @@
+; RUN: llc -mtriple=x86_64-pc-windows-coreclr -verify-machineinstrs < %s | FileCheck %s
+
+declare void @ProcessCLRException()
+declare void @f(i32)
+declare void @g(i8 addrspace(1)*)
+declare i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token)
+
+; Simplified IR for pseudo-C# like the following:
+; void test1() {
+; try {
+; f(1);
+; try {
+; f(2);
+; } catch (type1) {
+; f(3);
+; } catch (type2) {
+; f(4);
+; try {
+; f(5);
+; } fault {
+; f(6);
+; }
+; }
+; } finally {
+; f(7);
+; }
+; f(8);
+; }
+
+; CHECK-LABEL: test1: # @test1
+; CHECK-NEXT: [[L_begin:.*func_begin.*]]:
+define void @test1() personality i8* bitcast (void ()* @ProcessCLRException to i8*) {
+entry:
+; CHECK: # %entry
+; CHECK: leaq [[FPOffset:[0-9]+]](%rsp), %rbp
+; CHECK: .seh_endprologue
+; CHECK: movq %rsp, [[PSPSymOffset:[0-9]+]](%rsp)
+; CHECK: [[L_before_f1:.+]]:
+; CHECK-NEXT: movl $1, %ecx
+; CHECK-NEXT: callq f
+; CHECK-NEXT: [[L_after_f1:.+]]:
+ invoke void @f(i32 1)
+ to label %inner_try unwind label %finally.pad
+inner_try:
+; CHECK: # %inner_try
+; CHECK: [[L_before_f2:.+]]:
+; CHECK-NEXT: movl $2, %ecx
+; CHECK-NEXT: callq f
+; CHECK-NEXT: [[L_after_f2:.+]]:
+ invoke void @f(i32 2)
+ to label %finally.clone unwind label %catch1.pad
+catch1.pad:
+ %cs1 = catchswitch within none [label %catch1.body, label %catch2.body] unwind label %finally.pad
+catch1.body:
+ %catch1 = catchpad within %cs1 [i32 1]
+; CHECK: .seh_proc [[L_catch1:[^ ]+]]
+; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]]
+; ^ all funclets use the same frame size
+; CHECK: movq [[PSPSymOffset]](%rcx), %rcx
+; ^ establisher frame pointer passed in rcx
+; CHECK: movq %rcx, [[PSPSymOffset]](%rsp)
+; CHECK: leaq [[FPOffset]](%rcx), %rbp
+; CHECK: .seh_endprologue
+; CHECK: movq %rdx, %rcx
+; ^ exception pointer passed in rdx
+; CHECK-NEXT: callq g
+ %exn1 = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch1)
+ call void @g(i8 addrspace(1)* %exn1)
+; CHECK: [[L_before_f3:.+]]:
+; CHECK-NEXT: movl $3, %ecx
+; CHECK-NEXT: callq f
+; CHECK-NEXT: [[L_after_f3:.+]]:
+ invoke void @f(i32 3)
+ to label %catch1.ret unwind label %finally.pad
+catch1.ret:
+ catchret from %catch1 to label %finally.clone
+catch2.body:
+ %catch2 = catchpad within %cs1 [i32 2]
+; CHECK: .seh_proc [[L_catch2:[^ ]+]]
+; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]]
+; ^ all funclets use the same frame size
+; CHECK: movq [[PSPSymOffset]](%rcx), %rcx
+; ^ establisher frame pointer passed in rcx
+; CHECK: movq %rcx, [[PSPSymOffset]](%rsp)
+; CHECK: leaq [[FPOffset]](%rcx), %rbp
+; CHECK: .seh_endprologue
+; CHECK: movq %rdx, %rcx
+; ^ exception pointer passed in rdx
+; CHECK-NEXT: callq g
+ %exn2 = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch2)
+ call void @g(i8 addrspace(1)* %exn2)
+; CHECK: [[L_before_f4:.+]]:
+; CHECK-NEXT: movl $4, %ecx
+; CHECK-NEXT: callq f
+; CHECK-NEXT: [[L_after_f4:.+]]:
+ invoke void @f(i32 4)
+ to label %try_in_catch unwind label %finally.pad
+try_in_catch:
+; CHECK: # %try_in_catch
+; CHECK: [[L_before_f5:.+]]:
+; CHECK-NEXT: movl $5, %ecx
+; CHECK-NEXT: callq f
+; CHECK-NEXT: [[L_after_f5:.+]]:
+ invoke void @f(i32 5)
+ to label %catch2.ret unwind label %fault.pad
+fault.pad:
+; CHECK: .seh_proc [[L_fault:[^ ]+]]
+ %fault = cleanuppad within none [i32 undef]
+; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]]
+; ^ all funclets use the same frame size
+; CHECK: movq [[PSPSymOffset]](%rcx), %rcx
+; ^ establisher frame pointer passed in rcx
+; CHECK: movq %rcx, [[PSPSymOffset]](%rsp)
+; CHECK: leaq [[FPOffset]](%rcx), %rbp
+; CHECK: .seh_endprologue
+; CHECK: [[L_before_f6:.+]]:
+; CHECK-NEXT: movl $6, %ecx
+; CHECK-NEXT: callq f
+; CHECK-NEXT: [[L_after_f6:.+]]:
+ invoke void @f(i32 6)
+ to label %fault.ret unwind label %finally.pad
+fault.ret:
+ cleanupret from %fault unwind label %finally.pad
+catch2.ret:
+ catchret from %catch2 to label %finally.clone
+finally.clone:
+ call void @f(i32 7)
+ br label %tail
+finally.pad:
+; CHECK: .seh_proc [[L_finally:[^ ]+]]
+ %finally = cleanuppad within none []
+; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]]
+; ^ all funclets use the same frame size
+; CHECK: movq [[PSPSymOffset]](%rcx), %rcx
+; ^ establisher frame pointer passed in rcx
+; CHECK: movq %rcx, [[PSPSymOffset]](%rsp)
+; CHECK: leaq [[FPOffset]](%rcx), %rbp
+; CHECK: .seh_endprologue
+; CHECK-NEXT: movl $7, %ecx
+; CHECK-NEXT: callq f
+ call void @f(i32 7)
+ cleanupret from %finally unwind to caller
+tail:
+ call void @f(i32 8)
+ ret void
+; CHECK: [[L_end:.*func_end.*]]:
+}
+
+; FIXME: Verify that the new clauses are correct and re-enable these checks.
+
+; Now check for EH table in xdata (following standard xdata)
+; CHECKX-LABEL: .section .xdata
+; standard xdata comes here
+; CHECKX: .long 4{{$}}
+; ^ number of funclets
+; CHECKX-NEXT: .long [[L_catch1]]-[[L_begin]]
+; ^ offset from L_begin to start of 1st funclet
+; CHECKX-NEXT: .long [[L_catch2]]-[[L_begin]]
+; ^ offset from L_begin to start of 2nd funclet
+; CHECKX-NEXT: .long [[L_fault]]-[[L_begin]]
+; ^ offset from L_begin to start of 3rd funclet
+; CHECKX-NEXT: .long [[L_finally]]-[[L_begin]]
+; ^ offset from L_begin to start of 4th funclet
+; CHECKX-NEXT: .long [[L_end]]-[[L_begin]]
+; ^ offset from L_begin to end of last funclet
+; CHECKX-NEXT: .long 7
+; ^ number of EH clauses
+; Clause 1: call f(2) is guarded by catch1
+; CHECKX-NEXT: .long 0
+; ^ flags (0 => catch handler)
+; CHECKX-NEXT: .long ([[L_before_f2]]-[[L_begin]])+1
+; ^ offset of start of clause
+; CHECKX-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1
+; ^ offset of end of clause
+; CHECKX-NEXT: .long [[L_catch1]]-[[L_begin]]
+; ^ offset of start of handler
+; CHECKX-NEXT: .long [[L_catch2]]-[[L_begin]]
+; ^ offset of end of handler
+; CHECKX-NEXT: .long 1
+; ^ type token of catch (from catchpad)
+; Clause 2: call f(2) is also guarded by catch2
+; CHECKX-NEXT: .long 0
+; ^ flags (0 => catch handler)
+; CHECKX-NEXT: .long ([[L_before_f2]]-[[L_begin]])+1
+; ^ offset of start of clause
+; CHECKX-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1
+; ^ offset of end of clause
+; CHECKX-NEXT: .long [[L_catch2]]-[[L_begin]]
+; ^ offset of start of handler
+; CHECKX-NEXT: .long [[L_fault]]-[[L_begin]]
+; ^ offset of end of handler
+; CHECKX-NEXT: .long 2
+; ^ type token of catch (from catchpad)
+; Clause 3: calls f(1) and f(2) are guarded by finally
+; CHECKX-NEXT: .long 2
+; ^ flags (2 => finally handler)
+; CHECKX-NEXT: .long ([[L_before_f1]]-[[L_begin]])+1
+; ^ offset of start of clause
+; CHECKX-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1
+; ^ offset of end of clause
+; CHECKX-NEXT: .long [[L_finally]]-[[L_begin]]
+; ^ offset of start of handler
+; CHECKX-NEXT: .long [[L_end]]-[[L_begin]]
+; ^ offset of end of handler
+; CHECKX-NEXT: .long 0
+; ^ type token slot (null for finally)
+; Clause 4: call f(3) is guarded by finally
+; This is a "duplicate" because the protected range (f(3))
+; is in funclet catch1 but the finally's immediate parent
+; is the main function, not that funclet.
+; CHECKX-NEXT: .long 10
+; ^ flags (2 => finally handler | 8 => duplicate)
+; CHECKX-NEXT: .long ([[L_before_f3]]-[[L_begin]])+1
+; ^ offset of start of clause
+; CHECKX-NEXT: .long ([[L_after_f3]]-[[L_begin]])+1
+; ^ offset of end of clause
+; CHECKX-NEXT: .long [[L_finally]]-[[L_begin]]
+; ^ offset of start of handler
+; CHECKX-NEXT: .long [[L_end]]-[[L_begin]]
+; ^ offset of end of handler
+; CHECKX-NEXT: .long 0
+; ^ type token slot (null for finally)
+; Clause 5: call f(5) is guarded by fault
+; CHECKX-NEXT: .long 4
+; ^ flags (4 => fault handler)
+; CHECKX-NEXT: .long ([[L_before_f5]]-[[L_begin]])+1
+; ^ offset of start of clause
+; CHECKX-NEXT: .long ([[L_after_f5]]-[[L_begin]])+1
+; ^ offset of end of clause
+; CHECKX-NEXT: .long [[L_fault]]-[[L_begin]]
+; ^ offset of start of handler
+; CHECKX-NEXT: .long [[L_finally]]-[[L_begin]]
+; ^ offset of end of handler
+; CHECKX-NEXT: .long 0
+; ^ type token slot (null for fault)
+; Clause 6: calls f(4) and f(5) are guarded by finally
+; This is a "duplicate" because the protected range (f(4)-f(5))
+; is in funclet catch2 but the finally's immediate parent
+; is the main function, not that funclet.
+; CHECKX-NEXT: .long 10
+; ^ flags (2 => finally handler | 8 => duplicate)
+; CHECKX-NEXT: .long ([[L_before_f4]]-[[L_begin]])+1
+; ^ offset of start of clause
+; CHECKX-NEXT: .long ([[L_after_f5]]-[[L_begin]])+1
+; ^ offset of end of clause
+; CHECKX-NEXT: .long [[L_finally]]-[[L_begin]]
+; ^ offset of start of handler
+; CHECKX-NEXT: .long [[L_end]]-[[L_begin]]
+; ^ offset of end of handler
+; CHECKX-NEXT: .long 0
+; ^ type token slot (null for finally)
+; Clause 7: call f(6) is guarded by finally
+; This is a "duplicate" because the protected range (f(3))
+; is in funclet catch1 but the finally's immediate parent
+; is the main function, not that funclet.
+; CHECKX-NEXT: .long 10
+; ^ flags (2 => finally handler | 8 => duplicate)
+; CHECKX-NEXT: .long ([[L_before_f6]]-[[L_begin]])+1
+; ^ offset of start of clause
+; CHECKX-NEXT: .long ([[L_after_f6]]-[[L_begin]])+1
+; ^ offset of end of clause
+; CHECKX-NEXT: .long [[L_finally]]-[[L_begin]]
+; ^ offset of start of handler
+; CHECKX-NEXT: .long [[L_end]]-[[L_begin]]
+; ^ offset of end of handler
+; CHECKX-NEXT: .long 0
+; ^ type token slot (null for finally)
diff --git a/llvm/test/CodeGen/X86/wineh-exceptionpointer.ll b/llvm/test/CodeGen/X86/wineh-exceptionpointer.ll
new file mode 100644
index 0000000..9c1f0aa
--- /dev/null
+++ b/llvm/test/CodeGen/X86/wineh-exceptionpointer.ll
@@ -0,0 +1,26 @@
+; RUN: llc -mtriple=x86_64-pc-windows-coreclr < %s | FileCheck %s
+
+declare void @ProcessCLRException()
+declare i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token)
+declare void @f()
+declare void @g(i32 addrspace(1)*)
+
+; CHECK-LABEL: test1: # @test1
+define void @test1() personality i8* bitcast (void ()* @ProcessCLRException to i8*) {
+entry:
+ invoke void @f()
+ to label %exit unwind label %catch.pad
+catch.pad:
+ %cs1 = catchswitch within none [label %catch.body] unwind to caller
+catch.body:
+ ; CHECK: {{^[^: ]+}}: # %catch.body
+ ; CHECK: movq %rdx, %rcx
+ ; CHECK-NEXT: callq g
+ %catch = catchpad within %cs1 [i32 5]
+ %exn = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch)
+ %cast_exn = bitcast i8 addrspace(1)* %exn to i32 addrspace(1)*
+ call void @g(i32 addrspace(1)* %cast_exn)
+ catchret from %catch to label %exit
+exit:
+ ret void
+}