https://github.com/arsenm updated 
https://github.com/llvm/llvm-project/pull/170329

>From 05d4afa766293ae1279ca0fad66b816d868553f3 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <[email protected]>
Date: Mon, 24 Nov 2025 13:48:45 -0500
Subject: [PATCH] StackProtector: Use LibcallLoweringInfo analysis

---
 llvm/lib/CodeGen/StackProtector.cpp           | 82 +++++++++++++------
 .../NVPTX/no-stack-protector-libcall-error.ll |  2 +-
 .../X86/stack-protector-atomicrmw-xchg.ll     |  4 +-
 .../cross-dso-cfi-stack-chk-fail.ll           |  2 +-
 .../StackProtector/missing-analysis.ll        |  7 ++
 .../StackProtector/stack-chk-fail-alias.ll    |  2 +-
 6 files changed, 67 insertions(+), 32 deletions(-)
 create mode 100644 llvm/test/Transforms/StackProtector/missing-analysis.ll

diff --git a/llvm/lib/CodeGen/StackProtector.cpp 
b/llvm/lib/CodeGen/StackProtector.cpp
index 5fd5d6cce23df..d56ef00ac7d08 100644
--- a/llvm/lib/CodeGen/StackProtector.cpp
+++ b/llvm/lib/CodeGen/StackProtector.cpp
@@ -69,13 +69,15 @@ static cl::opt<bool> 
DisableCheckNoReturn("disable-check-noreturn-call",
 ///  - The prologue code loads and stores the stack guard onto the stack.
 ///  - The epilogue checks the value stored in the prologue against the 
original
 ///    value. It calls __stack_chk_fail if they differ.
-static bool InsertStackProtectors(const TargetMachine *TM, Function *F,
-                                  DomTreeUpdater *DTU, bool &HasPrologue,
-                                  bool &HasIRCheck);
+static bool InsertStackProtectors(const TargetLowering &TLI,
+                                  const LibcallLoweringInfo &Libcalls,
+                                  Function *F, DomTreeUpdater *DTU,
+                                  bool &HasPrologue, bool &HasIRCheck);
 
 /// CreateFailBB - Create a basic block to jump to when the stack protector
 /// check fails.
-static BasicBlock *CreateFailBB(Function *F, const TargetLowering &TLI);
+static BasicBlock *CreateFailBB(Function *F,
+                                const LibcallLoweringInfo &Libcalls);
 
 bool SSPLayoutInfo::shouldEmitSDCheck(const BasicBlock &BB) const {
   return HasPrologue && !HasIRCheck && isa<ReturnInst>(BB.getTerminator());
@@ -131,8 +133,23 @@ PreservedAnalyses StackProtectorPass::run(Function &F,
       return PreservedAnalyses::all();
   }
 
+  auto &MAMProxy = FAM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
+  const LibcallLoweringModuleAnalysisResult *LibcallLowering =
+      MAMProxy.getCachedResult<LibcallLoweringModuleAnalysis>(*F.getParent());
+
+  if (!LibcallLowering) {
+    F.getContext().emitError("'" + LibcallLoweringModuleAnalysis::name() +
+                             "' analysis required");
+    return PreservedAnalyses::all();
+  }
+
+  const TargetSubtargetInfo *STI = TM->getSubtargetImpl(F);
+  const TargetLowering *TLI = STI->getTargetLowering();
+  const LibcallLoweringInfo &Libcalls =
+      LibcallLowering->getLibcallLowering(*STI);
+
   ++NumFunProtected;
-  bool Changed = InsertStackProtectors(TM, &F, DT ? &DTU : nullptr,
+  bool Changed = InsertStackProtectors(*TLI, Libcalls, &F, DT ? &DTU : nullptr,
                                        Info.HasPrologue, Info.HasIRCheck);
 #ifdef EXPENSIVE_CHECKS
   assert((!DT ||
@@ -156,6 +173,7 @@ StackProtector::StackProtector() : FunctionPass(ID) {
 
 INITIALIZE_PASS_BEGIN(StackProtector, DEBUG_TYPE,
                       "Insert stack protectors", false, true)
+INITIALIZE_PASS_DEPENDENCY(LibcallLoweringInfoWrapper)
 INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
 INITIALIZE_PASS_END(StackProtector, DEBUG_TYPE,
@@ -164,6 +182,7 @@ INITIALIZE_PASS_END(StackProtector, DEBUG_TYPE,
 FunctionPass *llvm::createStackProtectorPass() { return new StackProtector(); }
 
 void StackProtector::getAnalysisUsage(AnalysisUsage &AU) const {
+  AU.addRequired<LibcallLoweringInfoWrapper>();
   AU.addRequired<TargetPassConfig>();
   AU.addPreserved<DominatorTreeWrapperPass>();
 }
@@ -190,9 +209,16 @@ bool StackProtector::runOnFunction(Function &Fn) {
       return false;
   }
 
+  const TargetSubtargetInfo *Subtarget = TM->getSubtargetImpl(Fn);
+  const LibcallLoweringInfo &Libcalls =
+      getAnalysis<LibcallLoweringInfoWrapper>().getLibcallLowering(*M,
+                                                                   *Subtarget);
+
+  const TargetLowering *TLI = Subtarget->getTargetLowering();
+
   ++NumFunProtected;
   bool Changed =
-      InsertStackProtectors(TM, F, DTU ? &*DTU : nullptr,
+      InsertStackProtectors(*TLI, Libcalls, F, DTU ? &*DTU : nullptr,
                             LayoutInfo.HasPrologue, LayoutInfo.HasIRCheck);
 #ifdef EXPENSIVE_CHECKS
   assert((!DTU ||
@@ -519,10 +545,10 @@ bool SSPLayoutAnalysis::requiresStackProtector(Function 
*F,
 
 /// Create a stack guard loading and populate whether SelectionDAG SSP is
 /// supported.
-static Value *getStackGuard(const TargetLoweringBase *TLI, Module *M,
+static Value *getStackGuard(const TargetLoweringBase &TLI, Module *M,
                             IRBuilder<> &B,
                             bool *SupportsSelectionDAGSP = nullptr) {
-  Value *Guard = TLI->getIRStackGuard(B);
+  Value *Guard = TLI.getIRStackGuard(B);
   StringRef GuardMode = M->getStackProtectorGuard();
   if ((GuardMode == "tls" || GuardMode.empty()) && Guard)
     return B.CreateLoad(B.getPtrTy(), Guard, true, "StackGuard");
@@ -540,7 +566,7 @@ static Value *getStackGuard(const TargetLoweringBase *TLI, 
Module *M,
   // actually conveys the same information getIRStackGuard() already gives.
   if (SupportsSelectionDAGSP)
     *SupportsSelectionDAGSP = true;
-  TLI->insertSSPDeclarations(*M);
+  TLI.insertSSPDeclarations(*M);
   return B.CreateIntrinsic(Intrinsic::stackguard, {});
 }
 
@@ -561,23 +587,23 @@ static bool CreatePrologue(Function *F, Module *M, 
Instruction *CheckLoc,
   PointerType *PtrTy = PointerType::getUnqual(CheckLoc->getContext());
   AI = B.CreateAlloca(PtrTy, nullptr, "StackGuardSlot");
 
-  Value *GuardSlot = getStackGuard(TLI, M, B, &SupportsSelectionDAGSP);
+  Value *GuardSlot = getStackGuard(*TLI, M, B, &SupportsSelectionDAGSP);
   B.CreateIntrinsic(Intrinsic::stackprotector, {GuardSlot, AI});
   return SupportsSelectionDAGSP;
 }
 
-bool InsertStackProtectors(const TargetMachine *TM, Function *F,
+bool InsertStackProtectors(const TargetLowering &TLI,
+                           const LibcallLoweringInfo &Libcalls, Function *F,
                            DomTreeUpdater *DTU, bool &HasPrologue,
                            bool &HasIRCheck) {
   auto *M = F->getParent();
-  auto *TLI = TM->getSubtargetImpl(*F)->getTargetLowering();
 
   // If the target wants to XOR the frame pointer into the guard value, it's
   // impossible to emit the check in IR, so the target *must* support stack
   // protection in SDAG.
   bool SupportsSelectionDAGSP =
-      TLI->useStackGuardXorFP() ||
-      (EnableSelectionDAGSP && !TM->Options.EnableFastISel);
+      TLI.useStackGuardXorFP() ||
+      (EnableSelectionDAGSP && !TLI.getTargetMachine().Options.EnableFastISel);
   AllocaInst *AI = nullptr; // Place on stack that stores the stack guard.
   BasicBlock *FailBB = nullptr;
 
@@ -610,7 +636,7 @@ bool InsertStackProtectors(const TargetMachine *TM, 
Function *F,
     // Generate prologue instrumentation if not already generated.
     if (!HasPrologue) {
       HasPrologue = true;
-      SupportsSelectionDAGSP &= CreatePrologue(F, M, CheckLoc, TLI, AI);
+      SupportsSelectionDAGSP &= CreatePrologue(F, M, CheckLoc, &TLI, AI);
     }
 
     // SelectionDAG based code generation. Nothing else needs to be done here.
@@ -635,13 +661,13 @@ bool InsertStackProtectors(const TargetMachine *TM, 
Function *F,
     // inserted before the call rather than between it and the return.
     Instruction *Prev = CheckLoc->getPrevNode();
     if (auto *CI = dyn_cast_if_present<CallInst>(Prev))
-      if (CI->isTailCall() && isInTailCallPosition(*CI, *TM))
+      if (CI->isTailCall() && isInTailCallPosition(*CI, 
TLI.getTargetMachine()))
         CheckLoc = Prev;
 
     // Generate epilogue instrumentation. The epilogue intrumentation can be
     // function-based or inlined depending on which mechanism the target is
     // providing.
-    if (Function *GuardCheck = TLI->getSSPStackGuardCheck(*M)) {
+    if (Function *GuardCheck = TLI.getSSPStackGuardCheck(*M)) {
       // Generate the function-based epilogue instrumentation.
       // The target provides a guard check function, generate a call to it.
       IRBuilder<> B(CheckLoc);
@@ -680,7 +706,7 @@ bool InsertStackProtectors(const TargetMachine *TM, 
Function *F,
       // merge pass will merge together all of the various BB into one 
including
       // fail BB generated by the stack protector pseudo instruction.
       if (!FailBB)
-        FailBB = CreateFailBB(F, *TLI);
+        FailBB = CreateFailBB(F, Libcalls);
 
       IRBuilder<> B(CheckLoc);
       Value *Guard = getStackGuard(TLI, M, B);
@@ -713,7 +739,7 @@ bool InsertStackProtectors(const TargetMachine *TM, 
Function *F,
   return HasPrologue;
 }
 
-BasicBlock *CreateFailBB(Function *F, const TargetLowering &TLI) {
+BasicBlock *CreateFailBB(Function *F, const LibcallLoweringInfo &Libcalls) {
   auto *M = F->getParent();
   LLVMContext &Context = F->getContext();
   BasicBlock *FailBB = BasicBlock::Create(Context, "CallStackCheckFailBlk", F);
@@ -724,14 +750,16 @@ BasicBlock *CreateFailBB(Function *F, const 
TargetLowering &TLI) {
   FunctionCallee StackChkFail;
   SmallVector<Value *, 1> Args;
 
-  if (const char *ChkFailName =
-          TLI.getLibcallName(RTLIB::STACKPROTECTOR_CHECK_FAIL)) {
-    StackChkFail =
-        M->getOrInsertFunction(ChkFailName, Type::getVoidTy(Context));
-  } else if (const char *SSHName =
-                 TLI.getLibcallName(RTLIB::STACK_SMASH_HANDLER)) {
-    StackChkFail = M->getOrInsertFunction(SSHName, Type::getVoidTy(Context),
-                                          PointerType::getUnqual(Context));
+  if (RTLIB::LibcallImpl ChkFailImpl =
+          Libcalls.getLibcallImpl(RTLIB::STACKPROTECTOR_CHECK_FAIL)) {
+    StackChkFail = M->getOrInsertFunction(
+        RTLIB::RuntimeLibcallsInfo::getLibcallImplName(ChkFailImpl),
+        Type::getVoidTy(Context));
+  } else if (RTLIB::LibcallImpl SSHImpl =
+                 Libcalls.getLibcallImpl(RTLIB::STACK_SMASH_HANDLER)) {
+    StackChkFail = M->getOrInsertFunction(
+        RTLIB::RuntimeLibcallsInfo::getLibcallImplName(SSHImpl),
+        Type::getVoidTy(Context), PointerType::getUnqual(Context));
     Args.push_back(B.CreateGlobalString(F->getName(), "SSH"));
   } else {
     Context.emitError("no libcall available for stack protector");
diff --git a/llvm/test/CodeGen/NVPTX/no-stack-protector-libcall-error.ll 
b/llvm/test/CodeGen/NVPTX/no-stack-protector-libcall-error.ll
index f877d95dd3769..69f3c2945064e 100644
--- a/llvm/test/CodeGen/NVPTX/no-stack-protector-libcall-error.ll
+++ b/llvm/test/CodeGen/NVPTX/no-stack-protector-libcall-error.ll
@@ -1,4 +1,4 @@
-; RUN: not opt -disable-output -mtriple=nvptx64-- -enable-selectiondag-sp=0 
-passes=stack-protector %s 2>&1 | FileCheck %s
+; RUN: not opt -disable-output -mtriple=nvptx64-- -enable-selectiondag-sp=0 
-passes='require<libcall-lowering-info>,stack-protector' %s 2>&1 | FileCheck %s
 
 ; CHECK: error: no libcall available for stack protector
 define void @func() sspreq nounwind {
diff --git a/llvm/test/CodeGen/X86/stack-protector-atomicrmw-xchg.ll 
b/llvm/test/CodeGen/X86/stack-protector-atomicrmw-xchg.ll
index 486cb4cfa509d..7eb809c927b93 100644
--- a/llvm/test/CodeGen/X86/stack-protector-atomicrmw-xchg.ll
+++ b/llvm/test/CodeGen/X86/stack-protector-atomicrmw-xchg.ll
@@ -1,6 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 
UTC_ARGS: --version 5
-; RUN: opt -S -mtriple=x86_64-unknown-linux-gnu -passes=stack-protector < %s | 
FileCheck %s
-; RUN: opt -S -mtriple=x86_64-unknown-linux-gnu 
-passes='require<domtree>,stack-protector' < %s | FileCheck %s
+; RUN: opt -S -mtriple=x86_64-unknown-linux-gnu 
-passes='require<libcall-lowering-info>,stack-protector' < %s | FileCheck %s
+; RUN: opt -S -mtriple=x86_64-unknown-linux-gnu 
-passes='require<libcall-lowering-info>,function(require<domtree>,stack-protector)'
 < %s | FileCheck %s
 
 define void @atomicrmw_xchg(ptr %p) sspstrong {
 ; CHECK-LABEL: define void @atomicrmw_xchg(
diff --git 
a/llvm/test/Transforms/StackProtector/cross-dso-cfi-stack-chk-fail.ll 
b/llvm/test/Transforms/StackProtector/cross-dso-cfi-stack-chk-fail.ll
index 9a102768b1277..53b109914ebf7 100644
--- a/llvm/test/Transforms/StackProtector/cross-dso-cfi-stack-chk-fail.ll
+++ b/llvm/test/Transforms/StackProtector/cross-dso-cfi-stack-chk-fail.ll
@@ -1,7 +1,7 @@
 ;; This is a minimal reproducer that caused StackProtector to crash with a bad 
cast when
 ;; CrossDSOCFI is used. This test just needs to not crash.
 ; REQUIRES: x86-registered-target
-; RUN: opt -mtriple=x86_64-pc-linux-gnu %s 
-passes=lowertypetests,cross-dso-cfi,stack-protector
+; RUN: opt -mtriple=x86_64-pc-linux-gnu %s 
-passes='require<libcall-lowering-info>,lowertypetests,cross-dso-cfi,stack-protector'
 
 define hidden void @__stack_chk_fail() !type !1{
   unreachable
diff --git a/llvm/test/Transforms/StackProtector/missing-analysis.ll 
b/llvm/test/Transforms/StackProtector/missing-analysis.ll
new file mode 100644
index 0000000000000..a9f86edb22783
--- /dev/null
+++ b/llvm/test/Transforms/StackProtector/missing-analysis.ll
@@ -0,0 +1,7 @@
+; REQUIRES: x86-registered-target
+; RUN: not opt -mtriple=x86_64-- -passes=expand-fp -disable-output %s 2>&1 | 
FileCheck %s
+
+; CHECK: 'LibcallLoweringModuleAnalysis' analysis required
+define void @empty() {
+  ret void
+}
diff --git a/llvm/test/Transforms/StackProtector/stack-chk-fail-alias.ll 
b/llvm/test/Transforms/StackProtector/stack-chk-fail-alias.ll
index def3e014797de..4b1d8919b5499 100644
--- a/llvm/test/Transforms/StackProtector/stack-chk-fail-alias.ll
+++ b/llvm/test/Transforms/StackProtector/stack-chk-fail-alias.ll
@@ -1,6 +1,6 @@
 ;; __stack_chk_fail should have the noreturn attr even if it is an alias
 ; REQUIRES: x86-registered-target
-; RUN: opt -mtriple=x86_64-pc-linux-gnu %s -passes=stack-protector -S | 
FileCheck %s
+; RUN: opt -mtriple=x86_64-pc-linux-gnu %s 
-passes='require<libcall-lowering-info>,stack-protector' -S | FileCheck %s
 
 define hidden void @__stack_chk_fail_impl() {
   unreachable

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to