1//===-- APINotesWriter.h - API Notes Writer ---------------------*- 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#ifndef LLVM_CLANG_LIB_APINOTES_APINOTESFORMAT_H
10#define LLVM_CLANG_LIB_APINOTES_APINOTESFORMAT_H
11
12#include "clang/APINotes/Types.h"
13#include "llvm/ADT/PointerEmbeddedInt.h"
14#include "llvm/Bitcode/BitcodeConvenience.h"
15
16namespace clang {
17namespace api_notes {
18/// Magic number for API notes files.
19const unsigned char API_NOTES_SIGNATURE[] = {0xE2, 0x9C, 0xA8, 0x01};
20
21/// API notes file major version number.
22const uint16_t VERSION_MAJOR = 0;
23
24/// API notes file minor version number.
25///
26/// When the format changes IN ANY WAY, this number should be incremented.
27const uint16_t VERSION_MINOR = 27; // SingleDeclTableKey
28
29const uint8_t kSwiftCopyable = 1;
30const uint8_t kSwiftNonCopyable = 2;
31
32using IdentifierID = llvm::PointerEmbeddedInt<unsigned, 31>;
33using IdentifierIDField = llvm::BCVBR<16>;
34
35using SelectorID = llvm::PointerEmbeddedInt<unsigned, 31>;
36using SelectorIDField = llvm::BCVBR<16>;
37
38/// The various types of blocks that can occur within a API notes file.
39///
40/// These IDs must \em not be renumbered or reordered without incrementing
41/// VERSION_MAJOR.
42enum BlockID {
43 /// The control block, which contains all of the information that needs to
44 /// be validated prior to committing to loading the API notes file.
45 ///
46 /// \sa control_block
47 CONTROL_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID,
48
49 /// The identifier data block, which maps identifier strings to IDs.
50 IDENTIFIER_BLOCK_ID,
51
52 /// The Objective-C context data block, which contains information about
53 /// Objective-C classes and protocols.
54 OBJC_CONTEXT_BLOCK_ID,
55
56 /// The Objective-C property data block, which maps Objective-C
57 /// (class name, property name) pairs to information about the
58 /// property.
59 OBJC_PROPERTY_BLOCK_ID,
60
61 /// The Objective-C property data block, which maps Objective-C
62 /// (class name, selector, is_instance_method) tuples to information
63 /// about the method.
64 OBJC_METHOD_BLOCK_ID,
65
66 /// The C++ method data block, which maps C++ (context id, method name) pairs
67 /// to information about the method.
68 CXX_METHOD_BLOCK_ID,
69
70 /// The Objective-C selector data block, which maps Objective-C
71 /// selector names (# of pieces, identifier IDs) to the selector ID
72 /// used in other tables.
73 OBJC_SELECTOR_BLOCK_ID,
74
75 /// The global variables data block, which maps global variable names to
76 /// information about the global variable.
77 GLOBAL_VARIABLE_BLOCK_ID,
78
79 /// The (global) functions data block, which maps global function names to
80 /// information about the global function.
81 GLOBAL_FUNCTION_BLOCK_ID,
82
83 /// The tag data block, which maps tag names to information about
84 /// the tags.
85 TAG_BLOCK_ID,
86
87 /// The typedef data block, which maps typedef names to information about
88 /// the typedefs.
89 TYPEDEF_BLOCK_ID,
90
91 /// The enum constant data block, which maps enumerator names to
92 /// information about the enumerators.
93 ENUM_CONSTANT_BLOCK_ID,
94};
95
96namespace control_block {
97// These IDs must \em not be renumbered or reordered without incrementing
98// VERSION_MAJOR.
99enum {
100 METADATA = 1,
101 MODULE_NAME = 2,
102 MODULE_OPTIONS = 3,
103 SOURCE_FILE = 4,
104};
105
106using MetadataLayout =
107 llvm::BCRecordLayout<METADATA, // ID
108 llvm::BCFixed<16>, // Module format major version
109 llvm::BCFixed<16> // Module format minor version
110 >;
111
112using ModuleNameLayout = llvm::BCRecordLayout<MODULE_NAME,
113 llvm::BCBlob // Module name
114 >;
115
116using ModuleOptionsLayout =
117 llvm::BCRecordLayout<MODULE_OPTIONS,
118 llvm::BCFixed<1> // SwiftInferImportAsMember
119 >;
120
121using SourceFileLayout = llvm::BCRecordLayout<SOURCE_FILE,
122 llvm::BCVBR<16>, // file size
123 llvm::BCVBR<16> // creation time
124 >;
125} // namespace control_block
126
127namespace identifier_block {
128enum {
129 IDENTIFIER_DATA = 1,
130};
131
132using IdentifierDataLayout = llvm::BCRecordLayout<
133 IDENTIFIER_DATA, // record ID
134 llvm::BCVBR<16>, // table offset within the blob (see below)
135 llvm::BCBlob // map from identifier strings to decl kinds / decl IDs
136 >;
137} // namespace identifier_block
138
139namespace context_block {
140enum {
141 CONTEXT_ID_DATA = 1,
142 CONTEXT_INFO_DATA = 2,
143};
144
145using ContextIDLayout =
146 llvm::BCRecordLayout<CONTEXT_ID_DATA, // record ID
147 llvm::BCVBR<16>, // table offset within the blob (see
148 // below)
149 llvm::BCBlob // map from ObjC class names/protocol (as
150 // IDs) to context IDs
151 >;
152
153using ContextInfoLayout = llvm::BCRecordLayout<
154 CONTEXT_INFO_DATA, // record ID
155 llvm::BCVBR<16>, // table offset within the blob (see below)
156 llvm::BCBlob // map from ObjC context IDs to context information.
157 >;
158} // namespace context_block
159
160namespace objc_property_block {
161enum {
162 OBJC_PROPERTY_DATA = 1,
163};
164
165using ObjCPropertyDataLayout = llvm::BCRecordLayout<
166 OBJC_PROPERTY_DATA, // record ID
167 llvm::BCVBR<16>, // table offset within the blob (see below)
168 llvm::BCBlob // map from ObjC (class name, property name) pairs to
169 // ObjC property information
170 >;
171} // namespace objc_property_block
172
173namespace objc_method_block {
174enum {
175 OBJC_METHOD_DATA = 1,
176};
177
178using ObjCMethodDataLayout =
179 llvm::BCRecordLayout<OBJC_METHOD_DATA, // record ID
180 llvm::BCVBR<16>, // table offset within the blob (see
181 // below)
182 llvm::BCBlob // map from ObjC (class names, selector,
183 // is-instance-method) tuples to ObjC
184 // method information
185 >;
186} // namespace objc_method_block
187
188namespace cxx_method_block {
189enum {
190 CXX_METHOD_DATA = 1,
191};
192
193using CXXMethodDataLayout =
194 llvm::BCRecordLayout<CXX_METHOD_DATA, // record ID
195 llvm::BCVBR<16>, // table offset within the blob (see
196 // below)
197 llvm::BCBlob // map from C++ (context id, name)
198 // tuples to C++ method information
199 >;
200} // namespace cxx_method_block
201
202namespace objc_selector_block {
203enum {
204 OBJC_SELECTOR_DATA = 1,
205};
206
207using ObjCSelectorDataLayout =
208 llvm::BCRecordLayout<OBJC_SELECTOR_DATA, // record ID
209 llvm::BCVBR<16>, // table offset within the blob (see
210 // below)
211 llvm::BCBlob // map from (# pieces, identifier IDs) to
212 // Objective-C selector ID.
213 >;
214} // namespace objc_selector_block
215
216namespace global_variable_block {
217enum { GLOBAL_VARIABLE_DATA = 1 };
218
219using GlobalVariableDataLayout = llvm::BCRecordLayout<
220 GLOBAL_VARIABLE_DATA, // record ID
221 llvm::BCVBR<16>, // table offset within the blob (see below)
222 llvm::BCBlob // map from name to global variable information
223 >;
224} // namespace global_variable_block
225
226namespace global_function_block {
227enum { GLOBAL_FUNCTION_DATA = 1 };
228
229using GlobalFunctionDataLayout = llvm::BCRecordLayout<
230 GLOBAL_FUNCTION_DATA, // record ID
231 llvm::BCVBR<16>, // table offset within the blob (see below)
232 llvm::BCBlob // map from name to global function information
233 >;
234} // namespace global_function_block
235
236namespace tag_block {
237enum { TAG_DATA = 1 };
238
239using TagDataLayout =
240 llvm::BCRecordLayout<TAG_DATA, // record ID
241 llvm::BCVBR<16>, // table offset within the blob (see
242 // below)
243 llvm::BCBlob // map from name to tag information
244 >;
245} // namespace tag_block
246
247namespace typedef_block {
248enum { TYPEDEF_DATA = 1 };
249
250using TypedefDataLayout =
251 llvm::BCRecordLayout<TYPEDEF_DATA, // record ID
252 llvm::BCVBR<16>, // table offset within the blob (see
253 // below)
254 llvm::BCBlob // map from name to typedef information
255 >;
256} // namespace typedef_block
257
258namespace enum_constant_block {
259enum { ENUM_CONSTANT_DATA = 1 };
260
261using EnumConstantDataLayout =
262 llvm::BCRecordLayout<ENUM_CONSTANT_DATA, // record ID
263 llvm::BCVBR<16>, // table offset within the blob (see
264 // below)
265 llvm::BCBlob // map from name to enumerator information
266 >;
267} // namespace enum_constant_block
268
269/// A stored Objective-C selector.
270struct StoredObjCSelector {
271 unsigned NumArgs;
272 llvm::SmallVector<IdentifierID, 2> Identifiers;
273};
274
275/// A stored Objective-C or C++ context, represented by the ID of its parent
276/// context, the kind of this context (Objective-C class / C++ namespace / etc),
277/// and the ID of this context.
278struct ContextTableKey {
279 uint32_t parentContextID;
280 uint8_t contextKind;
281 uint32_t contextID;
282
283 ContextTableKey() : parentContextID(-1), contextKind(-1), contextID(-1) {}
284
285 ContextTableKey(uint32_t parentContextID, uint8_t contextKind,
286 uint32_t contextID)
287 : parentContextID(parentContextID), contextKind(contextKind),
288 contextID(contextID) {}
289
290 ContextTableKey(std::optional<ContextID> ParentContextID, ContextKind Kind,
291 uint32_t ContextID)
292 : parentContextID(ParentContextID ? ParentContextID->Value : -1),
293 contextKind(static_cast<uint8_t>(Kind)), contextID(ContextID) {}
294
295 ContextTableKey(std::optional<Context> ParentContext, ContextKind Kind,
296 uint32_t ContextID)
297 : ContextTableKey(ParentContext ? std::make_optional(t&: ParentContext->id)
298 : std::nullopt,
299 Kind, ContextID) {}
300
301 llvm::hash_code hashValue() const {
302 return llvm::hash_value(
303 arg: std::tuple{parentContextID, contextKind, contextID});
304 }
305};
306
307inline bool operator==(const ContextTableKey &lhs, const ContextTableKey &rhs) {
308 return lhs.parentContextID == rhs.parentContextID &&
309 lhs.contextKind == rhs.contextKind && lhs.contextID == rhs.contextID;
310}
311
312/// A stored Objective-C or C++ declaration, represented by the ID of its parent
313/// context, and the name of the declaration.
314struct SingleDeclTableKey {
315 uint32_t parentContextID;
316 uint32_t nameID;
317
318 SingleDeclTableKey() : parentContextID(-1), nameID(-1) {}
319
320 SingleDeclTableKey(uint32_t ParentContextID, uint32_t NameID)
321 : parentContextID(ParentContextID), nameID(NameID) {}
322
323 SingleDeclTableKey(std::optional<Context> ParentCtx, IdentifierID NameID)
324 : parentContextID(ParentCtx ? ParentCtx->id.Value
325 : static_cast<uint32_t>(-1)),
326 nameID(NameID) {}
327
328 llvm::hash_code hashValue() const {
329 return llvm::hash_value(arg: std::make_pair(x: parentContextID, y: nameID));
330 }
331};
332
333inline bool operator==(const SingleDeclTableKey &lhs,
334 const SingleDeclTableKey &rhs) {
335 return lhs.parentContextID == rhs.parentContextID && lhs.nameID == rhs.nameID;
336}
337
338} // namespace api_notes
339} // namespace clang
340
341namespace llvm {
342template <> struct DenseMapInfo<clang::api_notes::StoredObjCSelector> {
343 typedef DenseMapInfo<unsigned> UnsignedInfo;
344
345 static inline clang::api_notes::StoredObjCSelector getEmptyKey() {
346 return clang::api_notes::StoredObjCSelector{.NumArgs: UnsignedInfo::getEmptyKey(),
347 .Identifiers: {}};
348 }
349
350 static inline clang::api_notes::StoredObjCSelector getTombstoneKey() {
351 return clang::api_notes::StoredObjCSelector{.NumArgs: UnsignedInfo::getTombstoneKey(),
352 .Identifiers: {}};
353 }
354
355 static unsigned
356 getHashValue(const clang::api_notes::StoredObjCSelector &Selector) {
357 auto hash = llvm::hash_value(value: Selector.NumArgs);
358 hash = hash_combine(args: hash, args: Selector.Identifiers.size());
359 for (auto piece : Selector.Identifiers)
360 hash = hash_combine(args: hash, args: static_cast<unsigned>(piece));
361 // FIXME: Mix upper/lower 32-bit values together to produce
362 // unsigned rather than truncating.
363 return hash;
364 }
365
366 static bool isEqual(const clang::api_notes::StoredObjCSelector &LHS,
367 const clang::api_notes::StoredObjCSelector &RHS) {
368 return LHS.NumArgs == RHS.NumArgs && LHS.Identifiers == RHS.Identifiers;
369 }
370};
371
372template <> struct DenseMapInfo<clang::api_notes::ContextTableKey> {
373 static inline clang::api_notes::ContextTableKey getEmptyKey() {
374 return clang::api_notes::ContextTableKey();
375 }
376
377 static inline clang::api_notes::ContextTableKey getTombstoneKey() {
378 return clang::api_notes::ContextTableKey{
379 DenseMapInfo<uint32_t>::getTombstoneKey(),
380 DenseMapInfo<uint8_t>::getTombstoneKey(),
381 DenseMapInfo<uint32_t>::getTombstoneKey()};
382 }
383
384 static unsigned getHashValue(const clang::api_notes::ContextTableKey &value) {
385 return value.hashValue();
386 }
387
388 static bool isEqual(const clang::api_notes::ContextTableKey &lhs,
389 const clang::api_notes::ContextTableKey &rhs) {
390 return lhs == rhs;
391 }
392};
393
394template <> struct DenseMapInfo<clang::api_notes::SingleDeclTableKey> {
395 static inline clang::api_notes::SingleDeclTableKey getEmptyKey() {
396 return clang::api_notes::SingleDeclTableKey();
397 }
398
399 static inline clang::api_notes::SingleDeclTableKey getTombstoneKey() {
400 return clang::api_notes::SingleDeclTableKey{
401 DenseMapInfo<uint32_t>::getTombstoneKey(),
402 DenseMapInfo<uint32_t>::getTombstoneKey()};
403 }
404
405 static unsigned
406 getHashValue(const clang::api_notes::SingleDeclTableKey &value) {
407 return value.hashValue();
408 }
409
410 static bool isEqual(const clang::api_notes::SingleDeclTableKey &lhs,
411 const clang::api_notes::SingleDeclTableKey &rhs) {
412 return lhs == rhs;
413 }
414};
415
416} // namespace llvm
417
418#endif
419