From 2bd0221fa494b081cbff49fbb0ca98d7c2e50116 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Thu, 11 Jun 2015 23:37:18 +0000 Subject: [PATCH] [WinEH] Put finally pointers in the handler scope table field We were putting them in the filter field, which is correct for 64-bit but wrong for 32-bit. Also switch the order of scope table entry emission so outermost entries are emitted first, and fix an obvious state assignment bug. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239574 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/AsmPrinter/WinException.cpp | 27 ++++++++-------- lib/Target/X86/X86WinEHState.cpp | 2 +- test/CodeGen/X86/seh-finally.ll | 41 +++++++++++++++++-------- test/CodeGen/X86/seh-safe-div-win32.ll | 6 ++-- test/CodeGen/X86/win32-eh.ll | 33 +++++++++++++++----- 5 files changed, 71 insertions(+), 38 deletions(-) diff --git a/lib/CodeGen/AsmPrinter/WinException.cpp b/lib/CodeGen/AsmPrinter/WinException.cpp index 75287fd9855..1ba6060a89f 100644 --- a/lib/CodeGen/AsmPrinter/WinException.cpp +++ b/lib/CodeGen/AsmPrinter/WinException.cpp @@ -613,8 +613,8 @@ void WinException::emitExceptHandlerTable(const MachineFunction *MF) { // For each action in each lpad, emit one of these: // struct ScopeTableEntry { // int32_t EnclosingLevel; - // int32_t (__cdecl *FilterOrFinally)(); - // void *HandlerLabel; + // int32_t (__cdecl *Filter)(); + // void *HandlerOrFinally; // }; // // The "outermost" action will use BaseState as its enclosing level. Each @@ -625,21 +625,20 @@ void WinException::emitExceptHandlerTable(const MachineFunction *MF) { assert(CurState + int(LPInfo->SEHHandlers.size()) - 1 == LPInfo->WinEHState && "gaps in the SEH scope table"); - for (const SEHHandler &Handler : LPInfo->SEHHandlers) { - // Emit the filter or finally function pointer, if present. Otherwise, - // emit '0' to indicate a catch-all. - const Function *F = Handler.FilterOrFinally; - const MCExpr *FilterOrFinally = - create32bitRef(F ? Asm->getSymbol(F) : nullptr); - - // Compute the recovery address, which is a block address or null. + for (auto I = LPInfo->SEHHandlers.rbegin(), E = LPInfo->SEHHandlers.rend(); + I != E; ++I) { + const SEHHandler &Handler = *I; const BlockAddress *BA = Handler.RecoverBA; - const MCExpr *RecoverBBOrNull = - create32bitRef(BA ? Asm->GetBlockAddressSymbol(BA) : nullptr); + const Function *F = Handler.FilterOrFinally; + assert(F && "cannot catch all in 32-bit SEH without filter function"); + const MCExpr *FilterOrNull = + create32bitRef(BA ? Asm->getSymbol(F) : nullptr); + const MCExpr *ExceptOrFinally = create32bitRef( + BA ? Asm->GetBlockAddressSymbol(BA) : Asm->getSymbol(F)); OS.EmitIntValue(EnclosingLevel, 4); - OS.EmitValue(FilterOrFinally, 4); - OS.EmitValue(RecoverBBOrNull, 4); + OS.EmitValue(FilterOrNull, 4); + OS.EmitValue(ExceptOrFinally, 4); // The next state unwinds to this state. EnclosingLevel = CurState; diff --git a/lib/Target/X86/X86WinEHState.cpp b/lib/Target/X86/X86WinEHState.cpp index e037f08790c..356d0a77132 100644 --- a/lib/Target/X86/X86WinEHState.cpp +++ b/lib/Target/X86/X86WinEHState.cpp @@ -508,7 +508,7 @@ void WinEHStatePass::addSEHStateStores(Function &F, MachineModuleInfo &MMI) { // Look up the state number of the landingpad this unwinds to. LandingPadInst *LPI = II->getUnwindDest()->getLandingPadInst(); auto InsertionPair = - FuncInfo.LandingPadStateMap.insert(std::make_pair(LPI, 0)); + FuncInfo.LandingPadStateMap.insert(std::make_pair(LPI, CurState)); auto Iter = InsertionPair.first; int &State = Iter->second; bool Inserted = InsertionPair.second; diff --git a/test/CodeGen/X86/seh-finally.ll b/test/CodeGen/X86/seh-finally.ll index 91baed570f2..9deffe13e01 100644 --- a/test/CodeGen/X86/seh-finally.ll +++ b/test/CodeGen/X86/seh-finally.ll @@ -1,4 +1,6 @@ -; RUN: llc -mtriple=x86_64-windows-msvc < %s | FileCheck %s +; RUN: llc -mtriple=x86_64-windows-msvc < %s | FileCheck %s --check-prefix=X64 +; RUN: sed -e 's/__C_specific_handler/_except_handler3/' %s | \ +; RUN: llc -mtriple=i686-windows-msvc | FileCheck %s --check-prefix=X86 @str_recovered = internal unnamed_addr constant [10 x i8] c"recovered\00", align 1 @@ -32,17 +34,32 @@ terminate.lpad: ; preds = %lpad unreachable } -; CHECK-LABEL: main: -; CHECK: .seh_handlerdata -; CHECK-NEXT: .long 1 -; CHECK-NEXT: .long .Ltmp0@IMGREL -; CHECK-NEXT: .long .Ltmp1@IMGREL -; CHECK-NEXT: .long main.cleanup@IMGREL -; CHECK-NEXT: .long 0 - -; CHECK-LABEL: main.cleanup: -; CHECK: callq puts -; CHECK: retq +; X64-LABEL: main: +; X64: retq + +; X64: .seh_handlerdata +; 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: callq puts +; X64: retq + +; X86-LABEL: _main: +; 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 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 ab58a4b99ca..b5f9a3688ba 100644 --- a/test/CodeGen/X86/seh-safe-div-win32.ll +++ b/test/CodeGen/X86/seh-safe-div-win32.ll @@ -92,11 +92,11 @@ __try.cont: ; CHECK: .section .xdata,"dr" ; CHECK: L__ehtable$safe_div: ; CHECK-NEXT: .long -1 -; CHECK-NEXT: .long _safe_div_filt0 -; CHECK-NEXT: .long [[handler0]] -; CHECK-NEXT: .long 0 ; CHECK-NEXT: .long _safe_div_filt1 ; CHECK-NEXT: .long [[handler1]] +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long _safe_div_filt0 +; CHECK-NEXT: .long [[handler0]] define void @try_body(i32* %r, i32* %n, i32* %d) { entry: diff --git a/test/CodeGen/X86/win32-eh.ll b/test/CodeGen/X86/win32-eh.ll index 6d816d7770c..584b409c705 100644 --- a/test/CodeGen/X86/win32-eh.ll +++ b/test/CodeGen/X86/win32-eh.ll @@ -6,16 +6,27 @@ declare i32 @_except_handler4(...) declare i32 @__CxxFrameHandler3(...) declare void @llvm.eh.begincatch(i8*, i8*) declare void @llvm.eh.endcatch() +declare i32 @llvm.eh.typeid.for(i8*) + +define internal i32 @catchall_filt() { + ret i32 1 +} define void @use_except_handler3() { +entry: invoke void @may_throw_or_crash() to label %cont unwind label %catchall cont: ret void catchall: - landingpad { i8*, i32 } personality i32 (...)* @_except_handler3 - catch i8* null - br label %cont + %0 = landingpad { i8*, i32 } personality i32 (...)* @_except_handler3 + catch i8* bitcast (i32 ()* @catchall_filt to i8*) + %1 = extractvalue { i8*, i32 } %0, 1 + %2 = call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @catchall_filt to i8*)) #4 + %matches = icmp eq i32 %1, %2 + br i1 %matches, label %cont, label %eh.resume +eh.resume: + resume { i8*, i32 } %0 } ; CHECK-LABEL: _use_except_handler3: @@ -37,18 +48,24 @@ catchall: ; CHECK: .section .xdata,"dr" ; CHECK-LABEL: L__ehtable$use_except_handler3: ; CHECK-NEXT: .long -1 -; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long _catchall_filt ; CHECK-NEXT: .long Ltmp{{[0-9]+}} define void @use_except_handler4() { +entry: invoke void @may_throw_or_crash() to label %cont unwind label %catchall cont: ret void catchall: - landingpad { i8*, i32 } personality i32 (...)* @_except_handler4 - catch i8* null - br label %cont + %0 = landingpad { i8*, i32 } personality i32 (...)* @_except_handler4 + catch i8* bitcast (i32 ()* @catchall_filt to i8*) + %1 = extractvalue { i8*, i32 } %0, 1 + %2 = call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @catchall_filt to i8*)) #4 + %matches = icmp eq i32 %1, %2 + br i1 %matches, label %cont, label %eh.resume +eh.resume: + resume { i8*, i32 } %0 } ; CHECK-LABEL: _use_except_handler4: @@ -77,7 +94,7 @@ catchall: ; CHECK-NEXT: .long 9999 ; CHECK-NEXT: .long 0 ; CHECK-NEXT: .long -2 -; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long _catchall_filt ; CHECK-NEXT: .long Ltmp{{[0-9]+}} define void @use_CxxFrameHandler3() { -- 2.34.1