@@ -33,8 +33,6 @@ static cl::opt<int> StackSafetyMaxIterations("stack-safety-max-iterations",
3333
3434namespace {
3535
36- using GVToSSI = StackSafetyGlobalInfo::GVToSSI;
37-
3836// / Rewrite an SCEV expression for a memory access address to an expression that
3937// / represents offset from the given alloca.
4038class AllocaOffsetRewriter : public SCEVRewriteVisitor <AllocaOffsetRewriter> {
@@ -178,15 +176,17 @@ struct FunctionInfo {
178176 }
179177};
180178
179+ using GVToSSI = std::map<const GlobalValue *, FunctionInfo>;
180+
181181} // namespace
182182
183183struct StackSafetyInfo ::InfoTy {
184184 FunctionInfo Info;
185185};
186186
187- StackSafetyInfo makeSSI (FunctionInfo Info) {
188- return StackSafetyInfo (StackSafetyInfo::InfoTy{ std::move ( Info)}) ;
189- }
187+ struct StackSafetyGlobalInfo ::InfoTy {
188+ GVToSSI Info;
189+ };
190190
191191namespace {
192192
@@ -430,17 +430,10 @@ class StackSafetyDataFlowAnalysis {
430430 void verifyFixedPoint ();
431431#endif
432432
433- uint32_t findPointerWidth () const {
434- for (auto &F : Functions)
435- for (auto &P : F.second .Params )
436- return P.Range .getBitWidth ();
437- return 1 ;
438- }
439-
440433public:
441- explicit StackSafetyDataFlowAnalysis (FunctionMap Functions)
434+ StackSafetyDataFlowAnalysis (uint32_t PointerBitWidth, FunctionMap Functions)
442435 : Functions(std::move(Functions)),
443- UnknownRange(ConstantRange::getFull(findPointerWidth() )) {}
436+ UnknownRange (ConstantRange::getFull(PointerBitWidth )) {}
444437
445438 const FunctionMap &run ();
446439
@@ -560,7 +553,7 @@ bool setStackSafetyMetadata(Module &M, const GVToSSI &SSGI) {
560553 auto Iter = SSGI.find (&F);
561554 if (Iter == SSGI.end ())
562555 continue ;
563- const FunctionInfo &Summary = Iter->second . getInfo (). Info ;
556+ const FunctionInfo &Summary = Iter->second ;
564557 size_t Pos = 0 ;
565558 for (auto &I : instructions (F)) {
566559 if (auto AI = dyn_cast<AllocaInst>(&I)) {
@@ -623,57 +616,103 @@ GVToSSI createGlobalStackSafetyInfo(
623616 for (auto &FI : Copy)
624617 ResolveAllCalls (FI.second .Params );
625618
626- StackSafetyDataFlowAnalysis SSDFA (std::move (Copy));
619+ uint32_t PointerSize = Copy.begin ()
620+ ->first ->getParent ()
621+ ->getDataLayout ()
622+ .getMaxPointerSizeInBits ();
623+ StackSafetyDataFlowAnalysis SSDFA (PointerSize, std::move (Copy));
627624
628625 for (auto &F : SSDFA.run ()) {
629626 auto FI = F.second ;
630627 size_t Pos = 0 ;
628+ auto &SrcF = Functions[F.first ];
631629 for (auto &A : FI.Allocas ) {
632630 ResolveAllCalls (A);
633631 for (auto &C : A.Calls ) {
634632 A.updateRange (
635633 SSDFA.getArgumentAccessRange (C.Callee , C.ParamNo , C.Offset ));
636634 }
637635 // FIXME: This is needed only to preserve calls in print() results.
638- A.Calls = Functions[F. first ] .Allocas [Pos].Calls ;
636+ A.Calls = SrcF .Allocas [Pos].Calls ;
639637 ++Pos;
640638 }
641639 Pos = 0 ;
642640 for (auto &P : FI.Params ) {
643- P.Calls = Functions[F. first ] .Params [Pos].Calls ;
641+ P.Calls = SrcF .Params [Pos].Calls ;
644642 ++Pos;
645643 }
646- SSI. emplace ( F.first , makeSSI ( std::move (FI)) );
644+ SSI[ F.first ] = std::move (FI);
647645 }
648646
649647 return SSI;
650648}
651649
652650} // end anonymous namespace
653651
652+ StackSafetyInfo::StackSafetyInfo () = default;
653+
654+ StackSafetyInfo::StackSafetyInfo (Function *F,
655+ std::function<ScalarEvolution &()> GetSE)
656+ : F(F), GetSE(GetSE) {}
657+
654658StackSafetyInfo::StackSafetyInfo (StackSafetyInfo &&) = default;
655- StackSafetyInfo &StackSafetyInfo::operator =(StackSafetyInfo &&) = default ;
656659
657- StackSafetyInfo::StackSafetyInfo (InfoTy Info)
658- : Info(new InfoTy(std::move(Info))) {}
660+ StackSafetyInfo &StackSafetyInfo::operator =(StackSafetyInfo &&) = default ;
659661
660662StackSafetyInfo::~StackSafetyInfo () = default ;
661663
662- void StackSafetyInfo::print (raw_ostream &O, const GlobalValue &F) const {
663- Info->Info .print (O, F.getName (), dyn_cast<Function>(&F));
664+ const StackSafetyInfo::InfoTy &StackSafetyInfo::getInfo () const {
665+ if (!Info) {
666+ StackSafetyLocalAnalysis SSLA (*F, GetSE ());
667+ Info.reset (new InfoTy{SSLA.run ()});
668+ }
669+ return *Info;
670+ }
671+
672+ void StackSafetyInfo::print (raw_ostream &O) const {
673+ getInfo ().Info .print (O, F->getName (), dyn_cast<Function>(F));
674+ }
675+
676+ const StackSafetyGlobalInfo::InfoTy &StackSafetyGlobalInfo::getInfo () const {
677+ if (!Info) {
678+ std::map<const GlobalValue *, FunctionInfo> Functions;
679+ for (auto &F : M->functions ()) {
680+ if (!F.isDeclaration ()) {
681+ auto FI = GetSSI (F).getInfo ().Info ;
682+ Functions.emplace (&F, std::move (FI));
683+ }
684+ }
685+ Info.reset (new InfoTy{createGlobalStackSafetyInfo (std::move (Functions))});
686+ }
687+ return *Info;
664688}
665689
690+ StackSafetyGlobalInfo::StackSafetyGlobalInfo () = default;
691+
692+ StackSafetyGlobalInfo::StackSafetyGlobalInfo (
693+ Module *M, std::function<const StackSafetyInfo &(Function &F)> GetSSI)
694+ : M(M), GetSSI(GetSSI) {}
695+
696+ StackSafetyGlobalInfo::StackSafetyGlobalInfo (StackSafetyGlobalInfo &&) =
697+ default;
698+
699+ StackSafetyGlobalInfo &
700+ StackSafetyGlobalInfo::operator =(StackSafetyGlobalInfo &&) = default ;
701+
702+ StackSafetyGlobalInfo::~StackSafetyGlobalInfo () = default ;
703+
666704bool StackSafetyGlobalInfo::setMetadata (Module &M) const {
667- return setStackSafetyMetadata (M, SSGI );
705+ return setStackSafetyMetadata (M, getInfo (). Info );
668706}
669707
670708void StackSafetyGlobalInfo::print (raw_ostream &O) const {
671- if (SSGI.empty ())
709+ auto &SSI = getInfo ().Info ;
710+ if (SSI.empty ())
672711 return ;
673- const Module &M = *SSGI .begin ()->first ->getParent ();
712+ const Module &M = *SSI .begin ()->first ->getParent ();
674713 for (auto &F : M.functions ()) {
675714 if (!F.isDeclaration ()) {
676- SSGI .find (&F)->second .print (O, F);
715+ SSI .find (&F)->second .print (O, F. getName (), & F);
677716 O << " \n " ;
678717 }
679718 }
@@ -685,14 +724,15 @@ AnalysisKey StackSafetyAnalysis::Key;
685724
686725StackSafetyInfo StackSafetyAnalysis::run (Function &F,
687726 FunctionAnalysisManager &AM) {
688- StackSafetyLocalAnalysis SSLA (F, AM.getResult <ScalarEvolutionAnalysis>(F));
689- return makeSSI (SSLA.run ());
727+ return StackSafetyInfo (&F, [&AM, &F]() -> ScalarEvolution & {
728+ return AM.getResult <ScalarEvolutionAnalysis>(F);
729+ });
690730}
691731
692732PreservedAnalyses StackSafetyPrinterPass::run (Function &F,
693733 FunctionAnalysisManager &AM) {
694734 OS << " 'Stack Safety Local Analysis' for function '" << F.getName () << " '\n " ;
695- AM.getResult <StackSafetyAnalysis>(F).print (OS, F );
735+ AM.getResult <StackSafetyAnalysis>(F).print (OS);
696736 return PreservedAnalyses::all ();
697737}
698738
@@ -703,19 +743,17 @@ StackSafetyInfoWrapperPass::StackSafetyInfoWrapperPass() : FunctionPass(ID) {
703743}
704744
705745void StackSafetyInfoWrapperPass::getAnalysisUsage (AnalysisUsage &AU) const {
706- AU.addRequired <ScalarEvolutionWrapperPass>();
746+ AU.addRequiredTransitive <ScalarEvolutionWrapperPass>();
707747 AU.setPreservesAll ();
708748}
709749
710750void StackSafetyInfoWrapperPass::print (raw_ostream &O, const Module *M) const {
711- SSI-> print (O, *F );
751+ SSI. print (O);
712752}
713753
714754bool StackSafetyInfoWrapperPass::runOnFunction (Function &F) {
715- StackSafetyLocalAnalysis SSLA (
716- F, getAnalysis<ScalarEvolutionWrapperPass>().getSE ());
717- SSI = makeSSI (SSLA.run ());
718- this ->F = &F;
755+ auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE ();
756+ SSI = {&F, [SE]() -> ScalarEvolution & { return *SE; }};
719757 return false ;
720758}
721759
@@ -725,18 +763,9 @@ StackSafetyGlobalInfo
725763StackSafetyGlobalAnalysis::run (Module &M, ModuleAnalysisManager &AM) {
726764 FunctionAnalysisManager &FAM =
727765 AM.getResult <FunctionAnalysisManagerModuleProxy>(M).getManager ();
728-
729- // FIXME: Lookup Module Summary.
730- std::map<const GlobalValue *, FunctionInfo> Functions;
731-
732- for (auto &F : M.functions ()) {
733- if (!F.isDeclaration ()) {
734- auto FI = FAM.getResult <StackSafetyAnalysis>(F).getInfo ().Info ;
735- Functions.emplace (&F, std::move (FI));
736- }
737- }
738-
739- return createGlobalStackSafetyInfo (std::move (Functions));
766+ return {&M, [&FAM](Function &F) -> const StackSafetyInfo & {
767+ return FAM.getResult <StackSafetyAnalysis>(F);
768+ }};
740769}
741770
742771PreservedAnalyses StackSafetyGlobalPrinterPass::run (Module &M,
@@ -761,6 +790,8 @@ StackSafetyGlobalInfoWrapperPass::StackSafetyGlobalInfoWrapperPass()
761790 *PassRegistry::getPassRegistry ());
762791}
763792
793+ StackSafetyGlobalInfoWrapperPass::~StackSafetyGlobalInfoWrapperPass () = default ;
794+
764795void StackSafetyGlobalInfoWrapperPass::print (raw_ostream &O,
765796 const Module *M) const {
766797 SSGI.print (O);
@@ -772,16 +803,9 @@ void StackSafetyGlobalInfoWrapperPass::getAnalysisUsage(
772803}
773804
774805bool StackSafetyGlobalInfoWrapperPass::runOnModule (Module &M) {
775- std::map<const GlobalValue *, FunctionInfo> Functions;
776- for (auto &F : M.functions ()) {
777- if (!F.isDeclaration ()) {
778- auto FI =
779- getAnalysis<StackSafetyInfoWrapperPass>(F).getResult ().getInfo ().Info ;
780- Functions.emplace (&F, std::move (FI));
781- }
782- }
783-
784- SSGI = createGlobalStackSafetyInfo (std::move (Functions));
806+ SSGI = {&M, [this ](Function &F) -> const StackSafetyInfo & {
807+ return getAnalysis<StackSafetyInfoWrapperPass>(F).getResult ();
808+ }};
785809 return SSGI.setMetadata (M);
786810}
787811
0 commit comments