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 | arg: 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{.NumArgs: UnsignedInfo::getEmptyKey(), |
295 | .Identifiers: {}}; |
296 | } |
297 | |
298 | static inline clang::api_notes::StoredObjCSelector getTombstoneKey() { |
299 | return clang::api_notes::StoredObjCSelector{.NumArgs: UnsignedInfo::getTombstoneKey(), |
300 | .Identifiers: {}}; |
301 | } |
302 | |
303 | static unsigned |
304 | getHashValue(const clang::api_notes::StoredObjCSelector &Selector) { |
305 | auto hash = llvm::hash_value(value: Selector.NumArgs); |
306 | hash = hash_combine(args: hash, args: Selector.Identifiers.size()); |
307 | for (auto piece : Selector.Identifiers) |
308 | hash = hash_combine(args: hash, args: 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 | |