From 718acd5cded2acd10e55107bda084ff12e01611e Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 12 Dec 2024 14:09:58 +0100 Subject: [PATCH 1/2] [WinEH] Take musttail calls into account when unlinking eh records Exception handling records are unlinked on function return. However, if there is a musttail call before the return, that's the de-facto point of termination and the unlinking instructions must be inserted *before* that. Fixes #119255 --- llvm/lib/Target/X86/X86WinEHState.cpp | 10 ++++++ .../test/CodeGen/WinEH/wineh-musttail-call.ll | 32 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 llvm/test/CodeGen/WinEH/wineh-musttail-call.ll diff --git a/llvm/lib/Target/X86/X86WinEHState.cpp b/llvm/lib/Target/X86/X86WinEHState.cpp index b3e4c70eb57f3..fcbce15564ae3 100644 --- a/llvm/lib/Target/X86/X86WinEHState.cpp +++ b/llvm/lib/Target/X86/X86WinEHState.cpp @@ -363,6 +363,16 @@ void WinEHStatePass::emitExceptionRegistrationRecord(Function *F) { Instruction *T = BB.getTerminator(); if (!isa(T)) continue; + + // Back up to any preceding musttail call, the de-facto terminator. + Instruction *Prev = T->getPrevNonDebugInstruction(); + if (isa_and_present(Prev)) + Prev = T->getPrevNonDebugInstruction(); + if (CallInst *CI = dyn_cast_or_null(Prev)) { + if (CI->isMustTailCall()) + T = CI; + } + Builder.SetInsertPoint(T); unlinkExceptionRegistration(Builder); } diff --git a/llvm/test/CodeGen/WinEH/wineh-musttail-call.ll b/llvm/test/CodeGen/WinEH/wineh-musttail-call.ll new file mode 100644 index 0000000000000..7f508090a1bc7 --- /dev/null +++ b/llvm/test/CodeGen/WinEH/wineh-musttail-call.ll @@ -0,0 +1,32 @@ +; RUN: llc < %s | FileCheck %s + +target triple = "i386-pc-windows-msvc" + +; Check that codegen doesn't fail due to wineh inserting instructions between +; the musttail call and return instruction. + + +define void @test() personality ptr @__CxxFrameHandler3 { +; CHECK-LABEL: test: + +entry: + invoke void @foo() to label %try.cont unwind label %catch.dispatch + +catch.dispatch: + %0 = catchswitch within none [label %catch] unwind to caller + +catch: + %1 = catchpad within %0 [ptr null, i32 64, ptr null] + catchret from %1 to label %try.cont + +try.cont: +; CHECK: movl %{{[a-z0-9]+}}, %fs:0 +; CHECK: jmp _bar + + musttail call void @bar() + ret void +} + +declare i32 @__CxxFrameHandler3(...) +declare void @foo() +declare void @bar() From 24568b055b82c9ac997864b1355580baaf8fb262 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 12 Dec 2024 19:24:02 +0100 Subject: [PATCH 2/2] use BB.getTerminatingMustTailCall() --- llvm/lib/Target/X86/X86WinEHState.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Target/X86/X86WinEHState.cpp b/llvm/lib/Target/X86/X86WinEHState.cpp index fcbce15564ae3..35b7d7f508b02 100644 --- a/llvm/lib/Target/X86/X86WinEHState.cpp +++ b/llvm/lib/Target/X86/X86WinEHState.cpp @@ -364,14 +364,9 @@ void WinEHStatePass::emitExceptionRegistrationRecord(Function *F) { if (!isa(T)) continue; - // Back up to any preceding musttail call, the de-facto terminator. - Instruction *Prev = T->getPrevNonDebugInstruction(); - if (isa_and_present(Prev)) - Prev = T->getPrevNonDebugInstruction(); - if (CallInst *CI = dyn_cast_or_null(Prev)) { - if (CI->isMustTailCall()) - T = CI; - } + // If there is a musttail call, that's the de-facto terminator. + if (CallInst *CI = BB.getTerminatingMustTailCall()) + T = CI; Builder.SetInsertPoint(T); unlinkExceptionRegistration(Builder);