https://github.com/trungnt2910 created https://github.com/llvm/llvm-project/pull/184953
This commit implements Windows Structured Exception Handling (SEH) support for ARM `clang` in MSVC mode. This includes enabling the relevant language constructs in the Clang frontend and adding new ARM-specific code lowering logic. >From b44eb075b248044353a44f5379809699de0a2cac Mon Sep 17 00:00:00 2001 From: Trung Nguyen <[email protected]> Date: Fri, 6 Mar 2026 16:52:19 +1100 Subject: [PATCH] [ARM] Add support for Windows SEH This commit implements Windows Structured Exception Handling (SEH) support for ARM `clang` in MSVC mode. This includes enabling the relevant language constructs in the Clang frontend and adding new ARM-specific code lowering logic. --- clang/include/clang/Basic/TargetInfo.h | 3 ++- llvm/lib/CodeGen/AsmPrinter/WinException.cpp | 7 ++++--- llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp | 10 ++++++++++ llvm/lib/Target/ARM/ARMFrameLowering.cpp | 6 ++++++ llvm/lib/Target/ARM/ARMISelLowering.cpp | 17 +++++++++++++++++ llvm/lib/Target/ARM/ARMInstrInfo.td | 6 ++++++ 6 files changed, 45 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index ec6cd2be7c3c5..05c8615deb3ce 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -1664,7 +1664,8 @@ class TargetInfo : public TransferrableTargetInfo, bool isSEHTrySupported() const { return getTriple().isOSWindows() && (getTriple().isX86() || - getTriple().getArch() == llvm::Triple::aarch64); + getTriple().getArch() == llvm::Triple::aarch64 || + getTriple().isThumb()); } /// Return true if {|} are normal characters in the asm string. diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp index 90d8196ffb82a..ca579c22f66be 100644 --- a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp @@ -33,9 +33,10 @@ using namespace llvm; WinException::WinException(AsmPrinter *A) : EHStreamer(A) { - // MSVC's EH tables are always composed of 32-bit words. All known 64-bit - // platforms use an imagerel32 relocation to refer to symbols. - useImageRel32 = (A->getDataLayout().getPointerSizeInBits() == 64); + // MSVC's EH tables are always composed of 32-bit words. All known + // architectures use an imagerel32 relocation to refer to symbols, except + // 32-bit x86. + useImageRel32 = A->TM.getTargetTriple().getArch() != Triple::x86; isAArch64 = Asm->TM.getTargetTriple().isAArch64(); isThumb = Asm->TM.getTargetTriple().isThumb(); } diff --git a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp index 14e4c19a8ac1a..69154fd6e749a 100644 --- a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -2242,6 +2242,16 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, return true; } + case ARM::CLEANUPRET: + case ARM::CATCHRET: { + bool isThumb = STI->isThumb(); + unsigned RetOpc = isThumb ? ARM::tBX_RET : ARM::BX_RET; + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(RetOpc)) + .add(predOps(ARMCC::AL)); + MI.eraseFromParent(); + return true; + } + case ARM::TCRETURNdi: case ARM::TCRETURNri: case ARM::TCRETURNrinotr12: { diff --git a/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/llvm/lib/Target/ARM/ARMFrameLowering.cpp index 7d6be065d208a..940ae6006777c 100644 --- a/llvm/lib/Target/ARM/ARMFrameLowering.cpp +++ b/llvm/lib/Target/ARM/ARMFrameLowering.cpp @@ -443,6 +443,9 @@ static MachineBasicBlock::iterator insertSEH(MachineBasicBlock::iterator MBBI, default: report_fatal_error("No SEH Opcode for instruction " + TII.getName(Opc)); break; + case ARM::CLEANUPRET: + case ARM::CATCHRET: + break; case ARM::t2ADDri: // add.w r11, sp, #xx case ARM::t2ADDri12: // add.w r11, sp, #xx case ARM::t2MOVTi16: // movt r4, #xx @@ -2369,6 +2372,9 @@ static unsigned estimateRSStackSizeLimit(MachineFunction &MF, if (!MI.getOperand(i).isFI()) continue; + if (MI.getOpcode() == TargetOpcode::LOCAL_ESCAPE) + break; + // When using ADDri to get the address of a stack object, 255 is the // largest offset guaranteed to fit in the immediate offset. if (MI.getOpcode() == ARM::ADDri) { diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index eb757df6a9f28..c1b5879e10276 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -3838,6 +3838,23 @@ ARMTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG, SDLoc dl(Op); switch (IntNo) { default: return SDValue(); // Don't custom lower most intrinsics. + case Intrinsic::localaddress: { + const MachineFunction &MF = DAG.getMachineFunction(); + const TargetRegisterInfo *RegInfo = Subtarget->getRegisterInfo(); + unsigned Reg = RegInfo->getFrameRegister(MF); + return DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg, + Op.getSimpleValueType()); + } + case Intrinsic::eh_recoverfp: { + SDValue FnOp = Op.getOperand(1); + SDValue IncomingFPOp = Op.getOperand(2); + GlobalAddressSDNode *GSD = dyn_cast<GlobalAddressSDNode>(FnOp); + auto *Fn = dyn_cast_or_null<Function>(GSD ? GSD->getGlobal() : nullptr); + if (!Fn) + report_fatal_error( + "llvm.eh.recoverfp must take a function as the first argument"); + return IncomingFPOp; + } case Intrinsic::thread_pointer: { EVT PtrVT = getPointerTy(DAG.getDataLayout()); return DAG.getNode(ARMISD::THREAD_POINTER, dl, PtrVT); diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td index b72aa4b28736e..b2c7337041800 100644 --- a/llvm/lib/Target/ARM/ARMInstrInfo.td +++ b/llvm/lib/Target/ARM/ARMInstrInfo.td @@ -6725,3 +6725,9 @@ let isPseudo = 1 in { let isTerminator = 1 in def SEH_EpilogEnd : PseudoInst<(outs), (ins), NoItinerary, []>, Sched<[]>; } + +// C++ Exception / SEH Pseudo Instructions +let isTerminator = 1, isReturn = 1, isBarrier = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in { + def CLEANUPRET : PseudoInst<(outs), (ins), NoItinerary, [(cleanupret bb)]>, Sched<[]>; + def CATCHRET : PseudoInst<(outs), (ins arm_br_target:$dst, arm_br_target:$src), NoItinerary, [(catchret bb:$dst, bb:$src)]>, Sched<[]>; +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
