llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-llvm-globalisel Author: Matt Arsenault (arsenm) <details> <summary>Changes</summary> --- Full diff: https://github.com/llvm/llvm-project/pull/170329.diff 6 Files Affected: - (modified) llvm/lib/CodeGen/StackProtector.cpp (+55-27) - (modified) llvm/test/CodeGen/NVPTX/no-stack-protector-libcall-error.ll (+1-1) - (modified) llvm/test/CodeGen/X86/stack-protector-atomicrmw-xchg.ll (+2-2) - (modified) llvm/test/Transforms/StackProtector/cross-dso-cfi-stack-chk-fail.ll (+1-1) - (added) llvm/test/Transforms/StackProtector/missing-analysis.ll (+7) - (modified) llvm/test/Transforms/StackProtector/stack-chk-fail-alias.ll (+1-1) ``````````diff 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 `````````` </details> https://github.com/llvm/llvm-project/pull/170329 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
