diff --git a/llvm/include/llvm/Analysis/StackSafetyAnalysis.h b/llvm/include/llvm/Analysis/StackSafetyAnalysis.h --- a/llvm/include/llvm/Analysis/StackSafetyAnalysis.h +++ b/llvm/include/llvm/Analysis/StackSafetyAnalysis.h @@ -15,6 +15,7 @@ #include "llvm/IR/PassManager.h" #include "llvm/Pass.h" +#include "llvm/IR/Instructions.h" namespace llvm { @@ -35,6 +36,8 @@ // TODO: Add useful for client methods. void print(raw_ostream &O) const; + bool isSafe(const AllocaInst *AI) const; + uint64_t getSizeOf(const AllocaInst *AI) const; }; /// StackSafetyInfo wrapper for the new pass manager. diff --git a/llvm/lib/Analysis/StackSafetyAnalysis.cpp b/llvm/lib/Analysis/StackSafetyAnalysis.cpp --- a/llvm/lib/Analysis/StackSafetyAnalysis.cpp +++ b/llvm/lib/Analysis/StackSafetyAnalysis.cpp @@ -146,7 +146,7 @@ // May be a Function or a GlobalAlias const GlobalValue *GV = nullptr; // Informations about allocas uses. - SmallVector Allocas; + DenseMap Allocas; // Informations about parameters uses. SmallVector Params; // TODO: describe return value as depending on one or more of its arguments. @@ -178,7 +178,7 @@ O << " " << P << "\n"; O << " allocas uses:\n"; for (auto &AS : Allocas) - O << " " << AS << "\n"; + O << " " << AS.second << "\n"; } private: @@ -372,9 +372,10 @@ for (auto &I : instructions(F)) { if (auto AI = dyn_cast(&I)) { - Info.Allocas.emplace_back(PointerSize, AI, - getStaticAllocaAllocationSize(AI)); - AllocaInfo &AS = Info.Allocas.back(); + auto inserted = Info.Allocas.insert(std::make_pair( + AI, AllocaInfo{PointerSize, AI, getStaticAllocaAllocationSize(AI)})); + // Obtain the AllocaInfo + AllocaInfo &AS = inserted.first->second; analyzeAllUses(AI, AS.Use); } } @@ -481,7 +482,7 @@ bool UpdateToFullSet = FS.UpdateCount > StackSafetyMaxIterations; bool Changed = false; for (auto &AS : FS.Allocas) - Changed |= updateOneUse(AS.Use, UpdateToFullSet); + Changed |= updateOneUse(AS.second.Use, UpdateToFullSet); for (auto &PS : FS.Params) Changed |= updateOneUse(PS.Use, UpdateToFullSet); @@ -506,7 +507,7 @@ Callees.clear(); StackSafetyInfo::FunctionInfo &FS = F.second; for (auto &AS : FS.Allocas) - for (auto &CS : AS.Use.Calls) + for (auto &CS : AS.second.Use.Calls) Callees.push_back(CS.Callee); for (auto &PS : FS.Params) for (auto &CS : PS.Use.Calls) @@ -575,6 +576,28 @@ void StackSafetyInfo::print(raw_ostream &O) const { Info->print(O); } +bool StackSafetyInfo::isSafe(const AllocaInst *AI) const { + auto iter = Info->Allocas.find(AI); + assert(iter != Info->Allocas.end() && "The specified AllocaInst is not a part of this function"); + + auto &UI = iter->second.Use; + if (UI.Range.isFullSet()) // FullSet indicates that the analysis cannot prove the safety of the alloca + return false; + else if (UI.Range.getLower().getLimitedValue() < 0) + return false; + else if (UI.Range.getUpper().getLimitedValue() > iter->second.Size) + return false; + return true; +} + +uint64_t StackSafetyInfo::getSizeOf(const AllocaInst *AI) const { + auto iter = Info->Allocas.find(AI); + assert(iter != Info->Allocas.end() && + "The specified AllocaInst is not a part of this function"); + + return iter->second.Size; +} + AnalysisKey StackSafetyAnalysis::Key; StackSafetyInfo StackSafetyAnalysis::run(Function &F,