From: Reid Kleckner Date: Fri, 9 Oct 2015 23:05:54 +0000 (+0000) Subject: [SEH] Update SEH codegen tests to use the new IR X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=f33149e67f446658b57ac95a314b10b058a8347f [SEH] Update SEH codegen tests to use the new IR Also Fix a buglet where SEH tables had ranges that spanned funclets. The remaining tests using the old landingpad IR are preparation tests, and will be deleted along with the old preparation. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@249917 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/AsmPrinter/WinException.cpp b/lib/CodeGen/AsmPrinter/WinException.cpp index a5172fdd7d7..63be0daa708 100644 --- a/lib/CodeGen/AsmPrinter/WinException.cpp +++ b/lib/CodeGen/AsmPrinter/WinException.cpp @@ -458,6 +458,11 @@ void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) { // 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 diff --git a/test/CodeGen/X86/seh-catch-all-win32.ll b/test/CodeGen/X86/seh-catch-all-win32.ll index a4ea8ab78c7..0ad385375f7 100644 --- a/test/CodeGen/X86/seh-catch-all-win32.ll +++ b/test/CodeGen/X86/seh-catch-all-win32.ll @@ -22,23 +22,19 @@ entry: 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"() { @@ -71,19 +67,18 @@ entry: ; 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 @@ -94,7 +89,7 @@ entry: ; 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 diff --git a/test/CodeGen/X86/seh-catchpad.ll b/test/CodeGen/X86/seh-catchpad.ll index e981744db42..b59aa8d4c78 100644 --- a/test/CodeGen/X86/seh-catchpad.ll +++ b/test/CodeGen/X86/seh-catchpad.ll @@ -147,7 +147,7 @@ ehcleanup.end: ; preds = %ehcleanup ; 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: diff --git a/test/CodeGen/X86/seh-except-finally.ll b/test/CodeGen/X86/seh-except-finally.ll index 5a529cd8d7a..7acb802aa68 100644 --- a/test/CodeGen/X86/seh-except-finally.ll +++ b/test/CodeGen/X86/seh-except-finally.ll @@ -38,49 +38,38 @@ entry: %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 @@ -97,29 +86,27 @@ eh.resume: ; preds = %catch.dispatch ; 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 { diff --git a/test/CodeGen/X86/seh-filter.ll b/test/CodeGen/X86/seh-filter.ll deleted file mode 100644 index 37ed15841a9..00000000000 --- a/test/CodeGen/X86/seh-filter.ll +++ /dev/null @@ -1,21 +0,0 @@ -; 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 diff --git a/test/CodeGen/X86/seh-finally.ll b/test/CodeGen/X86/seh-finally.ll index 99f3b658a51..57c2c8c20f7 100644 --- a/test/CodeGen/X86/seh-finally.ll +++ b/test/CodeGen/X86/seh-finally.ll @@ -17,53 +17,46 @@ invoke.cont: ; preds = %entry 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(...) diff --git a/test/CodeGen/X86/seh-safe-div-win32.ll b/test/CodeGen/X86/seh-safe-div-win32.ll index b1bcde2c7ff..d17f2217ca2 100644 --- a/test/CodeGen/X86/seh-safe-div-win32.ll +++ b/test/CodeGen/X86/seh-safe-div-win32.ll @@ -28,35 +28,31 @@ entry: %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 @@ -75,15 +71,13 @@ __try.cont: ; 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 @@ -93,10 +87,10 @@ __try.cont: ; 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: diff --git a/test/CodeGen/X86/seh-safe-div.ll b/test/CodeGen/X86/seh-safe-div.ll index cd0ef717195..809d261b7d7 100644 --- a/test/CodeGen/X86/seh-safe-div.ll +++ b/test/CodeGen/X86/seh-safe-div.ll @@ -27,35 +27,31 @@ define i32 @safe_div(i32* %n, i32* %d) personality i8* bitcast (i32 (...)* @__C_ 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 @@ -68,7 +64,7 @@ __try.cont: ; 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]+]]: @@ -77,36 +73,31 @@ __try.cont: ; 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 diff --git a/test/CodeGen/X86/seh-stack-realign-win32.ll b/test/CodeGen/X86/seh-stack-realign-win32.ll deleted file mode 100644 index f3ab71803ca..00000000000 --- a/test/CodeGen/X86/seh-stack-realign-win32.ll +++ /dev/null @@ -1,99 +0,0 @@ -; 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]], {{.*}}(%{{.*}}) diff --git a/test/CodeGen/X86/seh-stack-realign.ll b/test/CodeGen/X86/seh-stack-realign.ll index f2fb28a081f..a06b2360fff 100644 --- a/test/CodeGen/X86/seh-stack-realign.ll +++ b/test/CodeGen/X86/seh-stack-realign.ll @@ -23,23 +23,19 @@ entry: 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"() { @@ -68,18 +64,14 @@ entry: ; 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 @@ -89,7 +81,7 @@ entry: ; 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 diff --git a/test/CodeGen/X86/win-mixed-ehpersonality.ll b/test/CodeGen/X86/win-mixed-ehpersonality.ll new file mode 100644 index 00000000000..9b6916554e5 --- /dev/null +++ b/test/CodeGen/X86/win-mixed-ehpersonality.ll @@ -0,0 +1,83 @@ +; 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 diff --git a/test/CodeGen/X86/win_eh_prepare.ll b/test/CodeGen/X86/win_eh_prepare.ll deleted file mode 100644 index 3e3f9af0582..00000000000 --- a/test/CodeGen/X86/win_eh_prepare.ll +++ /dev/null @@ -1,82 +0,0 @@ -; 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)