xref: /llvm-project/clang/lib/APINotes/APINotesFormat.h (revision 48f7f63ac723a5001b74627493d360ff3d8d1186)
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 = 34; // SwiftReturnOwnership
28 
29 const uint8_t kSwiftConforms = 1;
30 const uint8_t kSwiftDoesNotConform = 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 fields data block, which maps names fields of C records to
76   /// information about the field.
77   FIELD_BLOCK_ID,
78 
79   /// The global variables data block, which maps global variable names to
80   /// information about the global variable.
81   GLOBAL_VARIABLE_BLOCK_ID,
82 
83   /// The (global) functions data block, which maps global function names to
84   /// information about the global function.
85   GLOBAL_FUNCTION_BLOCK_ID,
86 
87   /// The tag data block, which maps tag names to information about
88   /// the tags.
89   TAG_BLOCK_ID,
90 
91   /// The typedef data block, which maps typedef names to information about
92   /// the typedefs.
93   TYPEDEF_BLOCK_ID,
94 
95   /// The enum constant data block, which maps enumerator names to
96   /// information about the enumerators.
97   ENUM_CONSTANT_BLOCK_ID,
98 };
99 
100 namespace control_block {
101 // These IDs must \em not be renumbered or reordered without incrementing
102 // VERSION_MAJOR.
103 enum {
104   METADATA = 1,
105   MODULE_NAME = 2,
106   MODULE_OPTIONS = 3,
107   SOURCE_FILE = 4,
108 };
109 
110 using MetadataLayout =
111     llvm::BCRecordLayout<METADATA,          // ID
112                          llvm::BCFixed<16>, // Module format major version
113                          llvm::BCFixed<16>  // Module format minor version
114                          >;
115 
116 using ModuleNameLayout = llvm::BCRecordLayout<MODULE_NAME,
117                                               llvm::BCBlob // Module name
118                                               >;
119 
120 using ModuleOptionsLayout =
121     llvm::BCRecordLayout<MODULE_OPTIONS,
122                          llvm::BCFixed<1> // SwiftInferImportAsMember
123                          >;
124 
125 using SourceFileLayout = llvm::BCRecordLayout<SOURCE_FILE,
126                                               llvm::BCVBR<16>, // file size
127                                               llvm::BCVBR<16>  // creation time
128                                               >;
129 } // namespace control_block
130 
131 namespace identifier_block {
132 enum {
133   IDENTIFIER_DATA = 1,
134 };
135 
136 using IdentifierDataLayout = llvm::BCRecordLayout<
137     IDENTIFIER_DATA, // record ID
138     llvm::BCVBR<16>, // table offset within the blob (see below)
139     llvm::BCBlob     // map from identifier strings to decl kinds / decl IDs
140     >;
141 } // namespace identifier_block
142 
143 namespace context_block {
144 enum {
145   CONTEXT_ID_DATA = 1,
146   CONTEXT_INFO_DATA = 2,
147 };
148 
149 using ContextIDLayout =
150     llvm::BCRecordLayout<CONTEXT_ID_DATA, // record ID
151                          llvm::BCVBR<16>, // table offset within the blob (see
152                                           // below)
153                          llvm::BCBlob // map from ObjC class names/protocol (as
154                                       // IDs) to context IDs
155                          >;
156 
157 using ContextInfoLayout = llvm::BCRecordLayout<
158     CONTEXT_INFO_DATA, // record ID
159     llvm::BCVBR<16>,   // table offset within the blob (see below)
160     llvm::BCBlob       // map from ObjC context IDs to context information.
161     >;
162 } // namespace context_block
163 
164 namespace objc_property_block {
165 enum {
166   OBJC_PROPERTY_DATA = 1,
167 };
168 
169 using ObjCPropertyDataLayout = llvm::BCRecordLayout<
170     OBJC_PROPERTY_DATA, // record ID
171     llvm::BCVBR<16>,    // table offset within the blob (see below)
172     llvm::BCBlob        // map from ObjC (class name, property name) pairs to
173                         // ObjC property information
174     >;
175 } // namespace objc_property_block
176 
177 namespace objc_method_block {
178 enum {
179   OBJC_METHOD_DATA = 1,
180 };
181 
182 using ObjCMethodDataLayout =
183     llvm::BCRecordLayout<OBJC_METHOD_DATA, // record ID
184                          llvm::BCVBR<16>,  // table offset within the blob (see
185                                            // below)
186                          llvm::BCBlob // map from ObjC (class names, selector,
187                                       // is-instance-method) tuples to ObjC
188                                       // method information
189                          >;
190 } // namespace objc_method_block
191 
192 namespace cxx_method_block {
193 enum {
194   CXX_METHOD_DATA = 1,
195 };
196 
197 using CXXMethodDataLayout =
198     llvm::BCRecordLayout<CXX_METHOD_DATA, // record ID
199                          llvm::BCVBR<16>, // table offset within the blob (see
200                                           // below)
201                          llvm::BCBlob     // map from C++ (context id, name)
202                                           // tuples to C++ method information
203                          >;
204 } // namespace cxx_method_block
205 
206 namespace field_block {
207 enum {
208   FIELD_DATA = 1,
209 };
210 
211 using FieldDataLayout =
212     llvm::BCRecordLayout<FIELD_DATA,      // record ID
213                          llvm::BCVBR<16>, // table offset within the blob (see
214                                           // below)
215                          llvm::BCBlob     // map from C (context id, name)
216                                           // tuples to C field information
217                          >;
218 } // namespace field_block
219 
220 namespace objc_selector_block {
221 enum {
222   OBJC_SELECTOR_DATA = 1,
223 };
224 
225 using ObjCSelectorDataLayout =
226     llvm::BCRecordLayout<OBJC_SELECTOR_DATA, // record ID
227                          llvm::BCVBR<16>, // table offset within the blob (see
228                                           // below)
229                          llvm::BCBlob // map from (# pieces, identifier IDs) to
230                                       // Objective-C selector ID.
231                          >;
232 } // namespace objc_selector_block
233 
234 namespace global_variable_block {
235 enum { GLOBAL_VARIABLE_DATA = 1 };
236 
237 using GlobalVariableDataLayout = llvm::BCRecordLayout<
238     GLOBAL_VARIABLE_DATA, // record ID
239     llvm::BCVBR<16>,      // table offset within the blob (see below)
240     llvm::BCBlob          // map from name to global variable information
241     >;
242 } // namespace global_variable_block
243 
244 namespace global_function_block {
245 enum { GLOBAL_FUNCTION_DATA = 1 };
246 
247 using GlobalFunctionDataLayout = llvm::BCRecordLayout<
248     GLOBAL_FUNCTION_DATA, // record ID
249     llvm::BCVBR<16>,      // table offset within the blob (see below)
250     llvm::BCBlob          // map from name to global function information
251     >;
252 } // namespace global_function_block
253 
254 namespace tag_block {
255 enum { TAG_DATA = 1 };
256 
257 using TagDataLayout =
258     llvm::BCRecordLayout<TAG_DATA,        // record ID
259                          llvm::BCVBR<16>, // table offset within the blob (see
260                                           // below)
261                          llvm::BCBlob     // map from name to tag information
262                          >;
263 } // namespace tag_block
264 
265 namespace typedef_block {
266 enum { TYPEDEF_DATA = 1 };
267 
268 using TypedefDataLayout =
269     llvm::BCRecordLayout<TYPEDEF_DATA,    // record ID
270                          llvm::BCVBR<16>, // table offset within the blob (see
271                                           // below)
272                          llvm::BCBlob // map from name to typedef information
273                          >;
274 } // namespace typedef_block
275 
276 namespace enum_constant_block {
277 enum { ENUM_CONSTANT_DATA = 1 };
278 
279 using EnumConstantDataLayout =
280     llvm::BCRecordLayout<ENUM_CONSTANT_DATA, // record ID
281                          llvm::BCVBR<16>, // table offset within the blob (see
282                                           // below)
283                          llvm::BCBlob // map from name to enumerator information
284                          >;
285 } // namespace enum_constant_block
286 
287 /// A stored Objective-C selector.
288 struct StoredObjCSelector {
289   unsigned NumArgs;
290   llvm::SmallVector<IdentifierID, 2> Identifiers;
291 };
292 
293 /// A stored Objective-C or C++ context, represented by the ID of its parent
294 /// context, the kind of this context (Objective-C class / C++ namespace / etc),
295 /// and the ID of this context.
296 struct ContextTableKey {
297   uint32_t parentContextID;
298   uint8_t contextKind;
299   uint32_t contextID;
300 
301   ContextTableKey() : parentContextID(-1), contextKind(-1), contextID(-1) {}
302 
303   ContextTableKey(uint32_t parentContextID, uint8_t contextKind,
304                   uint32_t contextID)
305       : parentContextID(parentContextID), contextKind(contextKind),
306         contextID(contextID) {}
307 
308   ContextTableKey(std::optional<ContextID> ParentContextID, ContextKind Kind,
309                   uint32_t ContextID)
310       : parentContextID(ParentContextID ? ParentContextID->Value : -1),
311         contextKind(static_cast<uint8_t>(Kind)), contextID(ContextID) {}
312 
313   ContextTableKey(std::optional<Context> ParentContext, ContextKind Kind,
314                   uint32_t ContextID)
315       : ContextTableKey(ParentContext ? std::make_optional(ParentContext->id)
316                                       : std::nullopt,
317                         Kind, ContextID) {}
318 
319   llvm::hash_code hashValue() const {
320     return llvm::hash_value(
321         std::tuple{parentContextID, contextKind, contextID});
322   }
323 };
324 
325 inline bool operator==(const ContextTableKey &lhs, const ContextTableKey &rhs) {
326   return lhs.parentContextID == rhs.parentContextID &&
327          lhs.contextKind == rhs.contextKind && lhs.contextID == rhs.contextID;
328 }
329 
330 /// A stored Objective-C or C++ declaration, represented by the ID of its parent
331 /// context, and the name of the declaration.
332 struct SingleDeclTableKey {
333   uint32_t parentContextID;
334   uint32_t nameID;
335 
336   SingleDeclTableKey() : parentContextID(-1), nameID(-1) {}
337 
338   SingleDeclTableKey(uint32_t ParentContextID, uint32_t NameID)
339       : parentContextID(ParentContextID), nameID(NameID) {}
340 
341   SingleDeclTableKey(std::optional<Context> ParentCtx, IdentifierID NameID)
342       : parentContextID(ParentCtx ? ParentCtx->id.Value
343                                   : static_cast<uint32_t>(-1)),
344         nameID(NameID) {}
345 
346   llvm::hash_code hashValue() const {
347     return llvm::hash_value(std::make_pair(parentContextID, nameID));
348   }
349 };
350 
351 inline bool operator==(const SingleDeclTableKey &lhs,
352                        const SingleDeclTableKey &rhs) {
353   return lhs.parentContextID == rhs.parentContextID && lhs.nameID == rhs.nameID;
354 }
355 
356 } // namespace api_notes
357 } // namespace clang
358 
359 namespace llvm {
360 template <> struct DenseMapInfo<clang::api_notes::StoredObjCSelector> {
361   typedef DenseMapInfo<unsigned> UnsignedInfo;
362 
363   static inline clang::api_notes::StoredObjCSelector getEmptyKey() {
364     return clang::api_notes::StoredObjCSelector{UnsignedInfo::getEmptyKey(),
365                                                 {}};
366   }
367 
368   static inline clang::api_notes::StoredObjCSelector getTombstoneKey() {
369     return clang::api_notes::StoredObjCSelector{UnsignedInfo::getTombstoneKey(),
370                                                 {}};
371   }
372 
373   static unsigned
374   getHashValue(const clang::api_notes::StoredObjCSelector &Selector) {
375     auto hash = llvm::hash_value(Selector.NumArgs);
376     hash = hash_combine(hash, Selector.Identifiers.size());
377     for (auto piece : Selector.Identifiers)
378       hash = hash_combine(hash, static_cast<unsigned>(piece));
379     // FIXME: Mix upper/lower 32-bit values together to produce
380     // unsigned rather than truncating.
381     return hash;
382   }
383 
384   static bool isEqual(const clang::api_notes::StoredObjCSelector &LHS,
385                       const clang::api_notes::StoredObjCSelector &RHS) {
386     return LHS.NumArgs == RHS.NumArgs && LHS.Identifiers == RHS.Identifiers;
387   }
388 };
389 
390 template <> struct DenseMapInfo<clang::api_notes::ContextTableKey> {
391   static inline clang::api_notes::ContextTableKey getEmptyKey() {
392     return clang::api_notes::ContextTableKey();
393   }
394 
395   static inline clang::api_notes::ContextTableKey getTombstoneKey() {
396     return clang::api_notes::ContextTableKey{
397         DenseMapInfo<uint32_t>::getTombstoneKey(),
398         DenseMapInfo<uint8_t>::getTombstoneKey(),
399         DenseMapInfo<uint32_t>::getTombstoneKey()};
400   }
401 
402   static unsigned getHashValue(const clang::api_notes::ContextTableKey &value) {
403     return value.hashValue();
404   }
405 
406   static bool isEqual(const clang::api_notes::ContextTableKey &lhs,
407                       const clang::api_notes::ContextTableKey &rhs) {
408     return lhs == rhs;
409   }
410 };
411 
412 template <> struct DenseMapInfo<clang::api_notes::SingleDeclTableKey> {
413   static inline clang::api_notes::SingleDeclTableKey getEmptyKey() {
414     return clang::api_notes::SingleDeclTableKey();
415   }
416 
417   static inline clang::api_notes::SingleDeclTableKey getTombstoneKey() {
418     return clang::api_notes::SingleDeclTableKey{
419         DenseMapInfo<uint32_t>::getTombstoneKey(),
420         DenseMapInfo<uint32_t>::getTombstoneKey()};
421   }
422 
423   static unsigned
424   getHashValue(const clang::api_notes::SingleDeclTableKey &value) {
425     return value.hashValue();
426   }
427 
428   static bool isEqual(const clang::api_notes::SingleDeclTableKey &lhs,
429                       const clang::api_notes::SingleDeclTableKey &rhs) {
430     return lhs == rhs;
431   }
432 };
433 
434 } // namespace llvm
435 
436 #endif
437