xref: /freebsd/contrib/llvm-project/clang/lib/APINotes/APINotesFormat.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 
16 namespace clang {
17 namespace api_notes {
18 /// Magic number for API notes files.
19 const unsigned char API_NOTES_SIGNATURE[] = {0xE2, 0x9C, 0xA8, 0x01};
20 
21 /// API notes file major version number.
22 const 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.
27 const uint16_t VERSION_MINOR = 27; // SingleDeclTableKey
28 
29 const uint8_t kSwiftCopyable = 1;
30 const uint8_t kSwiftNonCopyable = 2;
31 
32 using IdentifierID = llvm::PointerEmbeddedInt<unsigned, 31>;
33 using IdentifierIDField = llvm::BCVBR<16>;
34 
35 using SelectorID = llvm::PointerEmbeddedInt<unsigned, 31>;
36 using 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.
42 enum 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 
96 namespace control_block {
97 // These IDs must \em not be renumbered or reordered without incrementing
98 // VERSION_MAJOR.
99 enum {
100   METADATA = 1,
101   MODULE_NAME = 2,
102   MODULE_OPTIONS = 3,
103   SOURCE_FILE = 4,
104 };
105 
106 using MetadataLayout =
107     llvm::BCRecordLayout<METADATA,          // ID
108                          llvm::BCFixed<16>, // Module format major version
109                          llvm::BCFixed<16>  // Module format minor version
110                          >;
111 
112 using ModuleNameLayout = llvm::BCRecordLayout<MODULE_NAME,
113                                               llvm::BCBlob // Module name
114                                               >;
115 
116 using ModuleOptionsLayout =
117     llvm::BCRecordLayout<MODULE_OPTIONS,
118                          llvm::BCFixed<1> // SwiftInferImportAsMember
119                          >;
120 
121 using SourceFileLayout = llvm::BCRecordLayout<SOURCE_FILE,
122                                               llvm::BCVBR<16>, // file size
123                                               llvm::BCVBR<16>  // creation time
124                                               >;
125 } // namespace control_block
126 
127 namespace identifier_block {
128 enum {
129   IDENTIFIER_DATA = 1,
130 };
131 
132 using 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 
139 namespace context_block {
140 enum {
141   CONTEXT_ID_DATA = 1,
142   CONTEXT_INFO_DATA = 2,
143 };
144 
145 using 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 
153 using 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 
160 namespace objc_property_block {
161 enum {
162   OBJC_PROPERTY_DATA = 1,
163 };
164 
165 using 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 
173 namespace objc_method_block {
174 enum {
175   OBJC_METHOD_DATA = 1,
176 };
177 
178 using 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 
188 namespace cxx_method_block {
189 enum {
190   CXX_METHOD_DATA = 1,
191 };
192 
193 using 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 
202 namespace objc_selector_block {
203 enum {
204   OBJC_SELECTOR_DATA = 1,
205 };
206 
207 using 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 
216 namespace global_variable_block {
217 enum { GLOBAL_VARIABLE_DATA = 1 };
218 
219 using 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 
226 namespace global_function_block {
227 enum { GLOBAL_FUNCTION_DATA = 1 };
228 
229 using 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 
236 namespace tag_block {
237 enum { TAG_DATA = 1 };
238 
239 using 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 
247 namespace typedef_block {
248 enum { TYPEDEF_DATA = 1 };
249 
250 using 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 
258 namespace enum_constant_block {
259 enum { ENUM_CONSTANT_DATA = 1 };
260 
261 using 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.
270 struct 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.
278 struct ContextTableKey {
279   uint32_t parentContextID;
280   uint8_t contextKind;
281   uint32_t contextID;
282 
ContextTableKeyContextTableKey283   ContextTableKey() : parentContextID(-1), contextKind(-1), contextID(-1) {}
284 
ContextTableKeyContextTableKey285   ContextTableKey(uint32_t parentContextID, uint8_t contextKind,
286                   uint32_t contextID)
287       : parentContextID(parentContextID), contextKind(contextKind),
288         contextID(contextID) {}
289 
ContextTableKeyContextTableKey290   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 
ContextTableKeyContextTableKey295   ContextTableKey(std::optional<Context> ParentContext, ContextKind Kind,
296                   uint32_t ContextID)
297       : ContextTableKey(ParentContext ? std::make_optional(ParentContext->id)
298                                       : std::nullopt,
299                         Kind, ContextID) {}
300 
hashValueContextTableKey301   llvm::hash_code hashValue() const {
302     return llvm::hash_value(
303         std::tuple{parentContextID, contextKind, contextID});
304   }
305 };
306 
307 inline 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.
314 struct SingleDeclTableKey {
315   uint32_t parentContextID;
316   uint32_t nameID;
317 
SingleDeclTableKeySingleDeclTableKey318   SingleDeclTableKey() : parentContextID(-1), nameID(-1) {}
319 
SingleDeclTableKeySingleDeclTableKey320   SingleDeclTableKey(uint32_t ParentContextID, uint32_t NameID)
321       : parentContextID(ParentContextID), nameID(NameID) {}
322 
SingleDeclTableKeySingleDeclTableKey323   SingleDeclTableKey(std::optional<Context> ParentCtx, IdentifierID NameID)
324       : parentContextID(ParentCtx ? ParentCtx->id.Value
325                                   : static_cast<uint32_t>(-1)),
326         nameID(NameID) {}
327 
hashValueSingleDeclTableKey328   llvm::hash_code hashValue() const {
329     return llvm::hash_value(std::make_pair(parentContextID, nameID));
330   }
331 };
332 
333 inline 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 
341 namespace llvm {
342 template <> 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{UnsignedInfo::getEmptyKey(),
347                                                 {}};
348   }
349 
350   static inline clang::api_notes::StoredObjCSelector getTombstoneKey() {
351     return clang::api_notes::StoredObjCSelector{UnsignedInfo::getTombstoneKey(),
352                                                 {}};
353   }
354 
355   static unsigned
356   getHashValue(const clang::api_notes::StoredObjCSelector &Selector) {
357     auto hash = llvm::hash_value(Selector.NumArgs);
358     hash = hash_combine(hash, Selector.Identifiers.size());
359     for (auto piece : Selector.Identifiers)
360       hash = hash_combine(hash, 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 
372 template <> 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 
394 template <> 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