clang 23.0.0git
DerivedAnalysis.h
Go to the documentation of this file.
1//===- DerivedAnalysis.h ----------------------------------------*- C++ -*-===//
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//
9// Defines DerivedAnalysisBase (type-erased base known to AnalysisDriver) and
10// the typed intermediate DerivedAnalysis<ResultT, DepResultTs...> that
11// concrete analyses inherit from.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
16#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
17
23#include "llvm/Support/Error.h"
24#include <map>
25#include <memory>
26#include <vector>
27
28namespace clang::ssaf {
29
30class AnalysisDriver;
32
33/// Type-erased base for derived analyses. Known to AnalysisDriver.
34///
35/// Not subclassed directly -- use DerivedAnalysis<ResultT, DepResultTs...>.
36/// A derived analysis consumes previously produced AnalysisResult objects
37/// and computes a new one via an initialize/step/finalize lifecycle.
39 friend class AnalysisDriver;
40
41protected:
43
44private:
45 /// Called once with the dependency results before the step() loop.
46 ///
47 /// \param DepResults Immutable results of all declared dependencies, keyed
48 /// by AnalysisName. Guaranteed to contain every name
49 /// returned by dependencyNames().
50 virtual llvm::Error initialize(
51 const std::map<AnalysisName, const AnalysisResult *> &DepResults) = 0;
52
53 /// Performs one pass.
54 /// Returns true if another pass is needed; false when converged.
55 virtual llvm::Expected<bool> step() = 0;
56
57 /// Called after the step() loop converges. Default is a no-op.
58 virtual llvm::Error finalize() { return llvm::Error::success(); }
59};
60
61/// Typed intermediate that concrete derived analyses inherit from.
62///
63/// Concrete analyses must implement:
64/// llvm::Error initialize(const DepResultTs &...) override;
65/// llvm::Expected<bool> step() override;
66/// and may override finalize().
67///
68/// Dependencies are fixed for the lifetime of the analysis: initialize()
69/// binds them once, step() is called until it returns false, and
70/// finalize() post-processes after convergence.
71template <typename ResultT, typename... DepResultTs>
73 static_assert(std::is_base_of_v<AnalysisResult, ResultT>,
74 "ResultT must derive from AnalysisResult");
75 static_assert(HasAnalysisName_v<ResultT>,
76 "ResultT must have a static analysisName() method");
77 static_assert((std::is_base_of_v<AnalysisResult, DepResultTs> && ...),
78 "Every DepResultT must derive from AnalysisResult");
79 static_assert((HasAnalysisName_v<DepResultTs> && ...),
80 "Every DepResultT must have a static analysisName() method");
81
82 friend class AnalysisRegistry;
83 using ResultType = ResultT;
84
85 std::unique_ptr<ResultT> Result = std::make_unique<ResultT>();
86
87public:
88 /// Used by AnalysisRegistry::Add to derive the registry entry name.
89 AnalysisName getAnalysisName() const final { return ResultT::analysisName(); }
90
91 const std::vector<AnalysisName> &getDependencyNames() const final {
92 static const std::vector<AnalysisName> Names = {
93 DepResultTs::analysisName()...};
94 return Names;
95 }
96
97 /// Called once with the fixed dependency results before the step() loop.
98 virtual llvm::Error initialize(const DepResultTs &...) = 0;
99
100protected:
101 /// Read-only access to the result being built.
102 const ResultT &getResult() const & { return *Result; }
103
104 /// Mutable access to the result being built.
105 ResultT &getResult() & { return *Result; }
106
107private:
108 /// Seals the type-erased base overload, downcasts, and dispatches to the
109 /// typed initialize(). All dependencies are guaranteed present by the driver.
110 llvm::Error
111 initialize(const std::map<AnalysisName, const AnalysisResult *> &Map) final {
112 auto lookup = [&Map](const AnalysisName &Name) -> const AnalysisResult * {
113 auto It = Map.find(Name);
114 if (It == Map.end()) {
115 ErrorBuilder::fatal("dependency '{0}' missing from DepResults map; "
116 "dependency graph is not topologically sorted",
117 Name);
118 }
119 return It->second;
120 };
121 return initialize(*static_cast<const DepResultTs *>(
122 lookup(DepResultTs::analysisName()))...);
123 }
124
125 /// Type-erased result extraction for the driver.
126 std::unique_ptr<AnalysisResult> takeResult() && final {
127 return std::move(Result);
128 }
129};
130
131} // namespace clang::ssaf
132
133#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
Orchestrates whole-program analysis over an LUSummary.
Uniquely identifies a whole-program analysis and the AnalysisResult it produces.
Unified registry for SummaryAnalysis and DerivedAnalysis implementations.
Base class for whole-program analysis results.
Typed intermediate that concrete derived analyses inherit from.
virtual llvm::Error initialize(const DepResultTs &...)=0
Called once with the fixed dependency results before the step() loop.
AnalysisName getAnalysisName() const final
Used by AnalysisRegistry::Add to derive the registry entry name.
ResultT & getResult() &
Mutable access to the result being built.
const std::vector< AnalysisName > & getDependencyNames() const final
AnalysisNames of all AnalysisResult dependencies.
const ResultT & getResult() const &
Read-only access to the result being built.
static void fatal(const char *Fmt, Args &&...ArgVals)
Report a fatal error with formatted message and terminate execution.
constexpr bool HasAnalysisName_v
void initialize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)
void finalize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)
float __ovld __cnfn step(float, float)
Returns 0.0 if x < edge, otherwise it returns 1.0.