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 = 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 {
133 using TypedSerializerFn = SerRet (*)(const AnalysisResultT &, SerArgs...);
134
136 static inline DeserializerFn SavedDeserialize;
137
138 /// Takes the plugin's typed serializer and the deserializer, and
139 /// inserts them into \c llvm::Registry<Codec>.
140 Add(TypedSerializerFn TypedSerialize, DeserializerFn Deserialize) {
141 /// Per-\c AnalysisResultT guard: each template instantiation gets
142 /// its own \c static \c bool, so double-registration of the same
143 /// analysis is caught even across translation units.
144 static bool Registered = false;
145 if (Registered) {
146 ErrorBuilder::fatal("support is already registered for analysis: {0}",
147 AnalysisResultT::analysisName());
148 }
149 Registered = true;
150
151 /// The plugin's serializer and deserializer are captured in
152 /// static inline members of the Add template so that the
153 /// \c ConcreteCodec default constructor (required by \c llvm::Registry)
154 /// can read them. They use raw function pointers to prevent dangling
155 /// references to temporary stack variables during registration.
156 ///
157 /// Once read by the constructor, they are stored as instance members
158 /// of \c ConcreteCodec rather than directly executed from the \c static
159 /// \c inline class members. This prevents symbol visibility issues
160 /// across shared library boundaries on Linux (where \c dlopen with \c
161 /// RTLD_LOCAL can give the host and plugin separate copies of \c static
162 /// \c inline members).
163 SavedSerialize = TypedSerialize;
164 SavedDeserialize = Deserialize;
165
166 /// Concrete subclass of \c Codec for \c AnalysisResultT.
167 /// The \c serialize() override performs the downcast from
168 /// \c AnalysisResult to \c AnalysisResultT.
169 struct ConcreteCodec final : Codec {
170 TypedSerializerFn SerFn;
171 DeserializerFn DesFn;
172
173 ConcreteCodec() : SerFn(SavedSerialize), DesFn(SavedDeserialize) {}
174
175 SerRet serialize(const AnalysisResult &Base,
176 SerArgs... args) const override {
177 return SerFn(static_cast<const AnalysisResultT &>(Base), args...);
178 }
179
180 DesRet deserialize(DesArgs... args) const override {
181 return DesFn(args...);
182 }
183 };
184
185 /// \c llvm::Registry stores the name as a \c StringRef, so the
186 /// underlying string must be kept alive with a static declaration.
187 static std::string NameStr =
188 AnalysisResultT::analysisName().str().str();
189
190 /// This performs the actual registration. It appends a factory for \c
191 /// ConcreteCodec to the global \c llvm::Registry<Codec>. \c static
192 /// ensures the `Registry::Add` object lives for the entire program,
193 /// keeping its codec and node alive in the registry's linked list.
194 [[maybe_unused]] static
195 typename llvm::Registry<Codec>::template Add<ConcreteCodec>
196 RegisterUsingCtorSideEffect(NameStr, "");
197 }
198 };
199
200 /// Looks up the codec for \p Name by walking the registry list.
203 for (const auto &E : llvm::Registry<Codec>::entries()) {
204 if (E.getName() == Name.str()) {
205 return E.instantiate();
206 }
207 }
208 return ErrorBuilder::create(std::errc::invalid_argument,
209 "no support registered for analysis: {0}",
210 Name)
211 .build();
212 }
213 };
214};
215
216template <class SerializerFn, class DeserializerFn> struct FormatInfoEntry {
221 virtual ~FormatInfoEntry() = default;
222
224 SerializerFn Serialize;
225 DeserializerFn Deserialize;
226};
227
228} // namespace clang::ssaf
229
230#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>...