Lines Matching +full:auto +full:- +full:range
1 //===- StackSafetyAnalysis.cpp - Stack memory safety analysis -------------===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 //===----------------------------------------------------------------------===//
38 #define DEBUG_TYPE "stack-safety"
58 STATISTIC(NumIndexCalleeMultipleWeak, "Number of index callee non-unique weak.");
59 STATISTIC(NumIndexCalleeMultipleExternal, "Number of index callee non-unique external.");
62 static cl::opt<int> StackSafetyMaxIterations("stack-safety-max-iterations",
65 static cl::opt<bool> StackSafetyPrint("stack-safety-print", cl::init(false),
68 static cl::opt<bool> StackSafetyRun("stack-safety-run", cl::init(false),
92 auto Result = L.unionWith(R);
93 // Two non-wrapped sets can produce wrapped.
118 // Access range if the address (alloca or parameters).
119 // It is allowed to be empty-set when there are no known accesses.
120 ConstantRange Range;
124 // Value is offset range of address from base address (alloca or calling
125 // function argument). Range should never set to empty-set, that is an invalid
126 // access range that can cause empty-set to be propagated with
132 UseInfo(unsigned PointerSize) : Range{PointerSize, false} {}
134 void updateRange(const ConstantRange &R) { Range = unionNoWrap(Range, R); }
144 OS << U.Range;
145 for (auto &Call : U.Calls)
147 << "@" << Call.first.Callee->getName() << "(arg" << Call.first.ParamNo
152 /// Calculate the allocation size of a given alloca. Returns empty range
158 // Fallback to empty range for alloca size.
166 const auto *C = dyn_cast<ConstantInt>(AI.getArraySize());
170 APInt Mul = C->getValue();
194 O << " @" << Name << ((F && F->isDSOLocal()) ? "" : " dso_preemptable")
195 << ((F && F->isInterposable()) ? " interposable" : "") << "\n";
198 for (auto &KV : Params) {
201 O << F->getArg(KV.first)->getName();
209 for (const auto &I : instructions(F)) {
211 auto &AS = Allocas.find(AI)->second;
212 O << " " << AI->getName() << "["
280 Type *ValTy = Val->getType();
283 if (!ValTy->isPointerTy()) {
284 auto *PtrTy = PointerType::getUnqual(SE.getContext());
288 if (ValTy->getPointerAddressSpace() != 0)
294 if (!SE.isSCEVable(Addr->getType()) || !SE.isSCEVable(Base->getType()))
315 // Zero-size loads and stores do not access memory.
343 if (const auto *MTI = dyn_cast<MemTransferInst>(MI)) {
344 if (MTI->getRawSource() != U && MTI->getRawDest() != U)
347 if (MI->getRawDest() != U)
351 auto *CalculationTy = IntegerType::getIntNTy(SE.getContext(), PointerSize);
352 if (!SE.isSCEVable(MI->getLength()->getType()))
356 SE.getTruncateOrZeroExtend(SE.getSCEV(MI->getLength()), CalculationTy);
361 ConstantRange SizeRange(APInt::getZero(PointerSize), Sizes.getUpper() - 1);
374 auto *CalculationTy = IntegerType::getIntNTy(SE.getContext(), PointerSize);
387 const auto *I = cast<Instruction>(U.getUser());
398 auto Size = getStaticAllocaSizeRange(*AI);
400 auto *CalculationTy = IntegerType::getIntNTy(SE.getContext(), PointerSize);
401 auto ToDiffTy = [&](const SCEV *V) {
414 /// calculates local access range and all function calls where it was used.
426 for (const Use &UI : V->uses()) {
427 const auto *I = cast<Instruction>(UI.getUser());
433 auto RecordStore = [&](const Value* StoredVal) {
435 // Stored the pointer - conservatively assume it may be unsafe.
443 auto TypeSize = DL.getTypeStoreSize(StoredVal->getType());
444 auto AccessRange = getAccessRange(UI, Ptr, TypeSize);
450 switch (I->getOpcode()) {
456 auto TypeSize = DL.getTypeStoreSize(I->getType());
457 auto AccessRange = getAccessRange(UI, Ptr, TypeSize);
464 // "va-arg" from a pointer is safe.
467 RecordStore(cast<StoreInst>(I)->getValueOperand());
470 RecordStore(cast<AtomicCmpXchgInst>(I)->getNewValOperand());
473 RecordStore(cast<AtomicRMWInst>(I)->getValOperand());
485 if (I->isLifetimeStartOrEnd())
493 auto AccessRange = getMemIntrinsicAccessRange(MI, UI, Ptr);
495 if (const auto *MTI = dyn_cast<MemTransferInst>(MI)) {
496 if (MTI->getRawSource() != UI && MTI->getRawDest() != UI)
498 } else if (MI->getRawDest() != UI) {
501 Safe = Safe || isSafeAccess(UI, AI, MI->getLength());
506 const auto &CB = cast<CallBase>(*I);
519 auto TypeSize = DL.getTypeStoreSize(CB.getParamByValType(ArgNo));
520 auto AccessRange = getAccessRange(UI, Ptr, TypeSize);
530 dyn_cast<GlobalValue>(CB.getCalledOperand()->stripPointerCasts());
538 auto Insert =
541 Insert.first->second = Insert.first->second.unionWith(Offsets);
561 for (auto &I : instructions(F))
562 if (auto *AI = dyn_cast<AllocaInst>(&I))
567 for (auto *AI : Allocas) {
568 auto &UI = Info.Allocas.emplace(AI, PointerSize).first->second;
575 if (A.getType()->isPointerTy() && !A.hasByValAttr()) {
576 auto &UI = Info.Params.emplace(A.getArgNo(), PointerSize).first->second;
592 // Callee-to-Caller multimap.
599 updateOneNode(Callee, Functions.find(Callee)->second);
602 for (auto &F : Functions)
625 auto FnIt = Functions.find(Callee);
629 auto &FS = FnIt->second;
630 auto ParamIt = FS.Params.find(ParamNo);
633 auto &Access = ParamIt->second.Range;
645 for (auto &KV : US.Calls) {
647 "Param range can't be empty-set, invalid offset range");
651 if (!US.Range.contains(CalleeRange)) {
654 US.Range = UnknownRange;
667 for (auto &KV : FS.Params)
672 << (UpdateToFullSet ? ", full-set" : "") << "] " << &FS
675 for (auto &CallerID : Callers[Callee])
685 for (auto &F : Functions) {
687 auto &FS = F.second;
688 for (auto &KV : FS.Params)
689 for (auto &CS : KV.second.Calls)
695 for (auto &Callee : Callees)
727 auto SummaryList = VI.getSummaryList();
729 for (const auto& GVS : SummaryList) {
730 if (!GVS->isLive())
733 if (!AS->hasAliasee())
735 if (!isa<FunctionSummary>(GVS->getBaseObject()))
737 if (GlobalValue::isLocalLinkage(GVS->linkage())) {
738 if (GVS->modulePath() == ModuleId) {
742 } else if (GlobalValue::isExternalLinkage(GVS->linkage())) {
748 } else if (GlobalValue::isWeakLinkage(GVS->linkage())) {
754 } else if (GlobalValue::isAvailableExternallyLinkage(GVS->linkage()) ||
755 GlobalValue::isLinkOnceLinkage(GVS->linkage())) {
764 if (!S->isLive() || !S->isDSOLocal())
769 if (!AS || !AS->hasAliasee())
771 S = AS->getBaseObject();
780 if (GV->isDeclaration() || GV->isInterposable() || !GV->isDSOLocal())
787 GV = A->getAliaseeObject();
798 for (const auto &PS : FS.paramAccesses())
806 ConstantRange FullSet(Use.Range.getBitWidth(), true);
807 // Move Use.Calls to a temp storage and repopulate - don't use std::move as it
811 for (const auto &C : TmpCalls) {
821 findCalleeFunctionSummary(Index->getValueInfo(C.first.Callee->getGUID()),
822 C.first.Callee->getParent()->getModuleIdentifier());
829 if (!Found || Found->isFullSet())
831 ConstantRange Access = Found->sextOrTrunc(Use.Range.getBitWidth());
845 auto Copy = Functions;
847 for (auto &FnKV : Copy)
848 for (auto &KV : FnKV.second.Params) {
850 if (KV.second.Range.isFullSet())
855 Copy.begin()->first->getDataLayout().getPointerSizeInBits();
858 for (const auto &F : SSDFA.run()) {
859 auto FI = F.second;
860 auto &SrcF = Functions[F.first];
861 for (auto &KV : FI.Allocas) {
862 auto &A = KV.second;
864 for (auto &C : A.Calls) {
869 A.Calls = SrcF.Allocas.find(KV.first)->second.Calls;
871 for (auto &KV : FI.Params) {
872 auto &P = KV.second;
873 P.Calls = SrcF.Params.find(KV.first)->second.Calls;
904 getInfo().Info.print(O, F->getName(), dyn_cast<Function>(F));
911 for (auto &F : M->functions()) {
913 auto FI = GetSSI(F).getInfo().Info;
920 for (auto &FnKV : Info->Info) {
921 for (auto &KV : FnKV.second.Allocas) {
924 auto AIRange = getStaticAllocaSizeRange(*AI);
925 if (AIRange.contains(KV.second.Range)) {
926 Info->SafeAllocas.insert(AI);
929 Info->UnsafeAccesses.insert(KV.second.UnsafeAccesses.begin(),
945 for (const auto &KV : getInfo().Info.Params) {
946 auto &PS = KV.second;
950 if (PS.Range.isFullSet())
953 ParamAccesses.emplace_back(KV.first, PS.Range);
957 for (const auto &C : PS.Calls) {
959 // will make ParamAccess::Range as FullSet anyway. So we can drop the
999 const auto &Info = getInfo();
1004 const auto &Info = getInfo();
1009 auto &SSI = getInfo().Info;
1012 const Module &M = *SSI.begin()->first->getParent();
1013 for (const auto &F : M.functions()) {
1015 SSI.find(&F)->second.print(O, F.getName(), &F);
1018 for (const auto &I : instructions(F)) {
1022 (Call && Call->hasByValArgument())) &&
1038 return StackSafetyInfo(&F, [&AM, &F]() -> ScalarEvolution & {
1066 auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
1067 SSI = {&F, [SE]() -> ScalarEvolution & { return *SE; }};
1079 [&FAM](Function &F) -> const StackSafetyInfo & {
1115 if (auto *IndexWrapperPass =
1117 ImportSummary = IndexWrapperPass->getIndex();
1120 [this](Function &F) -> const StackSafetyInfo & {
1130 for (const auto &F : M.functions())
1141 auto CountParamAccesses = [&](auto &Stat) {
1144 for (auto &GVS : Index)
1145 for (auto &GV : GVS.second.SummaryList)
1147 Stat += FS->paramAccesses().size();
1155 for (auto &GVS : Index) {
1156 for (auto &GV : GVS.second.SummaryList) {
1158 if (!FS || FS->paramAccesses().empty())
1160 if (FS->isLive() && FS->isDSOLocal()) {
1162 for (const auto &PS : FS->paramAccesses()) {
1163 auto &US =
1166 .first->second;
1167 US.Range = PS.Use;
1168 for (const auto &Call : PS.Calls) {
1171 findCalleeFunctionSummary(Call.Callee, FS->modulePath());
1175 US.Range = FullSet;
1188 FS->setParamAccesses({});
1194 for (const auto &KV : SSDFA.run()) {
1197 for (const auto &Param : KV.second.Params) {
1199 if (Param.second.Range.isFullSet())
1204 New.Use = Param.second.Range; // Only range is needed.
1206 const_cast<FunctionSummary *>(KV.first)->setParamAccesses(
1213 static const char LocalPassArg[] = "stack-safety-local";