clang 24.0.0git
AnalysisDriver.cpp
Go to the documentation of this file.
1//===- AnalysisDriver.cpp -------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
14#include "llvm/ADT/STLExtras.h"
15#include "llvm/Support/Error.h"
16#include "llvm/Support/ErrorHandling.h"
17#include <map>
18#include <vector>
19
20using namespace clang;
21using namespace ssaf;
22
23AnalysisDriver::AnalysisDriver(std::unique_ptr<LUSummary> LU)
24 : LU(std::move(LU)) {}
25
27AnalysisDriver::toposort(llvm::ArrayRef<AnalysisName> Roots) {
28 struct Visitor {
29 enum class State { Unvisited, Visiting, Visited };
30
31 std::map<AnalysisName, State> Marks;
32 std::vector<AnalysisName> Path;
33 std::vector<std::unique_ptr<AnalysisBase>> Result;
34
35 explicit Visitor(size_t N) {
36 Path.reserve(N);
37 Result.reserve(N);
38 }
39
40 std::string formatCycle(const AnalysisName &CycleEntry) const {
41 auto CycleBegin = llvm::find(Path, CycleEntry);
42 std::string Cycle;
43 llvm::raw_string_ostream OS(Cycle);
44 llvm::interleave(llvm::make_range(CycleBegin, Path.end()), OS, " -> ");
45 OS << " -> " << CycleEntry;
46 return Cycle;
47 }
48
49 llvm::Error visit(const AnalysisName &Name) {
50 auto [It, _] = Marks.emplace(Name, State::Unvisited);
51
52 switch (It->second) {
53 case State::Visited:
54 return llvm::Error::success();
55
56 case State::Visiting:
57 return ErrorBuilder::create(std::errc::invalid_argument,
58 "cycle detected: {0}", formatCycle(Name))
59 .build();
60
61 case State::Unvisited: {
62 It->second = State::Visiting;
63 Path.push_back(Name);
64
65 llvm::Expected<std::unique_ptr<AnalysisBase>> V =
66 AnalysisRegistry::instantiate(Name);
67 if (!V) {
68 return V.takeError();
69 }
70
71 // Unwrap for convenience to avoid the noise of dereferencing an
72 // Expected on every subsequent access.
73 std::unique_ptr<AnalysisBase> Analysis = std::move(*V);
74
75 for (const auto &Dep : Analysis->getDependencyNames()) {
76 if (auto Err = visit(Dep)) {
77 return Err;
78 }
79 }
80
81 // std::map iterators are not invalidated by insertions, so It remains
82 // valid after recursive visit() calls that insert new entries.
83 It->second = State::Visited;
84 Path.pop_back();
85 Result.push_back(std::move(Analysis));
86
87 return llvm::Error::success();
88 }
89 }
90 llvm_unreachable("unhandled State");
91 }
92 };
93
94 Visitor V(Roots.size());
95 for (const auto &Root : Roots) {
96 if (auto Err = V.visit(Root)) {
97 return std::move(Err);
98 }
99 }
100 return std::move(V.Result);
101}
102
103llvm::Error AnalysisDriver::executeSummaryAnalysis(SummaryAnalysisBase &Summary,
104 WPASuite &Suite) const {
105 if (auto Err = Summary.initialize())
106 return Err;
107
108 auto DataIt = LU->Data.find(Summary.getSummaryName());
109 if (DataIt != LU->Data.end()) {
110 for (auto &[Id, EntitySummary] : DataIt->second)
111 if (auto Err = Summary.add(Id, *EntitySummary))
112 return Err;
113 }
114 return Summary.finalize();
115}
116
117llvm::Error AnalysisDriver::executeDerivedAnalysis(DerivedAnalysisBase &Derived,
118 WPASuite &Suite) const {
119 std::map<AnalysisName, const AnalysisResult *> DepMap;
120
121 for (const auto &DepName : Derived.getDependencyNames()) {
122 auto It = Suite.Data.find(DepName);
123 if (It == Suite.Data.end()) {
124 ErrorBuilder::fatal("missing dependency '{0}' for analysis '{1}': "
125 "dependency graph is not topologically sorted",
126 DepName, Derived.getAnalysisName());
127 }
128 DepMap[DepName] = It->second.get();
129 }
130
131 if (auto Err = Derived.initialize(DepMap)) {
132 return Err;
133 }
134
135 while (true) {
136 auto StepOrErr = Derived.step();
137 if (!StepOrErr) {
138 return StepOrErr.takeError();
139 }
140 if (!*StepOrErr) {
141 break;
142 }
143 }
144
145 if (auto Err = Derived.finalize()) {
146 return Err;
147 }
148
149 return llvm::Error::success();
150}
151
152llvm::Expected<WPASuite> AnalysisDriver::execute(
153 EntityIdTable IdTable,
154 llvm::ArrayRef<std::unique_ptr<AnalysisBase>> Sorted) const {
155 WPASuite Suite;
156 Suite.IdTable = std::move(IdTable);
157
158 for (auto &Analysis : Sorted) {
159 switch (Analysis->TheKind) {
160 case AnalysisBase::Kind::Summary: {
161 SummaryAnalysisBase &SA = static_cast<SummaryAnalysisBase &>(*Analysis);
162 if (auto Err = executeSummaryAnalysis(SA, Suite)) {
163 return std::move(Err);
164 }
165 break;
166 }
167 case AnalysisBase::Kind::Derived: {
168 DerivedAnalysisBase &DA = static_cast<DerivedAnalysisBase &>(*Analysis);
169 if (auto Err = executeDerivedAnalysis(DA, Suite)) {
170 return std::move(Err);
171 }
172 break;
173 }
174 }
175 AnalysisName Name = Analysis->getAnalysisName();
176 Suite.Data.emplace(std::move(Name), std::move(*Analysis).takeResult());
177 }
178
179 return std::move(Suite);
180}
181
183 auto ExpectedSorted = toposort(AnalysisRegistry::names());
184 if (!ExpectedSorted) {
185 return ExpectedSorted.takeError();
186 }
187 return execute(std::move(LU->IdTable), *ExpectedSorted);
188}
189
192 auto ExpectedSorted = toposort(Names);
193 if (!ExpectedSorted) {
194 return ExpectedSorted.takeError();
195 }
196
197 return execute(LU->IdTable, *ExpectedSorted);
198}
#define V(N, I)
Result
Implement __builtin_bit_cast and related operations.
virtual const std::vector< AnalysisName > & getDependencyNames() const =0
AnalysisNames of all AnalysisResult dependencies.
virtual AnalysisName getAnalysisName() const =0
Name of this analysis.
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.
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 getSummaryName() 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...
Definition WPASuite.h:37
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
Definition TypeBase.h:906