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 = 25; // SwiftImportAs
28 
29 using IdentifierID = llvm::PointerEmbeddedInt<unsigned, 31>;
30 using IdentifierIDField = llvm::BCVBR<16>;
31 
32 using SelectorID = llvm::PointerEmbeddedInt<unsigned, 31>;
33 using SelectorIDField = llvm::BCVBR<16>;
34 
35 /// The various types of blocks that can occur within a API notes file.
36 ///
37 /// These IDs must \em not be renumbered or reordered without incrementing
38 /// VERSION_MAJOR.
39 enum BlockID {
40   /// The control block, which contains all of the information that needs to
41   /// be validated prior to committing to loading the API notes file.
42   ///
43   /// \sa control_block
44   CONTROL_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID,
45 
46   /// The identifier data block, which maps identifier strings to IDs.
47   IDENTIFIER_BLOCK_ID,
48 
49   /// The Objective-C context data block, which contains information about
50   /// Objective-C classes and protocols.
51   OBJC_CONTEXT_BLOCK_ID,
52 
53   /// The Objective-C property data block, which maps Objective-C
54   /// (class name, property name) pairs to information about the
55   /// property.
56   OBJC_PROPERTY_BLOCK_ID,
57 
58   /// The Objective-C property data block, which maps Objective-C
59   /// (class name, selector, is_instance_method) tuples to information
60   /// about the method.
61   OBJC_METHOD_BLOCK_ID,
62 
63   /// The Objective-C selector data block, which maps Objective-C
64   /// selector names (# of pieces, identifier IDs) to the selector ID
65   /// used in other tables.
66   OBJC_SELECTOR_BLOCK_ID,
67 
68   /// The global variables data block, which maps global variable names to
69   /// information about the global variable.
70   GLOBAL_VARIABLE_BLOCK_ID,
71 
72   /// The (global) functions data block, which maps global function names to
73   /// information about the global function.
74   GLOBAL_FUNCTION_BLOCK_ID,
75 
76   /// The tag data block, which maps tag names to information about
77   /// the tags.
78   TAG_BLOCK_ID,
79 
80   /// The typedef data block, which maps typedef names to information about
81   /// the typedefs.
82   TYPEDEF_BLOCK_ID,
83 
84   /// The enum constant data block, which maps enumerator names to
85   /// information about the enumerators.
86   ENUM_CONSTANT_BLOCK_ID,
87 };
88 
89 namespace control_block {
90 // These IDs must \em not be renumbered or reordered without incrementing
91 // VERSION_MAJOR.
92 enum {
93   METADATA = 1,
94   MODULE_NAME = 2,
95   MODULE_OPTIONS = 3,
96   SOURCE_FILE = 4,
97 };
98 
99 using MetadataLayout =
100     llvm::BCRecordLayout<METADATA,          // ID
101                          llvm::BCFixed<16>, // Module format major version
102                          llvm::BCFixed<16>  // Module format minor version
103                          >;
104 
105 using ModuleNameLayout = llvm::BCRecordLayout<MODULE_NAME,
106                                               llvm::BCBlob // Module name
107                                               >;
108 
109 using ModuleOptionsLayout =
110     llvm::BCRecordLayout<MODULE_OPTIONS,
111                          llvm::BCFixed<1> // SwiftInferImportAsMember
112                          >;
113 
114 using SourceFileLayout = llvm::BCRecordLayout<SOURCE_FILE,
115                                               llvm::BCVBR<16>, // file size
116                                               llvm::BCVBR<16>  // creation time
117                                               >;
118 } // namespace control_block
119 
120 namespace identifier_block {
121 enum {
122   IDENTIFIER_DATA = 1,
123 };
124 
125 using IdentifierDataLayout = llvm::BCRecordLayout<
126     IDENTIFIER_DATA, // record ID
127     llvm::BCVBR<16>, // table offset within the blob (see below)
128     llvm::BCBlob     // map from identifier strings to decl kinds / decl IDs
129     >;
130 } // namespace identifier_block
131 
132 namespace objc_context_block {
133 enum {
134   OBJC_CONTEXT_ID_DATA = 1,
135   OBJC_CONTEXT_INFO_DATA = 2,
136 };
137 
138 using ObjCContextIDLayout =
139     llvm::BCRecordLayout<OBJC_CONTEXT_ID_DATA, // record ID
140                          llvm::BCVBR<16>, // table offset within the blob (see
141                                           // below)
142                          llvm::BCBlob // map from ObjC class names/protocol (as
143                                       // IDs) to context IDs
144                          >;
145 
146 using ObjCContextInfoLayout = llvm::BCRecordLayout<
147     OBJC_CONTEXT_INFO_DATA, // record ID
148     llvm::BCVBR<16>,        // table offset within the blob (see below)
149     llvm::BCBlob            // map from ObjC context IDs to context information.
150     >;
151 } // namespace objc_context_block
152 
153 namespace objc_property_block {
154 enum {
155   OBJC_PROPERTY_DATA = 1,
156 };
157 
158 using ObjCPropertyDataLayout = llvm::BCRecordLayout<
159     OBJC_PROPERTY_DATA, // record ID
160     llvm::BCVBR<16>,    // table offset within the blob (see below)
161     llvm::BCBlob        // map from ObjC (class name, property name) pairs to
162                         // ObjC property information
163     >;
164 } // namespace objc_property_block
165 
166 namespace objc_method_block {
167 enum {
168   OBJC_METHOD_DATA = 1,
169 };
170 
171 using ObjCMethodDataLayout =
172     llvm::BCRecordLayout<OBJC_METHOD_DATA, // record ID
173                          llvm::BCVBR<16>,  // table offset within the blob (see
174                                            // below)
175                          llvm::BCBlob // map from ObjC (class names, selector,
176                                       // is-instance-method) tuples to ObjC
177                                       // method information
178                          >;
179 } // namespace objc_method_block
180 
181 namespace objc_selector_block {
182 enum {
183   OBJC_SELECTOR_DATA = 1,
184 };
185 
186 using ObjCSelectorDataLayout =
187     llvm::BCRecordLayout<OBJC_SELECTOR_DATA, // record ID
188                          llvm::BCVBR<16>, // table offset within the blob (see
189                                           // below)
190                          llvm::BCBlob // map from (# pieces, identifier IDs) to
191                                       // Objective-C selector ID.
192                          >;
193 } // namespace objc_selector_block
194 
195 namespace global_variable_block {
196 enum { GLOBAL_VARIABLE_DATA = 1 };
197 
198 using GlobalVariableDataLayout = llvm::BCRecordLayout<
199     GLOBAL_VARIABLE_DATA, // record ID
200     llvm::BCVBR<16>,      // table offset within the blob (see below)
201     llvm::BCBlob          // map from name to global variable information
202     >;
203 } // namespace global_variable_block
204 
205 namespace global_function_block {
206 enum { GLOBAL_FUNCTION_DATA = 1 };
207 
208 using GlobalFunctionDataLayout = llvm::BCRecordLayout<
209     GLOBAL_FUNCTION_DATA, // record ID
210     llvm::BCVBR<16>,      // table offset within the blob (see below)
211     llvm::BCBlob          // map from name to global function information
212     >;
213 } // namespace global_function_block
214 
215 namespace tag_block {
216 enum { TAG_DATA = 1 };
217 
218 using TagDataLayout =
219     llvm::BCRecordLayout<TAG_DATA,        // record ID
220                          llvm::BCVBR<16>, // table offset within the blob (see
221                                           // below)
222                          llvm::BCBlob     // map from name to tag information
223                          >;
224 } // namespace tag_block
225 
226 namespace typedef_block {
227 enum { TYPEDEF_DATA = 1 };
228 
229 using TypedefDataLayout =
230     llvm::BCRecordLayout<TYPEDEF_DATA,    // record ID
231                          llvm::BCVBR<16>, // table offset within the blob (see
232                                           // below)
233                          llvm::BCBlob // map from name to typedef information
234                          >;
235 } // namespace typedef_block
236 
237 namespace enum_constant_block {
238 enum { ENUM_CONSTANT_DATA = 1 };
239 
240 using EnumConstantDataLayout =
241     llvm::BCRecordLayout<ENUM_CONSTANT_DATA, // record ID
242                          llvm::BCVBR<16>, // table offset within the blob (see
243                                           // below)
244                          llvm::BCBlob // map from name to enumerator information
245                          >;
246 } // namespace enum_constant_block
247 
248 /// A stored Objective-C selector.
249 struct StoredObjCSelector {
250   unsigned NumArgs;
251   llvm::SmallVector<IdentifierID, 2> Identifiers;
252 };
253 
254 /// A stored Objective-C or C++ context, represented by the ID of its parent
255 /// context, the kind of this context (Objective-C class / C++ namespace / etc),
256 /// and the ID of this context.
257 struct ContextTableKey {
258   uint32_t parentContextID;
259   uint8_t contextKind;
260   uint32_t contextID;
261 
262   ContextTableKey() : parentContextID(-1), contextKind(-1), contextID(-1) {}
263 
264   ContextTableKey(uint32_t parentContextID, uint8_t contextKind,
265                   uint32_t contextID)
266       : parentContextID(parentContextID), contextKind(contextKind),
267         contextID(contextID) {}
268 
269   ContextTableKey(std::optional<Context> context, IdentifierID nameID)
270       : parentContextID(context ? context->id.Value : (uint32_t)-1),
271         contextKind(context ? static_cast<uint8_t>(context->kind)
272                             : static_cast<uint8_t>(-1)),
273         contextID(nameID) {}
274 
275   llvm::hash_code hashValue() const {
276     return llvm::hash_value(
277         std::tuple{parentContextID, contextKind, contextID});
278   }
279 };
280 
281 inline bool operator==(const ContextTableKey &lhs, const ContextTableKey &rhs) {
282   return lhs.parentContextID == rhs.parentContextID &&
283          lhs.contextKind == rhs.contextKind && lhs.contextID == rhs.contextID;
284 }
285 
286 } // namespace api_notes
287 } // namespace clang
288 
289 namespace llvm {
290 template <> struct DenseMapInfo<clang::api_notes::StoredObjCSelector> {
291   typedef DenseMapInfo<unsigned> UnsignedInfo;
292 
293   static inline clang::api_notes::StoredObjCSelector getEmptyKey() {
294     return clang::api_notes::StoredObjCSelector{UnsignedInfo::getEmptyKey(),
295                                                 {}};
296   }
297 
298   static inline clang::api_notes::StoredObjCSelector getTombstoneKey() {
299     return clang::api_notes::StoredObjCSelector{UnsignedInfo::getTombstoneKey(),
300                                                 {}};
301   }
302 
303   static unsigned
304   getHashValue(const clang::api_notes::StoredObjCSelector &Selector) {
305     auto hash = llvm::hash_value(Selector.NumArgs);
306     hash = hash_combine(hash, Selector.Identifiers.size());
307     for (auto piece : Selector.Identifiers)
308       hash = hash_combine(hash, static_cast<unsigned>(piece));
309     // FIXME: Mix upper/lower 32-bit values together to produce
310     // unsigned rather than truncating.
311     return hash;
312   }
313 
314   static bool isEqual(const clang::api_notes::StoredObjCSelector &LHS,
315                       const clang::api_notes::StoredObjCSelector &RHS) {
316     return LHS.NumArgs == RHS.NumArgs && LHS.Identifiers == RHS.Identifiers;
317   }
318 };
319 
320 template <> struct DenseMapInfo<clang::api_notes::ContextTableKey> {
321   static inline clang::api_notes::ContextTableKey getEmptyKey() {
322     return clang::api_notes::ContextTableKey();
323   }
324 
325   static inline clang::api_notes::ContextTableKey getTombstoneKey() {
326     return clang::api_notes::ContextTableKey{
327         DenseMapInfo<uint32_t>::getTombstoneKey(),
328         DenseMapInfo<uint8_t>::getTombstoneKey(),
329         DenseMapInfo<uint32_t>::getTombstoneKey()};
330   }
331 
332   static unsigned getHashValue(const clang::api_notes::ContextTableKey &value) {
333     return value.hashValue();
334   }
335 
336   static bool isEqual(const clang::api_notes::ContextTableKey &lhs,
337                       const clang::api_notes::ContextTableKey &rhs) {
338     return lhs == rhs;
339   }
340 };
341 } // namespace llvm
342 
343 #endif
344