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 | |
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 | |
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 | |
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 | |
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{.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 | |
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 | |