14#include "llvm/ADT/STLExtras.h"
15#include "llvm/Support/Error.h"
16#include "llvm/Support/ErrorHandling.h"
24 : LU(
std::move(LU)) {}
29 enum class State { Unvisited, Visiting, Visited };
31 std::map<AnalysisName, State> Marks;
32 std::vector<AnalysisName> Path;
33 std::vector<std::unique_ptr<AnalysisBase>>
Result;
35 explicit Visitor(
size_t N) {
40 std::string formatCycle(
const AnalysisName &CycleEntry)
const {
41 auto CycleBegin = llvm::find(Path, CycleEntry);
43 llvm::raw_string_ostream OS(Cycle);
44 llvm::interleave(llvm::make_range(CycleBegin, Path.end()), OS,
" -> ");
45 OS <<
" -> " << CycleEntry;
49 llvm::Error visit(
const AnalysisName &Name) {
50 auto [It, _] = Marks.emplace(Name, State::Unvisited);
54 return llvm::Error::success();
58 "cycle detected: {0}", formatCycle(Name))
61 case State::Unvisited: {
62 It->second = State::Visiting;
65 llvm::Expected<std::unique_ptr<AnalysisBase>>
V =
73 std::unique_ptr<AnalysisBase> Analysis = std::move(*
V);
75 for (
const auto &Dep : Analysis->dependencyNames()) {
76 if (
auto Err = visit(Dep)) {
83 It->second = State::Visited;
85 Result.push_back(std::move(Analysis));
87 return llvm::Error::success();
90 llvm_unreachable(
"unhandled State");
94 Visitor
V(Roots.size());
95 for (
const auto &Root : Roots) {
96 if (
auto Err =
V.visit(Root)) {
97 return std::move(Err);
100 return std::move(
V.Result);
106 auto DataIt = LU->Data.find(SN);
107 if (DataIt == LU->Data.end()) {
109 "no data for analysis '{0}' in LUSummary",
114 if (
auto Err = Summary.initialize()) {
118 for (
auto &[Id, EntitySummary] : DataIt->second) {
119 if (
auto Err = Summary.add(Id, *EntitySummary)) {
124 if (
auto Err = Summary.finalize()) {
128 return llvm::Error::success();
133 std::map<AnalysisName, const AnalysisResult *> DepMap;
136 auto It = Suite.Data.find(DepName);
137 if (It == Suite.Data.end()) {
139 "dependency graph is not topologically sorted",
142 DepMap[DepName] = It->second.get();
145 if (
auto Err = Derived.initialize(DepMap)) {
150 auto StepOrErr = Derived.step();
152 return StepOrErr.takeError();
159 if (
auto Err = Derived.finalize()) {
163 return llvm::Error::success();
166llvm::Expected<WPASuite> AnalysisDriver::execute(
168 llvm::ArrayRef<std::unique_ptr<AnalysisBase>> Sorted)
const {
170 Suite.IdTable = std::move(IdTable);
172 for (
auto &Analysis : Sorted) {
173 switch (Analysis->TheKind) {
174 case AnalysisBase::Kind::Summary: {
175 SummaryAnalysisBase &SA =
static_cast<SummaryAnalysisBase &
>(*Analysis);
176 if (
auto Err = executeSummaryAnalysis(SA, Suite)) {
177 return std::move(Err);
181 case AnalysisBase::Kind::Derived: {
182 DerivedAnalysisBase &DA =
static_cast<DerivedAnalysisBase &
>(*Analysis);
183 if (
auto Err = executeDerivedAnalysis(DA, Suite)) {
184 return std::move(Err);
189 AnalysisName Name = Analysis->analysisName();
190 Suite.Data.emplace(std::move(Name), std::move(*Analysis).result());
193 return std::move(Suite);
198 if (!ExpectedSorted) {
199 return ExpectedSorted.takeError();
201 return execute(std::move(LU->IdTable), *ExpectedSorted);
206 auto ExpectedSorted = toposort(Names);
207 if (!ExpectedSorted) {
208 return ExpectedSorted.takeError();
211 return execute(LU->IdTable, *ExpectedSorted);
virtual AnalysisName analysisName() const =0
Name of this analysis.
virtual const std::vector< AnalysisName > & dependencyNames() const =0
AnalysisNames of all AnalysisResult dependencies.
llvm::Expected< WPASuite > run() const
Type-safe variant of run(names).
AnalysisDriver(std::unique_ptr< LUSummary > LU)
Uniquely identifies a whole-program analysis and the AnalysisResult it produces.
static const std::vector< AnalysisName > & names()
Returns the names of all registered analyses.
static llvm::Expected< std::unique_ptr< AnalysisBase > > instantiate(const AnalysisName &Name)
Instantiates the analysis registered under Name, or returns an error if no such analysis is registere...
Type-erased base for derived analyses.
Manages entity name interning and provides efficient EntityId handles.
static ErrorBuilder create(std::error_code EC, const char *Fmt, Args &&...ArgVals)
Create an ErrorBuilder with an error code and formatted message.
static void fatal(const char *Fmt, Args &&...ArgVals)
Report a fatal error with formatted message and terminate execution.
llvm::Error build() const
Build and return the final error.
Type-erased base for summary analyses.
virtual SummaryName summaryName() const =0
SummaryName of the EntitySummary type this analysis consumes.
Bundles the EntityIdTable (moved from the LUSummary) and the analysis results produced by one Analysi...
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.