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(ParentContext->id) 298 : std::nullopt, 299 Kind, ContextID) {} 300 301 llvm::hash_code hashValue() const { 302 return llvm::hash_value( 303 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(std::make_pair(parentContextID, 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{UnsignedInfo::getEmptyKey(), 347 {}}; 348 } 349 350 static inline clang::api_notes::StoredObjCSelector getTombstoneKey() { 351 return clang::api_notes::StoredObjCSelector{UnsignedInfo::getTombstoneKey(), 352 {}}; 353 } 354 355 static unsigned 356 getHashValue(const clang::api_notes::StoredObjCSelector &Selector) { 357 auto hash = llvm::hash_value(Selector.NumArgs); 358 hash = hash_combine(hash, Selector.Identifiers.size()); 359 for (auto piece : Selector.Identifiers) 360 hash = hash_combine(hash, 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