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