[llvm] 21af99a - [WinEH] Emit state stores for SEH scopes (#116546)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 27 15:43:24 PST 2024
Author: Maurice Heumann
Date: 2024-11-27T15:43:20-08:00
New Revision: 21af99ab84e434819b20452367325b187492d372
URL: https://github.com/llvm/llvm-project/commit/21af99ab84e434819b20452367325b187492d372
DIFF: https://github.com/llvm/llvm-project/commit/21af99ab84e434819b20452367325b187492d372.diff
LOG: [WinEH] Emit state stores for SEH scopes (#116546)
At the moment Windows 32 bit SEH state stores are only emitted for
throwing calls.
Windows 32 bit SEH state stores should also be emitted before SEH scope
begin and before SEH scope end.
An invalid inline memory access would otherwise not trigger unwinding,
in combination with /EHa.
This fixes #90946
Added:
llvm/test/CodeGen/WinEH/wineh-scope-statenumbering.ll
Modified:
llvm/lib/Target/X86/X86WinEHState.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Target/X86/X86WinEHState.cpp b/llvm/lib/Target/X86/X86WinEHState.cpp
index 85485229aaf243..b3e4c70eb57f30 100644
--- a/llvm/lib/Target/X86/X86WinEHState.cpp
+++ b/llvm/lib/Target/X86/X86WinEHState.cpp
@@ -517,11 +517,28 @@ int WinEHStatePass::getBaseStateForBB(
return BaseState;
}
+static bool isIntrinsic(const CallBase &Call, Intrinsic::ID ID) {
+ const Function *CF = Call.getCalledFunction();
+ return CF && CF->isIntrinsic() && CF->getIntrinsicID() == ID;
+}
+
+static bool isSehScopeEnd(const CallBase &Call) {
+ return isIntrinsic(Call, Intrinsic::seh_scope_end);
+}
+
+static bool isSehScopeBegin(const CallBase &Call) {
+ return isIntrinsic(Call, Intrinsic::seh_scope_begin);
+}
+
// Calculate the state a call-site is in.
int WinEHStatePass::getStateForCall(
DenseMap<BasicBlock *, ColorVector> &BlockColors, WinEHFuncInfo &FuncInfo,
CallBase &Call) {
if (auto *II = dyn_cast<InvokeInst>(&Call)) {
+ if (isSehScopeEnd(*II)) {
+ return getBaseStateForBB(BlockColors, FuncInfo, II->getNormalDest());
+ }
+
// Look up the state number of the EH pad this unwinds to.
assert(FuncInfo.InvokeStateMap.count(II) && "invoke has no state!");
return FuncInfo.InvokeStateMap[II];
@@ -610,6 +627,10 @@ static int getSuccState(DenseMap<BasicBlock *, int> &InitialStates, Function &F,
bool WinEHStatePass::isStateStoreNeeded(EHPersonality Personality,
CallBase &Call) {
+ if (isSehScopeBegin(Call) || isSehScopeEnd(Call)) {
+ return true;
+ }
+
// If the function touches memory, it needs a state store.
if (isAsynchronousEHPersonality(Personality))
return !Call.doesNotAccessMemory();
diff --git a/llvm/test/CodeGen/WinEH/wineh-scope-statenumbering.ll b/llvm/test/CodeGen/WinEH/wineh-scope-statenumbering.ll
new file mode 100644
index 00000000000000..9cebb9a8330ab1
--- /dev/null
+++ b/llvm/test/CodeGen/WinEH/wineh-scope-statenumbering.ll
@@ -0,0 +1,45 @@
+; RUN: opt -mtriple=i386-pc-windows-msvc -S -x86-winehstate < %s | FileCheck %s
+
+target datalayout = "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
+target triple = "i386-pc-windows-msvc19.42.34433"
+
+%struct.Destructor = type { ptr }
+
+define dso_local void @"?HandleDestructorCallWithException@@YAXPA_N at Z"(ptr noundef %destructorCalled) personality ptr @__CxxFrameHandler3 {
+entry:
+ %destructorCalled.addr = alloca ptr, align 4
+ %x = alloca %struct.Destructor, align 4
+ store ptr %destructorCalled, ptr %destructorCalled.addr, align 4
+ %0 = load ptr, ptr %destructorCalled.addr, align 4
+ %call = call x86_thiscallcc noundef ptr @"??0Destructor@@QAE at PA_N@Z"(ptr noundef nonnull align 4 dereferenceable(4) %x, ptr noundef %0)
+ ; CHECK: store i32 0, ptr %9, align 4
+ ; CHECK-NEXT: invoke void @llvm.seh.scope.begin()
+ invoke void @llvm.seh.scope.begin()
+ to label %invoke.cont unwind label %ehcleanup
+
+invoke.cont:
+ store i32 1, ptr inttoptr (i32 1 to ptr), align 4
+ ; CHECK: store i32 -1, ptr %10, align 4
+ ; CHECK-NEXT: invoke void @llvm.seh.scope.end()
+ invoke void @llvm.seh.scope.end()
+ to label %invoke.cont1 unwind label %ehcleanup
+
+invoke.cont1:
+ call x86_thiscallcc void @"??1Destructor@@QAE at XZ"(ptr noundef nonnull align 4 dereferenceable(4) %x) #1
+ ret void
+
+ehcleanup:
+ %1 = cleanuppad within none []
+ call x86_thiscallcc void @"??1Destructor@@QAE at XZ"(ptr noundef nonnull align 4 dereferenceable(4) %x) #1 [ "funclet"(token %1) ]
+ cleanupret from %1 unwind to caller
+}
+
+declare dso_local i32 @__CxxFrameHandler3(...)
+declare dso_local void @llvm.seh.scope.begin() #0
+declare dso_local void @llvm.seh.scope.end() #0
+
+declare dso_local x86_thiscallcc noundef ptr @"??0Destructor@@QAE at PA_N@Z"(ptr noundef nonnull returned align 4 dereferenceable(4) %this, ptr noundef %destructorCalled)
+declare dso_local x86_thiscallcc void @"??1Destructor@@QAE at XZ"(ptr noundef nonnull align 4 dereferenceable(4) %this) #1
+
+attributes #0 = { nounwind memory(none) }
+attributes #1 = { nounwind }
More information about the llvm-commits
mailing list