// the actions that would be taken in that state. This means our tables are
// slightly bigger, which is OK.
for (const auto &MBB : *MF) {
+ // Break out before we enter into a finally funclet.
+ // FIXME: We need to emit separate EH tables for cleanups.
+ if (MBB.isEHFuncletEntry() && &MBB != MF->begin())
+ break;
+
for (InvokeRange &I : invoke_ranges(FuncInfo, MBB)) {
// If this invoke is in the same state as the last invoke and there were
// no non-throwing calls between it, extend the range to include both
to label %__try.cont unwind label %lpad
lpad: ; preds = %entry
- %0 = landingpad { i8*, i32 }
- catch i8* bitcast (i32 ()* @"filt$main" to i8*)
- %1 = extractvalue { i8*, i32 } %0, 1
- %2 = call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @"filt$main" to i8*)) #4
- %matches = icmp eq i32 %1, %2
- br i1 %matches, label %__except, label %eh.resume
+ %p = catchpad [i8* bitcast (i32 ()* @"filt$main" to i8*)]
+ to label %__except unwind label %endpad
__except: ; preds = %lpad
- %3 = 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 %3) #4
- br label %__try.cont
+ %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
__try.cont: ; preds = %entry, %__except
ret i32 0
-
-eh.resume: ; preds = %lpad
- resume { i8*, i32 } %0
}
define internal i32 @"filt$main"() {
; CHECK: Lmain$frame_escape_1 = [[reg_offs:[-0-9]+]]
; CHECK: movl %esp, [[reg_offs]](%ebp)
; CHECK: movl $L__ehtable$main,
-; EH state 0
+; EH state 0
; CHECK: movl $0, -16(%ebp)
; CHECK: calll _crash
; CHECK: popl %esi
; CHECK: popl %edi
; CHECK: popl %ebx
; CHECK: retl
-; CHECK: # Block address taken
-; stackrestore
+; CHECK: LBB0_[[lpbb:[0-9]+]]: # %lpad{{$}}
+; stackrestore
; CHECK: movl -24(%ebp), %esp
-; EH state -1
+; EH state -1
; CHECK: movl [[code_offs]](%ebp), %[[code:[a-z]+]]
-; CHECK: movl $-1, -16(%ebp)
; CHECK-DAG: movl %[[code]], 4(%esp)
; CHECK-DAG: movl $_str, (%esp)
; CHECK: calll _printf
; CHECK: L__ehtable$main
; CHECK-NEXT: .long -1
; CHECK-NEXT: .long _filt$main
-; CHECK-NEXT: .long Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long LBB0_[[lpbb]]
; CHECK-LABEL: _filt$main:
; CHECK: pushl %ebp
; CHECK-NEXT: .long "?filt$0@0@main@@"@IMGREL
; CHECK-NEXT: .long .LBB1_6@IMGREL
; CHECK-NEXT: .long .Ltmp6@IMGREL+1
-; CHECK-NEXT: .long .Ltmp5@IMGREL+1
+; CHECK-NEXT: .long .Ltmp7@IMGREL+1
; CHECK-NEXT: .long "?filt$0@0@main@@"@IMGREL
; CHECK-NEXT: .long .LBB1_6@IMGREL
; CHECK-NEXT: .Llsda_end0:
%exn.slot = alloca i8*
%ehselector.slot = alloca i32
invoke void @crash() #5
- to label %invoke.cont unwind label %lpad
+ to label %invoke.cont unwind label %__finally
invoke.cont: ; preds = %entry
%0 = call i8* @llvm.localaddress()
invoke void @"\01?fin$0@0@use_both@@"(i1 zeroext false, i8* %0) #5
- to label %invoke.cont2 unwind label %lpad1
+ to label %invoke.cont2 unwind label %catch.dispatch
invoke.cont2: ; preds = %invoke.cont
br label %__try.cont
-lpad: ; preds = %entry
- %1 = landingpad { i8*, i32 }
- cleanup
- catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_both@@" to i8*)
- %2 = extractvalue { i8*, i32 } %1, 0
- store i8* %2, i8** %exn.slot
- %3 = extractvalue { i8*, i32 } %1, 1
- store i32 %3, i32* %ehselector.slot
- %4 = call i8* @llvm.localaddress()
- invoke void @"\01?fin$0@0@use_both@@"(i1 zeroext true, i8* %4) #5
- to label %invoke.cont3 unwind label %lpad1
-
-lpad1: ; preds = %lpad, %invoke.cont
- %5 = landingpad { i8*, i32 }
- catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_both@@" to i8*)
- %6 = extractvalue { i8*, i32 } %5, 0
- store i8* %6, i8** %exn.slot
- %7 = extractvalue { i8*, i32 } %5, 1
- store i32 %7, i32* %ehselector.slot
- br label %catch.dispatch
+__finally: ; preds = %entry
+ %cleanuppad = cleanuppad []
+ %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
+
+invoke.cont3: ; preds = %__finally
+ cleanupret %cleanuppad unwind label %catch.dispatch
-invoke.cont3: ; preds = %lpad
- br label %catch.dispatch
+cleanupendpad:
+ cleanupendpad %cleanuppad unwind label %catch.dispatch
catch.dispatch: ; preds = %invoke.cont3, %lpad1
- %sel = load i32, i32* %ehselector.slot
- %8 = call i32 @llvm.eh.typeid.for(i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_both@@" to i8*)) #6
- %matches = icmp eq i32 %sel, %8
- br i1 %matches, label %__except, label %eh.resume
+ %catchpad = catchpad [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_both@@" to i8*)]
+ to label %__except unwind label %catchendpad
__except: ; preds = %catch.dispatch
%call = call i32 @puts(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @"\01??_C@_08MLCMLGHM@__except?$AA@", i32 0, i32 0))
- br label %__try.cont
+ catchret %catchpad to label %__try.cont
+
+catchendpad:
+ catchendpad unwind to caller
__try.cont: ; preds = %__except, %invoke.cont2
ret void
; CHECK: .Ltmp0
; CHECK: callq crash
; CHECK: .Ltmp1
-; CHECK: .Ltmp3
-; CHECK: callq "?fin$0@0@use_both@@"
; CHECK: .Ltmp4
+; CHECK: callq "?fin$0@0@use_both@@"
+; CHECK: .Ltmp5
; CHECK: retq
;
; CHECK: .seh_handlerdata
-; CHECK-NEXT: .text
-; CHECK-NEXT: .Ltmp{{[0-9]+}}
-; CHECK-NEXT: .seh_endproc
-; CHECK-NEXT: .section .xdata,"dr"
-; CHECK-NEXT: .long 3
-; CHECK-NEXT: .long .Ltmp0@IMGREL
+; CHECK-NEXT: .long (.Llsda_end0-.Llsda_begin0)/16
+; CHECK-NEXT: .Llsda_begin0:
+; CHECK-NEXT: .long .Ltmp0@IMGREL+1
; CHECK-NEXT: .long .Ltmp1@IMGREL+1
-; CHECK-NEXT: .long "?fin$0@0@use_both@@"@IMGREL
+; CHECK-NEXT: .long "?dtor$2@?0?use_both@4HA"@IMGREL
; CHECK-NEXT: .long 0
-; CHECK-NEXT: .long .Ltmp0@IMGREL
+; CHECK-NEXT: .long .Ltmp0@IMGREL+1
; CHECK-NEXT: .long .Ltmp1@IMGREL+1
; CHECK-NEXT: .long "?filt$0@0@use_both@@"@IMGREL
-; CHECK-NEXT: .long .Ltmp{{[0-9]+}}@IMGREL
-; CHECK-NEXT: .long .Ltmp3@IMGREL
+; CHECK-NEXT: .long .LBB0_{{[0-9]+}}@IMGREL
; CHECK-NEXT: .long .Ltmp4@IMGREL+1
+; CHECK-NEXT: .long .Ltmp5@IMGREL+1
; CHECK-NEXT: .long "?filt$0@0@use_both@@"@IMGREL
-; CHECK-NEXT: .long .Ltmp{{[0-9]+}}@IMGREL
+; CHECK-NEXT: .long .LBB0_{{[0-9]+}}@IMGREL
+; CHECK-NEXT: .Llsda_end0:
; Function Attrs: noinline nounwind
define internal i32 @"\01?filt$0@0@use_both@@"(i8* %exception_pointers, i8* %frame_pointer) #2 {
+++ /dev/null
-; RUN: llc -O0 -mtriple=x86_64-windows-msvc < %s | FileCheck %s
-
-declare void @g()
-define void @f() personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) {
- invoke void @g() to label %return unwind label %lpad
-
-return:
- ret void
-
-lpad:
- %ehptrs = landingpad {i8*, i32}
- filter [0 x i8*] zeroinitializer
- call void @__cxa_call_unexpected(i8* null)
- unreachable
-}
-declare i32 @__C_specific_handler(...)
-declare void @__cxa_call_unexpected(i8*)
-
-; We don't emit entries for filters.
-; CHECK: .seh_handlerdata
-; CHECK: .long 0
ret i32 0
lpad: ; preds = %entry
- %0 = landingpad { i8*, i32 }
- cleanup
- %1 = extractvalue { i8*, i32 } %0, 0
- %2 = extractvalue { i8*, i32 } %0, 1
+ %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 %terminate.lpad
+ to label %invoke.cont1 unwind label %endpad
invoke.cont1: ; preds = %lpad
- resume { i8*, i32 } %0
+ cleanupret %p unwind to caller
-terminate.lpad: ; preds = %lpad
- %3 = landingpad { i8*, i32 }
- catch i8* null
- call void @abort()
- unreachable
+endpad: ; preds = %lpad
+ cleanupendpad %p unwind to caller
}
; X64-LABEL: main:
; X64: retq
; X64: .seh_handlerdata
-; X64-NEXT: .text
-; X64-NEXT: .Ltmp{{[0-9]+}}:
-; X64-NEXT: .seh_endproc
-; X64-NEXT: .section .xdata,"dr"
-; X64-NEXT: .long 1
-; X64-NEXT: .long .Ltmp0@IMGREL
-; X64-NEXT: .long .Ltmp1@IMGREL
-; X64-NEXT: .long main.cleanup@IMGREL
-; X64-NEXT: .long 0
-
-; X64-LABEL: main.cleanup:
+; X64-NEXT: .long (.Llsda_end0-.Llsda_begin0)/16
+; X64-NEXT: .Llsda_begin0:
+; X64-NEXT: .long .Ltmp0@IMGREL+1
+; X64-NEXT: .long .Ltmp1@IMGREL+1
+; X64-NEXT: .long "?dtor$2@?0?main@4HA"@IMGREL
+; X64-NEXT: .long 0
+; X64-NEXT: .Llsda_end0:
+
+; X64-LABEL: "?dtor$2@?0?main@4HA":
; X64: callq puts
; X64: retq
; X86-LABEL: _main:
; X86: retl
+; X86-LABEL: "?dtor$2@?0?main@4HA":
+; X86: LBB0_2:
+; X86: calll _puts
+; X86: retl
+
; X86: .section .xdata,"dr"
; X86: L__ehtable$main:
; X86-NEXT: .long -1
; X86-NEXT: .long 0
-; X86-NEXT: .long _main.cleanup
-
-; X86-LABEL: _main.cleanup:
-; X86: calll _puts
-; X86: retl
+; X86-NEXT: .long LBB0_2
declare i32 @__C_specific_handler(...)
%r = alloca i32, align 4
store i32 42, i32* %r
invoke void @try_body(i32* %r, i32* %n, i32* %d)
- to label %__try.cont unwind label %lpad
-
-lpad:
- %vals = landingpad { i8*, i32 }
- catch i8* bitcast (i32 ()* @safe_div_filt0 to i8*)
- catch i8* bitcast (i32 ()* @safe_div_filt1 to i8*)
- %ehptr = extractvalue { i8*, i32 } %vals, 0
- %sel = extractvalue { i8*, i32 } %vals, 1
- %filt0_val = call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @safe_div_filt0 to i8*))
- %is_filt0 = icmp eq i32 %sel, %filt0_val
- br i1 %is_filt0, label %handler0, label %eh.dispatch1
-
-eh.dispatch1:
- %filt1_val = call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @safe_div_filt1 to i8*))
- %is_filt1 = icmp eq i32 %sel, %filt1_val
- br i1 %is_filt1, label %handler1, label %eh.resume
+ to label %__try.cont unwind label %lpad0
+
+lpad0:
+ %p0 = catchpad [i8* bitcast (i32 ()* @safe_div_filt0 to i8*)]
+ to label %handler0 unwind label %endpad0
handler0:
call void @puts(i8* getelementptr ([27 x i8], [27 x i8]* @str1, i32 0, i32 0))
store i32 -1, i32* %r, align 4
- br label %__try.cont
+ catchret %p0 to label %__try.cont
+
+endpad0:
+ catchendpad unwind label %lpad1
+
+lpad1:
+ %p1 = catchpad [i8* bitcast (i32 ()* @safe_div_filt1 to i8*)]
+ to label %handler1 unwind label %endpad1
handler1:
call void @puts(i8* getelementptr ([29 x i8], [29 x i8]* @str2, i32 0, i32 0))
store i32 -2, i32* %r, align 4
- br label %__try.cont
+ catchret %p1 to label %__try.cont
-eh.resume:
- resume { i8*, i32 } %vals
+endpad1:
+ catchendpad unwind to caller
__try.cont:
%safe_ret = load i32, i32* %r, align 4
; Landing pad code
-; CHECK: [[handler0:Ltmp[0-9]+]]: # Block address taken
-; CHECK: # %handler0
+; CHECK: [[lpad1:LBB0_[0-9]+]]: # %lpad1
; Restore SP
; CHECK: movl {{.*}}(%ebp), %esp
; CHECK: calll _puts
; CHECK: jmp [[cont_bb]]
-; CHECK: [[handler1:Ltmp[0-9]+]]: # Block address taken
-; CHECK: # %handler1
+; CHECK: [[lpad0:LBB0_[0-9]+]]: # %lpad0
; Restore SP
; CHECK: movl {{.*}}(%ebp), %esp
; CHECK: calll _puts
; CHECK: L__ehtable$safe_div:
; CHECK-NEXT: .long -1
; CHECK-NEXT: .long _safe_div_filt1
-; CHECK-NEXT: .long [[handler1]]
+; CHECK-NEXT: .long [[lpad1]]
; CHECK-NEXT: .long 0
; CHECK-NEXT: .long _safe_div_filt0
-; CHECK-NEXT: .long [[handler0]]
+; CHECK-NEXT: .long [[lpad0]]
define void @try_body(i32* %r, i32* %n, i32* %d) {
entry:
entry:
%r = alloca i32, align 4
invoke void @try_body(i32* %r, i32* %n, i32* %d)
- to label %__try.cont unwind label %lpad
-
-lpad:
- %vals = landingpad { i8*, i32 }
- catch i8* bitcast (i32 (i8*, i8*)* @safe_div_filt0 to i8*)
- catch i8* bitcast (i32 (i8*, i8*)* @safe_div_filt1 to i8*)
- %ehptr = extractvalue { i8*, i32 } %vals, 0
- %sel = extractvalue { i8*, i32 } %vals, 1
- %filt0_val = call i32 @llvm.eh.typeid.for(i8* bitcast (i32 (i8*, i8*)* @safe_div_filt0 to i8*))
- %is_filt0 = icmp eq i32 %sel, %filt0_val
- br i1 %is_filt0, label %handler0, label %eh.dispatch1
-
-eh.dispatch1:
- %filt1_val = call i32 @llvm.eh.typeid.for(i8* bitcast (i32 (i8*, i8*)* @safe_div_filt1 to i8*))
- %is_filt1 = icmp eq i32 %sel, %filt1_val
- br i1 %is_filt1, label %handler1, label %eh.resume
+ 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
handler0:
call void @puts(i8* getelementptr ([27 x i8], [27 x i8]* @str1, i32 0, i32 0))
store i32 -1, i32* %r, align 4
- br label %__try.cont
+ catchret %p0 to label %__try.cont
+
+endpad0:
+ catchendpad unwind label %lpad1
+
+lpad1:
+ %p1 = catchpad [i8* bitcast (i32 (i8*, i8*)* @safe_div_filt1 to i8*)]
+ to label %handler1 unwind label %endpad1
handler1:
call void @puts(i8* getelementptr ([29 x i8], [29 x i8]* @str2, i32 0, i32 0))
store i32 -2, i32* %r, align 4
- br label %__try.cont
+ catchret %p1 to label %__try.cont
-eh.resume:
- resume { i8*, i32 } %vals
+endpad1:
+ catchendpad unwind to caller
__try.cont:
%safe_ret = load i32, i32* %r, align 4
; CHECK: .seh_proc safe_div
; CHECK: .seh_handler __C_specific_handler, @unwind, @except
; CHECK: .Ltmp0:
-; CHECK: leaq [[rloc:.*\(%rsp\)]], %rcx
+; CHECK: leaq [[rloc:.*\(%rbp\)]], %rcx
; CHECK: callq try_body
; CHECK-NEXT: .Ltmp1
; CHECK: [[cont_bb:\.LBB0_[0-9]+]]:
; Landing pad code
-; CHECK: [[handler0:\.Ltmp[0-9]+]]: # Block address taken
-; CHECK: # %handler0
+; CHECK: [[lpad1:\.LBB0_[0-9]+]]: # %lpad1
; CHECK: callq puts
-; CHECK: movl $-1, [[rloc]]
+; CHECK: movl $-2, [[rloc]]
; CHECK: jmp [[cont_bb]]
-; CHECK: [[handler1:\.Ltmp[0-9]+]]: # Block address taken
-; CHECK: # %handler1
+; CHECK: [[lpad0:\.LBB0_[0-9]+]]: # %lpad0
; CHECK: callq puts
-; CHECK: movl $-2, [[rloc]]
+; CHECK: movl $-1, [[rloc]]
; CHECK: jmp [[cont_bb]]
; CHECK: .seh_handlerdata
-; CHECK-NEXT: .text
-; CHECK-NEXT: .Ltmp{{[0-9]+}}
-; CHECK-NEXT: .seh_endproc
-; CHECK-NEXT: .section .xdata,"dr"
-; CHECK-NEXT: .long 2
-; CHECK-NEXT: .long .Ltmp0@IMGREL
+; CHECK-NEXT: .long (.Llsda_end0-.Llsda_begin0)/16
+; CHECK-NEXT: .Llsda_begin0:
+; CHECK-NEXT: .long .Ltmp0@IMGREL+1
; CHECK-NEXT: .long .Ltmp1@IMGREL+1
; CHECK-NEXT: .long safe_div_filt0@IMGREL
-; CHECK-NEXT: .long [[handler0]]@IMGREL
-; CHECK-NEXT: .long .Ltmp0@IMGREL
+; CHECK-NEXT: .long [[lpad0]]@IMGREL
+; CHECK-NEXT: .long .Ltmp0@IMGREL+1
; CHECK-NEXT: .long .Ltmp1@IMGREL+1
; CHECK-NEXT: .long safe_div_filt1@IMGREL
-; CHECK-NEXT: .long [[handler1]]@IMGREL
+; CHECK-NEXT: .long [[lpad1]]@IMGREL
+; CHECK-NEXT: .Llsda_end0:
; CHECK: .text
; CHECK: .seh_endproc
-
define void @try_body(i32* %r, i32* %n, i32* %d) {
entry:
%0 = load i32, i32* %n, align 4
+++ /dev/null
-; RUN: llc -mtriple=i686-windows-msvc < %s | FileCheck %s
-
-; 32-bit catch-all has to use a filter function because that's how it saves the
-; exception code.
-
-@str = linkonce_odr unnamed_addr constant [27 x i8] c"GetExceptionCode(): 0x%lx\0A\00", align 1
-
-declare i32 @_except_handler3(...)
-declare void @crash()
-declare i32 @printf(i8* nocapture readonly, ...) nounwind
-declare i32 @llvm.eh.typeid.for(i8*)
-declare i8* @llvm.frameaddress(i32)
-declare i8* @llvm.localrecover(i8*, i8*, i32)
-declare void @llvm.localescape(...)
-declare i8* @llvm.x86.seh.recoverfp(i8*, i8*)
-
-define i32 @main() personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) {
-entry:
- ; The EH code allocation is overaligned, triggering realignment.
- %__exceptioncode = alloca i32, align 8
- call void (...) @llvm.localescape(i32* %__exceptioncode)
- invoke void @crash() #5
- to label %__try.cont unwind label %lpad
-
-lpad: ; preds = %entry
- %0 = landingpad { i8*, i32 }
- catch i8* bitcast (i32 ()* @"filt$main" to i8*)
- %1 = extractvalue { i8*, i32 } %0, 1
- %2 = call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @"filt$main" to i8*)) #4
- %matches = icmp eq i32 %1, %2
- br i1 %matches, label %__except, label %eh.resume
-
-__except: ; preds = %lpad
- %3 = 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 %3) #4
- br label %__try.cont
-
-__try.cont: ; preds = %entry, %__except
- ret i32 0
-
-eh.resume: ; preds = %lpad
- resume { i8*, i32 } %0
-}
-
-define internal i32 @"filt$main"() {
-entry:
- %ebp = tail call i8* @llvm.frameaddress(i32 1)
- %parentfp = tail call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* @main to i8*), i8* %ebp)
- %code.i8 = tail call i8* @llvm.localrecover(i8* bitcast (i32 ()* @main to i8*), i8* %parentfp, i32 0)
- %__exceptioncode = bitcast i8* %code.i8 to i32*
- %info.addr = getelementptr inbounds i8, i8* %ebp, i32 -20
- %0 = bitcast i8* %info.addr to i32***
- %1 = load i32**, i32*** %0, align 4
- %2 = load i32*, i32** %1, align 4
- %3 = load i32, i32* %2, align 4
- store i32 %3, i32* %__exceptioncode, align 4
- ret i32 1
-}
-
-; Check that we can get the exception code from eax to the printf.
-
-; CHECK-LABEL: _main:
-; CHECK: Lmain$frame_escape_0 = [[code_offs:[-0-9]+]]
-; CHECK: Lmain$frame_escape_1 = [[reg_offs:[-0-9]+]]
-; CHECK: movl %esp, [[reg_offs]](%esi)
-; CHECK: movl $L__ehtable$main,
-; EH state 0
-; CHECK: movl $0, 40(%esi)
-; CHECK: calll _crash
-; CHECK: retl
-; CHECK: # Block address taken
-; stackrestore
-; CHECK: movl -24(%ebp), %esp
-; CHECK: movl $Lmain$parent_frame_offset, %eax
-; CHECK: negl %eax
-; CHECK: leal -24(%ebp,%eax), %esi
-; CHECK: movl 12(%esi), %ebp # 4-byte Reload
-; EH state -1
-; CHECK: movl [[code_offs]](%esi), %[[code:[a-z]+]]
-; CHECK: movl $-1, 40(%esi)
-; CHECK-DAG: movl %[[code]], 4(%esp)
-; CHECK-DAG: movl $_str, (%esp)
-; CHECK: calll _printf
-
-; CHECK: .section .xdata,"dr"
-; CHECK: Lmain$parent_frame_offset = Lmain$frame_escape_1
-; CHECK: L__ehtable$main
-; CHECK-NEXT: .long -1
-; CHECK-NEXT: .long _filt$main
-; CHECK-NEXT: .long Ltmp{{[0-9]+}}
-
-; CHECK-LABEL: _filt$main:
-; CHECK: pushl %ebp
-; CHECK: movl %esp, %ebp
-; CHECK: movl (%ebp), %[[oldebp:[a-z]+]]
-; CHECK: movl -20(%[[oldebp]]), %[[ehinfo:[a-z]+]]
-; CHECK: movl (%[[ehinfo]]), %[[ehrec:[a-z]+]]
-; CHECK: movl (%[[ehrec]]), %[[ehcode:[a-z]+]]
-; CHECK: movl %[[ehcode]], {{.*}}(%{{.*}})
to label %__try.cont unwind label %lpad
lpad: ; preds = %entry
- %0 = landingpad { i8*, i32 }
- catch i8* bitcast (i32 ()* @"filt$main" to i8*)
- %1 = extractvalue { i8*, i32 } %0, 1
- %2 = call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @"filt$main" to i8*)) #4
- %matches = icmp eq i32 %1, %2
- br i1 %matches, label %__except, label %eh.resume
+ %p = catchpad [i8* bitcast (i32 ()* @"filt$main" to i8*)]
+ to label %__except unwind label %endpad
__except: ; preds = %lpad
- %3 = 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 %3) #4
- br label %__try.cont
+ %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
__try.cont: ; preds = %entry, %__except
ret i32 0
-
-eh.resume: ; preds = %lpad
- resume { i8*, i32 } %0
}
define internal i32 @"filt$main"() {
; CHECK: movl $0, 40(%esi)
; CHECK: calll _crash
; CHECK: retl
-; CHECK: # Block address taken
+; CHECK: LBB0_[[lpbb:[0-9]+]]: # %lpad
; Restore ESP
; CHECK: movl -24(%ebp), %esp
; Restore ESI
-; CHECK: movl $Lmain$parent_frame_offset, %eax
-; CHECK: negl %eax
-; CHECK: leal -24(%ebp,%eax), %esi
+; CHECK: leal -44(%ebp), %esi
; Restore EBP
-; CHECK: movl 12(%esi), %ebp # 4-byte Reload
-; EH state -1
+; CHECK: movl 12(%esi), %ebp
; CHECK: movl [[code_offs]](%esi), %[[code:[a-z]+]]
-; CHECK: movl $-1, 40(%esi)
; CHECK-DAG: movl %[[code]], 4(%esp)
; CHECK-DAG: movl $_str, (%esp)
; CHECK: calll _printf
; CHECK: L__ehtable$main
; CHECK-NEXT: .long -1
; CHECK-NEXT: .long _filt$main
-; CHECK-NEXT: .long Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long LBB0_[[lpbb]]
; CHECK-LABEL: _filt$main:
; CHECK: pushl %ebp
--- /dev/null
+; RUN: llc -mtriple x86_64-pc-windows-msvc < %s | FileCheck %s
+
+declare void @maybe_throw()
+
+@_ZTIi = external constant i8*
+@g = external global i32
+
+declare i32 @__C_specific_handler(...)
+declare i32 @__gxx_personality_seh0(...)
+declare i32 @llvm.eh.typeid.for(i8*) readnone nounwind
+
+define i32 @use_seh() personality i32 (...)* @__C_specific_handler {
+entry:
+ invoke void @maybe_throw()
+ to label %cont unwind label %lpad
+
+cont:
+ ret i32 0
+
+lpad:
+ %p = catchpad [i8* bitcast (i32 (i8*, i8*)* @filt_g to i8*)]
+ to label %catch unwind label %endpad
+catch:
+ catchret %p to label %ret1
+endpad:
+ catchendpad unwind to caller
+
+ret1:
+ ret i32 1
+}
+
+define internal i32 @filt_g(i8*, i8*) {
+ %g = load i32, i32* @g
+ ret i32 %g
+}
+
+; CHECK-LABEL: use_seh:
+; CHECK: callq maybe_throw
+; CHECK: xorl %eax, %eax
+; CHECK: .LBB0_[[epilogue:[0-9]+]]
+; CHECK: retq
+; CHECK: # %lpad
+; CHECK: movl $1, %eax
+; CHECK: jmp .LBB0_[[epilogue]]
+
+; A MinGW64-ish EH style. It could happen if a binary uses both MSVC CRT and
+; mingw CRT and is linked with LTO.
+define i32 @use_gcc() personality i32 (...)* @__gxx_personality_seh0 {
+entry:
+ invoke void @maybe_throw()
+ to label %cont unwind label %lpad
+
+cont:
+ ret i32 0
+
+lpad:
+ %ehvals = landingpad { i8*, i32 }
+ cleanup
+ catch i8* bitcast (i8** @_ZTIi to i8*)
+ %ehsel = extractvalue { i8*, i32 } %ehvals, 1
+ %filt_g_sel = call i32 @llvm.eh.typeid.for(i8* bitcast (i32 (i8*, i8*)* @filt_g to i8*))
+ %matches = icmp eq i32 %ehsel, %filt_g_sel
+ br i1 %matches, label %ret1, label %eh.resume
+
+ret1:
+ ret i32 1
+
+eh.resume:
+ resume { i8*, i32 } %ehvals
+}
+
+; CHECK-LABEL: use_gcc:
+; CHECK: callq maybe_throw
+; CHECK: xorl %eax, %eax
+;
+; CHECK: # %lpad
+; CHECK: cmpl $2, %edx
+; CHECK: jne
+;
+; CHECK: # %ret1
+; CHECK: movl $1, %eax
+;
+; CHECK: callq _Unwind_Resume
+++ /dev/null
-; RUN: opt -S -winehprepare -dwarfehprepare -mtriple x86_64-pc-windows-msvc < %s | FileCheck %s
-
-; FIXME: Add and test outlining here.
-
-declare void @maybe_throw()
-
-@_ZTIi = external constant i8*
-@g = external global i32
-
-declare i32 @__C_specific_handler(...)
-declare i32 @__gxx_personality_seh0(...)
-declare i32 @llvm.eh.typeid.for(i8*) readnone nounwind
-
-define i32 @use_seh() personality i32 (...)* @__C_specific_handler {
-entry:
- invoke void @maybe_throw()
- to label %cont unwind label %lpad
-
-cont:
- ret i32 0
-
-lpad:
- %ehvals = landingpad { i8*, i32 }
- cleanup
- catch i8* bitcast (i32 (i8*, i8*)* @filt_g to i8*)
- %ehsel = extractvalue { i8*, i32 } %ehvals, 1
- %filt_g_sel = call i32 @llvm.eh.typeid.for(i8* bitcast (i32 (i8*, i8*)* @filt_g to i8*))
- %matches = icmp eq i32 %ehsel, %filt_g_sel
- br i1 %matches, label %ret1, label %eh.resume
-
-ret1:
- ret i32 1
-
-eh.resume:
- resume { i8*, i32 } %ehvals
-}
-
-define internal i32 @filt_g(i8*, i8*) {
- %g = load i32, i32* @g
- ret i32 %g
-}
-
-; CHECK-LABEL: define i32 @use_seh()
-; CHECK: invoke void @maybe_throw()
-; CHECK-NEXT: to label %cont unwind label %lpad
-; CHECK: landingpad
-; CHECK-NEXT: cleanup
-; CHECK-NEXT: catch
-; CHECK-NEXT: call i8* (...) @llvm.eh.actions({{.*}})
-
-
-; A MinGW64-ish EH style. It could happen if a binary uses both MSVC CRT and
-; mingw CRT and is linked with LTO.
-define i32 @use_gcc() personality i32 (...)* @__gxx_personality_seh0 {
-entry:
- invoke void @maybe_throw()
- to label %cont unwind label %lpad
-
-cont:
- ret i32 0
-
-lpad:
- %ehvals = landingpad { i8*, i32 }
- cleanup
- catch i8* bitcast (i8** @_ZTIi to i8*)
- %ehsel = extractvalue { i8*, i32 } %ehvals, 1
- %filt_g_sel = call i32 @llvm.eh.typeid.for(i8* bitcast (i32 (i8*, i8*)* @filt_g to i8*))
- %matches = icmp eq i32 %ehsel, %filt_g_sel
- br i1 %matches, label %ret1, label %eh.resume
-
-ret1:
- ret i32 1
-
-eh.resume:
- resume { i8*, i32 } %ehvals
-}
-
-; CHECK-LABEL: define i32 @use_gcc()
-; CHECK: invoke void @maybe_throw()
-; CHECK-NEXT: to label %cont unwind label %lpad
-; CHECK: eh.resume:
-; CHECK: call void @_Unwind_Resume(i8* %exn.obj)