clang 23.0.0git
SerializationFormat.h
Go to the documentation of this file.
1//===- SerializationFormat.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// Abstract SerializationFormat interface for reading and writing
10// TUSummary and LinkUnitResolution data.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_SERIALIZATIONFORMAT_H
15#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_SERIALIZATIONFORMAT_H
16
25#include "llvm/ADT/STLFunctionalExtras.h"
26#include "llvm/ADT/StringRef.h"
27#include "llvm/Support/Error.h"
28#include "llvm/Support/Registry.h"
29
30namespace clang::ssaf {
31
32/// Abstract base class for serialization formats.
34public:
35 virtual ~SerializationFormat() = default;
36
37 virtual llvm::Expected<TUSummary> readTUSummary(llvm::StringRef Path) = 0;
38
39 virtual llvm::Error writeTUSummary(const TUSummary &Summary,
40 llvm::StringRef Path) = 0;
41
43 readTUSummaryEncoding(llvm::StringRef Path) = 0;
44
45 virtual llvm::Error
47 llvm::StringRef Path) = 0;
48
49 virtual llvm::Expected<LUSummary> readLUSummary(llvm::StringRef Path) = 0;
50
51 virtual llvm::Error writeLUSummary(const LUSummary &Summary,
52 llvm::StringRef Path) = 0;
53
55 readLUSummaryEncoding(llvm::StringRef Path) = 0;
56
57 virtual llvm::Error
59 llvm::StringRef Path) = 0;
60
61 virtual llvm::Expected<WPASuite> readWPASuite(llvm::StringRef Path) = 0;
62
63 virtual llvm::Error writeWPASuite(const WPASuite &Suite,
64 llvm::StringRef Path) = 0;
65
66 /// Invokes \p Callback once for each analysis that has registered
67 /// serialization support for this format.
69 llvm::function_ref<void(llvm::StringRef Name, llvm::StringRef Desc)>
70 Callback) const = 0;
71
72protected:
73 // Helpers providing access to implementation details of basic data structures
74 // for efficient serialization/deserialization.
75
76 static EntityId makeEntityId(const size_t Index) { return EntityId(Index); }
77
78 /// Constructs an empty WPASuite. Bypasses the private default constructor
79 /// so that deserialization code can build a WPASuite incrementally.
80 static WPASuite makeWPASuite() { return WPASuite(); }
81
82#define FIELD(CLASS, FIELD_NAME) \
83 static const auto &get##FIELD_NAME(const CLASS &X) { return X.FIELD_NAME; } \
84 static auto &get##FIELD_NAME(CLASS &X) { return X.FIELD_NAME; }
85#include "clang/ScalableStaticAnalysisFramework/Core/Model/PrivateFieldNames.def"
86
87 /// Per-format plugin registry for analysis result (de)serializers.
88 ///
89 /// Each concrete format (e.g. JSONFormat) instantiates this template once
90 /// via a public \c using alias. Analysis authors register support with:
91 ///
92 /// \code
93 /// static MyFormat::AnalysisResultRegistry::Add<MyAnalysisResult>
94 /// Reg(serializeFn, deserializeFn);
95 /// \endcode
96 ///
97 /// The serializer receives a \c const reference to \c MyAnalysisResult
98 /// directly and the \c Add wrapper handles the downcast from \c
99 /// AnalysisResult internally via virtual dispatch.
100 ///
101 /// \tparam FormatT Phantom type is needed to disambiguate \c llvm::Registry
102 /// instantiations. \c llvm::Registry is keyed on the \c Entry type,
103 /// so two formats sharing the same serializer/deserializer signatures
104 /// would collide on the same registry without this parameter.
105 template <class FormatT, class SerializerFn, class DeserializerFn>
107
108 template <class FormatT, class SerRet, class... SerArgs, class DesRet,
109 class... DesArgs>
111 FormatT, llvm::function_ref<SerRet(const AnalysisResult &, SerArgs...)>,
112 llvm::function_ref<DesRet(DesArgs...)>> {
113
114 using DeserializerFn = llvm::function_ref<DesRet(DesArgs...)>;
115
116 public:
117 /// Abstract base type stored in \c llvm::Registry<Codec>.
118 /// Subclasses override \c serialize() and \c deserialize() to
119 /// dispatch to the plugin's concrete functions.
120 ///
121 /// There is one \c Codec type (and one \c llvm::Registry<Codec>) per
122 /// format. All analysis-specific concrete subclasses for a given format
123 /// register into that single registry. The \c FormatT phantom type
124 /// parameter on the enclosing class ensures that different formats
125 /// produce distinct \c Codec types and thus separate registries.
126 struct Codec {
127 virtual ~Codec() = default;
128 virtual SerRet serialize(const AnalysisResult &, SerArgs...) const = 0;
129 virtual DesRet deserialize(DesArgs...) const = 0;
130 };
131
132 template <class AnalysisResultT> struct Add {
134 llvm::function_ref<SerRet(const AnalysisResultT &, SerArgs...)>;
135
136 /// Takes the plugin's typed serializer and the deserializer, and
137 /// inserts them into \c llvm::Registry<Codec>.
138 Add(TypedSerializerFn TypedSerialize, DeserializerFn Deserialize) {
139 /// Per-\c AnalysisResultT guard: each template instantiation gets
140 /// its own \c static \c bool, so double-registration of the same
141 /// analysis is caught even across translation units.
142 static bool Registered = false;
143 if (Registered) {
144 ErrorBuilder::fatal("support is already registered for analysis: {0}",
145 AnalysisResultT::analysisName());
146 }
147 Registered = true;
148
149 /// The plugin's serializer and deserializer are captured in
150 /// function-local statics so that the \c ConcreteCodec default
151 /// constructor (required by \c llvm::Registry) can read them.
152 /// They are stored as instance members of \c ConcreteCodec rather
153 /// than \c static \c inline class members to avoid symbol
154 /// visibility issues across shared library boundaries on Linux
155 /// (where \c dlopen with \c RTLD_LOCAL can give the host and
156 /// plugin separate copies of \c static \c inline members).
157 static TypedSerializerFn SavedSerialize = TypedSerialize;
158 static DeserializerFn SavedDeserialize = Deserialize;
159
160 /// Concrete subclass of \c Codec for \c AnalysisResultT.
161 /// The \c serialize() override performs the downcast from
162 /// \c AnalysisResult to \c AnalysisResultT.
163 struct ConcreteCodec final : Codec {
164 TypedSerializerFn SerFn;
165 DeserializerFn DesFn;
166
167 ConcreteCodec() : SerFn(SavedSerialize), DesFn(SavedDeserialize) {}
168
169 SerRet serialize(const AnalysisResult &Base,
170 SerArgs... args) const override {
171 return SerFn(static_cast<const AnalysisResultT &>(Base), args...);
172 }
173
174 DesRet deserialize(DesArgs... args) const override {
175 return DesFn(args...);
176 }
177 };
178
179 /// \c llvm::Registry stores the name as a \c StringRef, so the
180 /// underlying string must be kept alive with a static declaration.
181 static std::string NameStr =
182 AnalysisResultT::analysisName().str().str();
183
184 /// This performs the actual registration. It appends a factory for \c
185 /// ConcreteCodec to the global \c llvm::Registry<Codec>. \c static
186 /// ensures the `Registry::Add` object lives for the entire program,
187 /// keeping its codec and node alive in the registry's linked list.
188 [[maybe_unused]] static
189 typename llvm::Registry<Codec>::template Add<ConcreteCodec>
190 RegisterUsingCtorSideEffect(NameStr, "");
191 }
192 };
193
194 /// Looks up the codec for \p Name by walking the registry list.
197 for (const auto &E : llvm::Registry<Codec>::entries()) {
198 if (E.getName() == Name.str()) {
199 return E.instantiate();
200 }
201 }
202 return ErrorBuilder::create(std::errc::invalid_argument,
203 "no support registered for analysis: {0}",
204 Name)
205 .build();
206 }
207 };
208};
209
210template <class SerializerFn, class DeserializerFn> struct FormatInfoEntry {
215 virtual ~FormatInfoEntry() = default;
216
218 SerializerFn Serialize;
219 DeserializerFn Deserialize;
220};
221
222} // namespace clang::ssaf
223
224#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_SERIALIZATIONFORMAT_H
static json::Object serialize(const EntitySummary &Summary, JSONFormat::EntityIdToJSONFn ToJSON)
static Expected< std::unique_ptr< EntitySummary > > deserialize(const json::Object &Obj, EntityIdTable &IdTable, JSONFormat::EntityIdFromJSONFn FromJSON)
Uniquely identifies a whole-program analysis and the AnalysisResult it produces.
llvm::StringRef str() const
Explicit conversion to the underlying string representation.
Base class for whole-program analysis results.
Lightweight opaque handle representing an entity in an EntityIdTable.
Definition EntityId.h:31
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.
Represents a link unit summary in its serialized encoding.
Represents a link unit (LU) summary containing merged entity summaries.
Definition LUSummary.h:33
static llvm::Expected< std::unique_ptr< Codec > > instantiate(const AnalysisName &Name)
Looks up the codec for Name by walking the registry list.
Per-format plugin registry for analysis result (de)serializers.
Abstract base class for serialization formats.
virtual llvm::Error writeLUSummary(const LUSummary &Summary, llvm::StringRef Path)=0
virtual llvm::Expected< LUSummary > readLUSummary(llvm::StringRef Path)=0
virtual llvm::Expected< WPASuite > readWPASuite(llvm::StringRef Path)=0
static EntityId makeEntityId(const size_t Index)
virtual llvm::Expected< LUSummaryEncoding > readLUSummaryEncoding(llvm::StringRef Path)=0
virtual llvm::Error writeWPASuite(const WPASuite &Suite, llvm::StringRef Path)=0
virtual llvm::Error writeTUSummary(const TUSummary &Summary, llvm::StringRef Path)=0
virtual void forEachRegisteredAnalysis(llvm::function_ref< void(llvm::StringRef Name, llvm::StringRef Desc)> Callback) const =0
Invokes Callback once for each analysis that has registered serialization support for this format.
virtual ~SerializationFormat()=default
virtual llvm::Expected< TUSummaryEncoding > readTUSummaryEncoding(llvm::StringRef Path)=0
virtual llvm::Error writeLUSummaryEncoding(const LUSummaryEncoding &SummaryEncoding, llvm::StringRef Path)=0
virtual llvm::Expected< TUSummary > readTUSummary(llvm::StringRef Path)=0
virtual llvm::Error writeTUSummaryEncoding(const TUSummaryEncoding &SummaryEncoding, llvm::StringRef Path)=0
static WPASuite makeWPASuite()
Constructs an empty WPASuite.
Uniquely identifies an analysis summary.
Definition SummaryName.h:22
Represents a translation unit summary in its serialized encoding.
Data extracted for a given translation unit and for a given set of analyses.
Definition TUSummary.h:24
Bundles the EntityIdTable (moved from the LUSummary) and the analysis results produced by one Analysi...
Definition WPASuite.h:37
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
FormatInfoEntry(SummaryName ForSummary, SerializerFn Serialize, DeserializerFn Deserialize)
virtual ~FormatInfoEntry()=default
Add(TypedSerializerFn TypedSerialize, DeserializerFn Deserialize)
Takes the plugin's typed serializer and the deserializer, and inserts them into llvm::Registry<Codec>...