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