38#define DEBUG_TYPE "stack-safety"
40STATISTIC(NumAllocaStackSafe,
"Number of safe allocas");
41STATISTIC(NumAllocaTotal,
"Number of total allocas");
44 "Number of total callee lookups on combined index.");
46 "Number of failed callee lookups on combined index.");
48 "Number of total callee lookups on module index.");
50 "Number of failed callee lookups on module index.");
52 "Number of total param accesses before generateParamAccessSummary.");
54 "Number of total param accesses after generateParamAccessSummary.");
56 "Number of total nodes in combined index for dataflow processing.");
57STATISTIC(NumIndexCalleeUnhandled,
"Number of index callee which are unhandled.");
58STATISTIC(NumIndexCalleeMultipleWeak,
"Number of index callee non-unique weak.");
59STATISTIC(NumIndexCalleeMultipleExternal,
"Number of index callee non-unique external.");
75 return R.isEmptySet() || R.isFullSet() || R.isUpperSignWrapped();
81 if (
L.signedAddMayOverflow(R) !=
82 ConstantRange::OverflowResult::NeverOverflows)
83 return ConstantRange::getFull(
L.getBitWidth());
94 if (
Result.isSignWrappedSet())
100template <
typename CalleeTy>
struct CallInfo {
102 const CalleeTy *
Callee =
nullptr;
106 CallInfo(
const CalleeTy *Callee,
size_t ParamNo)
111 return std::tie(
L.ParamNo,
L.Callee) < std::tie(
R.ParamNo,
R.Callee);
117template <
typename CalleeTy>
struct UseInfo {
121 std::set<const Instruction *> UnsafeAccesses;
137 UnsafeAccesses.insert(
I);
142template <
typename CalleeTy>
145 for (
auto &Call :
U.Calls)
147 <<
"@" <<
Call.first.Callee->getName() <<
"(arg" <<
Call.first.ParamNo
148 <<
", " <<
Call.second <<
")";
163 if (APSize.isNonPositive())
169 bool Overflow =
false;
171 if (
Mul.isNonPositive())
173 Mul =
Mul.sextOrTrunc(PointerSize);
174 APSize = APSize.smul_ov(
Mul, Overflow);
183template <
typename CalleeTy>
struct FunctionInfo {
184 std::map<const AllocaInst *, UseInfo<CalleeTy>> Allocas;
185 std::map<uint32_t, UseInfo<CalleeTy>> Params;
194 O <<
" @" <<
Name << ((
F &&
F->isDSOLocal()) ?
"" :
" dso_preemptable")
195 << ((
F &&
F->isInterposable()) ?
" interposable" :
"") <<
"\n";
197 O <<
" args uses:\n";
198 for (
auto &KV : Params) {
201 O <<
F->getArg(KV.first)->getName();
204 O <<
"[]: " << KV.second <<
"\n";
207 O <<
" allocas uses:\n";
210 if (
const AllocaInst *AI = dyn_cast<AllocaInst>(&
I)) {
211 auto &AS = Allocas.find(AI)->second;
213 << getStaticAllocaSizeRange(*AI).getUpper() <<
"]: " << AS <<
"\n";
222using GVToSSI = std::map<const GlobalValue *, FunctionInfo<GlobalValue>>;
227 FunctionInfo<GlobalValue>
Info;
238class StackSafetyLocalAnalysis {
242 unsigned PointerSize = 0;
252 const SCEV *getSCEVAsPointer(
Value *Val);
261 void analyzeAllUses(
Value *
Ptr, UseInfo<GlobalValue> &AS,
271 :
F(
F),
DL(
F.getDataLayout()), SE(SE),
272 PointerSize(
DL.getPointerSizeInBits()),
273 UnknownRange(PointerSize,
true) {}
276 FunctionInfo<GlobalValue> run();
279const SCEV *StackSafetyLocalAnalysis::getSCEVAsPointer(
Value *Val) {
284 auto *PtrTy = PointerType::getUnqual(SE.getContext());
285 return SE.getTruncateOrZeroExtend(SE.getSCEV(Val), PtrTy);
290 return SE.getSCEV(Val);
294 if (!SE.isSCEVable(
Addr->getType()) || !SE.isSCEVable(
Base->getType()))
297 const SCEV *AddrExp = getSCEVAsPointer(
Addr);
298 const SCEV *BaseExp = getSCEVAsPointer(
Base);
299 if (!AddrExp || !BaseExp)
302 const SCEV *Diff = SE.getMinusSCEV(AddrExp, BaseExp);
303 if (isa<SCEVCouldNotCompute>(Diff))
309 return Offset.sextOrTrunc(PointerSize);
317 return ConstantRange::getEmpty(PointerSize);
318 assert(!isUnsafe(SizeRange));
321 if (isUnsafe(Offsets))
324 Offsets = addOverflowNever(Offsets, SizeRange);
325 if (isUnsafe(Offsets))
332 if (
Size.isScalable())
334 APInt APSize(PointerSize,
Size.getFixedValue(),
true);
335 if (APSize.isNegative())
341ConstantRange StackSafetyLocalAnalysis::getMemIntrinsicAccessRange(
343 if (
const auto *MTI = dyn_cast<MemTransferInst>(
MI)) {
344 if (MTI->getRawSource() != U && MTI->getRawDest() != U)
345 return ConstantRange::getEmpty(PointerSize);
347 if (
MI->getRawDest() != U)
348 return ConstantRange::getEmpty(PointerSize);
351 auto *CalculationTy = IntegerType::getIntNTy(SE.getContext(), PointerSize);
352 if (!SE.isSCEVable(
MI->getLength()->getType()))
356 SE.getTruncateOrZeroExtend(SE.getSCEV(
MI->getLength()), CalculationTy);
358 if (!
Sizes.getUpper().isStrictlyPositive() || isUnsafe(Sizes))
362 return getAccessRange(U,
Base, SizeRange);
365bool StackSafetyLocalAnalysis::isSafeAccess(
const Use &U,
AllocaInst *AI,
367 return isSafeAccess(U, AI, SE.getSCEV(V));
370bool StackSafetyLocalAnalysis::isSafeAccess(
const Use &U,
AllocaInst *AI,
374 auto *CalculationTy = IntegerType::getIntNTy(SE.getContext(), PointerSize);
376 return isSafeAccess(U, AI, SV);
379bool StackSafetyLocalAnalysis::isSafeAccess(
const Use &U,
AllocaInst *AI,
380 const SCEV *AccessSize) {
384 if (isa<SCEVCouldNotCompute>(AccessSize))
387 const auto *
I = cast<Instruction>(
U.getUser());
389 const SCEV *AddrExp = getSCEVAsPointer(
U.get());
390 const SCEV *BaseExp = getSCEVAsPointer(AI);
391 if (!AddrExp || !BaseExp)
394 const SCEV *Diff = SE.getMinusSCEV(AddrExp, BaseExp);
395 if (isa<SCEVCouldNotCompute>(Diff))
398 auto Size = getStaticAllocaSizeRange(*AI);
400 auto *CalculationTy = IntegerType::getIntNTy(SE.getContext(), PointerSize);
401 auto ToDiffTy = [&](
const SCEV *
V) {
402 return SE.getTruncateOrZeroExtend(V, CalculationTy);
404 const SCEV *Min = ToDiffTy(SE.getConstant(
Size.getLower()));
405 const SCEV *
Max = SE.getMinusSCEV(ToDiffTy(SE.getConstant(
Size.getUpper())),
406 ToDiffTy(AccessSize));
407 return SE.evaluatePredicateAt(ICmpInst::Predicate::ICMP_SGE, Diff, Min,
I)
409 SE.evaluatePredicateAt(ICmpInst::Predicate::ICMP_SLE, Diff, Max,
I)
415void StackSafetyLocalAnalysis::analyzeAllUses(
Value *
Ptr,
416 UseInfo<GlobalValue> &US,
424 while (!WorkList.
empty()) {
426 for (
const Use &UI :
V->uses()) {
427 const auto *
I = cast<Instruction>(UI.getUser());
433 auto RecordStore = [&](
const Value* StoredVal) {
434 if (V == StoredVal) {
436 US.addRange(
I, UnknownRange,
false);
440 US.addRange(
I, UnknownRange,
false);
443 auto TypeSize =
DL.getTypeStoreSize(StoredVal->getType());
444 auto AccessRange = getAccessRange(UI,
Ptr,
TypeSize);
445 bool Safe = isSafeAccess(UI, AI,
TypeSize);
446 US.addRange(
I, AccessRange, Safe);
450 switch (
I->getOpcode()) {
451 case Instruction::Load: {
453 US.addRange(
I, UnknownRange,
false);
457 auto AccessRange = getAccessRange(UI,
Ptr,
TypeSize);
458 bool Safe = isSafeAccess(UI, AI,
TypeSize);
459 US.addRange(
I, AccessRange, Safe);
463 case Instruction::VAArg:
466 case Instruction::Store:
467 RecordStore(cast<StoreInst>(
I)->getValueOperand());
469 case Instruction::AtomicCmpXchg:
470 RecordStore(cast<AtomicCmpXchgInst>(
I)->getNewValOperand());
472 case Instruction::AtomicRMW:
473 RecordStore(cast<AtomicRMWInst>(
I)->getValOperand());
476 case Instruction::Ret:
480 US.addRange(
I, UnknownRange,
false);
483 case Instruction::Call:
484 case Instruction::Invoke: {
485 if (
I->isLifetimeStartOrEnd())
489 US.addRange(
I, UnknownRange,
false);
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());
502 US.addRange(
I, AccessRange, Safe);
506 const auto &CB = cast<CallBase>(*
I);
507 if (CB.getReturnedArgOperand() == V) {
509 WorkList.
push_back(cast<const Instruction>(
I));
512 if (!CB.isArgOperand(&UI)) {
513 US.addRange(
I, UnknownRange,
false);
517 unsigned ArgNo = CB.getArgOperandNo(&UI);
518 if (CB.isByValArgument(ArgNo)) {
519 auto TypeSize =
DL.getTypeStoreSize(CB.getParamByValType(ArgNo));
520 auto AccessRange = getAccessRange(UI,
Ptr,
TypeSize);
521 bool Safe = isSafeAccess(UI, AI,
TypeSize);
522 US.addRange(
I, AccessRange, Safe);
530 dyn_cast<GlobalValue>(CB.getCalledOperand()->stripPointerCasts());
531 if (!Callee || isa<GlobalIFunc>(Callee)) {
532 US.addRange(
I, UnknownRange,
false);
536 assert(isa<Function>(Callee) || isa<GlobalAlias>(Callee));
541 Insert.first->second =
Insert.first->second.unionWith(Offsets);
547 WorkList.
push_back(cast<const Instruction>(
I));
553FunctionInfo<GlobalValue> StackSafetyLocalAnalysis::run() {
554 FunctionInfo<GlobalValue>
Info;
556 "Can't run StackSafety on a function declaration");
562 if (
auto *AI = dyn_cast<AllocaInst>(&
I))
567 for (
auto *AI : Allocas) {
568 auto &UI =
Info.Allocas.emplace(AI, PointerSize).first->second;
569 analyzeAllUses(AI, UI, SL);
575 if (
A.getType()->isPointerTy() && !
A.hasByValAttr()) {
576 auto &UI =
Info.Params.emplace(
A.getArgNo(), PointerSize).first->second;
577 analyzeAllUses(&
A, UI, SL);
586template <
typename CalleeTy>
class StackSafetyDataFlowAnalysis {
587 using FunctionMap = std::map<const CalleeTy *, FunctionInfo<CalleeTy>>;
589 FunctionMap Functions;
596 bool updateOneUse(UseInfo<CalleeTy> &US,
bool UpdateToFullSet);
597 void updateOneNode(
const CalleeTy *Callee, FunctionInfo<CalleeTy> &FS);
598 void updateOneNode(
const CalleeTy *Callee) {
599 updateOneNode(Callee, Functions.find(Callee)->second);
601 void updateAllNodes() {
602 for (
auto &
F : Functions)
603 updateOneNode(
F.first,
F.second);
607 void verifyFixedPoint();
611 StackSafetyDataFlowAnalysis(
uint32_t PointerBitWidth, FunctionMap Functions)
612 : Functions(
std::
move(Functions)),
615 const FunctionMap &
run();
617 ConstantRange getArgumentAccessRange(
const CalleeTy *Callee,
unsigned ParamNo,
621template <
typename CalleeTy>
622ConstantRange StackSafetyDataFlowAnalysis<CalleeTy>::getArgumentAccessRange(
623 const CalleeTy *Callee,
unsigned ParamNo,
625 auto FnIt = Functions.find(Callee);
627 if (FnIt == Functions.end())
629 auto &
FS = FnIt->second;
630 auto ParamIt =
FS.Params.find(ParamNo);
631 if (ParamIt ==
FS.Params.end())
633 auto &
Access = ParamIt->second.Range;
638 return addOverflowNever(
Access, Offsets);
641template <
typename CalleeTy>
642bool StackSafetyDataFlowAnalysis<CalleeTy>::updateOneUse(UseInfo<CalleeTy> &US,
643 bool UpdateToFullSet) {
644 bool Changed =
false;
645 for (
auto &KV : US.Calls) {
646 assert(!KV.second.isEmptySet() &&
647 "Param range can't be empty-set, invalid offset range");
650 getArgumentAccessRange(KV.first.Callee, KV.first.ParamNo, KV.second);
651 if (!US.Range.contains(CalleeRange)) {
654 US.Range = UnknownRange;
656 US.updateRange(CalleeRange);
662template <
typename CalleeTy>
663void StackSafetyDataFlowAnalysis<CalleeTy>::updateOneNode(
664 const CalleeTy *Callee, FunctionInfo<CalleeTy> &FS) {
666 bool Changed =
false;
667 for (
auto &KV :
FS.Params)
668 Changed |= updateOneUse(KV.second, UpdateToFullSet);
672 << (UpdateToFullSet ?
", full-set" :
"") <<
"] " << &FS
675 for (
auto &CallerID : Callers[Callee])
676 WorkList.
insert(CallerID);
682template <
typename CalleeTy>
683void StackSafetyDataFlowAnalysis<CalleeTy>::runDataFlow() {
685 for (
auto &
F : Functions) {
688 for (
auto &KV :
FS.Params)
689 for (
auto &CS : KV.second.Calls)
695 for (
auto &Callee : Callees)
696 Callers[
Callee].push_back(
F.first);
701 while (!WorkList.
empty()) {
703 updateOneNode(Callee);
708template <
typename CalleeTy>
709void StackSafetyDataFlowAnalysis<CalleeTy>::verifyFixedPoint() {
716template <
typename CalleeTy>
717const typename StackSafetyDataFlowAnalysis<CalleeTy>::FunctionMap &
718StackSafetyDataFlowAnalysis<CalleeTy>::run() {
727 auto SummaryList =
VI.getSummaryList();
729 for (
const auto& GVS : SummaryList) {
732 if (
const AliasSummary *AS = dyn_cast<AliasSummary>(GVS.get()))
733 if (!AS->hasAliasee())
735 if (!isa<FunctionSummary>(GVS->getBaseObject()))
738 if (GVS->modulePath() == ModuleId) {
744 ++NumIndexCalleeMultipleExternal;
750 ++NumIndexCalleeMultipleWeak;
756 if (SummaryList.size() == 1)
760 ++NumIndexCalleeUnhandled;
782 if (
const Function *
F = dyn_cast<Function>(GV))
787 GV =
A->getAliaseeObject();
798 for (
const auto &PS :
FS.paramAccesses())
799 if (ParamNo == PS.ParamNo)
804void resolveAllCalls(UseInfo<GlobalValue> &
Use,
809 UseInfo<GlobalValue>::CallsTy TmpCalls;
811 for (
const auto &
C : TmpCalls) {
812 const Function *
F = findCalleeInModule(
C.first.Callee);
819 return Use.updateRange(FullSet);
821 findCalleeFunctionSummary(
Index->getValueInfo(
C.first.Callee->getGUID()),
822 C.first.Callee->getParent()->getModuleIdentifier());
823 ++NumModuleCalleeLookupTotal;
825 ++NumModuleCalleeLookupFailed;
826 return Use.updateRange(FullSet);
828 const ConstantRange *Found = findParamAccess(*FS,
C.first.ParamNo);
830 return Use.updateRange(FullSet);
833 Use.updateRange(addOverflowNever(
Access,
C.second));
837GVToSSI createGlobalStackSafetyInfo(
838 std::map<
const GlobalValue *, FunctionInfo<GlobalValue>> Functions,
841 if (Functions.empty())
845 auto Copy = Functions;
847 for (
auto &FnKV : Copy)
848 for (
auto &KV : FnKV.second.Params) {
849 resolveAllCalls(KV.second, Index);
850 if (KV.second.Range.isFullSet())
851 KV.second.Calls.clear();
855 Copy.begin()->first->getDataLayout().getPointerSizeInBits();
856 StackSafetyDataFlowAnalysis<GlobalValue> SSDFA(PointerSize, std::move(Copy));
858 for (
const auto &
F : SSDFA.run()) {
860 auto &SrcF = Functions[
F.first];
861 for (
auto &KV : FI.Allocas) {
863 resolveAllCalls(
A, Index);
864 for (
auto &
C :
A.Calls) {
865 A.updateRange(SSDFA.getArgumentAccessRange(
C.first.Callee,
866 C.first.ParamNo,
C.second));
869 A.Calls = SrcF.Allocas.find(KV.first)->second.Calls;
871 for (
auto &KV : FI.Params) {
873 P.Calls = SrcF.Params.find(KV.first)->second.Calls;
875 SSI[
F.first] = std::move(FI);
887 :
F(
F), GetSE(GetSE) {}
897 StackSafetyLocalAnalysis SSLA(*
F, GetSE());
904 getInfo().
Info.print(O,
F->getName(), dyn_cast<Function>(
F));
910 std::map<const GlobalValue *, FunctionInfo<GlobalValue>> Functions;
912 if (!
F.isDeclaration()) {
913 auto FI = GetSSI(
F).getInfo().Info;
914 Functions.emplace(&
F, std::move(FI));
917 Info.reset(
new InfoTy{
918 createGlobalStackSafetyInfo(std::move(Functions), Index), {}, {}});
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);
927 ++NumAllocaStackSafe;
929 Info->UnsafeAccesses.insert(KV.second.UnsafeAccesses.begin(),
930 KV.second.UnsafeAccesses.end());
940std::vector<FunctionSummary::ParamAccess>
944 std::vector<FunctionSummary::ParamAccess> ParamAccesses;
946 auto &PS = KV.second;
950 if (PS.Range.isFullSet())
953 ParamAccesses.emplace_back(KV.first, PS.Range);
956 Param.Calls.reserve(PS.Calls.size());
957 for (
const auto &
C : PS.Calls) {
962 if (
C.second.isFullSet()) {
963 ParamAccesses.pop_back();
966 Param.Calls.emplace_back(
C.first.ParamNo,
967 Index.getOrInsertValueInfo(
C.first.Callee),
974 return std::tie(L.ParamNo, L.Callee) < std::tie(R.ParamNo, R.Callee);
977 return ParamAccesses;
985 : M(M), GetSSI(GetSSI), Index(Index) {
999 const auto &
Info = getInfo();
1000 return Info.SafeAllocas.count(&AI);
1004 const auto &
Info = getInfo();
1005 return Info.UnsafeAccesses.find(&
I) ==
Info.UnsafeAccesses.end();
1009 auto &SSI = getInfo().
Info;
1012 const Module &M = *SSI.begin()->first->getParent();
1013 for (
const auto &
F : M.functions()) {
1014 if (!
F.isDeclaration()) {
1015 SSI.find(&
F)->second.print(O,
F.getName(), &
F);
1016 O <<
" safe accesses:"
1019 const CallInst *Call = dyn_cast<CallInst>(&
I);
1020 if ((isa<StoreInst>(
I) || isa<LoadInst>(
I) || isa<MemIntrinsic>(
I) ||
1021 isa<AtomicCmpXchgInst>(
I) || isa<AtomicRMWInst>(
I) ||
1022 (Call && Call->hasByValArgument())) &&
1024 O <<
" " <<
I <<
"\n";
1045 OS <<
"'Stack Safety Local Analysis' for function '" <<
F.getName() <<
"'\n";
1066 auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
1087 OS <<
"'Stack Safety Analysis' for module '" << M.getName() <<
"'\n";
1115 if (
auto *IndexWrapperPass =
1116 getAnalysisIfAvailable<ImmutableModuleSummaryIndexWrapperPass>())
1117 ImportSummary = IndexWrapperPass->getIndex();
1121 return getAnalysis<StackSafetyInfoWrapperPass>(
F).getResult();
1130 for (
const auto &
F : M.functions())
1131 if (
F.hasFnAttribute(Attribute::SanitizeMemTag))
1137 if (!Index.hasParamAccess())
1141 auto CountParamAccesses = [&](
auto &Stat) {
1144 for (
auto &GVS : Index)
1145 for (
auto &GV : GVS.second.SummaryList)
1147 Stat += FS->paramAccesses().size();
1150 CountParamAccesses(NumCombinedParamAccessesBefore);
1152 std::map<const FunctionSummary *, FunctionInfo<FunctionSummary>> Functions;
1155 for (
auto &GVS : Index) {
1156 for (
auto &GV : GVS.second.SummaryList) {
1158 if (!FS || FS->paramAccesses().empty())
1160 if (FS->isLive() && FS->isDSOLocal()) {
1161 FunctionInfo<FunctionSummary> FI;
1162 for (
const auto &PS : FS->paramAccesses()) {
1168 for (
const auto &Call : PS.Calls) {
1169 assert(!Call.Offsets.isFullSet());
1171 findCalleeFunctionSummary(Call.Callee, FS->modulePath());
1172 ++NumCombinedCalleeLookupTotal;
1174 ++NumCombinedCalleeLookupFailed;
1183 Functions.emplace(FS, std::move(FI));
1188 FS->setParamAccesses({});
1191 NumCombinedDataFlowNodes += Functions.size();
1192 StackSafetyDataFlowAnalysis<FunctionSummary> SSDFA(
1194 for (
const auto &KV : SSDFA.run()) {
1195 std::vector<FunctionSummary::ParamAccess> NewParams;
1196 NewParams.reserve(KV.second.Params.size());
1197 for (
const auto &Param : KV.second.Params) {
1199 if (Param.second.Range.isFullSet())
1201 NewParams.emplace_back();
1203 New.ParamNo = Param.first;
1204 New.Use = Param.second.Range;
1207 std::move(NewParams));
1210 CountParamAccesses(NumCombinedParamAccessesAfter);
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
Expand Atomic instructions
block Block Frequency Analysis
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Analysis containing CSE Info
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This is the interface to build a ModuleSummaryIndex for a module.
ModuleSummaryIndex.h This file contains the declarations the classes that hold the module index and s...
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
static const char LocalPassArg[]
static const char LocalPassName[]
static true const char GlobalPassName[]
static cl::opt< int > StackSafetyMaxIterations("stack-safety-max-iterations", cl::init(20), cl::Hidden)
static cl::opt< bool > StackSafetyRun("stack-safety-run", cl::init(false), cl::Hidden)
static cl::opt< bool > StackSafetyPrint("stack-safety-print", cl::init(false), cl::Hidden)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Class for arbitrary precision integers.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
Alias summary information.
an instruction to allocate memory on the stack
PointerType * getType() const
Overload to return most specific pointer type.
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
bool isArrayAllocation() const
Return true if there is an allocation size parameter to the allocation instruction that is not 1.
const Value * getArraySize() const
Get the number of elements allocated.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
AnalysisUsage & addRequiredTransitive()
This class represents an incoming formal argument to a Function.
This class represents a function call, abstracting a target machine's calling convention.
This class represents a range of values.
bool isFullSet() const
Return true if this set contains all of the elements possible for this data-type.
bool isEmptySet() const
Return true if this set contains no members.
ConstantRange sextOrTrunc(uint32_t BitWidth) const
Make this range have the bit width given by BitWidth.
A parsed version of the target data layout string in and methods for querying it.
FunctionPass class - This class is used to implement most global optimizations.
Function summary information to aid decisions and implementation of importing.
Function and variable summary information to aid decisions and implementation of importing.
GlobalValueSummary * getBaseObject()
If this is an alias summary, returns the summary of the aliased object (a global variable or function...
static bool isLocalLinkage(LinkageTypes Linkage)
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
static bool isLinkOnceLinkage(LinkageTypes Linkage)
static bool isAvailableExternallyLinkage(LinkageTypes Linkage)
static bool isExternalLinkage(LinkageTypes Linkage)
bool isInterposable() const
Return true if this global's definition can be substituted with an arbitrary definition at link time ...
static bool isWeakLinkage(LinkageTypes Linkage)
Legacy wrapper pass to provide the ModuleSummaryIndex object.
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
This is the common base class for memset/memcpy/memmove.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Class to hold module path string table and global value map, and encapsulate methods for operating on...
A Module instance is used to store all the information related to an LLVM module.
iterator_range< iterator > functions()
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
This class represents an analyzed expression in the program.
Analysis pass that exposes the ScalarEvolution for a function.
The main scalar evolution driver.
A vector that has set insertion semantics.
void clear()
Completely clear the SetVector.
bool empty() const
Determine if the SetVector is empty or not.
bool insert(const value_type &X)
Insert a new element into the SetVector.
value_type pop_back_val()
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
iterator erase(const_iterator CI)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Compute live ranges of allocas.
bool isReachable(const Instruction *I) const
Returns true if instruction is reachable from entry.
bool isAliveAfter(const AllocaInst *AI, const Instruction *I) const
Returns true if the alloca is alive after the instruction.
StackSafetyInfo wrapper for the new pass manager.
StackSafetyInfo run(Function &F, FunctionAnalysisManager &AM)
This pass performs the global (interprocedural) stack safety analysis (new pass manager).
Result run(Module &M, ModuleAnalysisManager &AM)
This pass performs the global (interprocedural) stack safety analysis (legacy pass manager).
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
StackSafetyGlobalInfoWrapperPass()
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
void print(raw_ostream &O, const Module *M) const override
print - Print out the internal state of the pass.
~StackSafetyGlobalInfoWrapperPass()
void print(raw_ostream &O) const
bool stackAccessIsSafe(const Instruction &I) const
bool isSafe(const AllocaInst &AI) const
StackSafetyGlobalInfo & operator=(StackSafetyGlobalInfo &&)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
StackSafetyInfo wrapper for the legacy pass manager.
void print(raw_ostream &O, const Module *M) const override
print - Print out the internal state of the pass.
bool runOnFunction(Function &F) override
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
StackSafetyInfoWrapperPass()
Interface to access stack safety analysis results for single function.
void print(raw_ostream &O) const
const InfoTy & getInfo() const
StackSafetyInfo & operator=(StackSafetyInfo &&)
std::vector< FunctionSummary::ParamAccess > getParamAccesses(ModuleSummaryIndex &Index) const
Parameters use for a FunctionSummary.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
StringRef - Represent a constant reference to a string, i.e.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isPointerTy() const
True if this is an instance of PointerType.
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
StringRef getName() const
Return a constant reference to the value's name.
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
This class implements an extremely fast bulk output stream that can only output to a stream.
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
constexpr uint64_t PointerSize
aarch64 pointer size.
This is an optimization pass for GlobalISel generic memory operations.
void generateParamAccessSummary(ModuleSummaryIndex &Index)
bool needsParamAccessSummary(const Module &M)
auto unique(Range &&R, Predicate P)
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr)
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool AreStatisticsEnabled()
Check if statistics are enabled.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void initializeStackSafetyGlobalInfoWrapperPassPass(PassRegistry &)
void initializeStackSafetyInfoWrapperPassPass(PassRegistry &)
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
std::set< const Instruction * > UnsafeAccesses
SmallPtrSet< const AllocaInst *, 8 > SafeAllocas
FunctionInfo< GlobalValue > Info
A special type used by analysis passes to provide an address that identifies that particular analysis...
Describes the use of a value in a call instruction, specifying the call's target, the value's paramet...
Describes the uses of a parameter by the function.
static constexpr uint32_t RangeWidth
Struct that holds a reference to a particular GUID in a global value summary.