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;
253 void analyzeAllUses(
Value *
Ptr, UseInfo<GlobalValue> &AS,
263 :
F(
F),
DL(
F.getParent()->getDataLayout()), SE(SE),
264 PointerSize(
DL.getPointerSizeInBits()),
265 UnknownRange(PointerSize,
true) {}
268 FunctionInfo<GlobalValue> run();
272 if (!SE.isSCEVable(
Addr->getType()) || !SE.isSCEVable(
Base->getType()))
275 auto *PtrTy = IntegerType::getInt8PtrTy(SE.getContext());
276 const SCEV *AddrExp = SE.getTruncateOrZeroExtend(SE.getSCEV(
Addr), PtrTy);
277 const SCEV *BaseExp = SE.getTruncateOrZeroExtend(SE.getSCEV(
Base), PtrTy);
278 const SCEV *Diff = SE.getMinusSCEV(AddrExp, BaseExp);
279 if (isa<SCEVCouldNotCompute>(Diff))
285 return Offset.sextOrTrunc(PointerSize);
293 return ConstantRange::getEmpty(PointerSize);
294 assert(!isUnsafe(SizeRange));
297 if (isUnsafe(Offsets))
300 Offsets = addOverflowNever(Offsets, SizeRange);
301 if (isUnsafe(Offsets))
308 if (
Size.isScalable())
310 APInt APSize(PointerSize,
Size.getFixedValue(),
true);
311 if (APSize.isNegative())
317ConstantRange StackSafetyLocalAnalysis::getMemIntrinsicAccessRange(
319 if (
const auto *MTI = dyn_cast<MemTransferInst>(
MI)) {
320 if (MTI->getRawSource() != U && MTI->getRawDest() != U)
321 return ConstantRange::getEmpty(PointerSize);
323 if (
MI->getRawDest() != U)
324 return ConstantRange::getEmpty(PointerSize);
327 auto *CalculationTy = IntegerType::getIntNTy(SE.getContext(), PointerSize);
328 if (!SE.isSCEVable(
MI->getLength()->getType()))
332 SE.getTruncateOrZeroExtend(SE.getSCEV(
MI->getLength()), CalculationTy);
334 if (
Sizes.getUpper().isNegative() || isUnsafe(Sizes))
338 return getAccessRange(U,
Base, SizeRange);
341bool StackSafetyLocalAnalysis::isSafeAccess(
const Use &U,
AllocaInst *AI,
343 return isSafeAccess(U, AI, SE.getSCEV(V));
346bool StackSafetyLocalAnalysis::isSafeAccess(
const Use &U,
AllocaInst *AI,
350 auto *CalculationTy = IntegerType::getIntNTy(SE.getContext(), PointerSize);
352 return isSafeAccess(U, AI, SV);
355bool StackSafetyLocalAnalysis::isSafeAccess(
const Use &U,
AllocaInst *AI,
356 const SCEV *AccessSize) {
360 if (isa<SCEVCouldNotCompute>(AccessSize))
363 const auto *
I = cast<Instruction>(
U.getUser());
365 auto ToCharPtr = [&](
const SCEV *
V) {
366 auto *PtrTy = IntegerType::getInt8PtrTy(SE.getContext());
367 return SE.getTruncateOrZeroExtend(V, PtrTy);
370 const SCEV *AddrExp = ToCharPtr(SE.getSCEV(
U.get()));
371 const SCEV *BaseExp = ToCharPtr(SE.getSCEV(AI));
372 const SCEV *Diff = SE.getMinusSCEV(AddrExp, BaseExp);
373 if (isa<SCEVCouldNotCompute>(Diff))
376 auto Size = getStaticAllocaSizeRange(*AI);
378 auto *CalculationTy = IntegerType::getIntNTy(SE.getContext(), PointerSize);
379 auto ToDiffTy = [&](
const SCEV *
V) {
380 return SE.getTruncateOrZeroExtend(V, CalculationTy);
382 const SCEV *Min = ToDiffTy(SE.getConstant(
Size.getLower()));
383 const SCEV *
Max = SE.getMinusSCEV(ToDiffTy(SE.getConstant(
Size.getUpper())),
384 ToDiffTy(AccessSize));
385 return SE.evaluatePredicateAt(ICmpInst::Predicate::ICMP_SGE, Diff, Min,
I)
387 SE.evaluatePredicateAt(ICmpInst::Predicate::ICMP_SLE, Diff, Max,
I)
393void StackSafetyLocalAnalysis::analyzeAllUses(
Value *
Ptr,
394 UseInfo<GlobalValue> &US,
402 while (!WorkList.
empty()) {
404 for (
const Use &UI :
V->uses()) {
405 const auto *
I = cast<Instruction>(UI.getUser());
411 auto RecordStore = [&](
const Value* StoredVal) {
412 if (V == StoredVal) {
414 US.addRange(
I, UnknownRange,
false);
418 US.addRange(
I, UnknownRange,
false);
421 auto TypeSize =
DL.getTypeStoreSize(StoredVal->getType());
422 auto AccessRange = getAccessRange(UI,
Ptr,
TypeSize);
423 bool Safe = isSafeAccess(UI, AI,
TypeSize);
424 US.addRange(
I, AccessRange, Safe);
428 switch (
I->getOpcode()) {
429 case Instruction::Load: {
431 US.addRange(
I, UnknownRange,
false);
435 auto AccessRange = getAccessRange(UI,
Ptr,
TypeSize);
436 bool Safe = isSafeAccess(UI, AI,
TypeSize);
437 US.addRange(
I, AccessRange, Safe);
441 case Instruction::VAArg:
444 case Instruction::Store:
445 RecordStore(cast<StoreInst>(
I)->getValueOperand());
447 case Instruction::AtomicCmpXchg:
448 RecordStore(cast<AtomicCmpXchgInst>(
I)->getNewValOperand());
450 case Instruction::AtomicRMW:
451 RecordStore(cast<AtomicRMWInst>(
I)->getValOperand());
454 case Instruction::Ret:
458 US.addRange(
I, UnknownRange,
false);
461 case Instruction::Call:
462 case Instruction::Invoke: {
463 if (
I->isLifetimeStartOrEnd())
467 US.addRange(
I, UnknownRange,
false);
471 auto AccessRange = getMemIntrinsicAccessRange(
MI, UI,
Ptr);
473 if (
const auto *MTI = dyn_cast<MemTransferInst>(
MI)) {
474 if (MTI->getRawSource() != UI && MTI->getRawDest() != UI)
476 }
else if (
MI->getRawDest() != UI) {
479 Safe = Safe || isSafeAccess(UI, AI,
MI->getLength());
480 US.addRange(
I, AccessRange, Safe);
484 const auto &CB = cast<CallBase>(*
I);
485 if (CB.getReturnedArgOperand() == V) {
487 WorkList.
push_back(cast<const Instruction>(
I));
490 if (!CB.isArgOperand(&UI)) {
491 US.addRange(
I, UnknownRange,
false);
495 unsigned ArgNo = CB.getArgOperandNo(&UI);
496 if (CB.isByValArgument(ArgNo)) {
497 auto TypeSize =
DL.getTypeStoreSize(CB.getParamByValType(ArgNo));
498 auto AccessRange = getAccessRange(UI,
Ptr,
TypeSize);
499 bool Safe = isSafeAccess(UI, AI,
TypeSize);
500 US.addRange(
I, AccessRange, Safe);
508 dyn_cast<GlobalValue>(CB.getCalledOperand()->stripPointerCasts());
510 US.addRange(
I, UnknownRange,
false);
514 assert(isa<Function>(Callee) || isa<GlobalAlias>(Callee));
519 Insert.first->second =
Insert.first->second.unionWith(Offsets);
525 WorkList.
push_back(cast<const Instruction>(
I));
531FunctionInfo<GlobalValue> StackSafetyLocalAnalysis::run() {
532 FunctionInfo<GlobalValue>
Info;
534 "Can't run StackSafety on a function declaration");
540 if (
auto *AI = dyn_cast<AllocaInst>(&
I))
545 for (
auto *AI : Allocas) {
546 auto &UI =
Info.Allocas.emplace(AI, PointerSize).first->second;
547 analyzeAllUses(AI, UI, SL);
553 if (
A.getType()->isPointerTy() && !
A.hasByValAttr()) {
554 auto &UI =
Info.Params.emplace(
A.getArgNo(), PointerSize).first->second;
555 analyzeAllUses(&
A, UI, SL);
564template <
typename CalleeTy>
class StackSafetyDataFlowAnalysis {
565 using FunctionMap = std::map<const CalleeTy *, FunctionInfo<CalleeTy>>;
567 FunctionMap Functions;
574 bool updateOneUse(UseInfo<CalleeTy> &US,
bool UpdateToFullSet);
575 void updateOneNode(
const CalleeTy *Callee, FunctionInfo<CalleeTy> &FS);
576 void updateOneNode(
const CalleeTy *Callee) {
577 updateOneNode(Callee, Functions.find(Callee)->second);
579 void updateAllNodes() {
580 for (
auto &
F : Functions)
581 updateOneNode(
F.first,
F.second);
585 void verifyFixedPoint();
589 StackSafetyDataFlowAnalysis(
uint32_t PointerBitWidth, FunctionMap Functions)
590 : Functions(
std::
move(Functions)),
593 const FunctionMap &
run();
595 ConstantRange getArgumentAccessRange(
const CalleeTy *Callee,
unsigned ParamNo,
599template <
typename CalleeTy>
600ConstantRange StackSafetyDataFlowAnalysis<CalleeTy>::getArgumentAccessRange(
601 const CalleeTy *Callee,
unsigned ParamNo,
603 auto FnIt = Functions.find(Callee);
605 if (FnIt == Functions.end())
607 auto &
FS = FnIt->second;
608 auto ParamIt =
FS.Params.find(ParamNo);
609 if (ParamIt ==
FS.Params.end())
611 auto &Access = ParamIt->second.Range;
612 if (Access.isEmptySet())
614 if (Access.isFullSet())
616 return addOverflowNever(Access, Offsets);
619template <
typename CalleeTy>
620bool StackSafetyDataFlowAnalysis<CalleeTy>::updateOneUse(UseInfo<CalleeTy> &US,
621 bool UpdateToFullSet) {
622 bool Changed =
false;
623 for (
auto &KV : US.Calls) {
624 assert(!KV.second.isEmptySet() &&
625 "Param range can't be empty-set, invalid offset range");
628 getArgumentAccessRange(KV.first.Callee, KV.first.ParamNo, KV.second);
629 if (!US.Range.contains(CalleeRange)) {
632 US.Range = UnknownRange;
634 US.updateRange(CalleeRange);
640template <
typename CalleeTy>
641void StackSafetyDataFlowAnalysis<CalleeTy>::updateOneNode(
642 const CalleeTy *Callee, FunctionInfo<CalleeTy> &FS) {
644 bool Changed =
false;
645 for (
auto &KV :
FS.Params)
646 Changed |= updateOneUse(KV.second, UpdateToFullSet);
650 << (UpdateToFullSet ?
", full-set" :
"") <<
"] " << &FS
653 for (
auto &CallerID : Callers[Callee])
654 WorkList.
insert(CallerID);
660template <
typename CalleeTy>
661void StackSafetyDataFlowAnalysis<CalleeTy>::runDataFlow() {
663 for (
auto &
F : Functions) {
666 for (
auto &KV :
FS.Params)
667 for (
auto &CS : KV.second.Calls)
673 for (
auto &Callee : Callees)
674 Callers[
Callee].push_back(
F.first);
679 while (!WorkList.
empty()) {
681 updateOneNode(Callee);
686template <
typename CalleeTy>
687void StackSafetyDataFlowAnalysis<CalleeTy>::verifyFixedPoint() {
694template <
typename CalleeTy>
695const typename StackSafetyDataFlowAnalysis<CalleeTy>::FunctionMap &
696StackSafetyDataFlowAnalysis<CalleeTy>::run() {
705 auto SummaryList =
VI.getSummaryList();
707 for (
const auto& GVS : SummaryList) {
710 if (
const AliasSummary *AS = dyn_cast<AliasSummary>(GVS.get()))
711 if (!AS->hasAliasee())
713 if (!isa<FunctionSummary>(GVS->getBaseObject()))
716 if (GVS->modulePath() == ModuleId) {
722 ++NumIndexCalleeMultipleExternal;
728 ++NumIndexCalleeMultipleWeak;
734 if (SummaryList.size() == 1)
738 ++NumIndexCalleeUnhandled;
760 if (
const Function *
F = dyn_cast<Function>(GV))
765 GV =
A->getAliaseeObject();
776 for (
const auto &PS :
FS.paramAccesses())
777 if (ParamNo == PS.ParamNo)
782void resolveAllCalls(UseInfo<GlobalValue> &
Use,
787 UseInfo<GlobalValue>::CallsTy TmpCalls;
789 for (
const auto &
C : TmpCalls) {
790 const Function *
F = findCalleeInModule(
C.first.Callee);
797 return Use.updateRange(FullSet);
799 findCalleeFunctionSummary(
Index->getValueInfo(
C.first.Callee->getGUID()),
800 C.first.Callee->getParent()->getModuleIdentifier());
801 ++NumModuleCalleeLookupTotal;
803 ++NumModuleCalleeLookupFailed;
804 return Use.updateRange(FullSet);
806 const ConstantRange *Found = findParamAccess(*FS,
C.first.ParamNo);
808 return Use.updateRange(FullSet);
811 Use.updateRange(addOverflowNever(Access,
C.second));
815GVToSSI createGlobalStackSafetyInfo(
816 std::map<
const GlobalValue *, FunctionInfo<GlobalValue>> Functions,
819 if (Functions.empty())
823 auto Copy = Functions;
825 for (
auto &FnKV : Copy)
826 for (
auto &KV : FnKV.second.Params) {
827 resolveAllCalls(KV.second,
Index);
828 if (KV.second.Range.isFullSet())
829 KV.second.Calls.clear();
833 Copy.begin()->first->getParent()->getDataLayout().getPointerSizeInBits();
834 StackSafetyDataFlowAnalysis<GlobalValue> SSDFA(PointerSize, std::move(Copy));
836 for (
const auto &
F : SSDFA.run()) {
838 auto &SrcF = Functions[
F.first];
839 for (
auto &KV : FI.Allocas) {
841 resolveAllCalls(
A,
Index);
842 for (
auto &
C :
A.Calls) {
843 A.updateRange(SSDFA.getArgumentAccessRange(
C.first.Callee,
844 C.first.ParamNo,
C.second));
847 A.Calls = SrcF.Allocas.find(KV.first)->second.Calls;
849 for (
auto &KV : FI.Params) {
851 P.Calls = SrcF.Params.find(KV.first)->second.Calls;
853 SSI[
F.first] = std::move(FI);
865 :
F(
F), GetSE(GetSE) {}
875 StackSafetyLocalAnalysis SSLA(*
F, GetSE());
882 getInfo().
Info.print(O,
F->getName(), dyn_cast<Function>(
F));
888 std::map<const GlobalValue *, FunctionInfo<GlobalValue>> Functions;
890 if (!
F.isDeclaration()) {
891 auto FI = GetSSI(
F).getInfo().Info;
892 Functions.emplace(&
F, std::move(FI));
895 Info.reset(
new InfoTy{
896 createGlobalStackSafetyInfo(std::move(Functions),
Index), {}, {}});
898 for (
auto &FnKV :
Info->Info) {
899 for (
auto &KV : FnKV.second.Allocas) {
902 auto AIRange = getStaticAllocaSizeRange(*AI);
903 if (AIRange.contains(KV.second.Range)) {
904 Info->SafeAllocas.insert(AI);
905 ++NumAllocaStackSafe;
907 Info->UnsafeAccesses.insert(KV.second.UnsafeAccesses.begin(),
908 KV.second.UnsafeAccesses.end());
918std::vector<FunctionSummary::ParamAccess>
922 std::vector<FunctionSummary::ParamAccess> ParamAccesses;
924 auto &PS = KV.second;
928 if (PS.Range.isFullSet())
931 ParamAccesses.emplace_back(KV.first, PS.Range);
934 Param.Calls.reserve(PS.Calls.size());
935 for (
const auto &
C : PS.Calls) {
940 if (
C.second.isFullSet()) {
941 ParamAccesses.pop_back();
944 Param.Calls.emplace_back(
C.first.ParamNo,
945 Index.getOrInsertValueInfo(
C.first.Callee),
952 return std::tie(L.ParamNo, L.Callee) < std::tie(R.ParamNo, R.Callee);
955 return ParamAccesses;
977 const auto &
Info = getInfo();
978 return Info.SafeAllocas.count(&AI);
982 const auto &
Info = getInfo();
983 return Info.UnsafeAccesses.find(&
I) ==
Info.UnsafeAccesses.end();
987 auto &SSI = getInfo().
Info;
990 const Module &M = *SSI.begin()->first->getParent();
991 for (
const auto &
F : M.functions()) {
992 if (!
F.isDeclaration()) {
993 SSI.find(&
F)->second.print(O,
F.getName(), &
F);
994 O <<
" safe accesses:"
997 const CallInst *Call = dyn_cast<CallInst>(&
I);
998 if ((isa<StoreInst>(
I) || isa<LoadInst>(
I) || isa<MemIntrinsic>(
I) ||
999 isa<AtomicCmpXchgInst>(
I) || isa<AtomicRMWInst>(
I) ||
1000 (Call && Call->hasByValArgument())) &&
1002 O <<
" " <<
I <<
"\n";
1023 OS <<
"'Stack Safety Local Analysis' for function '" <<
F.getName() <<
"'\n";
1044 auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
1065 OS <<
"'Stack Safety Analysis' for module '" << M.getName() <<
"'\n";
1093 if (
auto *IndexWrapperPass =
1094 getAnalysisIfAvailable<ImmutableModuleSummaryIndexWrapperPass>())
1095 ImportSummary = IndexWrapperPass->getIndex();
1099 return getAnalysis<StackSafetyInfoWrapperPass>(
F).getResult();
1108 for (
const auto &
F : M.functions())
1109 if (
F.hasFnAttribute(Attribute::SanitizeMemTag))
1115 if (!
Index.hasParamAccess())
1119 auto CountParamAccesses = [&](
auto &Stat) {
1122 for (
auto &GVS :
Index)
1123 for (
auto &GV : GVS.second.SummaryList)
1125 Stat += FS->paramAccesses().size();
1128 CountParamAccesses(NumCombinedParamAccessesBefore);
1130 std::map<const FunctionSummary *, FunctionInfo<FunctionSummary>> Functions;
1133 for (
auto &GVS :
Index) {
1134 for (
auto &GV : GVS.second.SummaryList) {
1136 if (!FS || FS->paramAccesses().empty())
1138 if (FS->isLive() && FS->isDSOLocal()) {
1139 FunctionInfo<FunctionSummary> FI;
1140 for (
const auto &PS : FS->paramAccesses()) {
1146 for (
const auto &Call : PS.Calls) {
1147 assert(!Call.Offsets.isFullSet());
1149 findCalleeFunctionSummary(Call.Callee, FS->modulePath());
1150 ++NumCombinedCalleeLookupTotal;
1152 ++NumCombinedCalleeLookupFailed;
1161 Functions.emplace(FS, std::move(FI));
1166 FS->setParamAccesses({});
1169 NumCombinedDataFlowNodes += Functions.size();
1170 StackSafetyDataFlowAnalysis<FunctionSummary> SSDFA(
1172 for (
const auto &KV : SSDFA.run()) {
1173 std::vector<FunctionSummary::ParamAccess> NewParams;
1174 NewParams.reserve(KV.second.Params.size());
1175 for (
const auto &Param : KV.second.Params) {
1177 if (Param.second.Range.isFullSet())
1179 NewParams.emplace_back();
1181 New.ParamNo = Param.first;
1182 New.Use = Param.second.Range;
1185 std::move(NewParams));
1188 CountParamAccesses(NumCombinedParamAccessesAfter);
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file implements a class to represent arbitrary precision integral constant values and operations...
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
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.
Select target instructions out of generic instructions
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...
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 Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
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()
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
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.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
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.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
void generateParamAccessSummary(ModuleSummaryIndex &Index)
bool needsParamAccessSummary(const Module &M)
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr)
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.