https://github.com/GkvJwa updated https://github.com/llvm/llvm-project/pull/180905
>From 9881686aeba91a427b1baa2084db3076ac3b16ed Mon Sep 17 00:00:00 2001 From: GkvJwa <[email protected]> Date: Wed, 11 Mar 2026 13:26:48 +0800 Subject: [PATCH 1/2] [WinEH] Fix crash when aligning parameters larger than ABI --- clang/lib/CodeGen/CGException.cpp | 34 ++++++++++++---- .../CodeGen/windows-seh-arg-capture-crash.cpp | 40 +++++++++++++++++++ 2 files changed, 67 insertions(+), 7 deletions(-) create mode 100644 clang/test/CodeGen/windows-seh-arg-capture-crash.cpp diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 98bc6ea34b0bc..1437bc2d32159 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -1834,10 +1834,27 @@ struct CaptureFinder : ConstStmtVisitor<CaptureFinder> { Address CodeGenFunction::recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF, Address ParentVar, llvm::Value *ParentFP) { - llvm::CallInst *RecoverCall = nullptr; + llvm::Value *RecoverCall = nullptr; CGBuilderTy Builder(CGM, AllocaInsertPt); - if (auto *ParentAlloca = - dyn_cast_or_null<llvm::AllocaInst>(ParentVar.getBasePointer())) { + // We are currently handling the following case: + // ParentAlloca: An alloca for a local variable/direct argument + // ParentArg: An argument pointer, pointing to an argument passed indirectly + // Other case: A call to localrecover, if this is a nested __try. + auto *ParentAlloca = + dyn_cast_or_null<llvm::AllocaInst>(ParentVar.getBasePointer()); + auto *ParentArg = + dyn_cast_or_null<llvm::Argument>(ParentVar.getBasePointer()); + if (!ParentAlloca) { + if (ParentArg) { + llvm::BasicBlock &EntryBB = ParentCGF.CurFn->getEntryBlock(); + llvm::IRBuilder<> ParentEntryBuilder(&EntryBB, EntryBB.begin()); + ParentAlloca = ParentEntryBuilder.CreateAlloca( + ParentArg->getType(), nullptr, ParentArg->getName() + ".spill"); + ParentEntryBuilder.CreateStore(ParentArg, ParentAlloca); + } + } + + if (ParentAlloca) { // Mark the variable escaped if nobody else referenced it and compute the // localescape index. auto InsertPair = ParentCGF.EscapedLocals.insert( @@ -1849,7 +1866,9 @@ Address CodeGenFunction::recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF, RecoverCall = Builder.CreateCall( FrameRecoverFn, {ParentCGF.CurFn, ParentFP, llvm::ConstantInt::get(Int32Ty, FrameEscapeIdx)}); - + if (ParentArg) + RecoverCall = Builder.CreateLoad( + Address(RecoverCall, ParentArg->getType(), getPointerAlign())); } else { // If the parent didn't have an alloca, we're doing some nested outlining. // Just clone the existing localrecover call, but tweak the FP argument to @@ -1858,9 +1877,10 @@ Address CodeGenFunction::recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF, ParentVar.emitRawPointer(*this)->stripPointerCasts()); assert(ParentRecover->getIntrinsicID() == llvm::Intrinsic::localrecover && "expected alloca or localrecover in parent LocalDeclMap"); - RecoverCall = cast<llvm::CallInst>(ParentRecover->clone()); - RecoverCall->setArgOperand(1, ParentFP); - RecoverCall->insertBefore(AllocaInsertPt->getIterator()); + RecoverCall = ParentRecover->clone(); + cast<llvm::CallInst>(RecoverCall)->setArgOperand(1, ParentFP); + cast<llvm::CallInst>(RecoverCall) + ->insertBefore(AllocaInsertPt->getIterator()); } // Bitcast the variable, rename it, and insert it in the local decl map. diff --git a/clang/test/CodeGen/windows-seh-arg-capture-crash.cpp b/clang/test/CodeGen/windows-seh-arg-capture-crash.cpp new file mode 100644 index 0000000000000..2e7490c2db0c9 --- /dev/null +++ b/clang/test/CodeGen/windows-seh-arg-capture-crash.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fms-extensions -fexceptions -emit-llvm -o - %s | FileCheck %s + +class span_a { + public: + char data_; + int size_; +}; + +long g(span_a input); + +void f(span_a input) { + __try { + } __except (g(input)) { + } +} + +// CHECK-LABEL: define dso_local void @"?f@@YAXVspan_a@@@Z"(i64 %input.coerce) +// CHECK: entry: +// CHECK: call void (...) @llvm.localescape(ptr %input) + +typedef __SIZE_TYPE__ size_t; + +class span_b { + public: + char data_; + size_t size_; +}; + +long g(span_b input); + +void f(span_b input) { + __try { + } __except (g(input)) { + } +} + +// CHECK-LABEL: define dso_local void @"?f@@YAXVspan_b@@@Z"(ptr noundef dead_on_return %input) +// CHECK: entry: +// CHECK: %input.spill = alloca ptr, align 8 +// CHECK: call void (...) @llvm.localescape(ptr %input.spill) >From d770a3b8717e0730576b687c4bb3d6a8bc9b6da4 Mon Sep 17 00:00:00 2001 From: GkvJwa <[email protected]> Date: Thu, 12 Mar 2026 00:00:30 +0800 Subject: [PATCH 2/2] Add localrecover and load --- .../CodeGen/windows-seh-arg-capture-crash.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/clang/test/CodeGen/windows-seh-arg-capture-crash.cpp b/clang/test/CodeGen/windows-seh-arg-capture-crash.cpp index 2e7490c2db0c9..089d966c86969 100644 --- a/clang/test/CodeGen/windows-seh-arg-capture-crash.cpp +++ b/clang/test/CodeGen/windows-seh-arg-capture-crash.cpp @@ -18,6 +18,14 @@ void f(span_a input) { // CHECK: entry: // CHECK: call void (...) @llvm.localescape(ptr %input) +// CHECK-LABEL: define internal noundef i32 @"?filt$0@0@f@@"(ptr noundef %exception_pointers +// CHECK: entry: +// CHECK: %frame_pointer.addr = alloca ptr, align 8 +// CHECK: %exception_pointers.addr = alloca ptr, align 8 +// CHECK: %0 = call ptr @llvm.eh.recoverfp(ptr @"?f@@YAXVspan_a@@@Z", ptr %frame_pointer) +// CHECK: %input = call ptr @llvm.localrecover(ptr @"?f@@YAXVspan_a@@@Z", ptr %0, i32 0) + + typedef __SIZE_TYPE__ size_t; class span_b { @@ -38,3 +46,11 @@ void f(span_b input) { // CHECK: entry: // CHECK: %input.spill = alloca ptr, align 8 // CHECK: call void (...) @llvm.localescape(ptr %input.spill) + +// CHECK-LABEL: define internal noundef i32 @"?filt$0@0@f@@.1"(ptr noundef %exception_pointers +// CHECK: entry: +// CHECK: %frame_pointer.addr = alloca ptr, align 8 +// CHECK: %exception_pointers.addr = alloca ptr, align 8 +// CHECK: %0 = call ptr @llvm.eh.recoverfp(ptr @"?f@@YAXVspan_b@@@Z", ptr %frame_pointer) +// CHECK: %1 = call ptr @llvm.localrecover(ptr @"?f@@YAXVspan_b@@@Z", ptr %0, i32 0) +// CHECK: %input = load ptr, ptr %1, align 8 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
