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