StackProtector: Use LibcallLoweringInfo analysis
diff --git a/llvm/lib/CodeGen/StackProtector.cpp b/llvm/lib/CodeGen/StackProtector.cpp
index 971c3e5..2fef484 100644
--- a/llvm/lib/CodeGen/StackProtector.cpp
+++ b/llvm/lib/CodeGen/StackProtector.cpp
@@ -69,13 +69,15 @@
/// - 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 @@
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 @@
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 @@
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 @@
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 @@
/// 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 @@
// 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 @@
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->useStackGuardMixCookie() ||
- (EnableSelectionDAGSP && !TM->Options.EnableFastISel);
+ TLI.useStackGuardMixCookie() ||
+ (EnableSelectionDAGSP && !TLI.getTargetMachine().Options.EnableFastISel);
AllocaInst *AI = nullptr; // Place on stack that stores the stack guard.
BasicBlock *FailBB = nullptr;
@@ -610,7 +636,7 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
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 f877d95..69f3c29 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 486cb4c..7eb809c 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 9a10276..53b1099 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 0000000..41f8f31
--- /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=stack-protector -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: 'LibcallLoweringModuleAnalysis' analysis required
+define void @empty() sspreq {
+ 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 def3e01..4b1d891 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