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
681template <
typename CalleeTy>
682void StackSafetyDataFlowAnalysis<CalleeTy>::runDataFlow() {
684 for (
auto &
F : Functions) {
687 for (
auto &KV :
FS.Params)
688 for (
auto &CS : KV.second.Calls)
694 for (
auto &Callee : Callees)
695 Callers[
Callee].push_back(
F.first);
700 while (!WorkList.
empty()) {
702 updateOneNode(Callee);
707template <
typename CalleeTy>
708void StackSafetyDataFlowAnalysis<CalleeTy>::verifyFixedPoint() {
715template <
typename CalleeTy>
716const typename StackSafetyDataFlowAnalysis<CalleeTy>::FunctionMap &
717StackSafetyDataFlowAnalysis<CalleeTy>::run() {
726 auto SummaryList =
VI.getSummaryList();
728 for (
const auto& GVS : SummaryList) {
731 if (
const AliasSummary *AS = dyn_cast<AliasSummary>(GVS.get()))
732 if (!AS->hasAliasee())
734 if (!isa<FunctionSummary>(GVS->getBaseObject()))
737 if (GVS->modulePath() == ModuleId) {
743 ++NumIndexCalleeMultipleExternal;
749 ++NumIndexCalleeMultipleWeak;
755 if (SummaryList.size() == 1)
759 ++NumIndexCalleeUnhandled;
781 if (
const Function *
F = dyn_cast<Function>(GV))
786 GV =
A->getAliaseeObject();
797 for (
const auto &PS :
FS.paramAccesses())
798 if (ParamNo == PS.ParamNo)
803void resolveAllCalls(UseInfo<GlobalValue> &
Use,
808 UseInfo<GlobalValue>::CallsTy TmpCalls;
810 for (
const auto &
C : TmpCalls) {
811 const Function *
F = findCalleeInModule(
C.first.Callee);
818 return Use.updateRange(FullSet);
820 findCalleeFunctionSummary(
Index->getValueInfo(
C.first.Callee->getGUID()),
821 C.first.Callee->getParent()->getModuleIdentifier());
822 ++NumModuleCalleeLookupTotal;
824 ++NumModuleCalleeLookupFailed;
825 return Use.updateRange(FullSet);
827 const ConstantRange *Found = findParamAccess(*FS,
C.first.ParamNo);
829 return Use.updateRange(FullSet);
832 Use.updateRange(addOverflowNever(
Access,
C.second));
836GVToSSI createGlobalStackSafetyInfo(
837 std::map<
const GlobalValue *, FunctionInfo<GlobalValue>> Functions,
840 if (Functions.empty())
844 auto Copy = Functions;
846 for (
auto &FnKV : Copy)
847 for (
auto &KV : FnKV.second.Params) {
848 resolveAllCalls(KV.second, Index);
849 if (KV.second.Range.isFullSet())
850 KV.second.Calls.clear();
854 Copy.begin()->first->getDataLayout().getPointerSizeInBits();
855 StackSafetyDataFlowAnalysis<GlobalValue> SSDFA(PointerSize, std::move(Copy));
857 for (
const auto &
F : SSDFA.run()) {
859 auto &SrcF = Functions[
F.first];
860 for (
auto &KV : FI.Allocas) {
862 resolveAllCalls(
A, Index);
863 for (
auto &
C :
A.Calls) {
864 A.updateRange(SSDFA.getArgumentAccessRange(
C.first.Callee,
865 C.first.ParamNo,
C.second));
868 A.Calls = SrcF.Allocas.find(KV.first)->second.Calls;
870 for (
auto &KV : FI.Params) {
872 P.Calls = SrcF.Params.find(KV.first)->second.Calls;
874 SSI[
F.first] = std::move(FI);
886 :
F(
F), GetSE(GetSE) {}
896 StackSafetyLocalAnalysis SSLA(*
F, GetSE());
903 getInfo().
Info.print(O,
F->getName(), dyn_cast<Function>(
F));
909 std::map<const GlobalValue *, FunctionInfo<GlobalValue>> Functions;
911 if (!
F.isDeclaration()) {
912 auto FI = GetSSI(
F).getInfo().Info;
913 Functions.emplace(&
F, std::move(FI));
916 Info.reset(
new InfoTy{
917 createGlobalStackSafetyInfo(std::move(Functions), Index), {}, {}});
919 for (
auto &FnKV :
Info->Info) {
920 for (
auto &KV : FnKV.second.Allocas) {
923 auto AIRange = getStaticAllocaSizeRange(*AI);
924 if (AIRange.contains(KV.second.Range)) {
925 Info->SafeAllocas.insert(AI);
926 ++NumAllocaStackSafe;
928 Info->UnsafeAccesses.insert(KV.second.UnsafeAccesses.begin(),
929 KV.second.UnsafeAccesses.end());
939std::vector<FunctionSummary::ParamAccess>
943 std::vector<FunctionSummary::ParamAccess> ParamAccesses;
945 auto &PS = KV.second;
949 if (PS.Range.isFullSet())
952 ParamAccesses.emplace_back(KV.first, PS.Range);
955 Param.Calls.reserve(PS.Calls.size());
956 for (
const auto &
C : PS.Calls) {
961 if (
C.second.isFullSet()) {
962 ParamAccesses.pop_back();
965 Param.Calls.emplace_back(
C.first.ParamNo,
966 Index.getOrInsertValueInfo(
C.first.Callee),
973 return std::tie(L.ParamNo, L.Callee) < std::tie(R.ParamNo, R.Callee);
976 return ParamAccesses;
984 : M(M), GetSSI(GetSSI), Index(Index) {
998 const auto &
Info = getInfo();
999 return Info.SafeAllocas.count(&AI);
1003 const auto &
Info = getInfo();
1004 return Info.UnsafeAccesses.find(&
I) ==
Info.UnsafeAccesses.end();
1008 auto &SSI = getInfo().
Info;
1011 const Module &M = *SSI.begin()->first->getParent();
1012 for (
const auto &
F : M.functions()) {
1013 if (!
F.isDeclaration()) {
1014 SSI.find(&
F)->second.print(O,
F.getName(), &
F);
1015 O <<
" safe accesses:"
1018 const CallInst *Call = dyn_cast<CallInst>(&
I);
1019 if ((isa<StoreInst>(
I) || isa<LoadInst>(
I) || isa<MemIntrinsic>(
I) ||
1020 isa<AtomicCmpXchgInst>(
I) || isa<AtomicRMWInst>(
I) ||
1021 (Call && Call->hasByValArgument())) &&
1023 O <<
" " <<
I <<
"\n";
1044 OS <<
"'Stack Safety Local Analysis' for function '" <<
F.getName() <<
"'\n";
1063 auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
1084 OS <<
"'Stack Safety Analysis' for module '" << M.getName() <<
"'\n";
1109 if (
auto *IndexWrapperPass =
1110 getAnalysisIfAvailable<ImmutableModuleSummaryIndexWrapperPass>())
1111 ImportSummary = IndexWrapperPass->getIndex();
1115 return getAnalysis<StackSafetyInfoWrapperPass>(
F).getResult();
1124 for (
const auto &
F : M.functions())
1125 if (
F.hasFnAttribute(Attribute::SanitizeMemTag))
1131 if (!Index.hasParamAccess())
1135 auto CountParamAccesses = [&](
auto &Stat) {
1138 for (
auto &GVS : Index)
1139 for (
auto &GV : GVS.second.SummaryList)
1141 Stat += FS->paramAccesses().size();
1144 CountParamAccesses(NumCombinedParamAccessesBefore);
1146 std::map<const FunctionSummary *, FunctionInfo<FunctionSummary>> Functions;
1149 for (
auto &GVS : Index) {
1150 for (
auto &GV : GVS.second.SummaryList) {
1152 if (!FS || FS->paramAccesses().empty())
1154 if (FS->isLive() && FS->isDSOLocal()) {
1155 FunctionInfo<FunctionSummary> FI;
1156 for (
const auto &PS : FS->paramAccesses()) {
1162 for (
const auto &Call : PS.Calls) {
1163 assert(!Call.Offsets.isFullSet());
1165 findCalleeFunctionSummary(Call.Callee, FS->modulePath());
1166 ++NumCombinedCalleeLookupTotal;
1168 ++NumCombinedCalleeLookupFailed;
1177 Functions.emplace(FS, std::move(FI));
1182 FS->setParamAccesses({});
1185 NumCombinedDataFlowNodes += Functions.size();
1186 StackSafetyDataFlowAnalysis<FunctionSummary> SSDFA(
1188 for (
const auto &KV : SSDFA.run()) {
1189 std::vector<FunctionSummary::ParamAccess> NewParams;
1190 NewParams.reserve(KV.second.Params.size());
1191 for (
const auto &Param : KV.second.Params) {
1193 if (Param.second.Range.isFullSet())
1195 NewParams.emplace_back();
1197 New.ParamNo = Param.first;
1198 New.Use = Param.second.Range;
1201 std::move(NewParams));
1204 CountParamAccesses(NumCombinedParamAccessesAfter);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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)
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.
LLVM_ABI 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.
LLVM_ABI bool isFullSet() const
Return true if this set contains all of the elements possible for this data-type.
LLVM_ABI bool isEmptySet() const
Return true if this set contains no members.
LLVM_ABI 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)
LLVM_ABI 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)
LLVM_ABI 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...
LLVM_ABI 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()
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 insert_range(Range &&R)
void clear()
Completely clear the SetVector.
bool empty() const
Determine if the SetVector is empty or not.
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.
LLVM_ABI 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.
LLVM_ABI 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.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
void generateParamAccessSummary(ModuleSummaryIndex &Index)
bool needsParamAccessSummary(const Module &M)
auto unique(Range &&R, Predicate P)
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI bool AreStatisticsEnabled()
Check if statistics are enabled.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
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.