437 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_CLANG_LIB_APINOTES_APINOTESFORMAT_H10#define LLVM_CLANG_LIB_APINOTES_APINOTESFORMAT_H11 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 = 38; // SwiftSafety28 29const uint8_t kSwiftConforms = 1;30const uint8_t kSwiftDoesNotConform = 2;31 32using IdentifierID = llvm::PointerEmbeddedInt<unsigned, 31>;33using IdentifierIDField = llvm::BCVBR<16>;34 35using SelectorID = llvm::PointerEmbeddedInt<unsigned, 31>;36using 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 incrementing41/// VERSION_MAJOR.42enum BlockID {43 /// The control block, which contains all of the information that needs to44 /// be validated prior to committing to loading the API notes file.45 ///46 /// \sa control_block47 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 about53 /// Objective-C classes and protocols.54 OBJC_CONTEXT_BLOCK_ID,55 56 /// The Objective-C property data block, which maps Objective-C57 /// (class name, property name) pairs to information about the58 /// property.59 OBJC_PROPERTY_BLOCK_ID,60 61 /// The Objective-C property data block, which maps Objective-C62 /// (class name, selector, is_instance_method) tuples to information63 /// about the method.64 OBJC_METHOD_BLOCK_ID,65 66 /// The C++ method data block, which maps C++ (context id, method name) pairs67 /// to information about the method.68 CXX_METHOD_BLOCK_ID,69 70 /// The Objective-C selector data block, which maps Objective-C71 /// selector names (# of pieces, identifier IDs) to the selector ID72 /// used in other tables.73 OBJC_SELECTOR_BLOCK_ID,74 75 /// The fields data block, which maps names fields of C records to76 /// information about the field.77 FIELD_BLOCK_ID,78 79 /// The global variables data block, which maps global variable names to80 /// information about the global variable.81 GLOBAL_VARIABLE_BLOCK_ID,82 83 /// The (global) functions data block, which maps global function names to84 /// information about the global function.85 GLOBAL_FUNCTION_BLOCK_ID,86 87 /// The tag data block, which maps tag names to information about88 /// the tags.89 TAG_BLOCK_ID,90 91 /// The typedef data block, which maps typedef names to information about92 /// the typedefs.93 TYPEDEF_BLOCK_ID,94 95 /// The enum constant data block, which maps enumerator names to96 /// information about the enumerators.97 ENUM_CONSTANT_BLOCK_ID,98};99 100namespace control_block {101// These IDs must \em not be renumbered or reordered without incrementing102// VERSION_MAJOR.103enum {104 METADATA = 1,105 MODULE_NAME = 2,106 MODULE_OPTIONS = 3,107 SOURCE_FILE = 4,108};109 110using MetadataLayout =111 llvm::BCRecordLayout<METADATA, // ID112 llvm::BCFixed<16>, // Module format major version113 llvm::BCFixed<16> // Module format minor version114 >;115 116using ModuleNameLayout = llvm::BCRecordLayout<MODULE_NAME,117 llvm::BCBlob // Module name118 >;119 120using ModuleOptionsLayout =121 llvm::BCRecordLayout<MODULE_OPTIONS,122 llvm::BCFixed<1> // SwiftInferImportAsMember123 >;124 125using SourceFileLayout = llvm::BCRecordLayout<SOURCE_FILE,126 llvm::BCVBR<16>, // file size127 llvm::BCVBR<16> // creation time128 >;129} // namespace control_block130 131namespace identifier_block {132enum {133 IDENTIFIER_DATA = 1,134};135 136using IdentifierDataLayout = llvm::BCRecordLayout<137 IDENTIFIER_DATA, // record ID138 llvm::BCVBR<16>, // table offset within the blob (see below)139 llvm::BCBlob // map from identifier strings to decl kinds / decl IDs140 >;141} // namespace identifier_block142 143namespace context_block {144enum {145 CONTEXT_ID_DATA = 1,146 CONTEXT_INFO_DATA = 2,147};148 149using ContextIDLayout =150 llvm::BCRecordLayout<CONTEXT_ID_DATA, // record ID151 llvm::BCVBR<16>, // table offset within the blob (see152 // below)153 llvm::BCBlob // map from ObjC class names/protocol (as154 // IDs) to context IDs155 >;156 157using ContextInfoLayout = llvm::BCRecordLayout<158 CONTEXT_INFO_DATA, // record ID159 llvm::BCVBR<16>, // table offset within the blob (see below)160 llvm::BCBlob // map from ObjC context IDs to context information.161 >;162} // namespace context_block163 164namespace objc_property_block {165enum {166 OBJC_PROPERTY_DATA = 1,167};168 169using ObjCPropertyDataLayout = llvm::BCRecordLayout<170 OBJC_PROPERTY_DATA, // record ID171 llvm::BCVBR<16>, // table offset within the blob (see below)172 llvm::BCBlob // map from ObjC (class name, property name) pairs to173 // ObjC property information174 >;175} // namespace objc_property_block176 177namespace objc_method_block {178enum {179 OBJC_METHOD_DATA = 1,180};181 182using ObjCMethodDataLayout =183 llvm::BCRecordLayout<OBJC_METHOD_DATA, // record ID184 llvm::BCVBR<16>, // table offset within the blob (see185 // below)186 llvm::BCBlob // map from ObjC (class names, selector,187 // is-instance-method) tuples to ObjC188 // method information189 >;190} // namespace objc_method_block191 192namespace cxx_method_block {193enum {194 CXX_METHOD_DATA = 1,195};196 197using CXXMethodDataLayout =198 llvm::BCRecordLayout<CXX_METHOD_DATA, // record ID199 llvm::BCVBR<16>, // table offset within the blob (see200 // below)201 llvm::BCBlob // map from C++ (context id, name)202 // tuples to C++ method information203 >;204} // namespace cxx_method_block205 206namespace field_block {207enum {208 FIELD_DATA = 1,209};210 211using FieldDataLayout =212 llvm::BCRecordLayout<FIELD_DATA, // record ID213 llvm::BCVBR<16>, // table offset within the blob (see214 // below)215 llvm::BCBlob // map from C (context id, name)216 // tuples to C field information217 >;218} // namespace field_block219 220namespace objc_selector_block {221enum {222 OBJC_SELECTOR_DATA = 1,223};224 225using ObjCSelectorDataLayout =226 llvm::BCRecordLayout<OBJC_SELECTOR_DATA, // record ID227 llvm::BCVBR<16>, // table offset within the blob (see228 // below)229 llvm::BCBlob // map from (# pieces, identifier IDs) to230 // Objective-C selector ID.231 >;232} // namespace objc_selector_block233 234namespace global_variable_block {235enum { GLOBAL_VARIABLE_DATA = 1 };236 237using GlobalVariableDataLayout = llvm::BCRecordLayout<238 GLOBAL_VARIABLE_DATA, // record ID239 llvm::BCVBR<16>, // table offset within the blob (see below)240 llvm::BCBlob // map from name to global variable information241 >;242} // namespace global_variable_block243 244namespace global_function_block {245enum { GLOBAL_FUNCTION_DATA = 1 };246 247using GlobalFunctionDataLayout = llvm::BCRecordLayout<248 GLOBAL_FUNCTION_DATA, // record ID249 llvm::BCVBR<16>, // table offset within the blob (see below)250 llvm::BCBlob // map from name to global function information251 >;252} // namespace global_function_block253 254namespace tag_block {255enum { TAG_DATA = 1 };256 257using TagDataLayout =258 llvm::BCRecordLayout<TAG_DATA, // record ID259 llvm::BCVBR<16>, // table offset within the blob (see260 // below)261 llvm::BCBlob // map from name to tag information262 >;263} // namespace tag_block264 265namespace typedef_block {266enum { TYPEDEF_DATA = 1 };267 268using TypedefDataLayout =269 llvm::BCRecordLayout<TYPEDEF_DATA, // record ID270 llvm::BCVBR<16>, // table offset within the blob (see271 // below)272 llvm::BCBlob // map from name to typedef information273 >;274} // namespace typedef_block275 276namespace enum_constant_block {277enum { ENUM_CONSTANT_DATA = 1 };278 279using EnumConstantDataLayout =280 llvm::BCRecordLayout<ENUM_CONSTANT_DATA, // record ID281 llvm::BCVBR<16>, // table offset within the blob (see282 // below)283 llvm::BCBlob // map from name to enumerator information284 >;285} // namespace enum_constant_block286 287/// A stored Objective-C selector.288struct StoredObjCSelector {289 unsigned NumArgs;290 llvm::SmallVector<IdentifierID, 2> Identifiers;291};292 293/// A stored Objective-C or C++ context, represented by the ID of its parent294/// context, the kind of this context (Objective-C class / C++ namespace / etc),295/// and the ID of this context.296struct ContextTableKey {297 uint32_t parentContextID;298 uint8_t contextKind;299 uint32_t contextID;300 301 ContextTableKey() : parentContextID(-1), contextKind(-1), contextID(-1) {}302 303 ContextTableKey(uint32_t parentContextID, uint8_t contextKind,304 uint32_t contextID)305 : parentContextID(parentContextID), contextKind(contextKind),306 contextID(contextID) {}307 308 ContextTableKey(std::optional<ContextID> ParentContextID, ContextKind Kind,309 uint32_t ContextID)310 : parentContextID(ParentContextID ? ParentContextID->Value : -1),311 contextKind(static_cast<uint8_t>(Kind)), contextID(ContextID) {}312 313 ContextTableKey(std::optional<Context> ParentContext, ContextKind Kind,314 uint32_t ContextID)315 : ContextTableKey(ParentContext ? std::make_optional(ParentContext->id)316 : std::nullopt,317 Kind, ContextID) {}318 319 llvm::hash_code hashValue() const {320 return llvm::hash_value(321 std::tuple{parentContextID, contextKind, contextID});322 }323};324 325inline bool operator==(const ContextTableKey &lhs, const ContextTableKey &rhs) {326 return lhs.parentContextID == rhs.parentContextID &&327 lhs.contextKind == rhs.contextKind && lhs.contextID == rhs.contextID;328}329 330/// A stored Objective-C or C++ declaration, represented by the ID of its parent331/// context, and the name of the declaration.332struct SingleDeclTableKey {333 uint32_t parentContextID;334 uint32_t nameID;335 336 SingleDeclTableKey() : parentContextID(-1), nameID(-1) {}337 338 SingleDeclTableKey(uint32_t ParentContextID, uint32_t NameID)339 : parentContextID(ParentContextID), nameID(NameID) {}340 341 SingleDeclTableKey(std::optional<Context> ParentCtx, IdentifierID NameID)342 : parentContextID(ParentCtx ? ParentCtx->id.Value343 : static_cast<uint32_t>(-1)),344 nameID(NameID) {}345 346 llvm::hash_code hashValue() const {347 return llvm::hash_value(std::make_pair(parentContextID, nameID));348 }349};350 351inline bool operator==(const SingleDeclTableKey &lhs,352 const SingleDeclTableKey &rhs) {353 return lhs.parentContextID == rhs.parentContextID && lhs.nameID == rhs.nameID;354}355 356} // namespace api_notes357} // namespace clang358 359namespace llvm {360template <> struct DenseMapInfo<clang::api_notes::StoredObjCSelector> {361 typedef DenseMapInfo<unsigned> UnsignedInfo;362 363 static inline clang::api_notes::StoredObjCSelector getEmptyKey() {364 return clang::api_notes::StoredObjCSelector{UnsignedInfo::getEmptyKey(),365 {}};366 }367 368 static inline clang::api_notes::StoredObjCSelector getTombstoneKey() {369 return clang::api_notes::StoredObjCSelector{UnsignedInfo::getTombstoneKey(),370 {}};371 }372 373 static unsigned374 getHashValue(const clang::api_notes::StoredObjCSelector &Selector) {375 auto hash = llvm::hash_value(Selector.NumArgs);376 hash = hash_combine(hash, Selector.Identifiers.size());377 for (auto piece : Selector.Identifiers)378 hash = hash_combine(hash, static_cast<unsigned>(piece));379 // FIXME: Mix upper/lower 32-bit values together to produce380 // unsigned rather than truncating.381 return hash;382 }383 384 static bool isEqual(const clang::api_notes::StoredObjCSelector &LHS,385 const clang::api_notes::StoredObjCSelector &RHS) {386 return LHS.NumArgs == RHS.NumArgs && LHS.Identifiers == RHS.Identifiers;387 }388};389 390template <> struct DenseMapInfo<clang::api_notes::ContextTableKey> {391 static inline clang::api_notes::ContextTableKey getEmptyKey() {392 return clang::api_notes::ContextTableKey();393 }394 395 static inline clang::api_notes::ContextTableKey getTombstoneKey() {396 return clang::api_notes::ContextTableKey{397 DenseMapInfo<uint32_t>::getTombstoneKey(),398 DenseMapInfo<uint8_t>::getTombstoneKey(),399 DenseMapInfo<uint32_t>::getTombstoneKey()};400 }401 402 static unsigned getHashValue(const clang::api_notes::ContextTableKey &value) {403 return value.hashValue();404 }405 406 static bool isEqual(const clang::api_notes::ContextTableKey &lhs,407 const clang::api_notes::ContextTableKey &rhs) {408 return lhs == rhs;409 }410};411 412template <> struct DenseMapInfo<clang::api_notes::SingleDeclTableKey> {413 static inline clang::api_notes::SingleDeclTableKey getEmptyKey() {414 return clang::api_notes::SingleDeclTableKey();415 }416 417 static inline clang::api_notes::SingleDeclTableKey getTombstoneKey() {418 return clang::api_notes::SingleDeclTableKey{419 DenseMapInfo<uint32_t>::getTombstoneKey(),420 DenseMapInfo<uint32_t>::getTombstoneKey()};421 }422 423 static unsigned424 getHashValue(const clang::api_notes::SingleDeclTableKey &value) {425 return value.hashValue();426 }427 428 static bool isEqual(const clang::api_notes::SingleDeclTableKey &lhs,429 const clang::api_notes::SingleDeclTableKey &rhs) {430 return lhs == rhs;431 }432};433 434} // namespace llvm435 436#endif437