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 = 34; // SwiftReturnOwnership 28 29 const uint8_t kSwiftConforms = 1; 30 const uint8_t kSwiftDoesNotConform = 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 fields data block, which maps names fields of C records to 76 /// information about the field. 77 FIELD_BLOCK_ID, 78 79 /// The global variables data block, which maps global variable names to 80 /// information about the global variable. 81 GLOBAL_VARIABLE_BLOCK_ID, 82 83 /// The (global) functions data block, which maps global function names to 84 /// information about the global function. 85 GLOBAL_FUNCTION_BLOCK_ID, 86 87 /// The tag data block, which maps tag names to information about 88 /// the tags. 89 TAG_BLOCK_ID, 90 91 /// The typedef data block, which maps typedef names to information about 92 /// the typedefs. 93 TYPEDEF_BLOCK_ID, 94 95 /// The enum constant data block, which maps enumerator names to 96 /// information about the enumerators. 97 ENUM_CONSTANT_BLOCK_ID, 98 }; 99 100 namespace control_block { 101 // These IDs must \em not be renumbered or reordered without incrementing 102 // VERSION_MAJOR. 103 enum { 104 METADATA = 1, 105 MODULE_NAME = 2, 106 MODULE_OPTIONS = 3, 107 SOURCE_FILE = 4, 108 }; 109 110 using MetadataLayout = 111 llvm::BCRecordLayout<METADATA, // ID 112 llvm::BCFixed<16>, // Module format major version 113 llvm::BCFixed<16> // Module format minor version 114 >; 115 116 using ModuleNameLayout = llvm::BCRecordLayout<MODULE_NAME, 117 llvm::BCBlob // Module name 118 >; 119 120 using ModuleOptionsLayout = 121 llvm::BCRecordLayout<MODULE_OPTIONS, 122 llvm::BCFixed<1> // SwiftInferImportAsMember 123 >; 124 125 using SourceFileLayout = llvm::BCRecordLayout<SOURCE_FILE, 126 llvm::BCVBR<16>, // file size 127 llvm::BCVBR<16> // creation time 128 >; 129 } // namespace control_block 130 131 namespace identifier_block { 132 enum { 133 IDENTIFIER_DATA = 1, 134 }; 135 136 using IdentifierDataLayout = llvm::BCRecordLayout< 137 IDENTIFIER_DATA, // record ID 138 llvm::BCVBR<16>, // table offset within the blob (see below) 139 llvm::BCBlob // map from identifier strings to decl kinds / decl IDs 140 >; 141 } // namespace identifier_block 142 143 namespace context_block { 144 enum { 145 CONTEXT_ID_DATA = 1, 146 CONTEXT_INFO_DATA = 2, 147 }; 148 149 using ContextIDLayout = 150 llvm::BCRecordLayout<CONTEXT_ID_DATA, // record ID 151 llvm::BCVBR<16>, // table offset within the blob (see 152 // below) 153 llvm::BCBlob // map from ObjC class names/protocol (as 154 // IDs) to context IDs 155 >; 156 157 using ContextInfoLayout = llvm::BCRecordLayout< 158 CONTEXT_INFO_DATA, // record ID 159 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_block 163 164 namespace objc_property_block { 165 enum { 166 OBJC_PROPERTY_DATA = 1, 167 }; 168 169 using ObjCPropertyDataLayout = llvm::BCRecordLayout< 170 OBJC_PROPERTY_DATA, // record ID 171 llvm::BCVBR<16>, // table offset within the blob (see below) 172 llvm::BCBlob // map from ObjC (class name, property name) pairs to 173 // ObjC property information 174 >; 175 } // namespace objc_property_block 176 177 namespace objc_method_block { 178 enum { 179 OBJC_METHOD_DATA = 1, 180 }; 181 182 using ObjCMethodDataLayout = 183 llvm::BCRecordLayout<OBJC_METHOD_DATA, // record ID 184 llvm::BCVBR<16>, // table offset within the blob (see 185 // below) 186 llvm::BCBlob // map from ObjC (class names, selector, 187 // is-instance-method) tuples to ObjC 188 // method information 189 >; 190 } // namespace objc_method_block 191 192 namespace cxx_method_block { 193 enum { 194 CXX_METHOD_DATA = 1, 195 }; 196 197 using CXXMethodDataLayout = 198 llvm::BCRecordLayout<CXX_METHOD_DATA, // record ID 199 llvm::BCVBR<16>, // table offset within the blob (see 200 // below) 201 llvm::BCBlob // map from C++ (context id, name) 202 // tuples to C++ method information 203 >; 204 } // namespace cxx_method_block 205 206 namespace field_block { 207 enum { 208 FIELD_DATA = 1, 209 }; 210 211 using FieldDataLayout = 212 llvm::BCRecordLayout<FIELD_DATA, // record ID 213 llvm::BCVBR<16>, // table offset within the blob (see 214 // below) 215 llvm::BCBlob // map from C (context id, name) 216 // tuples to C field information 217 >; 218 } // namespace field_block 219 220 namespace objc_selector_block { 221 enum { 222 OBJC_SELECTOR_DATA = 1, 223 }; 224 225 using ObjCSelectorDataLayout = 226 llvm::BCRecordLayout<OBJC_SELECTOR_DATA, // record ID 227 llvm::BCVBR<16>, // table offset within the blob (see 228 // below) 229 llvm::BCBlob // map from (# pieces, identifier IDs) to 230 // Objective-C selector ID. 231 >; 232 } // namespace objc_selector_block 233 234 namespace global_variable_block { 235 enum { GLOBAL_VARIABLE_DATA = 1 }; 236 237 using GlobalVariableDataLayout = llvm::BCRecordLayout< 238 GLOBAL_VARIABLE_DATA, // record ID 239 llvm::BCVBR<16>, // table offset within the blob (see below) 240 llvm::BCBlob // map from name to global variable information 241 >; 242 } // namespace global_variable_block 243 244 namespace global_function_block { 245 enum { GLOBAL_FUNCTION_DATA = 1 }; 246 247 using GlobalFunctionDataLayout = llvm::BCRecordLayout< 248 GLOBAL_FUNCTION_DATA, // record ID 249 llvm::BCVBR<16>, // table offset within the blob (see below) 250 llvm::BCBlob // map from name to global function information 251 >; 252 } // namespace global_function_block 253 254 namespace tag_block { 255 enum { TAG_DATA = 1 }; 256 257 using TagDataLayout = 258 llvm::BCRecordLayout<TAG_DATA, // record ID 259 llvm::BCVBR<16>, // table offset within the blob (see 260 // below) 261 llvm::BCBlob // map from name to tag information 262 >; 263 } // namespace tag_block 264 265 namespace typedef_block { 266 enum { TYPEDEF_DATA = 1 }; 267 268 using TypedefDataLayout = 269 llvm::BCRecordLayout<TYPEDEF_DATA, // record ID 270 llvm::BCVBR<16>, // table offset within the blob (see 271 // below) 272 llvm::BCBlob // map from name to typedef information 273 >; 274 } // namespace typedef_block 275 276 namespace enum_constant_block { 277 enum { ENUM_CONSTANT_DATA = 1 }; 278 279 using EnumConstantDataLayout = 280 llvm::BCRecordLayout<ENUM_CONSTANT_DATA, // record ID 281 llvm::BCVBR<16>, // table offset within the blob (see 282 // below) 283 llvm::BCBlob // map from name to enumerator information 284 >; 285 } // namespace enum_constant_block 286 287 /// A stored Objective-C selector. 288 struct 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 parent 294 /// context, the kind of this context (Objective-C class / C++ namespace / etc), 295 /// and the ID of this context. 296 struct 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 325 inline 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 parent 331 /// context, and the name of the declaration. 332 struct 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.Value 343 : 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 351 inline bool operator==(const SingleDeclTableKey &lhs, 352 const SingleDeclTableKey &rhs) { 353 return lhs.parentContextID == rhs.parentContextID && lhs.nameID == rhs.nameID; 354 } 355 356 } // namespace api_notes 357 } // namespace clang 358 359 namespace llvm { 360 template <> 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 unsigned 374 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 produce 380 // 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 390 template <> 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 412 template <> 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 unsigned 424 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 llvm 435 436 #endif 437