1 //===--- APINotesReader.cpp - API Notes Reader ------------------*- 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 #include "clang/APINotes/APINotesReader.h" 10 #include "APINotesFormat.h" 11 #include "llvm/ADT/Hashing.h" 12 #include "llvm/ADT/StringExtras.h" 13 #include "llvm/Bitstream/BitstreamReader.h" 14 #include "llvm/Support/DJB.h" 15 #include "llvm/Support/EndianStream.h" 16 #include "llvm/Support/OnDiskHashTable.h" 17 18 namespace clang { 19 namespace api_notes { 20 using namespace llvm::support; 21 22 namespace { 23 /// Deserialize a version tuple. 24 llvm::VersionTuple ReadVersionTuple(const uint8_t *&Data) { 25 uint8_t NumVersions = (*Data++) & 0x03; 26 27 unsigned Major = 28 endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); 29 if (NumVersions == 0) 30 return llvm::VersionTuple(Major); 31 32 unsigned Minor = 33 endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); 34 if (NumVersions == 1) 35 return llvm::VersionTuple(Major, Minor); 36 37 unsigned Subminor = 38 endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); 39 if (NumVersions == 2) 40 return llvm::VersionTuple(Major, Minor, Subminor); 41 42 unsigned Build = 43 endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); 44 return llvm::VersionTuple(Major, Minor, Subminor, Build); 45 } 46 47 /// An on-disk hash table whose data is versioned based on the Swift version. 48 template <typename Derived, typename KeyType, typename UnversionedDataType> 49 class VersionedTableInfo { 50 public: 51 using internal_key_type = KeyType; 52 using external_key_type = KeyType; 53 using data_type = 54 llvm::SmallVector<std::pair<llvm::VersionTuple, UnversionedDataType>, 1>; 55 using hash_value_type = size_t; 56 using offset_type = unsigned; 57 58 internal_key_type GetInternalKey(external_key_type Key) { return Key; } 59 60 external_key_type GetExternalKey(internal_key_type Key) { return Key; } 61 62 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) { 63 return LHS == RHS; 64 } 65 66 static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) { 67 unsigned KeyLength = 68 endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data); 69 unsigned DataLength = 70 endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data); 71 return {KeyLength, DataLength}; 72 } 73 74 static data_type ReadData(internal_key_type Key, const uint8_t *Data, 75 unsigned Length) { 76 unsigned NumElements = 77 endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data); 78 data_type Result; 79 Result.reserve(NumElements); 80 for (unsigned i = 0; i != NumElements; ++i) { 81 auto version = ReadVersionTuple(Data); 82 const auto *DataBefore = Data; 83 (void)DataBefore; 84 assert(Data != DataBefore && 85 "Unversioned data reader didn't move pointer"); 86 auto UnversionedData = Derived::readUnversioned(Key, Data); 87 Result.push_back({version, UnversionedData}); 88 } 89 return Result; 90 } 91 }; 92 93 /// Read serialized CommonEntityInfo. 94 void ReadCommonEntityInfo(const uint8_t *&Data, CommonEntityInfo &Info) { 95 uint8_t UnavailableBits = *Data++; 96 Info.Unavailable = (UnavailableBits >> 1) & 0x01; 97 Info.UnavailableInSwift = UnavailableBits & 0x01; 98 if ((UnavailableBits >> 2) & 0x01) 99 Info.setSwiftPrivate(static_cast<bool>((UnavailableBits >> 3) & 0x01)); 100 101 unsigned MsgLength = 102 endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data); 103 Info.UnavailableMsg = 104 std::string(reinterpret_cast<const char *>(Data), 105 reinterpret_cast<const char *>(Data) + MsgLength); 106 Data += MsgLength; 107 108 unsigned SwiftNameLength = 109 endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data); 110 Info.SwiftName = 111 std::string(reinterpret_cast<const char *>(Data), 112 reinterpret_cast<const char *>(Data) + SwiftNameLength); 113 Data += SwiftNameLength; 114 } 115 116 /// Read serialized CommonTypeInfo. 117 void ReadCommonTypeInfo(const uint8_t *&Data, CommonTypeInfo &Info) { 118 ReadCommonEntityInfo(Data, Info); 119 120 unsigned SwiftBridgeLength = 121 endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data); 122 if (SwiftBridgeLength > 0) { 123 Info.setSwiftBridge(std::string(reinterpret_cast<const char *>(Data), 124 SwiftBridgeLength - 1)); 125 Data += SwiftBridgeLength - 1; 126 } 127 128 unsigned ErrorDomainLength = 129 endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data); 130 if (ErrorDomainLength > 0) { 131 Info.setNSErrorDomain(std::optional<std::string>(std::string( 132 reinterpret_cast<const char *>(Data), ErrorDomainLength - 1))); 133 Data += ErrorDomainLength - 1; 134 } 135 } 136 137 /// Used to deserialize the on-disk identifier table. 138 class IdentifierTableInfo { 139 public: 140 using internal_key_type = llvm::StringRef; 141 using external_key_type = llvm::StringRef; 142 using data_type = IdentifierID; 143 using hash_value_type = uint32_t; 144 using offset_type = unsigned; 145 146 internal_key_type GetInternalKey(external_key_type Key) { return Key; } 147 148 external_key_type GetExternalKey(internal_key_type Key) { return Key; } 149 150 hash_value_type ComputeHash(internal_key_type Key) { 151 return llvm::hash_value(Key); 152 } 153 154 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) { 155 return LHS == RHS; 156 } 157 158 static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) { 159 unsigned KeyLength = 160 endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data); 161 unsigned DataLength = 162 endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data); 163 return {KeyLength, DataLength}; 164 } 165 166 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { 167 return llvm::StringRef(reinterpret_cast<const char *>(Data), Length); 168 } 169 170 static data_type ReadData(internal_key_type key, const uint8_t *Data, 171 unsigned Length) { 172 return endian::readNext<uint32_t, llvm::endianness::little, unaligned>( 173 Data); 174 } 175 }; 176 177 /// Used to deserialize the on-disk Objective-C class table. 178 class ObjCContextIDTableInfo { 179 public: 180 using internal_key_type = ContextTableKey; 181 using external_key_type = internal_key_type; 182 using data_type = unsigned; 183 using hash_value_type = size_t; 184 using offset_type = unsigned; 185 186 internal_key_type GetInternalKey(external_key_type Key) { return Key; } 187 188 external_key_type GetExternalKey(internal_key_type Key) { return Key; } 189 190 hash_value_type ComputeHash(internal_key_type Key) { 191 return static_cast<size_t>(Key.hashValue()); 192 } 193 194 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) { 195 return LHS == RHS; 196 } 197 198 static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) { 199 unsigned KeyLength = 200 endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data); 201 unsigned DataLength = 202 endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data); 203 return {KeyLength, DataLength}; 204 } 205 206 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { 207 auto ParentCtxID = 208 endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); 209 auto ContextKind = 210 endian::readNext<uint8_t, llvm::endianness::little, unaligned>(Data); 211 auto NameID = 212 endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); 213 return {ParentCtxID, ContextKind, NameID}; 214 } 215 216 static data_type ReadData(internal_key_type Key, const uint8_t *Data, 217 unsigned Length) { 218 return endian::readNext<uint32_t, llvm::endianness::little, unaligned>( 219 Data); 220 } 221 }; 222 223 /// Used to deserialize the on-disk Objective-C property table. 224 class ObjCContextInfoTableInfo 225 : public VersionedTableInfo<ObjCContextInfoTableInfo, unsigned, 226 ObjCContextInfo> { 227 public: 228 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { 229 return endian::readNext<uint32_t, llvm::endianness::little, unaligned>( 230 Data); 231 } 232 233 hash_value_type ComputeHash(internal_key_type Key) { 234 return static_cast<size_t>(llvm::hash_value(Key)); 235 } 236 237 static ObjCContextInfo readUnversioned(internal_key_type Key, 238 const uint8_t *&Data) { 239 ObjCContextInfo Info; 240 ReadCommonTypeInfo(Data, Info); 241 uint8_t Payload = *Data++; 242 243 if (Payload & 0x01) 244 Info.setHasDesignatedInits(true); 245 Payload = Payload >> 1; 246 247 if (Payload & 0x4) 248 Info.setDefaultNullability(static_cast<NullabilityKind>(Payload & 0x03)); 249 Payload >>= 3; 250 251 if (Payload & (1 << 1)) 252 Info.setSwiftObjCMembers(Payload & 1); 253 Payload >>= 2; 254 255 if (Payload & (1 << 1)) 256 Info.setSwiftImportAsNonGeneric(Payload & 1); 257 258 return Info; 259 } 260 }; 261 262 /// Read serialized VariableInfo. 263 void ReadVariableInfo(const uint8_t *&Data, VariableInfo &Info) { 264 ReadCommonEntityInfo(Data, Info); 265 if (*Data++) { 266 Info.setNullabilityAudited(static_cast<NullabilityKind>(*Data)); 267 } 268 ++Data; 269 270 auto TypeLen = 271 endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data); 272 Info.setType(std::string(Data, Data + TypeLen)); 273 Data += TypeLen; 274 } 275 276 /// Used to deserialize the on-disk Objective-C property table. 277 class ObjCPropertyTableInfo 278 : public VersionedTableInfo<ObjCPropertyTableInfo, 279 std::tuple<uint32_t, uint32_t, uint8_t>, 280 ObjCPropertyInfo> { 281 public: 282 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { 283 auto ClassID = 284 endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); 285 auto NameID = 286 endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); 287 char IsInstance = 288 endian::readNext<uint8_t, llvm::endianness::little, unaligned>(Data); 289 return {ClassID, NameID, IsInstance}; 290 } 291 292 hash_value_type ComputeHash(internal_key_type Key) { 293 return static_cast<size_t>(llvm::hash_value(Key)); 294 } 295 296 static ObjCPropertyInfo readUnversioned(internal_key_type Key, 297 const uint8_t *&Data) { 298 ObjCPropertyInfo Info; 299 ReadVariableInfo(Data, Info); 300 uint8_t Flags = *Data++; 301 if (Flags & (1 << 0)) 302 Info.setSwiftImportAsAccessors(Flags & (1 << 1)); 303 return Info; 304 } 305 }; 306 307 /// Read serialized ParamInfo. 308 void ReadParamInfo(const uint8_t *&Data, ParamInfo &Info) { 309 ReadVariableInfo(Data, Info); 310 311 uint8_t Payload = 312 endian::readNext<uint8_t, llvm::endianness::little, unaligned>(Data); 313 if (auto RawConvention = Payload & 0x7) { 314 auto Convention = static_cast<RetainCountConventionKind>(RawConvention - 1); 315 Info.setRetainCountConvention(Convention); 316 } 317 Payload >>= 3; 318 if (Payload & 0x01) 319 Info.setNoEscape(Payload & 0x02); 320 Payload >>= 2; 321 assert(Payload == 0 && "Bad API notes"); 322 } 323 324 /// Read serialized FunctionInfo. 325 void ReadFunctionInfo(const uint8_t *&Data, FunctionInfo &Info) { 326 ReadCommonEntityInfo(Data, Info); 327 328 uint8_t Payload = 329 endian::readNext<uint8_t, llvm::endianness::little, unaligned>(Data); 330 if (auto RawConvention = Payload & 0x7) { 331 auto Convention = static_cast<RetainCountConventionKind>(RawConvention - 1); 332 Info.setRetainCountConvention(Convention); 333 } 334 Payload >>= 3; 335 Info.NullabilityAudited = Payload & 0x1; 336 Payload >>= 1; 337 assert(Payload == 0 && "Bad API notes"); 338 339 Info.NumAdjustedNullable = 340 endian::readNext<uint8_t, llvm::endianness::little, unaligned>(Data); 341 Info.NullabilityPayload = 342 endian::readNext<uint64_t, llvm::endianness::little, unaligned>(Data); 343 344 unsigned NumParams = 345 endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data); 346 while (NumParams > 0) { 347 ParamInfo pi; 348 ReadParamInfo(Data, pi); 349 Info.Params.push_back(pi); 350 --NumParams; 351 } 352 353 unsigned ResultTypeLen = 354 endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data); 355 Info.ResultType = std::string(Data, Data + ResultTypeLen); 356 Data += ResultTypeLen; 357 } 358 359 /// Used to deserialize the on-disk Objective-C method table. 360 class ObjCMethodTableInfo 361 : public VersionedTableInfo<ObjCMethodTableInfo, 362 std::tuple<uint32_t, uint32_t, uint8_t>, 363 ObjCMethodInfo> { 364 public: 365 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { 366 auto ClassID = 367 endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); 368 auto SelectorID = 369 endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); 370 auto IsInstance = 371 endian::readNext<uint8_t, llvm::endianness::little, unaligned>(Data); 372 return {ClassID, SelectorID, IsInstance}; 373 } 374 375 hash_value_type ComputeHash(internal_key_type Key) { 376 return static_cast<size_t>(llvm::hash_value(Key)); 377 } 378 379 static ObjCMethodInfo readUnversioned(internal_key_type Key, 380 const uint8_t *&Data) { 381 ObjCMethodInfo Info; 382 uint8_t Payload = *Data++; 383 Info.RequiredInit = Payload & 0x01; 384 Payload >>= 1; 385 Info.DesignatedInit = Payload & 0x01; 386 Payload >>= 1; 387 388 ReadFunctionInfo(Data, Info); 389 return Info; 390 } 391 }; 392 393 /// Used to deserialize the on-disk Objective-C selector table. 394 class ObjCSelectorTableInfo { 395 public: 396 using internal_key_type = StoredObjCSelector; 397 using external_key_type = internal_key_type; 398 using data_type = SelectorID; 399 using hash_value_type = unsigned; 400 using offset_type = unsigned; 401 402 internal_key_type GetInternalKey(external_key_type Key) { return Key; } 403 404 external_key_type GetExternalKey(internal_key_type Key) { return Key; } 405 406 hash_value_type ComputeHash(internal_key_type Key) { 407 return llvm::DenseMapInfo<StoredObjCSelector>::getHashValue(Key); 408 } 409 410 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) { 411 return llvm::DenseMapInfo<StoredObjCSelector>::isEqual(LHS, RHS); 412 } 413 414 static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) { 415 unsigned KeyLength = 416 endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data); 417 unsigned DataLength = 418 endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data); 419 return {KeyLength, DataLength}; 420 } 421 422 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { 423 internal_key_type Key; 424 Key.NumArgs = 425 endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data); 426 unsigned NumIdents = (Length - sizeof(uint16_t)) / sizeof(uint32_t); 427 for (unsigned i = 0; i != NumIdents; ++i) { 428 Key.Identifiers.push_back( 429 endian::readNext<uint32_t, llvm::endianness::little, unaligned>( 430 Data)); 431 } 432 return Key; 433 } 434 435 static data_type ReadData(internal_key_type Key, const uint8_t *Data, 436 unsigned Length) { 437 return endian::readNext<uint32_t, llvm::endianness::little, unaligned>( 438 Data); 439 } 440 }; 441 442 /// Used to deserialize the on-disk global variable table. 443 class GlobalVariableTableInfo 444 : public VersionedTableInfo<GlobalVariableTableInfo, ContextTableKey, 445 GlobalVariableInfo> { 446 public: 447 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { 448 auto CtxID = 449 endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); 450 auto ContextKind = 451 endian::readNext<uint8_t, llvm::endianness::little, unaligned>(Data); 452 auto NameID = 453 endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); 454 return {CtxID, ContextKind, NameID}; 455 } 456 457 hash_value_type ComputeHash(internal_key_type Key) { 458 return static_cast<size_t>(Key.hashValue()); 459 } 460 461 static GlobalVariableInfo readUnversioned(internal_key_type Key, 462 const uint8_t *&Data) { 463 GlobalVariableInfo Info; 464 ReadVariableInfo(Data, Info); 465 return Info; 466 } 467 }; 468 469 /// Used to deserialize the on-disk global function table. 470 class GlobalFunctionTableInfo 471 : public VersionedTableInfo<GlobalFunctionTableInfo, ContextTableKey, 472 GlobalFunctionInfo> { 473 public: 474 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { 475 auto CtxID = 476 endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); 477 auto ContextKind = 478 endian::readNext<uint8_t, llvm::endianness::little, unaligned>(Data); 479 auto NameID = 480 endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); 481 return {CtxID, ContextKind, NameID}; 482 } 483 484 hash_value_type ComputeHash(internal_key_type Key) { 485 return static_cast<size_t>(Key.hashValue()); 486 } 487 488 static GlobalFunctionInfo readUnversioned(internal_key_type Key, 489 const uint8_t *&Data) { 490 GlobalFunctionInfo Info; 491 ReadFunctionInfo(Data, Info); 492 return Info; 493 } 494 }; 495 496 /// Used to deserialize the on-disk enumerator table. 497 class EnumConstantTableInfo 498 : public VersionedTableInfo<EnumConstantTableInfo, uint32_t, 499 EnumConstantInfo> { 500 public: 501 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { 502 auto NameID = 503 endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); 504 return NameID; 505 } 506 507 hash_value_type ComputeHash(internal_key_type Key) { 508 return static_cast<size_t>(llvm::hash_value(Key)); 509 } 510 511 static EnumConstantInfo readUnversioned(internal_key_type Key, 512 const uint8_t *&Data) { 513 EnumConstantInfo Info; 514 ReadCommonEntityInfo(Data, Info); 515 return Info; 516 } 517 }; 518 519 /// Used to deserialize the on-disk tag table. 520 class TagTableInfo 521 : public VersionedTableInfo<TagTableInfo, ContextTableKey, TagInfo> { 522 public: 523 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { 524 auto CtxID = 525 endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); 526 auto ContextKind = 527 endian::readNext<uint8_t, llvm::endianness::little, unaligned>(Data); 528 auto NameID = 529 endian::readNext<IdentifierID, llvm::endianness::little, unaligned>( 530 Data); 531 return {CtxID, ContextKind, NameID}; 532 } 533 534 hash_value_type ComputeHash(internal_key_type Key) { 535 return static_cast<size_t>(Key.hashValue()); 536 } 537 538 static TagInfo readUnversioned(internal_key_type Key, const uint8_t *&Data) { 539 TagInfo Info; 540 541 uint8_t Payload = *Data++; 542 if (Payload & 1) 543 Info.setFlagEnum(Payload & 2); 544 Payload >>= 2; 545 if (Payload > 0) 546 Info.EnumExtensibility = 547 static_cast<EnumExtensibilityKind>((Payload & 0x3) - 1); 548 549 unsigned ImportAsLength = 550 endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data); 551 if (ImportAsLength > 0) { 552 Info.SwiftImportAs = 553 std::string(reinterpret_cast<const char *>(Data), ImportAsLength - 1); 554 Data += ImportAsLength - 1; 555 } 556 unsigned RetainOpLength = 557 endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data); 558 if (RetainOpLength > 0) { 559 Info.SwiftRetainOp = 560 std::string(reinterpret_cast<const char *>(Data), RetainOpLength - 1); 561 Data += RetainOpLength - 1; 562 } 563 unsigned ReleaseOpLength = 564 endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data); 565 if (ReleaseOpLength > 0) { 566 Info.SwiftReleaseOp = std::string(reinterpret_cast<const char *>(Data), 567 ReleaseOpLength - 1); 568 Data += ReleaseOpLength - 1; 569 } 570 571 ReadCommonTypeInfo(Data, Info); 572 return Info; 573 } 574 }; 575 576 /// Used to deserialize the on-disk typedef table. 577 class TypedefTableInfo 578 : public VersionedTableInfo<TypedefTableInfo, ContextTableKey, 579 TypedefInfo> { 580 public: 581 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { 582 auto CtxID = 583 endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data); 584 auto ContextKind = 585 endian::readNext<uint8_t, llvm::endianness::little, unaligned>(Data); 586 auto nameID = 587 endian::readNext<IdentifierID, llvm::endianness::little, unaligned>( 588 Data); 589 return {CtxID, ContextKind, nameID}; 590 } 591 592 hash_value_type ComputeHash(internal_key_type Key) { 593 return static_cast<size_t>(Key.hashValue()); 594 } 595 596 static TypedefInfo readUnversioned(internal_key_type Key, 597 const uint8_t *&Data) { 598 TypedefInfo Info; 599 600 uint8_t Payload = *Data++; 601 if (Payload > 0) 602 Info.SwiftWrapper = static_cast<SwiftNewTypeKind>((Payload & 0x3) - 1); 603 604 ReadCommonTypeInfo(Data, Info); 605 return Info; 606 } 607 }; 608 } // end anonymous namespace 609 610 class APINotesReader::Implementation { 611 public: 612 /// The input buffer for the API notes data. 613 llvm::MemoryBuffer *InputBuffer; 614 615 /// The Swift version to use for filtering. 616 llvm::VersionTuple SwiftVersion; 617 618 /// The name of the module that we read from the control block. 619 std::string ModuleName; 620 621 // The size and modification time of the source file from 622 // which this API notes file was created, if known. 623 std::optional<std::pair<off_t, time_t>> SourceFileSizeAndModTime; 624 625 using SerializedIdentifierTable = 626 llvm::OnDiskIterableChainedHashTable<IdentifierTableInfo>; 627 628 /// The identifier table. 629 std::unique_ptr<SerializedIdentifierTable> IdentifierTable; 630 631 using SerializedObjCContextIDTable = 632 llvm::OnDiskIterableChainedHashTable<ObjCContextIDTableInfo>; 633 634 /// The Objective-C context ID table. 635 std::unique_ptr<SerializedObjCContextIDTable> ObjCContextIDTable; 636 637 using SerializedObjCContextInfoTable = 638 llvm::OnDiskIterableChainedHashTable<ObjCContextInfoTableInfo>; 639 640 /// The Objective-C context info table. 641 std::unique_ptr<SerializedObjCContextInfoTable> ObjCContextInfoTable; 642 643 using SerializedObjCPropertyTable = 644 llvm::OnDiskIterableChainedHashTable<ObjCPropertyTableInfo>; 645 646 /// The Objective-C property table. 647 std::unique_ptr<SerializedObjCPropertyTable> ObjCPropertyTable; 648 649 using SerializedObjCMethodTable = 650 llvm::OnDiskIterableChainedHashTable<ObjCMethodTableInfo>; 651 652 /// The Objective-C method table. 653 std::unique_ptr<SerializedObjCMethodTable> ObjCMethodTable; 654 655 using SerializedObjCSelectorTable = 656 llvm::OnDiskIterableChainedHashTable<ObjCSelectorTableInfo>; 657 658 /// The Objective-C selector table. 659 std::unique_ptr<SerializedObjCSelectorTable> ObjCSelectorTable; 660 661 using SerializedGlobalVariableTable = 662 llvm::OnDiskIterableChainedHashTable<GlobalVariableTableInfo>; 663 664 /// The global variable table. 665 std::unique_ptr<SerializedGlobalVariableTable> GlobalVariableTable; 666 667 using SerializedGlobalFunctionTable = 668 llvm::OnDiskIterableChainedHashTable<GlobalFunctionTableInfo>; 669 670 /// The global function table. 671 std::unique_ptr<SerializedGlobalFunctionTable> GlobalFunctionTable; 672 673 using SerializedEnumConstantTable = 674 llvm::OnDiskIterableChainedHashTable<EnumConstantTableInfo>; 675 676 /// The enumerator table. 677 std::unique_ptr<SerializedEnumConstantTable> EnumConstantTable; 678 679 using SerializedTagTable = llvm::OnDiskIterableChainedHashTable<TagTableInfo>; 680 681 /// The tag table. 682 std::unique_ptr<SerializedTagTable> TagTable; 683 684 using SerializedTypedefTable = 685 llvm::OnDiskIterableChainedHashTable<TypedefTableInfo>; 686 687 /// The typedef table. 688 std::unique_ptr<SerializedTypedefTable> TypedefTable; 689 690 /// Retrieve the identifier ID for the given string, or an empty 691 /// optional if the string is unknown. 692 std::optional<IdentifierID> getIdentifier(llvm::StringRef Str); 693 694 /// Retrieve the selector ID for the given selector, or an empty 695 /// optional if the string is unknown. 696 std::optional<SelectorID> getSelector(ObjCSelectorRef Selector); 697 698 bool readControlBlock(llvm::BitstreamCursor &Cursor, 699 llvm::SmallVectorImpl<uint64_t> &Scratch); 700 bool readIdentifierBlock(llvm::BitstreamCursor &Cursor, 701 llvm::SmallVectorImpl<uint64_t> &Scratch); 702 bool readObjCContextBlock(llvm::BitstreamCursor &Cursor, 703 llvm::SmallVectorImpl<uint64_t> &Scratch); 704 bool readObjCPropertyBlock(llvm::BitstreamCursor &Cursor, 705 llvm::SmallVectorImpl<uint64_t> &Scratch); 706 bool readObjCMethodBlock(llvm::BitstreamCursor &Cursor, 707 llvm::SmallVectorImpl<uint64_t> &Scratch); 708 bool readObjCSelectorBlock(llvm::BitstreamCursor &Cursor, 709 llvm::SmallVectorImpl<uint64_t> &Scratch); 710 bool readGlobalVariableBlock(llvm::BitstreamCursor &Cursor, 711 llvm::SmallVectorImpl<uint64_t> &Scratch); 712 bool readGlobalFunctionBlock(llvm::BitstreamCursor &Cursor, 713 llvm::SmallVectorImpl<uint64_t> &Scratch); 714 bool readEnumConstantBlock(llvm::BitstreamCursor &Cursor, 715 llvm::SmallVectorImpl<uint64_t> &Scratch); 716 bool readTagBlock(llvm::BitstreamCursor &Cursor, 717 llvm::SmallVectorImpl<uint64_t> &Scratch); 718 bool readTypedefBlock(llvm::BitstreamCursor &Cursor, 719 llvm::SmallVectorImpl<uint64_t> &Scratch); 720 }; 721 722 std::optional<IdentifierID> 723 APINotesReader::Implementation::getIdentifier(llvm::StringRef Str) { 724 if (!IdentifierTable) 725 return std::nullopt; 726 727 if (Str.empty()) 728 return IdentifierID(0); 729 730 auto Known = IdentifierTable->find(Str); 731 if (Known == IdentifierTable->end()) 732 return std::nullopt; 733 734 return *Known; 735 } 736 737 std::optional<SelectorID> 738 APINotesReader::Implementation::getSelector(ObjCSelectorRef Selector) { 739 if (!ObjCSelectorTable || !IdentifierTable) 740 return std::nullopt; 741 742 // Translate the identifiers. 743 StoredObjCSelector Key; 744 Key.NumArgs = Selector.NumArgs; 745 for (auto Ident : Selector.Identifiers) { 746 if (auto IdentID = getIdentifier(Ident)) { 747 Key.Identifiers.push_back(*IdentID); 748 } else { 749 return std::nullopt; 750 } 751 } 752 753 auto Known = ObjCSelectorTable->find(Key); 754 if (Known == ObjCSelectorTable->end()) 755 return std::nullopt; 756 757 return *Known; 758 } 759 760 bool APINotesReader::Implementation::readControlBlock( 761 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) { 762 if (Cursor.EnterSubBlock(CONTROL_BLOCK_ID)) 763 return true; 764 765 bool SawMetadata = false; 766 767 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance(); 768 if (!MaybeNext) { 769 // FIXME this drops the error on the floor. 770 consumeError(MaybeNext.takeError()); 771 return false; 772 } 773 llvm::BitstreamEntry Next = MaybeNext.get(); 774 775 while (Next.Kind != llvm::BitstreamEntry::EndBlock) { 776 if (Next.Kind == llvm::BitstreamEntry::Error) 777 return true; 778 779 if (Next.Kind == llvm::BitstreamEntry::SubBlock) { 780 // Unknown metadata sub-block, possibly for use by a future version of the 781 // API notes format. 782 if (Cursor.SkipBlock()) 783 return true; 784 785 MaybeNext = Cursor.advance(); 786 if (!MaybeNext) { 787 // FIXME this drops the error on the floor. 788 consumeError(MaybeNext.takeError()); 789 return false; 790 } 791 Next = MaybeNext.get(); 792 continue; 793 } 794 795 Scratch.clear(); 796 llvm::StringRef BlobData; 797 llvm::Expected<unsigned> MaybeKind = 798 Cursor.readRecord(Next.ID, Scratch, &BlobData); 799 if (!MaybeKind) { 800 // FIXME this drops the error on the floor. 801 consumeError(MaybeKind.takeError()); 802 return false; 803 } 804 unsigned Kind = MaybeKind.get(); 805 806 switch (Kind) { 807 case control_block::METADATA: 808 // Already saw metadata. 809 if (SawMetadata) 810 return true; 811 812 if (Scratch[0] != VERSION_MAJOR || Scratch[1] != VERSION_MINOR) 813 return true; 814 815 SawMetadata = true; 816 break; 817 818 case control_block::MODULE_NAME: 819 ModuleName = BlobData.str(); 820 break; 821 822 case control_block::MODULE_OPTIONS: 823 break; 824 825 case control_block::SOURCE_FILE: 826 SourceFileSizeAndModTime = {Scratch[0], Scratch[1]}; 827 break; 828 829 default: 830 // Unknown metadata record, possibly for use by a future version of the 831 // module format. 832 break; 833 } 834 835 MaybeNext = Cursor.advance(); 836 if (!MaybeNext) { 837 // FIXME this drops the error on the floor. 838 consumeError(MaybeNext.takeError()); 839 return false; 840 } 841 Next = MaybeNext.get(); 842 } 843 844 return !SawMetadata; 845 } 846 847 bool APINotesReader::Implementation::readIdentifierBlock( 848 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) { 849 if (Cursor.EnterSubBlock(IDENTIFIER_BLOCK_ID)) 850 return true; 851 852 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance(); 853 if (!MaybeNext) { 854 // FIXME this drops the error on the floor. 855 consumeError(MaybeNext.takeError()); 856 return false; 857 } 858 llvm::BitstreamEntry Next = MaybeNext.get(); 859 860 while (Next.Kind != llvm::BitstreamEntry::EndBlock) { 861 if (Next.Kind == llvm::BitstreamEntry::Error) 862 return true; 863 864 if (Next.Kind == llvm::BitstreamEntry::SubBlock) { 865 // Unknown sub-block, possibly for use by a future version of the 866 // API notes format. 867 if (Cursor.SkipBlock()) 868 return true; 869 870 MaybeNext = Cursor.advance(); 871 if (!MaybeNext) { 872 // FIXME this drops the error on the floor. 873 consumeError(MaybeNext.takeError()); 874 return false; 875 } 876 Next = MaybeNext.get(); 877 continue; 878 } 879 880 Scratch.clear(); 881 llvm::StringRef BlobData; 882 llvm::Expected<unsigned> MaybeKind = 883 Cursor.readRecord(Next.ID, Scratch, &BlobData); 884 if (!MaybeKind) { 885 // FIXME this drops the error on the floor. 886 consumeError(MaybeKind.takeError()); 887 return false; 888 } 889 unsigned Kind = MaybeKind.get(); 890 switch (Kind) { 891 case identifier_block::IDENTIFIER_DATA: { 892 // Already saw identifier table. 893 if (IdentifierTable) 894 return true; 895 896 uint32_t tableOffset; 897 identifier_block::IdentifierDataLayout::readRecord(Scratch, tableOffset); 898 auto base = reinterpret_cast<const uint8_t *>(BlobData.data()); 899 900 IdentifierTable.reset(SerializedIdentifierTable::Create( 901 base + tableOffset, base + sizeof(uint32_t), base)); 902 break; 903 } 904 905 default: 906 // Unknown record, possibly for use by a future version of the 907 // module format. 908 break; 909 } 910 911 MaybeNext = Cursor.advance(); 912 if (!MaybeNext) { 913 // FIXME this drops the error on the floor. 914 consumeError(MaybeNext.takeError()); 915 return false; 916 } 917 Next = MaybeNext.get(); 918 } 919 920 return false; 921 } 922 923 bool APINotesReader::Implementation::readObjCContextBlock( 924 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) { 925 if (Cursor.EnterSubBlock(OBJC_CONTEXT_BLOCK_ID)) 926 return true; 927 928 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance(); 929 if (!MaybeNext) { 930 // FIXME this drops the error on the floor. 931 consumeError(MaybeNext.takeError()); 932 return false; 933 } 934 llvm::BitstreamEntry Next = MaybeNext.get(); 935 936 while (Next.Kind != llvm::BitstreamEntry::EndBlock) { 937 if (Next.Kind == llvm::BitstreamEntry::Error) 938 return true; 939 940 if (Next.Kind == llvm::BitstreamEntry::SubBlock) { 941 // Unknown sub-block, possibly for use by a future version of the 942 // API notes format. 943 if (Cursor.SkipBlock()) 944 return true; 945 946 MaybeNext = Cursor.advance(); 947 if (!MaybeNext) { 948 // FIXME this drops the error on the floor. 949 consumeError(MaybeNext.takeError()); 950 return false; 951 } 952 Next = MaybeNext.get(); 953 continue; 954 } 955 956 Scratch.clear(); 957 llvm::StringRef BlobData; 958 llvm::Expected<unsigned> MaybeKind = 959 Cursor.readRecord(Next.ID, Scratch, &BlobData); 960 if (!MaybeKind) { 961 // FIXME this drops the error on the floor. 962 consumeError(MaybeKind.takeError()); 963 return false; 964 } 965 unsigned Kind = MaybeKind.get(); 966 switch (Kind) { 967 case objc_context_block::OBJC_CONTEXT_ID_DATA: { 968 // Already saw Objective-C context ID table. 969 if (ObjCContextIDTable) 970 return true; 971 972 uint32_t tableOffset; 973 objc_context_block::ObjCContextIDLayout::readRecord(Scratch, tableOffset); 974 auto base = reinterpret_cast<const uint8_t *>(BlobData.data()); 975 976 ObjCContextIDTable.reset(SerializedObjCContextIDTable::Create( 977 base + tableOffset, base + sizeof(uint32_t), base)); 978 break; 979 } 980 981 case objc_context_block::OBJC_CONTEXT_INFO_DATA: { 982 // Already saw Objective-C context info table. 983 if (ObjCContextInfoTable) 984 return true; 985 986 uint32_t tableOffset; 987 objc_context_block::ObjCContextInfoLayout::readRecord(Scratch, 988 tableOffset); 989 auto base = reinterpret_cast<const uint8_t *>(BlobData.data()); 990 991 ObjCContextInfoTable.reset(SerializedObjCContextInfoTable::Create( 992 base + tableOffset, base + sizeof(uint32_t), base)); 993 break; 994 } 995 996 default: 997 // Unknown record, possibly for use by a future version of the 998 // module format. 999 break; 1000 } 1001 1002 MaybeNext = Cursor.advance(); 1003 if (!MaybeNext) { 1004 // FIXME this drops the error on the floor. 1005 consumeError(MaybeNext.takeError()); 1006 return false; 1007 } 1008 Next = MaybeNext.get(); 1009 } 1010 1011 return false; 1012 } 1013 1014 bool APINotesReader::Implementation::readObjCPropertyBlock( 1015 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) { 1016 if (Cursor.EnterSubBlock(OBJC_PROPERTY_BLOCK_ID)) 1017 return true; 1018 1019 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance(); 1020 if (!MaybeNext) { 1021 // FIXME this drops the error on the floor. 1022 consumeError(MaybeNext.takeError()); 1023 return false; 1024 } 1025 llvm::BitstreamEntry Next = MaybeNext.get(); 1026 1027 while (Next.Kind != llvm::BitstreamEntry::EndBlock) { 1028 if (Next.Kind == llvm::BitstreamEntry::Error) 1029 return true; 1030 1031 if (Next.Kind == llvm::BitstreamEntry::SubBlock) { 1032 // Unknown sub-block, possibly for use by a future version of the 1033 // API notes format. 1034 if (Cursor.SkipBlock()) 1035 return true; 1036 1037 MaybeNext = Cursor.advance(); 1038 if (!MaybeNext) { 1039 // FIXME this drops the error on the floor. 1040 consumeError(MaybeNext.takeError()); 1041 return false; 1042 } 1043 Next = MaybeNext.get(); 1044 continue; 1045 } 1046 1047 Scratch.clear(); 1048 llvm::StringRef BlobData; 1049 llvm::Expected<unsigned> MaybeKind = 1050 Cursor.readRecord(Next.ID, Scratch, &BlobData); 1051 if (!MaybeKind) { 1052 // FIXME this drops the error on the floor. 1053 consumeError(MaybeKind.takeError()); 1054 return false; 1055 } 1056 unsigned Kind = MaybeKind.get(); 1057 switch (Kind) { 1058 case objc_property_block::OBJC_PROPERTY_DATA: { 1059 // Already saw Objective-C property table. 1060 if (ObjCPropertyTable) 1061 return true; 1062 1063 uint32_t tableOffset; 1064 objc_property_block::ObjCPropertyDataLayout::readRecord(Scratch, 1065 tableOffset); 1066 auto base = reinterpret_cast<const uint8_t *>(BlobData.data()); 1067 1068 ObjCPropertyTable.reset(SerializedObjCPropertyTable::Create( 1069 base + tableOffset, base + sizeof(uint32_t), base)); 1070 break; 1071 } 1072 1073 default: 1074 // Unknown record, possibly for use by a future version of the 1075 // module format. 1076 break; 1077 } 1078 1079 MaybeNext = Cursor.advance(); 1080 if (!MaybeNext) { 1081 // FIXME this drops the error on the floor. 1082 consumeError(MaybeNext.takeError()); 1083 return false; 1084 } 1085 Next = MaybeNext.get(); 1086 } 1087 1088 return false; 1089 } 1090 1091 bool APINotesReader::Implementation::readObjCMethodBlock( 1092 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) { 1093 if (Cursor.EnterSubBlock(OBJC_METHOD_BLOCK_ID)) 1094 return true; 1095 1096 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance(); 1097 if (!MaybeNext) { 1098 // FIXME this drops the error on the floor. 1099 consumeError(MaybeNext.takeError()); 1100 return false; 1101 } 1102 llvm::BitstreamEntry Next = MaybeNext.get(); 1103 while (Next.Kind != llvm::BitstreamEntry::EndBlock) { 1104 if (Next.Kind == llvm::BitstreamEntry::Error) 1105 return true; 1106 1107 if (Next.Kind == llvm::BitstreamEntry::SubBlock) { 1108 // Unknown sub-block, possibly for use by a future version of the 1109 // API notes format. 1110 if (Cursor.SkipBlock()) 1111 return true; 1112 1113 MaybeNext = Cursor.advance(); 1114 if (!MaybeNext) { 1115 // FIXME this drops the error on the floor. 1116 consumeError(MaybeNext.takeError()); 1117 return false; 1118 } 1119 Next = MaybeNext.get(); 1120 continue; 1121 } 1122 1123 Scratch.clear(); 1124 llvm::StringRef BlobData; 1125 llvm::Expected<unsigned> MaybeKind = 1126 Cursor.readRecord(Next.ID, Scratch, &BlobData); 1127 if (!MaybeKind) { 1128 // FIXME this drops the error on the floor. 1129 consumeError(MaybeKind.takeError()); 1130 return false; 1131 } 1132 unsigned Kind = MaybeKind.get(); 1133 switch (Kind) { 1134 case objc_method_block::OBJC_METHOD_DATA: { 1135 // Already saw Objective-C method table. 1136 if (ObjCMethodTable) 1137 return true; 1138 1139 uint32_t tableOffset; 1140 objc_method_block::ObjCMethodDataLayout::readRecord(Scratch, tableOffset); 1141 auto base = reinterpret_cast<const uint8_t *>(BlobData.data()); 1142 1143 ObjCMethodTable.reset(SerializedObjCMethodTable::Create( 1144 base + tableOffset, base + sizeof(uint32_t), base)); 1145 break; 1146 } 1147 1148 default: 1149 // Unknown record, possibly for use by a future version of the 1150 // module format. 1151 break; 1152 } 1153 1154 MaybeNext = Cursor.advance(); 1155 if (!MaybeNext) { 1156 // FIXME this drops the error on the floor. 1157 consumeError(MaybeNext.takeError()); 1158 return false; 1159 } 1160 Next = MaybeNext.get(); 1161 } 1162 1163 return false; 1164 } 1165 1166 bool APINotesReader::Implementation::readObjCSelectorBlock( 1167 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) { 1168 if (Cursor.EnterSubBlock(OBJC_SELECTOR_BLOCK_ID)) 1169 return true; 1170 1171 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance(); 1172 if (!MaybeNext) { 1173 // FIXME this drops the error on the floor. 1174 consumeError(MaybeNext.takeError()); 1175 return false; 1176 } 1177 llvm::BitstreamEntry Next = MaybeNext.get(); 1178 while (Next.Kind != llvm::BitstreamEntry::EndBlock) { 1179 if (Next.Kind == llvm::BitstreamEntry::Error) 1180 return true; 1181 1182 if (Next.Kind == llvm::BitstreamEntry::SubBlock) { 1183 // Unknown sub-block, possibly for use by a future version of the 1184 // API notes format. 1185 if (Cursor.SkipBlock()) 1186 return true; 1187 1188 MaybeNext = Cursor.advance(); 1189 if (!MaybeNext) { 1190 // FIXME this drops the error on the floor. 1191 consumeError(MaybeNext.takeError()); 1192 return false; 1193 } 1194 Next = MaybeNext.get(); 1195 continue; 1196 } 1197 1198 Scratch.clear(); 1199 llvm::StringRef BlobData; 1200 llvm::Expected<unsigned> MaybeKind = 1201 Cursor.readRecord(Next.ID, Scratch, &BlobData); 1202 if (!MaybeKind) { 1203 // FIXME this drops the error on the floor. 1204 consumeError(MaybeKind.takeError()); 1205 return false; 1206 } 1207 unsigned Kind = MaybeKind.get(); 1208 switch (Kind) { 1209 case objc_selector_block::OBJC_SELECTOR_DATA: { 1210 // Already saw Objective-C selector table. 1211 if (ObjCSelectorTable) 1212 return true; 1213 1214 uint32_t tableOffset; 1215 objc_selector_block::ObjCSelectorDataLayout::readRecord(Scratch, 1216 tableOffset); 1217 auto base = reinterpret_cast<const uint8_t *>(BlobData.data()); 1218 1219 ObjCSelectorTable.reset(SerializedObjCSelectorTable::Create( 1220 base + tableOffset, base + sizeof(uint32_t), base)); 1221 break; 1222 } 1223 1224 default: 1225 // Unknown record, possibly for use by a future version of the 1226 // module format. 1227 break; 1228 } 1229 1230 MaybeNext = Cursor.advance(); 1231 if (!MaybeNext) { 1232 // FIXME this drops the error on the floor. 1233 consumeError(MaybeNext.takeError()); 1234 return false; 1235 } 1236 Next = MaybeNext.get(); 1237 } 1238 1239 return false; 1240 } 1241 1242 bool APINotesReader::Implementation::readGlobalVariableBlock( 1243 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) { 1244 if (Cursor.EnterSubBlock(GLOBAL_VARIABLE_BLOCK_ID)) 1245 return true; 1246 1247 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance(); 1248 if (!MaybeNext) { 1249 // FIXME this drops the error on the floor. 1250 consumeError(MaybeNext.takeError()); 1251 return false; 1252 } 1253 llvm::BitstreamEntry Next = MaybeNext.get(); 1254 while (Next.Kind != llvm::BitstreamEntry::EndBlock) { 1255 if (Next.Kind == llvm::BitstreamEntry::Error) 1256 return true; 1257 1258 if (Next.Kind == llvm::BitstreamEntry::SubBlock) { 1259 // Unknown sub-block, possibly for use by a future version of the 1260 // API notes format. 1261 if (Cursor.SkipBlock()) 1262 return true; 1263 1264 MaybeNext = Cursor.advance(); 1265 if (!MaybeNext) { 1266 // FIXME this drops the error on the floor. 1267 consumeError(MaybeNext.takeError()); 1268 return false; 1269 } 1270 Next = MaybeNext.get(); 1271 continue; 1272 } 1273 1274 Scratch.clear(); 1275 llvm::StringRef BlobData; 1276 llvm::Expected<unsigned> MaybeKind = 1277 Cursor.readRecord(Next.ID, Scratch, &BlobData); 1278 if (!MaybeKind) { 1279 // FIXME this drops the error on the floor. 1280 consumeError(MaybeKind.takeError()); 1281 return false; 1282 } 1283 unsigned Kind = MaybeKind.get(); 1284 switch (Kind) { 1285 case global_variable_block::GLOBAL_VARIABLE_DATA: { 1286 // Already saw global variable table. 1287 if (GlobalVariableTable) 1288 return true; 1289 1290 uint32_t tableOffset; 1291 global_variable_block::GlobalVariableDataLayout::readRecord(Scratch, 1292 tableOffset); 1293 auto base = reinterpret_cast<const uint8_t *>(BlobData.data()); 1294 1295 GlobalVariableTable.reset(SerializedGlobalVariableTable::Create( 1296 base + tableOffset, base + sizeof(uint32_t), base)); 1297 break; 1298 } 1299 1300 default: 1301 // Unknown record, possibly for use by a future version of the 1302 // module format. 1303 break; 1304 } 1305 1306 MaybeNext = Cursor.advance(); 1307 if (!MaybeNext) { 1308 // FIXME this drops the error on the floor. 1309 consumeError(MaybeNext.takeError()); 1310 return false; 1311 } 1312 Next = MaybeNext.get(); 1313 } 1314 1315 return false; 1316 } 1317 1318 bool APINotesReader::Implementation::readGlobalFunctionBlock( 1319 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) { 1320 if (Cursor.EnterSubBlock(GLOBAL_FUNCTION_BLOCK_ID)) 1321 return true; 1322 1323 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance(); 1324 if (!MaybeNext) { 1325 // FIXME this drops the error on the floor. 1326 consumeError(MaybeNext.takeError()); 1327 return false; 1328 } 1329 llvm::BitstreamEntry Next = MaybeNext.get(); 1330 while (Next.Kind != llvm::BitstreamEntry::EndBlock) { 1331 if (Next.Kind == llvm::BitstreamEntry::Error) 1332 return true; 1333 1334 if (Next.Kind == llvm::BitstreamEntry::SubBlock) { 1335 // Unknown sub-block, possibly for use by a future version of the 1336 // API notes format. 1337 if (Cursor.SkipBlock()) 1338 return true; 1339 1340 MaybeNext = Cursor.advance(); 1341 if (!MaybeNext) { 1342 // FIXME this drops the error on the floor. 1343 consumeError(MaybeNext.takeError()); 1344 return false; 1345 } 1346 Next = MaybeNext.get(); 1347 continue; 1348 } 1349 1350 Scratch.clear(); 1351 llvm::StringRef BlobData; 1352 llvm::Expected<unsigned> MaybeKind = 1353 Cursor.readRecord(Next.ID, Scratch, &BlobData); 1354 if (!MaybeKind) { 1355 // FIXME this drops the error on the floor. 1356 consumeError(MaybeKind.takeError()); 1357 return false; 1358 } 1359 unsigned Kind = MaybeKind.get(); 1360 switch (Kind) { 1361 case global_function_block::GLOBAL_FUNCTION_DATA: { 1362 // Already saw global function table. 1363 if (GlobalFunctionTable) 1364 return true; 1365 1366 uint32_t tableOffset; 1367 global_function_block::GlobalFunctionDataLayout::readRecord(Scratch, 1368 tableOffset); 1369 auto base = reinterpret_cast<const uint8_t *>(BlobData.data()); 1370 1371 GlobalFunctionTable.reset(SerializedGlobalFunctionTable::Create( 1372 base + tableOffset, base + sizeof(uint32_t), base)); 1373 break; 1374 } 1375 1376 default: 1377 // Unknown record, possibly for use by a future version of the 1378 // module format. 1379 break; 1380 } 1381 1382 MaybeNext = Cursor.advance(); 1383 if (!MaybeNext) { 1384 // FIXME this drops the error on the floor. 1385 consumeError(MaybeNext.takeError()); 1386 return false; 1387 } 1388 Next = MaybeNext.get(); 1389 } 1390 1391 return false; 1392 } 1393 1394 bool APINotesReader::Implementation::readEnumConstantBlock( 1395 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) { 1396 if (Cursor.EnterSubBlock(ENUM_CONSTANT_BLOCK_ID)) 1397 return true; 1398 1399 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance(); 1400 if (!MaybeNext) { 1401 // FIXME this drops the error on the floor. 1402 consumeError(MaybeNext.takeError()); 1403 return false; 1404 } 1405 llvm::BitstreamEntry Next = MaybeNext.get(); 1406 while (Next.Kind != llvm::BitstreamEntry::EndBlock) { 1407 if (Next.Kind == llvm::BitstreamEntry::Error) 1408 return true; 1409 1410 if (Next.Kind == llvm::BitstreamEntry::SubBlock) { 1411 // Unknown sub-block, possibly for use by a future version of the 1412 // API notes format. 1413 if (Cursor.SkipBlock()) 1414 return true; 1415 1416 MaybeNext = Cursor.advance(); 1417 if (!MaybeNext) { 1418 // FIXME this drops the error on the floor. 1419 consumeError(MaybeNext.takeError()); 1420 return false; 1421 } 1422 Next = MaybeNext.get(); 1423 continue; 1424 } 1425 1426 Scratch.clear(); 1427 llvm::StringRef BlobData; 1428 llvm::Expected<unsigned> MaybeKind = 1429 Cursor.readRecord(Next.ID, Scratch, &BlobData); 1430 if (!MaybeKind) { 1431 // FIXME this drops the error on the floor. 1432 consumeError(MaybeKind.takeError()); 1433 return false; 1434 } 1435 unsigned Kind = MaybeKind.get(); 1436 switch (Kind) { 1437 case enum_constant_block::ENUM_CONSTANT_DATA: { 1438 // Already saw enumerator table. 1439 if (EnumConstantTable) 1440 return true; 1441 1442 uint32_t tableOffset; 1443 enum_constant_block::EnumConstantDataLayout::readRecord(Scratch, 1444 tableOffset); 1445 auto base = reinterpret_cast<const uint8_t *>(BlobData.data()); 1446 1447 EnumConstantTable.reset(SerializedEnumConstantTable::Create( 1448 base + tableOffset, base + sizeof(uint32_t), base)); 1449 break; 1450 } 1451 1452 default: 1453 // Unknown record, possibly for use by a future version of the 1454 // module format. 1455 break; 1456 } 1457 1458 MaybeNext = Cursor.advance(); 1459 if (!MaybeNext) { 1460 // FIXME this drops the error on the floor. 1461 consumeError(MaybeNext.takeError()); 1462 return false; 1463 } 1464 Next = MaybeNext.get(); 1465 } 1466 1467 return false; 1468 } 1469 1470 bool APINotesReader::Implementation::readTagBlock( 1471 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) { 1472 if (Cursor.EnterSubBlock(TAG_BLOCK_ID)) 1473 return true; 1474 1475 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance(); 1476 if (!MaybeNext) { 1477 // FIXME this drops the error on the floor. 1478 consumeError(MaybeNext.takeError()); 1479 return false; 1480 } 1481 llvm::BitstreamEntry Next = MaybeNext.get(); 1482 while (Next.Kind != llvm::BitstreamEntry::EndBlock) { 1483 if (Next.Kind == llvm::BitstreamEntry::Error) 1484 return true; 1485 1486 if (Next.Kind == llvm::BitstreamEntry::SubBlock) { 1487 // Unknown sub-block, possibly for use by a future version of the 1488 // API notes format. 1489 if (Cursor.SkipBlock()) 1490 return true; 1491 1492 MaybeNext = Cursor.advance(); 1493 if (!MaybeNext) { 1494 // FIXME this drops the error on the floor. 1495 consumeError(MaybeNext.takeError()); 1496 return false; 1497 } 1498 Next = MaybeNext.get(); 1499 continue; 1500 } 1501 1502 Scratch.clear(); 1503 llvm::StringRef BlobData; 1504 llvm::Expected<unsigned> MaybeKind = 1505 Cursor.readRecord(Next.ID, Scratch, &BlobData); 1506 if (!MaybeKind) { 1507 // FIXME this drops the error on the floor. 1508 consumeError(MaybeKind.takeError()); 1509 return false; 1510 } 1511 unsigned Kind = MaybeKind.get(); 1512 switch (Kind) { 1513 case tag_block::TAG_DATA: { 1514 // Already saw tag table. 1515 if (TagTable) 1516 return true; 1517 1518 uint32_t tableOffset; 1519 tag_block::TagDataLayout::readRecord(Scratch, tableOffset); 1520 auto base = reinterpret_cast<const uint8_t *>(BlobData.data()); 1521 1522 TagTable.reset(SerializedTagTable::Create(base + tableOffset, 1523 base + sizeof(uint32_t), base)); 1524 break; 1525 } 1526 1527 default: 1528 // Unknown record, possibly for use by a future version of the 1529 // module format. 1530 break; 1531 } 1532 1533 MaybeNext = Cursor.advance(); 1534 if (!MaybeNext) { 1535 // FIXME this drops the error on the floor. 1536 consumeError(MaybeNext.takeError()); 1537 return false; 1538 } 1539 Next = MaybeNext.get(); 1540 } 1541 1542 return false; 1543 } 1544 1545 bool APINotesReader::Implementation::readTypedefBlock( 1546 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) { 1547 if (Cursor.EnterSubBlock(TYPEDEF_BLOCK_ID)) 1548 return true; 1549 1550 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance(); 1551 if (!MaybeNext) { 1552 // FIXME this drops the error on the floor. 1553 consumeError(MaybeNext.takeError()); 1554 return false; 1555 } 1556 llvm::BitstreamEntry Next = MaybeNext.get(); 1557 while (Next.Kind != llvm::BitstreamEntry::EndBlock) { 1558 if (Next.Kind == llvm::BitstreamEntry::Error) 1559 return true; 1560 1561 if (Next.Kind == llvm::BitstreamEntry::SubBlock) { 1562 // Unknown sub-block, possibly for use by a future version of the 1563 // API notes format. 1564 if (Cursor.SkipBlock()) 1565 return true; 1566 1567 MaybeNext = Cursor.advance(); 1568 if (!MaybeNext) { 1569 // FIXME this drops the error on the floor. 1570 consumeError(MaybeNext.takeError()); 1571 return false; 1572 } 1573 Next = MaybeNext.get(); 1574 continue; 1575 } 1576 1577 Scratch.clear(); 1578 llvm::StringRef BlobData; 1579 llvm::Expected<unsigned> MaybeKind = 1580 Cursor.readRecord(Next.ID, Scratch, &BlobData); 1581 if (!MaybeKind) { 1582 // FIXME this drops the error on the floor. 1583 consumeError(MaybeKind.takeError()); 1584 return false; 1585 } 1586 unsigned Kind = MaybeKind.get(); 1587 switch (Kind) { 1588 case typedef_block::TYPEDEF_DATA: { 1589 // Already saw typedef table. 1590 if (TypedefTable) 1591 return true; 1592 1593 uint32_t tableOffset; 1594 typedef_block::TypedefDataLayout::readRecord(Scratch, tableOffset); 1595 auto base = reinterpret_cast<const uint8_t *>(BlobData.data()); 1596 1597 TypedefTable.reset(SerializedTypedefTable::Create( 1598 base + tableOffset, base + sizeof(uint32_t), base)); 1599 break; 1600 } 1601 1602 default: 1603 // Unknown record, possibly for use by a future version of the 1604 // module format. 1605 break; 1606 } 1607 1608 MaybeNext = Cursor.advance(); 1609 if (!MaybeNext) { 1610 // FIXME this drops the error on the floor. 1611 consumeError(MaybeNext.takeError()); 1612 return false; 1613 } 1614 Next = MaybeNext.get(); 1615 } 1616 1617 return false; 1618 } 1619 1620 APINotesReader::APINotesReader(llvm::MemoryBuffer *InputBuffer, 1621 llvm::VersionTuple SwiftVersion, bool &Failed) 1622 : Implementation(new class Implementation) { 1623 Failed = false; 1624 1625 // Initialize the input buffer. 1626 Implementation->InputBuffer = InputBuffer; 1627 Implementation->SwiftVersion = SwiftVersion; 1628 llvm::BitstreamCursor Cursor(*Implementation->InputBuffer); 1629 1630 // Validate signature. 1631 for (auto byte : API_NOTES_SIGNATURE) { 1632 if (Cursor.AtEndOfStream()) { 1633 Failed = true; 1634 return; 1635 } 1636 if (llvm::Expected<llvm::SimpleBitstreamCursor::word_t> maybeRead = 1637 Cursor.Read(8)) { 1638 if (maybeRead.get() != byte) { 1639 Failed = true; 1640 return; 1641 } 1642 } else { 1643 // FIXME this drops the error on the floor. 1644 consumeError(maybeRead.takeError()); 1645 Failed = true; 1646 return; 1647 } 1648 } 1649 1650 // Look at all of the blocks. 1651 bool HasValidControlBlock = false; 1652 llvm::SmallVector<uint64_t, 64> Scratch; 1653 while (!Cursor.AtEndOfStream()) { 1654 llvm::Expected<llvm::BitstreamEntry> MaybeTopLevelEntry = Cursor.advance(); 1655 if (!MaybeTopLevelEntry) { 1656 // FIXME this drops the error on the floor. 1657 consumeError(MaybeTopLevelEntry.takeError()); 1658 Failed = true; 1659 return; 1660 } 1661 llvm::BitstreamEntry TopLevelEntry = MaybeTopLevelEntry.get(); 1662 1663 if (TopLevelEntry.Kind != llvm::BitstreamEntry::SubBlock) 1664 break; 1665 1666 switch (TopLevelEntry.ID) { 1667 case llvm::bitc::BLOCKINFO_BLOCK_ID: 1668 if (!Cursor.ReadBlockInfoBlock()) { 1669 Failed = true; 1670 break; 1671 } 1672 break; 1673 1674 case CONTROL_BLOCK_ID: 1675 // Only allow a single control block. 1676 if (HasValidControlBlock || 1677 Implementation->readControlBlock(Cursor, Scratch)) { 1678 Failed = true; 1679 return; 1680 } 1681 1682 HasValidControlBlock = true; 1683 break; 1684 1685 case IDENTIFIER_BLOCK_ID: 1686 if (!HasValidControlBlock || 1687 Implementation->readIdentifierBlock(Cursor, Scratch)) { 1688 Failed = true; 1689 return; 1690 } 1691 break; 1692 1693 case OBJC_CONTEXT_BLOCK_ID: 1694 if (!HasValidControlBlock || 1695 Implementation->readObjCContextBlock(Cursor, Scratch)) { 1696 Failed = true; 1697 return; 1698 } 1699 1700 break; 1701 1702 case OBJC_PROPERTY_BLOCK_ID: 1703 if (!HasValidControlBlock || 1704 Implementation->readObjCPropertyBlock(Cursor, Scratch)) { 1705 Failed = true; 1706 return; 1707 } 1708 break; 1709 1710 case OBJC_METHOD_BLOCK_ID: 1711 if (!HasValidControlBlock || 1712 Implementation->readObjCMethodBlock(Cursor, Scratch)) { 1713 Failed = true; 1714 return; 1715 } 1716 break; 1717 1718 case OBJC_SELECTOR_BLOCK_ID: 1719 if (!HasValidControlBlock || 1720 Implementation->readObjCSelectorBlock(Cursor, Scratch)) { 1721 Failed = true; 1722 return; 1723 } 1724 break; 1725 1726 case GLOBAL_VARIABLE_BLOCK_ID: 1727 if (!HasValidControlBlock || 1728 Implementation->readGlobalVariableBlock(Cursor, Scratch)) { 1729 Failed = true; 1730 return; 1731 } 1732 break; 1733 1734 case GLOBAL_FUNCTION_BLOCK_ID: 1735 if (!HasValidControlBlock || 1736 Implementation->readGlobalFunctionBlock(Cursor, Scratch)) { 1737 Failed = true; 1738 return; 1739 } 1740 break; 1741 1742 case ENUM_CONSTANT_BLOCK_ID: 1743 if (!HasValidControlBlock || 1744 Implementation->readEnumConstantBlock(Cursor, Scratch)) { 1745 Failed = true; 1746 return; 1747 } 1748 break; 1749 1750 case TAG_BLOCK_ID: 1751 if (!HasValidControlBlock || 1752 Implementation->readTagBlock(Cursor, Scratch)) { 1753 Failed = true; 1754 return; 1755 } 1756 break; 1757 1758 case TYPEDEF_BLOCK_ID: 1759 if (!HasValidControlBlock || 1760 Implementation->readTypedefBlock(Cursor, Scratch)) { 1761 Failed = true; 1762 return; 1763 } 1764 break; 1765 1766 default: 1767 // Unknown top-level block, possibly for use by a future version of the 1768 // module format. 1769 if (Cursor.SkipBlock()) { 1770 Failed = true; 1771 return; 1772 } 1773 break; 1774 } 1775 } 1776 1777 if (!Cursor.AtEndOfStream()) { 1778 Failed = true; 1779 return; 1780 } 1781 } 1782 1783 APINotesReader::~APINotesReader() { delete Implementation->InputBuffer; } 1784 1785 std::unique_ptr<APINotesReader> 1786 APINotesReader::Create(std::unique_ptr<llvm::MemoryBuffer> InputBuffer, 1787 llvm::VersionTuple SwiftVersion) { 1788 bool Failed = false; 1789 std::unique_ptr<APINotesReader> Reader( 1790 new APINotesReader(InputBuffer.release(), SwiftVersion, Failed)); 1791 if (Failed) 1792 return nullptr; 1793 1794 return Reader; 1795 } 1796 1797 template <typename T> 1798 APINotesReader::VersionedInfo<T>::VersionedInfo( 1799 llvm::VersionTuple Version, 1800 llvm::SmallVector<std::pair<llvm::VersionTuple, T>, 1> Results) 1801 : Results(std::move(Results)) { 1802 1803 assert(!Results.empty()); 1804 assert(std::is_sorted( 1805 Results.begin(), Results.end(), 1806 [](const std::pair<llvm::VersionTuple, T> &left, 1807 const std::pair<llvm::VersionTuple, T> &right) -> bool { 1808 assert(left.first != right.first && "two entries for the same version"); 1809 return left.first < right.first; 1810 })); 1811 1812 Selected = std::nullopt; 1813 for (unsigned i = 0, n = Results.size(); i != n; ++i) { 1814 if (!Version.empty() && Results[i].first >= Version) { 1815 // If the current version is "4", then entries for 4 are better than 1816 // entries for 5, but both are valid. Because entries are sorted, we get 1817 // that behavior by picking the first match. 1818 Selected = i; 1819 break; 1820 } 1821 } 1822 1823 // If we didn't find a match but we have an unversioned result, use the 1824 // unversioned result. This will always be the first entry because we encode 1825 // it as version 0. 1826 if (!Selected && Results[0].first.empty()) 1827 Selected = 0; 1828 } 1829 1830 auto APINotesReader::lookupObjCClassID(llvm::StringRef Name) 1831 -> std::optional<ContextID> { 1832 if (!Implementation->ObjCContextIDTable) 1833 return std::nullopt; 1834 1835 std::optional<IdentifierID> ClassID = Implementation->getIdentifier(Name); 1836 if (!ClassID) 1837 return std::nullopt; 1838 1839 // ObjC classes can't be declared in C++ namespaces, so use -1 as the global 1840 // context. 1841 auto KnownID = Implementation->ObjCContextIDTable->find( 1842 ContextTableKey(-1, (uint8_t)ContextKind::ObjCClass, *ClassID)); 1843 if (KnownID == Implementation->ObjCContextIDTable->end()) 1844 return std::nullopt; 1845 1846 return ContextID(*KnownID); 1847 } 1848 1849 auto APINotesReader::lookupObjCClassInfo(llvm::StringRef Name) 1850 -> VersionedInfo<ObjCContextInfo> { 1851 if (!Implementation->ObjCContextInfoTable) 1852 return std::nullopt; 1853 1854 std::optional<ContextID> CtxID = lookupObjCClassID(Name); 1855 if (!CtxID) 1856 return std::nullopt; 1857 1858 auto KnownInfo = Implementation->ObjCContextInfoTable->find(CtxID->Value); 1859 if (KnownInfo == Implementation->ObjCContextInfoTable->end()) 1860 return std::nullopt; 1861 1862 return {Implementation->SwiftVersion, *KnownInfo}; 1863 } 1864 1865 auto APINotesReader::lookupObjCProtocolID(llvm::StringRef Name) 1866 -> std::optional<ContextID> { 1867 if (!Implementation->ObjCContextIDTable) 1868 return std::nullopt; 1869 1870 std::optional<IdentifierID> classID = Implementation->getIdentifier(Name); 1871 if (!classID) 1872 return std::nullopt; 1873 1874 // ObjC classes can't be declared in C++ namespaces, so use -1 as the global 1875 // context. 1876 auto KnownID = Implementation->ObjCContextIDTable->find( 1877 ContextTableKey(-1, (uint8_t)ContextKind::ObjCProtocol, *classID)); 1878 if (KnownID == Implementation->ObjCContextIDTable->end()) 1879 return std::nullopt; 1880 1881 return ContextID(*KnownID); 1882 } 1883 1884 auto APINotesReader::lookupObjCProtocolInfo(llvm::StringRef Name) 1885 -> VersionedInfo<ObjCContextInfo> { 1886 if (!Implementation->ObjCContextInfoTable) 1887 return std::nullopt; 1888 1889 std::optional<ContextID> CtxID = lookupObjCProtocolID(Name); 1890 if (!CtxID) 1891 return std::nullopt; 1892 1893 auto KnownInfo = Implementation->ObjCContextInfoTable->find(CtxID->Value); 1894 if (KnownInfo == Implementation->ObjCContextInfoTable->end()) 1895 return std::nullopt; 1896 1897 return {Implementation->SwiftVersion, *KnownInfo}; 1898 } 1899 1900 auto APINotesReader::lookupObjCProperty(ContextID CtxID, llvm::StringRef Name, 1901 bool IsInstance) 1902 -> VersionedInfo<ObjCPropertyInfo> { 1903 if (!Implementation->ObjCPropertyTable) 1904 return std::nullopt; 1905 1906 std::optional<IdentifierID> PropertyID = Implementation->getIdentifier(Name); 1907 if (!PropertyID) 1908 return std::nullopt; 1909 1910 auto Known = Implementation->ObjCPropertyTable->find( 1911 std::make_tuple(CtxID.Value, *PropertyID, (char)IsInstance)); 1912 if (Known == Implementation->ObjCPropertyTable->end()) 1913 return std::nullopt; 1914 1915 return {Implementation->SwiftVersion, *Known}; 1916 } 1917 1918 auto APINotesReader::lookupObjCMethod(ContextID CtxID, ObjCSelectorRef Selector, 1919 bool IsInstanceMethod) 1920 -> VersionedInfo<ObjCMethodInfo> { 1921 if (!Implementation->ObjCMethodTable) 1922 return std::nullopt; 1923 1924 std::optional<SelectorID> SelID = Implementation->getSelector(Selector); 1925 if (!SelID) 1926 return std::nullopt; 1927 1928 auto Known = Implementation->ObjCMethodTable->find( 1929 ObjCMethodTableInfo::internal_key_type{CtxID.Value, *SelID, 1930 IsInstanceMethod}); 1931 if (Known == Implementation->ObjCMethodTable->end()) 1932 return std::nullopt; 1933 1934 return {Implementation->SwiftVersion, *Known}; 1935 } 1936 1937 auto APINotesReader::lookupGlobalVariable(llvm::StringRef Name, 1938 std::optional<Context> Ctx) 1939 -> VersionedInfo<GlobalVariableInfo> { 1940 if (!Implementation->GlobalVariableTable) 1941 return std::nullopt; 1942 1943 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name); 1944 if (!NameID) 1945 return std::nullopt; 1946 1947 ContextTableKey Key(Ctx, *NameID); 1948 1949 auto Known = Implementation->GlobalVariableTable->find(Key); 1950 if (Known == Implementation->GlobalVariableTable->end()) 1951 return std::nullopt; 1952 1953 return {Implementation->SwiftVersion, *Known}; 1954 } 1955 1956 auto APINotesReader::lookupGlobalFunction(llvm::StringRef Name, 1957 std::optional<Context> Ctx) 1958 -> VersionedInfo<GlobalFunctionInfo> { 1959 if (!Implementation->GlobalFunctionTable) 1960 return std::nullopt; 1961 1962 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name); 1963 if (!NameID) 1964 return std::nullopt; 1965 1966 ContextTableKey Key(Ctx, *NameID); 1967 1968 auto Known = Implementation->GlobalFunctionTable->find(Key); 1969 if (Known == Implementation->GlobalFunctionTable->end()) 1970 return std::nullopt; 1971 1972 return {Implementation->SwiftVersion, *Known}; 1973 } 1974 1975 auto APINotesReader::lookupEnumConstant(llvm::StringRef Name) 1976 -> VersionedInfo<EnumConstantInfo> { 1977 if (!Implementation->EnumConstantTable) 1978 return std::nullopt; 1979 1980 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name); 1981 if (!NameID) 1982 return std::nullopt; 1983 1984 auto Known = Implementation->EnumConstantTable->find(*NameID); 1985 if (Known == Implementation->EnumConstantTable->end()) 1986 return std::nullopt; 1987 1988 return {Implementation->SwiftVersion, *Known}; 1989 } 1990 1991 auto APINotesReader::lookupTag(llvm::StringRef Name, std::optional<Context> Ctx) 1992 -> VersionedInfo<TagInfo> { 1993 if (!Implementation->TagTable) 1994 return std::nullopt; 1995 1996 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name); 1997 if (!NameID) 1998 return std::nullopt; 1999 2000 ContextTableKey Key(Ctx, *NameID); 2001 2002 auto Known = Implementation->TagTable->find(Key); 2003 if (Known == Implementation->TagTable->end()) 2004 return std::nullopt; 2005 2006 return {Implementation->SwiftVersion, *Known}; 2007 } 2008 2009 auto APINotesReader::lookupTypedef(llvm::StringRef Name, 2010 std::optional<Context> Ctx) 2011 -> VersionedInfo<TypedefInfo> { 2012 if (!Implementation->TypedefTable) 2013 return std::nullopt; 2014 2015 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name); 2016 if (!NameID) 2017 return std::nullopt; 2018 2019 ContextTableKey Key(Ctx, *NameID); 2020 2021 auto Known = Implementation->TypedefTable->find(Key); 2022 if (Known == Implementation->TypedefTable->end()) 2023 return std::nullopt; 2024 2025 return {Implementation->SwiftVersion, *Known}; 2026 } 2027 2028 auto APINotesReader::lookupNamespaceID( 2029 llvm::StringRef Name, std::optional<ContextID> ParentNamespaceID) 2030 -> std::optional<ContextID> { 2031 if (!Implementation->ObjCContextIDTable) 2032 return std::nullopt; 2033 2034 std::optional<IdentifierID> NamespaceID = Implementation->getIdentifier(Name); 2035 if (!NamespaceID) 2036 return std::nullopt; 2037 2038 uint32_t RawParentNamespaceID = 2039 ParentNamespaceID ? ParentNamespaceID->Value : -1; 2040 auto KnownID = Implementation->ObjCContextIDTable->find( 2041 {RawParentNamespaceID, (uint8_t)ContextKind::Namespace, *NamespaceID}); 2042 if (KnownID == Implementation->ObjCContextIDTable->end()) 2043 return std::nullopt; 2044 2045 return ContextID(*KnownID); 2046 } 2047 2048 } // namespace api_notes 2049 } // namespace clang 2050