https://github.com/GkvJwa updated https://github.com/llvm/llvm-project/pull/180905
>From decfff25fa4634bacdc90c306e7bea50fc697aef Mon Sep 17 00:00:00 2001 From: GkvJwa <[email protected]> Date: Mon, 2 Mar 2026 19:49:41 +0800 Subject: [PATCH] [WinEH] Fix crash when aligning parameters larger than ABI --- clang/lib/CodeGen/CGException.cpp | 30 ++++++++++---- .../windows-seh-arg-capture-crash.cpp.cpp | 40 +++++++++++++++++++ 2 files changed, 63 insertions(+), 7 deletions(-) create mode 100644 clang/test/CodeGen/windows-seh-arg-capture-crash.cpp.cpp diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 2f1df6e9a8a5c..b2eb00a7735cf 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -1834,10 +1834,23 @@ struct CaptureFinder : ConstStmtVisitor<CaptureFinder> { Address CodeGenFunction::recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF, Address ParentVar, llvm::Value *ParentFP) { - llvm::CallInst *RecoverCall = nullptr; + llvm::Value *RecoverCall = nullptr; CGBuilderTy Builder(*this, AllocaInsertPt); - if (auto *ParentAlloca = - dyn_cast_or_null<llvm::AllocaInst>(ParentVar.getBasePointer())) { + 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 +1862,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 +1873,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.cpp b/clang/test/CodeGen/windows-seh-arg-capture-crash.cpp.cpp new file mode 100644 index 0000000000000..612314229083d --- /dev/null +++ b/clang/test/CodeGen/windows-seh-arg-capture-crash.cpp.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) \ No newline at end of file _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
