Skip to content

Conversation

@arsenm
Copy link
Contributor

@arsenm arsenm commented Nov 11, 2025

Stop hardcoding different variants of __chkstk and query the
name through RuntimeLibcalls.

Copy link
Contributor Author

arsenm commented Nov 11, 2025

This stack of pull requests is managed by Graphite. Learn more about stacking.

@llvmbot
Copy link
Member

llvmbot commented Nov 11, 2025

@llvm/pr-subscribers-llvm-ir

@llvm/pr-subscribers-backend-arm

Author: Matt Arsenault (arsenm)

Changes

Stop hardcoding different variants of __chkstk and query the
name through RuntimeLibcalls.


Full diff: https://github.com/llvm/llvm-project/pull/167453.diff

7 Files Affected:

  • (modified) llvm/include/llvm/IR/RuntimeLibcalls.td (+35-2)
  • (modified) llvm/lib/Target/AArch64/AArch64ISelLowering.cpp (+6-2)
  • (modified) llvm/lib/Target/AArch64/AArch64PrologueEpilogue.cpp (+6-1)
  • (modified) llvm/lib/Target/AArch64/AArch64Subtarget.h (-6)
  • (modified) llvm/lib/Target/ARM/ARMFrameLowering.cpp (+9-3)
  • (modified) llvm/lib/Target/ARM/ARMISelLowering.cpp (+7-2)
  • (modified) llvm/lib/Target/X86/X86ISelLowering.cpp (+4-3)
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td index ee80606ed0dbf..48d443acd1a2c 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.td +++ b/llvm/include/llvm/IR/RuntimeLibcalls.td @@ -406,6 +406,7 @@ def STACK_SMASH_HANDLER : RuntimeLibcall; // Safe stack def SAFESTACK_POINTER_ADDRESS : RuntimeLibcall; +def STACK_PROBE : RuntimeLibcall; def SECURITY_CHECK_COOKIE : RuntimeLibcall; // Deoptimization @@ -1084,6 +1085,15 @@ def __stack_smash_handler : RuntimeLibcallImpl<STACK_SMASH_HANDLER>; def __riscv_flush_icache : RuntimeLibcallImpl<RISCV_FLUSH_ICACHE>; +def _chkstk : RuntimeLibcallImpl<STACK_PROBE>; +def _alloca : RuntimeLibcallImpl<STACK_PROBE>; + +def __chkstk : RuntimeLibcallImpl<STACK_PROBE>; +def ___chkstk_ms : RuntimeLibcallImpl<STACK_PROBE>; + +def __chkstk_ms : RuntimeLibcallImpl<STACK_PROBE>; +def __chkstk_arm64ec : RuntimeLibcallImpl<STACK_PROBE, "#__chkstk_arm64ec">; + def __security_check_cookie : RuntimeLibcallImpl<SECURITY_CHECK_COOKIE>; def __security_check_cookie_arm64ec : RuntimeLibcallImpl<SECURITY_CHECK_COOKIE, "#__security_check_cookie_arm64ec">; @@ -1260,6 +1270,9 @@ defvar SecurityCheckCookieIfWinMSVC = LibcallImpls<(add __security_check_cookie, __security_cookie), isWindowsMSVCOrItaniumEnvironment>; +defvar __chkstk_IfWinMSVC = + LibcallImpls<(add __chkstk), isWindowsMSVCEnvironment>; + defvar LibmHasSinCosF32 = LibcallImpls<(add sincosf), hasSinCos>; defvar LibmHasSinCosF64 = LibcallImpls<(add sincos), hasSinCos>; defvar LibmHasSinCosF80 = LibcallImpls<(add sincosl_f80), hasSinCos>; @@ -1418,6 +1431,7 @@ def AArch64SystemLibrary : SystemRuntimeLibrary< DefaultLibmExp10, DefaultStackProtector, SecurityCheckCookieIfWinMSVC, + __chkstk_IfWinMSVC, SMEABI_LibCalls_PreserveMost_From_X0, SMEABI_LibCalls_PreserveMost_From_X1, SMEABI_LibCalls_PreserveMost_From_X2) @@ -1465,6 +1479,7 @@ def WindowsARM64ECSystemLibrary LibcallImpls<(add __security_check_cookie_arm64ec, __security_cookie), isWindowsMSVCEnvironment>, + __chkstk_arm64ec, ExceptionModelCallsArm64EC)>; //===----------------------------------------------------------------------===// @@ -1882,6 +1897,7 @@ def ARMSystemLibrary WindowARMDivRemCalls, WindowARMFPIntCasts, SecurityCheckCookieIfWinMSVC, + LibcallImpls<(add __chkstk), isOSWindows>, AEABIDivRemCalls, DarwinSinCosStret, DarwinExp10, LibmHasSinCosF32, LibmHasSinCosF64, LibmHasSinCosF128, @@ -2552,6 +2568,19 @@ def isX86_32 : RuntimeLibcallPredicate<"TT.getArch() == Triple::x86">; def isX86_64 : RuntimeLibcallPredicate<"TT.getArch() == Triple::x86_64">; def isX86 : RuntimeLibcallPredicate<"TT.isX86()">; +def isCygwinMinGW64 : RuntimeLibcallPredicate< + [{TT.isOSCygMing() && TT.getArch() == Triple::x86_64}]>; +def isCygwinMinGW32 : RuntimeLibcallPredicate< + [{TT.isOSCygMing() && TT.getArch() == Triple::x86}]>; + +def isWin32NotCygMing : RuntimeLibcallPredicate< + [{TT.getArch() == Triple::x86 && + (TT.isOSWindows() || TT.isUEFI()) && !TT.isOSCygMing()}]>; +def isWin64NotCygMing : RuntimeLibcallPredicate< + [{TT.getArch() == Triple::x86_64 && + (TT.isOSWindows() || TT.isUEFI()) && !TT.isOSCygMing()}]>; + + // Some darwins have an optimized __bzero/bzero function. def darwinHas__bzero : RuntimeLibcallPredicate<"TT.isMacOSX() && !TT.isMacOSXVersionLT(10, 6)">; @@ -2581,8 +2610,12 @@ defvar X86CommonLibcalls = // FIXME: MSVCRT doesn't have powi. The f128 case is added as a // hack for one test relying on it. __powitf2_f128, - DefaultStackProtector - ); + DefaultStackProtector, + LibcallImpls<(add ___chkstk_ms), isCygwinMinGW64>, + LibcallImpls<(add __chkstk), isWin64NotCygMing>, + LibcallImpls<(add _alloca), isCygwinMinGW32>, + LibcallImpls<(add _chkstk), isWin32NotCygMing> +); defvar Windows32DivRemMulCalls = LibcallsWithCC<(add WindowsDivRemMulLibcalls), X86_STDCALL, diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 8457f6178fdc2..b47795517b0c9 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -16851,11 +16851,15 @@ AArch64TargetLowering::LowerWindowsDYNAMIC_STACKALLOC(SDValue Op, return DAG.getMergeValues(Ops, DL); } + RTLIB::LibcallImpl ChkStkImpl = getLibcallImpl(RTLIB::STACK_PROBE); + if (ChkStkImpl == RTLIB::Unsupported) + return SDValue(); + Chain = DAG.getCALLSEQ_START(Chain, 0, 0, DL); EVT PtrVT = getPointerTy(DAG.getDataLayout()); - SDValue Callee = DAG.getTargetExternalSymbol(Subtarget->getChkStkName(), - PtrVT, 0); + SDValue Callee = DAG.getTargetExternalSymbol( + getLibcallImplName(ChkStkImpl).data(), PtrVT, 0); const AArch64RegisterInfo *TRI = Subtarget->getRegisterInfo(); const uint32_t *Mask = TRI->getWindowsStackProbePreservedMask(); diff --git a/llvm/lib/Target/AArch64/AArch64PrologueEpilogue.cpp b/llvm/lib/Target/AArch64/AArch64PrologueEpilogue.cpp index 965585f40571b..dcddcb50bd91e 100644 --- a/llvm/lib/Target/AArch64/AArch64PrologueEpilogue.cpp +++ b/llvm/lib/Target/AArch64/AArch64PrologueEpilogue.cpp @@ -1135,7 +1135,12 @@ void AArch64PrologueEmitter::emitWindowsStackProbe( .setMIFlags(MachineInstr::FrameSetup); } - const char *ChkStk = Subtarget.getChkStkName(); + const AArch64TargetLowering *TLI = Subtarget.getTargetLowering(); + RTLIB::LibcallImpl ChkStkLibcall = TLI->getLibcallImpl(RTLIB::STACK_PROBE); + if (ChkStkLibcall == RTLIB::Unsupported) + reportFatalUsageError("no available implementation of __chkstk"); + + const char *ChkStk = TLI->getLibcallImplName(ChkStkLibcall).data(); switch (MF.getTarget().getCodeModel()) { case CodeModel::Tiny: case CodeModel::Small: diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.h b/llvm/lib/Target/AArch64/AArch64Subtarget.h index ab4004e30f629..8fc35bfeb01f9 100644 --- a/llvm/lib/Target/AArch64/AArch64Subtarget.h +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.h @@ -450,12 +450,6 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo { /// add + cnt instructions. bool useScalarIncVL() const; - const char* getChkStkName() const { - if (isWindowsArm64EC()) - return "#__chkstk_arm64ec"; - return "__chkstk"; - } - /// Choose a method of checking LR before performing a tail call. AArch64PAuth::AuthCheckMethod getAuthenticatedLRCheckMethod(const MachineFunction &MF) const; diff --git a/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/llvm/lib/Target/ARM/ARMFrameLowering.cpp index 21a113572ce93..db5674ca721cc 100644 --- a/llvm/lib/Target/ARM/ARMFrameLowering.cpp +++ b/llvm/lib/Target/ARM/ARMFrameLowering.cpp @@ -1138,6 +1138,12 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF, .add(predOps(ARMCC::AL)); } + const ARMTargetLowering *TLI = STI.getTargetLowering(); + RTLIB::LibcallImpl ChkStkLibcall = TLI->getLibcallImpl(RTLIB::STACK_PROBE); + if (ChkStkLibcall == RTLIB::Unsupported) + reportFatalUsageError("no available implementation of __chkstk"); + const char *ChkStk = TLI->getLibcallImplName(ChkStkLibcall).data(); + switch (TM.getCodeModel()) { case CodeModel::Tiny: llvm_unreachable("Tiny code model not available on ARM."); @@ -1146,14 +1152,14 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF, case CodeModel::Kernel: BuildMI(MBB, MBBI, dl, TII.get(ARM::tBL)) .add(predOps(ARMCC::AL)) - .addExternalSymbol("__chkstk") + .addExternalSymbol(ChkStk) .addReg(ARM::R4, RegState::Implicit) .setMIFlags(MachineInstr::FrameSetup); break; case CodeModel::Large: BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi32imm), ARM::R12) - .addExternalSymbol("__chkstk") - .setMIFlags(MachineInstr::FrameSetup); + .addExternalSymbol(ChkStk) + .setMIFlags(MachineInstr::FrameSetup); BuildMI(MBB, MBBI, dl, TII.get(ARM::tBLXr)) .add(predOps(ARMCC::AL)) diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 92fae71121a81..220cf16589679 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -11727,6 +11727,11 @@ ARMTargetLowering::EmitLowered__chkstk(MachineInstr &MI, // -mcmodel=large, alleviating the need for the trampoline which may clobber // IP. + RTLIB::LibcallImpl ChkStkLibcall = getLibcallImpl(RTLIB::STACK_PROBE); + if (ChkStkLibcall == RTLIB::Unsupported) + reportFatalUsageError("no available implementation of __chkstk"); + + const char *ChkStk = getLibcallImplName(ChkStkLibcall).data(); switch (TM.getCodeModel()) { case CodeModel::Tiny: llvm_unreachable("Tiny code model not available on ARM."); @@ -11735,7 +11740,7 @@ ARMTargetLowering::EmitLowered__chkstk(MachineInstr &MI, case CodeModel::Kernel: BuildMI(*MBB, MI, DL, TII.get(ARM::tBL)) .add(predOps(ARMCC::AL)) - .addExternalSymbol("__chkstk") + .addExternalSymbol(ChkStk) .addReg(ARM::R4, RegState::Implicit | RegState::Kill) .addReg(ARM::R4, RegState::Implicit | RegState::Define) .addReg(ARM::R12, @@ -11748,7 +11753,7 @@ ARMTargetLowering::EmitLowered__chkstk(MachineInstr &MI, Register Reg = MRI.createVirtualRegister(&ARM::rGPRRegClass); BuildMI(*MBB, MI, DL, TII.get(ARM::t2MOVi32imm), Reg) - .addExternalSymbol("__chkstk"); + .addExternalSymbol(ChkStk); BuildMI(*MBB, MI, DL, TII.get(gettBLXrOpcode(*MBB->getParent()))) .add(predOps(ARMCC::AL)) .addReg(Reg, RegState::Kill) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 5bce539c45341..cd9e530284e08 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -62436,9 +62436,10 @@ X86TargetLowering::getStackProbeSymbolName(const MachineFunction &MF) const { // We need a stack probe to conform to the Windows ABI. Choose the right // symbol. - if (Subtarget.is64Bit()) - return Subtarget.isTargetCygMing() ? "___chkstk_ms" : "__chkstk"; - return Subtarget.isTargetCygMing() ? "_alloca" : "_chkstk"; + RTLIB::LibcallImpl StackProbeImpl = getLibcallImpl(RTLIB::STACK_PROBE); + if (StackProbeImpl == RTLIB::Unsupported) + return ""; + return getLibcallImplName(StackProbeImpl); } unsigned 
@llvmbot
Copy link
Member

llvmbot commented Nov 11, 2025

@llvm/pr-subscribers-backend-aarch64

Author: Matt Arsenault (arsenm)

Changes

Stop hardcoding different variants of __chkstk and query the
name through RuntimeLibcalls.


Full diff: https://github.com/llvm/llvm-project/pull/167453.diff

7 Files Affected:

  • (modified) llvm/include/llvm/IR/RuntimeLibcalls.td (+35-2)
  • (modified) llvm/lib/Target/AArch64/AArch64ISelLowering.cpp (+6-2)
  • (modified) llvm/lib/Target/AArch64/AArch64PrologueEpilogue.cpp (+6-1)
  • (modified) llvm/lib/Target/AArch64/AArch64Subtarget.h (-6)
  • (modified) llvm/lib/Target/ARM/ARMFrameLowering.cpp (+9-3)
  • (modified) llvm/lib/Target/ARM/ARMISelLowering.cpp (+7-2)
  • (modified) llvm/lib/Target/X86/X86ISelLowering.cpp (+4-3)
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td index ee80606ed0dbf..48d443acd1a2c 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.td +++ b/llvm/include/llvm/IR/RuntimeLibcalls.td @@ -406,6 +406,7 @@ def STACK_SMASH_HANDLER : RuntimeLibcall; // Safe stack def SAFESTACK_POINTER_ADDRESS : RuntimeLibcall; +def STACK_PROBE : RuntimeLibcall; def SECURITY_CHECK_COOKIE : RuntimeLibcall; // Deoptimization @@ -1084,6 +1085,15 @@ def __stack_smash_handler : RuntimeLibcallImpl<STACK_SMASH_HANDLER>; def __riscv_flush_icache : RuntimeLibcallImpl<RISCV_FLUSH_ICACHE>; +def _chkstk : RuntimeLibcallImpl<STACK_PROBE>; +def _alloca : RuntimeLibcallImpl<STACK_PROBE>; + +def __chkstk : RuntimeLibcallImpl<STACK_PROBE>; +def ___chkstk_ms : RuntimeLibcallImpl<STACK_PROBE>; + +def __chkstk_ms : RuntimeLibcallImpl<STACK_PROBE>; +def __chkstk_arm64ec : RuntimeLibcallImpl<STACK_PROBE, "#__chkstk_arm64ec">; + def __security_check_cookie : RuntimeLibcallImpl<SECURITY_CHECK_COOKIE>; def __security_check_cookie_arm64ec : RuntimeLibcallImpl<SECURITY_CHECK_COOKIE, "#__security_check_cookie_arm64ec">; @@ -1260,6 +1270,9 @@ defvar SecurityCheckCookieIfWinMSVC = LibcallImpls<(add __security_check_cookie, __security_cookie), isWindowsMSVCOrItaniumEnvironment>; +defvar __chkstk_IfWinMSVC = + LibcallImpls<(add __chkstk), isWindowsMSVCEnvironment>; + defvar LibmHasSinCosF32 = LibcallImpls<(add sincosf), hasSinCos>; defvar LibmHasSinCosF64 = LibcallImpls<(add sincos), hasSinCos>; defvar LibmHasSinCosF80 = LibcallImpls<(add sincosl_f80), hasSinCos>; @@ -1418,6 +1431,7 @@ def AArch64SystemLibrary : SystemRuntimeLibrary< DefaultLibmExp10, DefaultStackProtector, SecurityCheckCookieIfWinMSVC, + __chkstk_IfWinMSVC, SMEABI_LibCalls_PreserveMost_From_X0, SMEABI_LibCalls_PreserveMost_From_X1, SMEABI_LibCalls_PreserveMost_From_X2) @@ -1465,6 +1479,7 @@ def WindowsARM64ECSystemLibrary LibcallImpls<(add __security_check_cookie_arm64ec, __security_cookie), isWindowsMSVCEnvironment>, + __chkstk_arm64ec, ExceptionModelCallsArm64EC)>; //===----------------------------------------------------------------------===// @@ -1882,6 +1897,7 @@ def ARMSystemLibrary WindowARMDivRemCalls, WindowARMFPIntCasts, SecurityCheckCookieIfWinMSVC, + LibcallImpls<(add __chkstk), isOSWindows>, AEABIDivRemCalls, DarwinSinCosStret, DarwinExp10, LibmHasSinCosF32, LibmHasSinCosF64, LibmHasSinCosF128, @@ -2552,6 +2568,19 @@ def isX86_32 : RuntimeLibcallPredicate<"TT.getArch() == Triple::x86">; def isX86_64 : RuntimeLibcallPredicate<"TT.getArch() == Triple::x86_64">; def isX86 : RuntimeLibcallPredicate<"TT.isX86()">; +def isCygwinMinGW64 : RuntimeLibcallPredicate< + [{TT.isOSCygMing() && TT.getArch() == Triple::x86_64}]>; +def isCygwinMinGW32 : RuntimeLibcallPredicate< + [{TT.isOSCygMing() && TT.getArch() == Triple::x86}]>; + +def isWin32NotCygMing : RuntimeLibcallPredicate< + [{TT.getArch() == Triple::x86 && + (TT.isOSWindows() || TT.isUEFI()) && !TT.isOSCygMing()}]>; +def isWin64NotCygMing : RuntimeLibcallPredicate< + [{TT.getArch() == Triple::x86_64 && + (TT.isOSWindows() || TT.isUEFI()) && !TT.isOSCygMing()}]>; + + // Some darwins have an optimized __bzero/bzero function. def darwinHas__bzero : RuntimeLibcallPredicate<"TT.isMacOSX() && !TT.isMacOSXVersionLT(10, 6)">; @@ -2581,8 +2610,12 @@ defvar X86CommonLibcalls = // FIXME: MSVCRT doesn't have powi. The f128 case is added as a // hack for one test relying on it. __powitf2_f128, - DefaultStackProtector - ); + DefaultStackProtector, + LibcallImpls<(add ___chkstk_ms), isCygwinMinGW64>, + LibcallImpls<(add __chkstk), isWin64NotCygMing>, + LibcallImpls<(add _alloca), isCygwinMinGW32>, + LibcallImpls<(add _chkstk), isWin32NotCygMing> +); defvar Windows32DivRemMulCalls = LibcallsWithCC<(add WindowsDivRemMulLibcalls), X86_STDCALL, diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 8457f6178fdc2..b47795517b0c9 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -16851,11 +16851,15 @@ AArch64TargetLowering::LowerWindowsDYNAMIC_STACKALLOC(SDValue Op, return DAG.getMergeValues(Ops, DL); } + RTLIB::LibcallImpl ChkStkImpl = getLibcallImpl(RTLIB::STACK_PROBE); + if (ChkStkImpl == RTLIB::Unsupported) + return SDValue(); + Chain = DAG.getCALLSEQ_START(Chain, 0, 0, DL); EVT PtrVT = getPointerTy(DAG.getDataLayout()); - SDValue Callee = DAG.getTargetExternalSymbol(Subtarget->getChkStkName(), - PtrVT, 0); + SDValue Callee = DAG.getTargetExternalSymbol( + getLibcallImplName(ChkStkImpl).data(), PtrVT, 0); const AArch64RegisterInfo *TRI = Subtarget->getRegisterInfo(); const uint32_t *Mask = TRI->getWindowsStackProbePreservedMask(); diff --git a/llvm/lib/Target/AArch64/AArch64PrologueEpilogue.cpp b/llvm/lib/Target/AArch64/AArch64PrologueEpilogue.cpp index 965585f40571b..dcddcb50bd91e 100644 --- a/llvm/lib/Target/AArch64/AArch64PrologueEpilogue.cpp +++ b/llvm/lib/Target/AArch64/AArch64PrologueEpilogue.cpp @@ -1135,7 +1135,12 @@ void AArch64PrologueEmitter::emitWindowsStackProbe( .setMIFlags(MachineInstr::FrameSetup); } - const char *ChkStk = Subtarget.getChkStkName(); + const AArch64TargetLowering *TLI = Subtarget.getTargetLowering(); + RTLIB::LibcallImpl ChkStkLibcall = TLI->getLibcallImpl(RTLIB::STACK_PROBE); + if (ChkStkLibcall == RTLIB::Unsupported) + reportFatalUsageError("no available implementation of __chkstk"); + + const char *ChkStk = TLI->getLibcallImplName(ChkStkLibcall).data(); switch (MF.getTarget().getCodeModel()) { case CodeModel::Tiny: case CodeModel::Small: diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.h b/llvm/lib/Target/AArch64/AArch64Subtarget.h index ab4004e30f629..8fc35bfeb01f9 100644 --- a/llvm/lib/Target/AArch64/AArch64Subtarget.h +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.h @@ -450,12 +450,6 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo { /// add + cnt instructions. bool useScalarIncVL() const; - const char* getChkStkName() const { - if (isWindowsArm64EC()) - return "#__chkstk_arm64ec"; - return "__chkstk"; - } - /// Choose a method of checking LR before performing a tail call. AArch64PAuth::AuthCheckMethod getAuthenticatedLRCheckMethod(const MachineFunction &MF) const; diff --git a/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/llvm/lib/Target/ARM/ARMFrameLowering.cpp index 21a113572ce93..db5674ca721cc 100644 --- a/llvm/lib/Target/ARM/ARMFrameLowering.cpp +++ b/llvm/lib/Target/ARM/ARMFrameLowering.cpp @@ -1138,6 +1138,12 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF, .add(predOps(ARMCC::AL)); } + const ARMTargetLowering *TLI = STI.getTargetLowering(); + RTLIB::LibcallImpl ChkStkLibcall = TLI->getLibcallImpl(RTLIB::STACK_PROBE); + if (ChkStkLibcall == RTLIB::Unsupported) + reportFatalUsageError("no available implementation of __chkstk"); + const char *ChkStk = TLI->getLibcallImplName(ChkStkLibcall).data(); + switch (TM.getCodeModel()) { case CodeModel::Tiny: llvm_unreachable("Tiny code model not available on ARM."); @@ -1146,14 +1152,14 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF, case CodeModel::Kernel: BuildMI(MBB, MBBI, dl, TII.get(ARM::tBL)) .add(predOps(ARMCC::AL)) - .addExternalSymbol("__chkstk") + .addExternalSymbol(ChkStk) .addReg(ARM::R4, RegState::Implicit) .setMIFlags(MachineInstr::FrameSetup); break; case CodeModel::Large: BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi32imm), ARM::R12) - .addExternalSymbol("__chkstk") - .setMIFlags(MachineInstr::FrameSetup); + .addExternalSymbol(ChkStk) + .setMIFlags(MachineInstr::FrameSetup); BuildMI(MBB, MBBI, dl, TII.get(ARM::tBLXr)) .add(predOps(ARMCC::AL)) diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 92fae71121a81..220cf16589679 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -11727,6 +11727,11 @@ ARMTargetLowering::EmitLowered__chkstk(MachineInstr &MI, // -mcmodel=large, alleviating the need for the trampoline which may clobber // IP. + RTLIB::LibcallImpl ChkStkLibcall = getLibcallImpl(RTLIB::STACK_PROBE); + if (ChkStkLibcall == RTLIB::Unsupported) + reportFatalUsageError("no available implementation of __chkstk"); + + const char *ChkStk = getLibcallImplName(ChkStkLibcall).data(); switch (TM.getCodeModel()) { case CodeModel::Tiny: llvm_unreachable("Tiny code model not available on ARM."); @@ -11735,7 +11740,7 @@ ARMTargetLowering::EmitLowered__chkstk(MachineInstr &MI, case CodeModel::Kernel: BuildMI(*MBB, MI, DL, TII.get(ARM::tBL)) .add(predOps(ARMCC::AL)) - .addExternalSymbol("__chkstk") + .addExternalSymbol(ChkStk) .addReg(ARM::R4, RegState::Implicit | RegState::Kill) .addReg(ARM::R4, RegState::Implicit | RegState::Define) .addReg(ARM::R12, @@ -11748,7 +11753,7 @@ ARMTargetLowering::EmitLowered__chkstk(MachineInstr &MI, Register Reg = MRI.createVirtualRegister(&ARM::rGPRRegClass); BuildMI(*MBB, MI, DL, TII.get(ARM::t2MOVi32imm), Reg) - .addExternalSymbol("__chkstk"); + .addExternalSymbol(ChkStk); BuildMI(*MBB, MI, DL, TII.get(gettBLXrOpcode(*MBB->getParent()))) .add(predOps(ARMCC::AL)) .addReg(Reg, RegState::Kill) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 5bce539c45341..cd9e530284e08 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -62436,9 +62436,10 @@ X86TargetLowering::getStackProbeSymbolName(const MachineFunction &MF) const { // We need a stack probe to conform to the Windows ABI. Choose the right // symbol. - if (Subtarget.is64Bit()) - return Subtarget.isTargetCygMing() ? "___chkstk_ms" : "__chkstk"; - return Subtarget.isTargetCygMing() ? "_alloca" : "_chkstk"; + RTLIB::LibcallImpl StackProbeImpl = getLibcallImpl(RTLIB::STACK_PROBE); + if (StackProbeImpl == RTLIB::Unsupported) + return ""; + return getLibcallImplName(StackProbeImpl); } unsigned 
@llvmbot
Copy link
Member

llvmbot commented Nov 11, 2025

@llvm/pr-subscribers-backend-x86

Author: Matt Arsenault (arsenm)

Changes

Stop hardcoding different variants of __chkstk and query the
name through RuntimeLibcalls.


Full diff: https://github.com/llvm/llvm-project/pull/167453.diff

7 Files Affected:

  • (modified) llvm/include/llvm/IR/RuntimeLibcalls.td (+35-2)
  • (modified) llvm/lib/Target/AArch64/AArch64ISelLowering.cpp (+6-2)
  • (modified) llvm/lib/Target/AArch64/AArch64PrologueEpilogue.cpp (+6-1)
  • (modified) llvm/lib/Target/AArch64/AArch64Subtarget.h (-6)
  • (modified) llvm/lib/Target/ARM/ARMFrameLowering.cpp (+9-3)
  • (modified) llvm/lib/Target/ARM/ARMISelLowering.cpp (+7-2)
  • (modified) llvm/lib/Target/X86/X86ISelLowering.cpp (+4-3)
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td index ee80606ed0dbf..48d443acd1a2c 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.td +++ b/llvm/include/llvm/IR/RuntimeLibcalls.td @@ -406,6 +406,7 @@ def STACK_SMASH_HANDLER : RuntimeLibcall; // Safe stack def SAFESTACK_POINTER_ADDRESS : RuntimeLibcall; +def STACK_PROBE : RuntimeLibcall; def SECURITY_CHECK_COOKIE : RuntimeLibcall; // Deoptimization @@ -1084,6 +1085,15 @@ def __stack_smash_handler : RuntimeLibcallImpl<STACK_SMASH_HANDLER>; def __riscv_flush_icache : RuntimeLibcallImpl<RISCV_FLUSH_ICACHE>; +def _chkstk : RuntimeLibcallImpl<STACK_PROBE>; +def _alloca : RuntimeLibcallImpl<STACK_PROBE>; + +def __chkstk : RuntimeLibcallImpl<STACK_PROBE>; +def ___chkstk_ms : RuntimeLibcallImpl<STACK_PROBE>; + +def __chkstk_ms : RuntimeLibcallImpl<STACK_PROBE>; +def __chkstk_arm64ec : RuntimeLibcallImpl<STACK_PROBE, "#__chkstk_arm64ec">; + def __security_check_cookie : RuntimeLibcallImpl<SECURITY_CHECK_COOKIE>; def __security_check_cookie_arm64ec : RuntimeLibcallImpl<SECURITY_CHECK_COOKIE, "#__security_check_cookie_arm64ec">; @@ -1260,6 +1270,9 @@ defvar SecurityCheckCookieIfWinMSVC = LibcallImpls<(add __security_check_cookie, __security_cookie), isWindowsMSVCOrItaniumEnvironment>; +defvar __chkstk_IfWinMSVC = + LibcallImpls<(add __chkstk), isWindowsMSVCEnvironment>; + defvar LibmHasSinCosF32 = LibcallImpls<(add sincosf), hasSinCos>; defvar LibmHasSinCosF64 = LibcallImpls<(add sincos), hasSinCos>; defvar LibmHasSinCosF80 = LibcallImpls<(add sincosl_f80), hasSinCos>; @@ -1418,6 +1431,7 @@ def AArch64SystemLibrary : SystemRuntimeLibrary< DefaultLibmExp10, DefaultStackProtector, SecurityCheckCookieIfWinMSVC, + __chkstk_IfWinMSVC, SMEABI_LibCalls_PreserveMost_From_X0, SMEABI_LibCalls_PreserveMost_From_X1, SMEABI_LibCalls_PreserveMost_From_X2) @@ -1465,6 +1479,7 @@ def WindowsARM64ECSystemLibrary LibcallImpls<(add __security_check_cookie_arm64ec, __security_cookie), isWindowsMSVCEnvironment>, + __chkstk_arm64ec, ExceptionModelCallsArm64EC)>; //===----------------------------------------------------------------------===// @@ -1882,6 +1897,7 @@ def ARMSystemLibrary WindowARMDivRemCalls, WindowARMFPIntCasts, SecurityCheckCookieIfWinMSVC, + LibcallImpls<(add __chkstk), isOSWindows>, AEABIDivRemCalls, DarwinSinCosStret, DarwinExp10, LibmHasSinCosF32, LibmHasSinCosF64, LibmHasSinCosF128, @@ -2552,6 +2568,19 @@ def isX86_32 : RuntimeLibcallPredicate<"TT.getArch() == Triple::x86">; def isX86_64 : RuntimeLibcallPredicate<"TT.getArch() == Triple::x86_64">; def isX86 : RuntimeLibcallPredicate<"TT.isX86()">; +def isCygwinMinGW64 : RuntimeLibcallPredicate< + [{TT.isOSCygMing() && TT.getArch() == Triple::x86_64}]>; +def isCygwinMinGW32 : RuntimeLibcallPredicate< + [{TT.isOSCygMing() && TT.getArch() == Triple::x86}]>; + +def isWin32NotCygMing : RuntimeLibcallPredicate< + [{TT.getArch() == Triple::x86 && + (TT.isOSWindows() || TT.isUEFI()) && !TT.isOSCygMing()}]>; +def isWin64NotCygMing : RuntimeLibcallPredicate< + [{TT.getArch() == Triple::x86_64 && + (TT.isOSWindows() || TT.isUEFI()) && !TT.isOSCygMing()}]>; + + // Some darwins have an optimized __bzero/bzero function. def darwinHas__bzero : RuntimeLibcallPredicate<"TT.isMacOSX() && !TT.isMacOSXVersionLT(10, 6)">; @@ -2581,8 +2610,12 @@ defvar X86CommonLibcalls = // FIXME: MSVCRT doesn't have powi. The f128 case is added as a // hack for one test relying on it. __powitf2_f128, - DefaultStackProtector - ); + DefaultStackProtector, + LibcallImpls<(add ___chkstk_ms), isCygwinMinGW64>, + LibcallImpls<(add __chkstk), isWin64NotCygMing>, + LibcallImpls<(add _alloca), isCygwinMinGW32>, + LibcallImpls<(add _chkstk), isWin32NotCygMing> +); defvar Windows32DivRemMulCalls = LibcallsWithCC<(add WindowsDivRemMulLibcalls), X86_STDCALL, diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 8457f6178fdc2..b47795517b0c9 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -16851,11 +16851,15 @@ AArch64TargetLowering::LowerWindowsDYNAMIC_STACKALLOC(SDValue Op, return DAG.getMergeValues(Ops, DL); } + RTLIB::LibcallImpl ChkStkImpl = getLibcallImpl(RTLIB::STACK_PROBE); + if (ChkStkImpl == RTLIB::Unsupported) + return SDValue(); + Chain = DAG.getCALLSEQ_START(Chain, 0, 0, DL); EVT PtrVT = getPointerTy(DAG.getDataLayout()); - SDValue Callee = DAG.getTargetExternalSymbol(Subtarget->getChkStkName(), - PtrVT, 0); + SDValue Callee = DAG.getTargetExternalSymbol( + getLibcallImplName(ChkStkImpl).data(), PtrVT, 0); const AArch64RegisterInfo *TRI = Subtarget->getRegisterInfo(); const uint32_t *Mask = TRI->getWindowsStackProbePreservedMask(); diff --git a/llvm/lib/Target/AArch64/AArch64PrologueEpilogue.cpp b/llvm/lib/Target/AArch64/AArch64PrologueEpilogue.cpp index 965585f40571b..dcddcb50bd91e 100644 --- a/llvm/lib/Target/AArch64/AArch64PrologueEpilogue.cpp +++ b/llvm/lib/Target/AArch64/AArch64PrologueEpilogue.cpp @@ -1135,7 +1135,12 @@ void AArch64PrologueEmitter::emitWindowsStackProbe( .setMIFlags(MachineInstr::FrameSetup); } - const char *ChkStk = Subtarget.getChkStkName(); + const AArch64TargetLowering *TLI = Subtarget.getTargetLowering(); + RTLIB::LibcallImpl ChkStkLibcall = TLI->getLibcallImpl(RTLIB::STACK_PROBE); + if (ChkStkLibcall == RTLIB::Unsupported) + reportFatalUsageError("no available implementation of __chkstk"); + + const char *ChkStk = TLI->getLibcallImplName(ChkStkLibcall).data(); switch (MF.getTarget().getCodeModel()) { case CodeModel::Tiny: case CodeModel::Small: diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.h b/llvm/lib/Target/AArch64/AArch64Subtarget.h index ab4004e30f629..8fc35bfeb01f9 100644 --- a/llvm/lib/Target/AArch64/AArch64Subtarget.h +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.h @@ -450,12 +450,6 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo { /// add + cnt instructions. bool useScalarIncVL() const; - const char* getChkStkName() const { - if (isWindowsArm64EC()) - return "#__chkstk_arm64ec"; - return "__chkstk"; - } - /// Choose a method of checking LR before performing a tail call. AArch64PAuth::AuthCheckMethod getAuthenticatedLRCheckMethod(const MachineFunction &MF) const; diff --git a/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/llvm/lib/Target/ARM/ARMFrameLowering.cpp index 21a113572ce93..db5674ca721cc 100644 --- a/llvm/lib/Target/ARM/ARMFrameLowering.cpp +++ b/llvm/lib/Target/ARM/ARMFrameLowering.cpp @@ -1138,6 +1138,12 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF, .add(predOps(ARMCC::AL)); } + const ARMTargetLowering *TLI = STI.getTargetLowering(); + RTLIB::LibcallImpl ChkStkLibcall = TLI->getLibcallImpl(RTLIB::STACK_PROBE); + if (ChkStkLibcall == RTLIB::Unsupported) + reportFatalUsageError("no available implementation of __chkstk"); + const char *ChkStk = TLI->getLibcallImplName(ChkStkLibcall).data(); + switch (TM.getCodeModel()) { case CodeModel::Tiny: llvm_unreachable("Tiny code model not available on ARM."); @@ -1146,14 +1152,14 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF, case CodeModel::Kernel: BuildMI(MBB, MBBI, dl, TII.get(ARM::tBL)) .add(predOps(ARMCC::AL)) - .addExternalSymbol("__chkstk") + .addExternalSymbol(ChkStk) .addReg(ARM::R4, RegState::Implicit) .setMIFlags(MachineInstr::FrameSetup); break; case CodeModel::Large: BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi32imm), ARM::R12) - .addExternalSymbol("__chkstk") - .setMIFlags(MachineInstr::FrameSetup); + .addExternalSymbol(ChkStk) + .setMIFlags(MachineInstr::FrameSetup); BuildMI(MBB, MBBI, dl, TII.get(ARM::tBLXr)) .add(predOps(ARMCC::AL)) diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 92fae71121a81..220cf16589679 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -11727,6 +11727,11 @@ ARMTargetLowering::EmitLowered__chkstk(MachineInstr &MI, // -mcmodel=large, alleviating the need for the trampoline which may clobber // IP. + RTLIB::LibcallImpl ChkStkLibcall = getLibcallImpl(RTLIB::STACK_PROBE); + if (ChkStkLibcall == RTLIB::Unsupported) + reportFatalUsageError("no available implementation of __chkstk"); + + const char *ChkStk = getLibcallImplName(ChkStkLibcall).data(); switch (TM.getCodeModel()) { case CodeModel::Tiny: llvm_unreachable("Tiny code model not available on ARM."); @@ -11735,7 +11740,7 @@ ARMTargetLowering::EmitLowered__chkstk(MachineInstr &MI, case CodeModel::Kernel: BuildMI(*MBB, MI, DL, TII.get(ARM::tBL)) .add(predOps(ARMCC::AL)) - .addExternalSymbol("__chkstk") + .addExternalSymbol(ChkStk) .addReg(ARM::R4, RegState::Implicit | RegState::Kill) .addReg(ARM::R4, RegState::Implicit | RegState::Define) .addReg(ARM::R12, @@ -11748,7 +11753,7 @@ ARMTargetLowering::EmitLowered__chkstk(MachineInstr &MI, Register Reg = MRI.createVirtualRegister(&ARM::rGPRRegClass); BuildMI(*MBB, MI, DL, TII.get(ARM::t2MOVi32imm), Reg) - .addExternalSymbol("__chkstk"); + .addExternalSymbol(ChkStk); BuildMI(*MBB, MI, DL, TII.get(gettBLXrOpcode(*MBB->getParent()))) .add(predOps(ARMCC::AL)) .addReg(Reg, RegState::Kill) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 5bce539c45341..cd9e530284e08 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -62436,9 +62436,10 @@ X86TargetLowering::getStackProbeSymbolName(const MachineFunction &MF) const { // We need a stack probe to conform to the Windows ABI. Choose the right // symbol. - if (Subtarget.is64Bit()) - return Subtarget.isTargetCygMing() ? "___chkstk_ms" : "__chkstk"; - return Subtarget.isTargetCygMing() ? "_alloca" : "_chkstk"; + RTLIB::LibcallImpl StackProbeImpl = getLibcallImpl(RTLIB::STACK_PROBE); + if (StackProbeImpl == RTLIB::Unsupported) + return ""; + return getLibcallImplName(StackProbeImpl); } unsigned 
Comment on lines +1088 to +1196
def _chkstk : RuntimeLibcallImpl<STACK_PROBE>;
def _alloca : RuntimeLibcallImpl<STACK_PROBE>;

def __chkstk : RuntimeLibcallImpl<STACK_PROBE>;
def ___chkstk_ms : RuntimeLibcallImpl<STACK_PROBE>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we merge __chkstk and _chkstk. They are not different names, they are the same name, the difference is __USER_LABEL_PREFIX__.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume the same applies for ___chkstk_ms and __chkstk_ms?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

Copy link
Collaborator

@efriedma-quic efriedma-quic Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

__chkstk and _chkstk are actually different symbols, I think? See #167303. CC @mstorsjo

I think there's only one __chkstk_ms, though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I try to use getNameWithPrefix or otherwise manually prepend getGlobalPrefix, it doesn't seem to be working out

@arsenm arsenm force-pushed the users/arsenm/runtime-libcalls/add-entries-chkstk branch 2 times, most recently from 5bfad60 to cd2660d Compare November 11, 2025 23:45
@arsenm
Copy link
Contributor Author

arsenm commented Nov 18, 2025

ping

Stop hardcoding different variants of __chkstk and query the name through RuntimeLibcalls.
@arsenm arsenm force-pushed the users/arsenm/runtime-libcalls/add-entries-chkstk branch from cd2660d to a124811 Compare November 25, 2025 23:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment