17#include "llvm/ADT/Hashing.h"
18#include "llvm/ADT/StringExtras.h"
19#include "llvm/Bitstream/BitstreamReader.h"
20#include "llvm/Support/DJB.h"
21#include "llvm/Support/EndianStream.h"
22#include "llvm/Support/OnDiskHashTable.h"
26using namespace llvm::support;
30llvm::VersionTuple ReadVersionTuple(
const uint8_t *&
Data) {
31 uint8_t NumVersions = (*
Data++) & 0x03;
33 unsigned Major = endian::readNext<uint32_t, llvm::endianness::little>(
Data);
35 return llvm::VersionTuple(Major);
37 unsigned Minor = endian::readNext<uint32_t, llvm::endianness::little>(
Data);
39 return llvm::VersionTuple(Major, Minor);
42 endian::readNext<uint32_t, llvm::endianness::little>(
Data);
44 return llvm::VersionTuple(Major, Minor, Subminor);
46 unsigned Build = endian::readNext<uint32_t, llvm::endianness::little>(
Data);
47 return llvm::VersionTuple(Major, Minor, Subminor, Build);
51template <
typename Derived,
typename KeyType,
typename UnversionedDataType>
52class VersionedTableInfo {
54 using internal_key_type = KeyType;
55 using external_key_type = KeyType;
58 using hash_value_type =
size_t;
61 internal_key_type GetInternalKey(external_key_type Key) {
return Key; }
63 external_key_type GetExternalKey(internal_key_type Key) {
return Key; }
65 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
69 static std::pair<unsigned, unsigned> ReadKeyDataLength(
const uint8_t *&
Data) {
71 endian::readNext<uint16_t, llvm::endianness::little>(
Data);
73 endian::readNext<uint16_t, llvm::endianness::little>(
Data);
74 return {KeyLength, DataLength};
77 static data_type ReadData(internal_key_type Key,
const uint8_t *
Data,
79 unsigned NumElements =
80 endian::readNext<uint16_t, llvm::endianness::little>(
Data);
82 Result.reserve(NumElements);
83 for (
unsigned i = 0; i != NumElements; ++i) {
84 auto version = ReadVersionTuple(
Data);
85 const auto *DataBefore =
Data;
87 auto UnversionedData = Derived::readUnversioned(Key,
Data);
88 assert(
Data != DataBefore &&
89 "Unversioned data reader didn't move pointer");
90 Result.push_back({version, UnversionedData});
97void ReadCommonEntityInfo(
const uint8_t *&
Data, CommonEntityInfo &Info) {
98 uint8_t UnavailableBits = *
Data++;
99 Info.Unavailable = (UnavailableBits >> 1) & 0x01;
100 Info.UnavailableInSwift = UnavailableBits & 0x01;
101 if ((UnavailableBits >> 2) & 0x01)
102 Info.setSwiftPrivate(
static_cast<bool>((UnavailableBits >> 3) & 0x01));
105 endian::readNext<uint16_t, llvm::endianness::little>(
Data);
106 Info.UnavailableMsg =
107 std::string(
reinterpret_cast<const char *
>(
Data),
108 reinterpret_cast<const char *
>(
Data) + MsgLength);
111 unsigned SwiftNameLength =
112 endian::readNext<uint16_t, llvm::endianness::little>(
Data);
114 std::string(
reinterpret_cast<const char *
>(
Data),
115 reinterpret_cast<const char *
>(
Data) + SwiftNameLength);
116 Data += SwiftNameLength;
120void ReadCommonTypeInfo(
const uint8_t *&
Data, CommonTypeInfo &Info) {
121 ReadCommonEntityInfo(
Data, Info);
123 unsigned SwiftBridgeLength =
124 endian::readNext<uint16_t, llvm::endianness::little>(
Data);
125 if (SwiftBridgeLength > 0) {
126 Info.setSwiftBridge(std::string(
reinterpret_cast<const char *
>(
Data),
127 SwiftBridgeLength - 1));
128 Data += SwiftBridgeLength - 1;
131 unsigned ErrorDomainLength =
132 endian::readNext<uint16_t, llvm::endianness::little>(
Data);
133 if (ErrorDomainLength > 0) {
134 Info.setNSErrorDomain(std::optional<std::string>(std::string(
135 reinterpret_cast<const char *
>(
Data), ErrorDomainLength - 1)));
136 Data += ErrorDomainLength - 1;
141class IdentifierTableInfo {
143 using internal_key_type = llvm::StringRef;
144 using external_key_type = llvm::StringRef;
146 using hash_value_type = uint32_t;
149 internal_key_type GetInternalKey(external_key_type Key) {
return Key; }
151 external_key_type GetExternalKey(internal_key_type Key) {
return Key; }
153 hash_value_type
ComputeHash(internal_key_type Key) {
154 return llvm::djbHash(Key);
157 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
161 static std::pair<unsigned, unsigned> ReadKeyDataLength(
const uint8_t *&
Data) {
163 endian::readNext<uint16_t, llvm::endianness::little>(
Data);
164 unsigned DataLength =
165 endian::readNext<uint16_t, llvm::endianness::little>(
Data);
166 return {KeyLength, DataLength};
169 static internal_key_type ReadKey(
const uint8_t *
Data,
unsigned Length) {
170 return llvm::StringRef(
reinterpret_cast<const char *
>(
Data), Length);
173 static data_type ReadData(internal_key_type key,
const uint8_t *
Data,
175 return endian::readNext<uint32_t, llvm::endianness::little>(
Data);
180class ObjCContextIDTableInfo {
182 using internal_key_type = ContextTableKey;
183 using external_key_type = internal_key_type;
185 using hash_value_type =
size_t;
188 internal_key_type GetInternalKey(external_key_type Key) {
return Key; }
190 external_key_type GetExternalKey(internal_key_type Key) {
return Key; }
192 hash_value_type
ComputeHash(internal_key_type Key) {
193 return static_cast<size_t>(Key.hashValue());
196 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
200 static std::pair<unsigned, unsigned> ReadKeyDataLength(
const uint8_t *&
Data) {
202 endian::readNext<uint16_t, llvm::endianness::little>(
Data);
203 unsigned DataLength =
204 endian::readNext<uint16_t, llvm::endianness::little>(
Data);
205 return {KeyLength, DataLength};
208 static internal_key_type ReadKey(
const uint8_t *
Data,
unsigned Length) {
210 endian::readNext<uint32_t, llvm::endianness::little>(
Data);
212 endian::readNext<uint8_t, llvm::endianness::little>(
Data);
213 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(
Data);
217 static data_type ReadData(internal_key_type Key,
const uint8_t *
Data,
219 return endian::readNext<uint32_t, llvm::endianness::little>(
Data);
224class ObjCContextInfoTableInfo
225 :
public VersionedTableInfo<ObjCContextInfoTableInfo, unsigned,
228 static internal_key_type ReadKey(
const uint8_t *
Data,
unsigned Length) {
229 return endian::readNext<uint32_t, llvm::endianness::little>(
Data);
232 hash_value_type
ComputeHash(internal_key_type Key) {
236 static ObjCContextInfo readUnversioned(internal_key_type Key,
237 const uint8_t *&
Data) {
238 ObjCContextInfo Info;
239 ReadCommonTypeInfo(
Data, Info);
240 uint8_t Payload = *
Data++;
243 Info.setHasDesignatedInits(
true);
244 Payload = Payload >> 1;
247 Info.setDefaultNullability(
static_cast<NullabilityKind>(Payload & 0x03));
250 if (Payload & (1 << 1))
251 Info.setSwiftObjCMembers(Payload & 1);
254 if (Payload & (1 << 1))
255 Info.setSwiftImportAsNonGeneric(Payload & 1);
262void ReadVariableInfo(
const uint8_t *&
Data, VariableInfo &Info) {
263 ReadCommonEntityInfo(
Data, Info);
269 auto TypeLen = endian::readNext<uint16_t, llvm::endianness::little>(
Data);
270 Info.setType(std::string(
Data,
Data + TypeLen));
275class ObjCPropertyTableInfo
276 :
public VersionedTableInfo<ObjCPropertyTableInfo,
277 std::tuple<uint32_t, uint32_t, uint8_t>,
280 static internal_key_type ReadKey(
const uint8_t *
Data,
unsigned Length) {
281 auto ClassID = endian::readNext<uint32_t, llvm::endianness::little>(
Data);
282 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(
Data);
283 char IsInstance = endian::readNext<uint8_t, llvm::endianness::little>(
Data);
284 return {ClassID, NameID, IsInstance};
287 hash_value_type
ComputeHash(internal_key_type Key) {
291 static ObjCPropertyInfo readUnversioned(internal_key_type Key,
292 const uint8_t *&
Data) {
293 ObjCPropertyInfo Info;
294 ReadVariableInfo(
Data, Info);
295 uint8_t Flags = *
Data++;
296 if (Flags & (1 << 0))
297 Info.setSwiftImportAsAccessors(Flags & (1 << 1));
303void ReadParamInfo(
const uint8_t *&
Data, ParamInfo &Info) {
304 ReadVariableInfo(
Data, Info);
306 uint8_t Payload = endian::readNext<uint8_t, llvm::endianness::little>(
Data);
307 if (
auto RawConvention = Payload & 0x7) {
309 Info.setRetainCountConvention(Convention);
313 Info.setNoEscape(Payload & 0x02);
315 assert(Payload == 0 &&
"Bad API notes");
319void ReadFunctionInfo(
const uint8_t *&
Data, FunctionInfo &Info) {
320 ReadCommonEntityInfo(
Data, Info);
322 uint8_t Payload = endian::readNext<uint8_t, llvm::endianness::little>(
Data);
323 if (
auto RawConvention = Payload & 0x7) {
325 Info.setRetainCountConvention(Convention);
328 Info.NullabilityAudited = Payload & 0x1;
330 assert(Payload == 0 &&
"Bad API notes");
332 Info.NumAdjustedNullable =
333 endian::readNext<uint8_t, llvm::endianness::little>(
Data);
334 Info.NullabilityPayload =
335 endian::readNext<uint64_t, llvm::endianness::little>(
Data);
338 endian::readNext<uint16_t, llvm::endianness::little>(
Data);
339 while (NumParams > 0) {
341 ReadParamInfo(
Data, pi);
342 Info.Params.push_back(pi);
346 unsigned ResultTypeLen =
347 endian::readNext<uint16_t, llvm::endianness::little>(
Data);
348 Info.ResultType = std::string(
Data,
Data + ResultTypeLen);
349 Data += ResultTypeLen;
353class ObjCMethodTableInfo
354 :
public VersionedTableInfo<ObjCMethodTableInfo,
355 std::tuple<uint32_t, uint32_t, uint8_t>,
358 static internal_key_type ReadKey(
const uint8_t *
Data,
unsigned Length) {
359 auto ClassID = endian::readNext<uint32_t, llvm::endianness::little>(
Data);
361 endian::readNext<uint32_t, llvm::endianness::little>(
Data);
362 auto IsInstance = endian::readNext<uint8_t, llvm::endianness::little>(
Data);
366 hash_value_type
ComputeHash(internal_key_type Key) {
370 static ObjCMethodInfo readUnversioned(internal_key_type Key,
371 const uint8_t *&
Data) {
373 uint8_t Payload = *
Data++;
374 Info.RequiredInit = Payload & 0x01;
376 Info.DesignatedInit = Payload & 0x01;
379 ReadFunctionInfo(
Data, Info);
385class ObjCSelectorTableInfo {
387 using internal_key_type = StoredObjCSelector;
388 using external_key_type = internal_key_type;
393 internal_key_type GetInternalKey(external_key_type Key) {
return Key; }
395 external_key_type GetExternalKey(internal_key_type Key) {
return Key; }
397 hash_value_type
ComputeHash(internal_key_type Key) {
398 return llvm::DenseMapInfo<StoredObjCSelector>::getHashValue(Key);
401 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
402 return llvm::DenseMapInfo<StoredObjCSelector>::isEqual(LHS, RHS);
405 static std::pair<unsigned, unsigned> ReadKeyDataLength(
const uint8_t *&
Data) {
407 endian::readNext<uint16_t, llvm::endianness::little>(
Data);
408 unsigned DataLength =
409 endian::readNext<uint16_t, llvm::endianness::little>(
Data);
410 return {KeyLength, DataLength};
413 static internal_key_type ReadKey(
const uint8_t *
Data,
unsigned Length) {
414 internal_key_type Key;
415 Key.NumArgs = endian::readNext<uint16_t, llvm::endianness::little>(
Data);
416 unsigned NumIdents = (Length -
sizeof(uint16_t)) /
sizeof(uint32_t);
417 for (
unsigned i = 0; i != NumIdents; ++i) {
418 Key.Identifiers.push_back(
419 endian::readNext<uint32_t, llvm::endianness::little>(
Data));
424 static data_type ReadData(internal_key_type Key,
const uint8_t *
Data,
426 return endian::readNext<uint32_t, llvm::endianness::little>(
Data);
431class GlobalVariableTableInfo
432 :
public VersionedTableInfo<GlobalVariableTableInfo, ContextTableKey,
433 GlobalVariableInfo> {
435 static internal_key_type ReadKey(
const uint8_t *
Data,
unsigned Length) {
436 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(
Data);
438 endian::readNext<uint8_t, llvm::endianness::little>(
Data);
439 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(
Data);
443 hash_value_type
ComputeHash(internal_key_type Key) {
444 return static_cast<size_t>(Key.hashValue());
447 static GlobalVariableInfo readUnversioned(internal_key_type Key,
448 const uint8_t *&
Data) {
449 GlobalVariableInfo Info;
450 ReadVariableInfo(
Data, Info);
456class GlobalFunctionTableInfo
457 :
public VersionedTableInfo<GlobalFunctionTableInfo, ContextTableKey,
458 GlobalFunctionInfo> {
460 static internal_key_type ReadKey(
const uint8_t *
Data,
unsigned Length) {
461 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(
Data);
463 endian::readNext<uint8_t, llvm::endianness::little>(
Data);
464 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(
Data);
468 hash_value_type
ComputeHash(internal_key_type Key) {
469 return static_cast<size_t>(Key.hashValue());
472 static GlobalFunctionInfo readUnversioned(internal_key_type Key,
473 const uint8_t *&
Data) {
474 GlobalFunctionInfo Info;
475 ReadFunctionInfo(
Data, Info);
481class EnumConstantTableInfo
482 :
public VersionedTableInfo<EnumConstantTableInfo, uint32_t,
485 static internal_key_type ReadKey(
const uint8_t *
Data,
unsigned Length) {
486 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(
Data);
490 hash_value_type
ComputeHash(internal_key_type Key) {
494 static EnumConstantInfo readUnversioned(internal_key_type Key,
495 const uint8_t *&
Data) {
496 EnumConstantInfo Info;
497 ReadCommonEntityInfo(
Data, Info);
504 :
public VersionedTableInfo<TagTableInfo, ContextTableKey, TagInfo> {
506 static internal_key_type ReadKey(
const uint8_t *
Data,
unsigned Length) {
507 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(
Data);
509 endian::readNext<uint8_t, llvm::endianness::little>(
Data);
511 endian::readNext<IdentifierID, llvm::endianness::little>(
Data);
515 hash_value_type
ComputeHash(internal_key_type Key) {
516 return static_cast<size_t>(Key.hashValue());
519 static TagInfo readUnversioned(internal_key_type Key,
const uint8_t *&
Data) {
522 uint8_t Payload = *
Data++;
524 Info.setFlagEnum(Payload & 2);
527 Info.EnumExtensibility =
531 endian::readNext<uint8_t, llvm::endianness::little>(
Data);
533 Info.setSwiftCopyable(std::optional(
false));
535 Info.setSwiftCopyable(std::optional(
true));
537 unsigned ImportAsLength =
538 endian::readNext<uint16_t, llvm::endianness::little>(
Data);
539 if (ImportAsLength > 0) {
541 std::string(
reinterpret_cast<const char *
>(
Data), ImportAsLength - 1);
542 Data += ImportAsLength - 1;
544 unsigned RetainOpLength =
545 endian::readNext<uint16_t, llvm::endianness::little>(
Data);
546 if (RetainOpLength > 0) {
548 std::string(
reinterpret_cast<const char *
>(
Data), RetainOpLength - 1);
549 Data += RetainOpLength - 1;
551 unsigned ReleaseOpLength =
552 endian::readNext<uint16_t, llvm::endianness::little>(
Data);
553 if (ReleaseOpLength > 0) {
554 Info.SwiftReleaseOp = std::string(
reinterpret_cast<const char *
>(
Data),
555 ReleaseOpLength - 1);
556 Data += ReleaseOpLength - 1;
559 ReadCommonTypeInfo(
Data, Info);
565class TypedefTableInfo
566 :
public VersionedTableInfo<TypedefTableInfo, ContextTableKey,
569 static internal_key_type ReadKey(
const uint8_t *
Data,
unsigned Length) {
570 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(
Data);
572 endian::readNext<uint8_t, llvm::endianness::little>(
Data);
574 endian::readNext<IdentifierID, llvm::endianness::little>(
Data);
578 hash_value_type
ComputeHash(internal_key_type Key) {
579 return static_cast<size_t>(Key.hashValue());
582 static TypedefInfo readUnversioned(internal_key_type Key,
583 const uint8_t *&
Data) {
586 uint8_t Payload = *
Data++;
590 ReadCommonTypeInfo(
Data, Info);
612 llvm::OnDiskIterableChainedHashTable<IdentifierTableInfo>;
618 llvm::OnDiskIterableChainedHashTable<ObjCContextIDTableInfo>;
624 llvm::OnDiskIterableChainedHashTable<ObjCContextInfoTableInfo>;
630 llvm::OnDiskIterableChainedHashTable<ObjCPropertyTableInfo>;
636 llvm::OnDiskIterableChainedHashTable<ObjCMethodTableInfo>;
642 llvm::OnDiskIterableChainedHashTable<ObjCSelectorTableInfo>;
648 llvm::OnDiskIterableChainedHashTable<GlobalVariableTableInfo>;
654 llvm::OnDiskIterableChainedHashTable<GlobalFunctionTableInfo>;
660 llvm::OnDiskIterableChainedHashTable<EnumConstantTableInfo>;
671 llvm::OnDiskIterableChainedHashTable<TypedefTableInfo>;
678 std::optional<IdentifierID>
getIdentifier(llvm::StringRef Str);
708std::optional<IdentifierID>
723std::optional<SelectorID>
731 for (
auto Ident :
Selector.Identifiers) {
739 auto Known = ObjCSelectorTable->find(Key);
740 if (Known == ObjCSelectorTable->end())
751 bool SawMetadata =
false;
756 consumeError(MaybeNext.takeError());
759 llvm::BitstreamEntry Next = MaybeNext.get();
761 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
762 if (Next.Kind == llvm::BitstreamEntry::Error)
765 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
768 if (Cursor.SkipBlock())
771 MaybeNext = Cursor.advance();
774 consumeError(MaybeNext.takeError());
777 Next = MaybeNext.get();
782 llvm::StringRef BlobData;
784 Cursor.readRecord(Next.ID, Scratch, &BlobData);
787 consumeError(MaybeKind.takeError());
790 unsigned Kind = MaybeKind.get();
805 ModuleName = BlobData.str();
812 SourceFileSizeAndModTime = {Scratch[0], Scratch[1]};
821 MaybeNext = Cursor.advance();
824 consumeError(MaybeNext.takeError());
827 Next = MaybeNext.get();
841 consumeError(MaybeNext.takeError());
844 llvm::BitstreamEntry Next = MaybeNext.get();
846 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
847 if (Next.Kind == llvm::BitstreamEntry::Error)
850 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
853 if (Cursor.SkipBlock())
856 MaybeNext = Cursor.advance();
859 consumeError(MaybeNext.takeError());
862 Next = MaybeNext.get();
867 llvm::StringRef BlobData;
869 Cursor.readRecord(Next.ID, Scratch, &BlobData);
872 consumeError(MaybeKind.takeError());
875 unsigned Kind = MaybeKind.get();
882 uint32_t tableOffset;
883 identifier_block::IdentifierDataLayout::readRecord(Scratch, tableOffset);
884 auto base =
reinterpret_cast<const uint8_t *
>(BlobData.data());
887 base + tableOffset, base +
sizeof(uint32_t), base));
897 MaybeNext = Cursor.advance();
900 consumeError(MaybeNext.takeError());
903 Next = MaybeNext.get();
917 consumeError(MaybeNext.takeError());
920 llvm::BitstreamEntry Next = MaybeNext.get();
922 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
923 if (Next.Kind == llvm::BitstreamEntry::Error)
926 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
929 if (Cursor.SkipBlock())
932 MaybeNext = Cursor.advance();
935 consumeError(MaybeNext.takeError());
938 Next = MaybeNext.get();
943 llvm::StringRef BlobData;
945 Cursor.readRecord(Next.ID, Scratch, &BlobData);
948 consumeError(MaybeKind.takeError());
951 unsigned Kind = MaybeKind.get();
955 if (ObjCContextIDTable)
958 uint32_t tableOffset;
959 objc_context_block::ObjCContextIDLayout::readRecord(Scratch, tableOffset);
960 auto base =
reinterpret_cast<const uint8_t *
>(BlobData.data());
962 ObjCContextIDTable.reset(SerializedObjCContextIDTable::Create(
963 base + tableOffset, base +
sizeof(uint32_t), base));
969 if (ObjCContextInfoTable)
972 uint32_t tableOffset;
973 objc_context_block::ObjCContextInfoLayout::readRecord(Scratch,
975 auto base =
reinterpret_cast<const uint8_t *
>(BlobData.data());
977 ObjCContextInfoTable.reset(SerializedObjCContextInfoTable::Create(
978 base + tableOffset, base +
sizeof(uint32_t), base));
988 MaybeNext = Cursor.advance();
991 consumeError(MaybeNext.takeError());
994 Next = MaybeNext.get();
1008 consumeError(MaybeNext.takeError());
1011 llvm::BitstreamEntry Next = MaybeNext.get();
1013 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1014 if (Next.Kind == llvm::BitstreamEntry::Error)
1017 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1020 if (Cursor.SkipBlock())
1023 MaybeNext = Cursor.advance();
1026 consumeError(MaybeNext.takeError());
1029 Next = MaybeNext.get();
1034 llvm::StringRef BlobData;
1036 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1039 consumeError(MaybeKind.takeError());
1042 unsigned Kind = MaybeKind.get();
1046 if (ObjCPropertyTable)
1049 uint32_t tableOffset;
1050 objc_property_block::ObjCPropertyDataLayout::readRecord(Scratch,
1052 auto base =
reinterpret_cast<const uint8_t *
>(BlobData.data());
1054 ObjCPropertyTable.reset(SerializedObjCPropertyTable::Create(
1055 base + tableOffset, base +
sizeof(uint32_t), base));
1065 MaybeNext = Cursor.advance();
1068 consumeError(MaybeNext.takeError());
1071 Next = MaybeNext.get();
1085 consumeError(MaybeNext.takeError());
1088 llvm::BitstreamEntry Next = MaybeNext.get();
1089 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1090 if (Next.Kind == llvm::BitstreamEntry::Error)
1093 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1096 if (Cursor.SkipBlock())
1099 MaybeNext = Cursor.advance();
1102 consumeError(MaybeNext.takeError());
1105 Next = MaybeNext.get();
1110 llvm::StringRef BlobData;
1112 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1115 consumeError(MaybeKind.takeError());
1118 unsigned Kind = MaybeKind.get();
1122 if (ObjCMethodTable)
1125 uint32_t tableOffset;
1126 objc_method_block::ObjCMethodDataLayout::readRecord(Scratch, tableOffset);
1127 auto base =
reinterpret_cast<const uint8_t *
>(BlobData.data());
1129 ObjCMethodTable.reset(SerializedObjCMethodTable::Create(
1130 base + tableOffset, base +
sizeof(uint32_t), base));
1140 MaybeNext = Cursor.advance();
1143 consumeError(MaybeNext.takeError());
1146 Next = MaybeNext.get();
1160 consumeError(MaybeNext.takeError());
1163 llvm::BitstreamEntry Next = MaybeNext.get();
1164 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1165 if (Next.Kind == llvm::BitstreamEntry::Error)
1168 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1171 if (Cursor.SkipBlock())
1174 MaybeNext = Cursor.advance();
1177 consumeError(MaybeNext.takeError());
1180 Next = MaybeNext.get();
1185 llvm::StringRef BlobData;
1187 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1190 consumeError(MaybeKind.takeError());
1193 unsigned Kind = MaybeKind.get();
1197 if (ObjCSelectorTable)
1200 uint32_t tableOffset;
1201 objc_selector_block::ObjCSelectorDataLayout::readRecord(Scratch,
1203 auto base =
reinterpret_cast<const uint8_t *
>(BlobData.data());
1205 ObjCSelectorTable.reset(SerializedObjCSelectorTable::Create(
1206 base + tableOffset, base +
sizeof(uint32_t), base));
1216 MaybeNext = Cursor.advance();
1219 consumeError(MaybeNext.takeError());
1222 Next = MaybeNext.get();
1236 consumeError(MaybeNext.takeError());
1239 llvm::BitstreamEntry Next = MaybeNext.get();
1240 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1241 if (Next.Kind == llvm::BitstreamEntry::Error)
1244 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1247 if (Cursor.SkipBlock())
1250 MaybeNext = Cursor.advance();
1253 consumeError(MaybeNext.takeError());
1256 Next = MaybeNext.get();
1261 llvm::StringRef BlobData;
1263 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1266 consumeError(MaybeKind.takeError());
1269 unsigned Kind = MaybeKind.get();
1273 if (GlobalVariableTable)
1276 uint32_t tableOffset;
1277 global_variable_block::GlobalVariableDataLayout::readRecord(Scratch,
1279 auto base =
reinterpret_cast<const uint8_t *
>(BlobData.data());
1281 GlobalVariableTable.reset(SerializedGlobalVariableTable::Create(
1282 base + tableOffset, base +
sizeof(uint32_t), base));
1292 MaybeNext = Cursor.advance();
1295 consumeError(MaybeNext.takeError());
1298 Next = MaybeNext.get();
1312 consumeError(MaybeNext.takeError());
1315 llvm::BitstreamEntry Next = MaybeNext.get();
1316 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1317 if (Next.Kind == llvm::BitstreamEntry::Error)
1320 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1323 if (Cursor.SkipBlock())
1326 MaybeNext = Cursor.advance();
1329 consumeError(MaybeNext.takeError());
1332 Next = MaybeNext.get();
1337 llvm::StringRef BlobData;
1339 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1342 consumeError(MaybeKind.takeError());
1345 unsigned Kind = MaybeKind.get();
1349 if (GlobalFunctionTable)
1352 uint32_t tableOffset;
1353 global_function_block::GlobalFunctionDataLayout::readRecord(Scratch,
1355 auto base =
reinterpret_cast<const uint8_t *
>(BlobData.data());
1357 GlobalFunctionTable.reset(SerializedGlobalFunctionTable::Create(
1358 base + tableOffset, base +
sizeof(uint32_t), base));
1368 MaybeNext = Cursor.advance();
1371 consumeError(MaybeNext.takeError());
1374 Next = MaybeNext.get();
1388 consumeError(MaybeNext.takeError());
1391 llvm::BitstreamEntry Next = MaybeNext.get();
1392 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1393 if (Next.Kind == llvm::BitstreamEntry::Error)
1396 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1399 if (Cursor.SkipBlock())
1402 MaybeNext = Cursor.advance();
1405 consumeError(MaybeNext.takeError());
1408 Next = MaybeNext.get();
1413 llvm::StringRef BlobData;
1415 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1418 consumeError(MaybeKind.takeError());
1421 unsigned Kind = MaybeKind.get();
1425 if (EnumConstantTable)
1428 uint32_t tableOffset;
1429 enum_constant_block::EnumConstantDataLayout::readRecord(Scratch,
1431 auto base =
reinterpret_cast<const uint8_t *
>(BlobData.data());
1433 EnumConstantTable.reset(SerializedEnumConstantTable::Create(
1434 base + tableOffset, base +
sizeof(uint32_t), base));
1444 MaybeNext = Cursor.advance();
1447 consumeError(MaybeNext.takeError());
1450 Next = MaybeNext.get();
1464 consumeError(MaybeNext.takeError());
1467 llvm::BitstreamEntry Next = MaybeNext.get();
1468 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1469 if (Next.Kind == llvm::BitstreamEntry::Error)
1472 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1475 if (Cursor.SkipBlock())
1478 MaybeNext = Cursor.advance();
1481 consumeError(MaybeNext.takeError());
1484 Next = MaybeNext.get();
1489 llvm::StringRef BlobData;
1491 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1494 consumeError(MaybeKind.takeError());
1497 unsigned Kind = MaybeKind.get();
1504 uint32_t tableOffset;
1505 tag_block::TagDataLayout::readRecord(Scratch, tableOffset);
1506 auto base =
reinterpret_cast<const uint8_t *
>(BlobData.data());
1508 TagTable.reset(SerializedTagTable::Create(base + tableOffset,
1509 base +
sizeof(uint32_t), base));
1519 MaybeNext = Cursor.advance();
1522 consumeError(MaybeNext.takeError());
1525 Next = MaybeNext.get();
1539 consumeError(MaybeNext.takeError());
1542 llvm::BitstreamEntry Next = MaybeNext.get();
1543 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1544 if (Next.Kind == llvm::BitstreamEntry::Error)
1547 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1550 if (Cursor.SkipBlock())
1553 MaybeNext = Cursor.advance();
1556 consumeError(MaybeNext.takeError());
1559 Next = MaybeNext.get();
1564 llvm::StringRef BlobData;
1566 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1569 consumeError(MaybeKind.takeError());
1572 unsigned Kind = MaybeKind.get();
1579 uint32_t tableOffset;
1580 typedef_block::TypedefDataLayout::readRecord(Scratch, tableOffset);
1581 auto base =
reinterpret_cast<const uint8_t *
>(BlobData.data());
1583 TypedefTable.reset(SerializedTypedefTable::Create(
1584 base + tableOffset, base +
sizeof(uint32_t), base));
1594 MaybeNext = Cursor.advance();
1597 consumeError(MaybeNext.takeError());
1600 Next = MaybeNext.get();
1606APINotesReader::APINotesReader(llvm::MemoryBuffer *InputBuffer,
1607 llvm::VersionTuple SwiftVersion,
bool &Failed)
1618 if (Cursor.AtEndOfStream()) {
1624 if (maybeRead.get() !=
byte) {
1630 consumeError(maybeRead.takeError());
1637 bool HasValidControlBlock =
false;
1639 while (!
Cursor.AtEndOfStream()) {
1641 if (!MaybeTopLevelEntry) {
1643 consumeError(MaybeTopLevelEntry.takeError());
1647 llvm::BitstreamEntry TopLevelEntry = MaybeTopLevelEntry.get();
1649 if (TopLevelEntry.Kind != llvm::BitstreamEntry::SubBlock)
1652 switch (TopLevelEntry.ID) {
1653 case llvm::bitc::BLOCKINFO_BLOCK_ID:
1654 if (!
Cursor.ReadBlockInfoBlock()) {
1662 if (HasValidControlBlock ||
1663 Implementation->readControlBlock(Cursor, Scratch)) {
1668 HasValidControlBlock =
true;
1672 if (!HasValidControlBlock ||
1673 Implementation->readIdentifierBlock(Cursor, Scratch)) {
1680 if (!HasValidControlBlock ||
1681 Implementation->readObjCContextBlock(Cursor, Scratch)) {
1689 if (!HasValidControlBlock ||
1690 Implementation->readObjCPropertyBlock(Cursor, Scratch)) {
1697 if (!HasValidControlBlock ||
1698 Implementation->readObjCMethodBlock(Cursor, Scratch)) {
1705 if (!HasValidControlBlock ||
1706 Implementation->readObjCSelectorBlock(Cursor, Scratch)) {
1713 if (!HasValidControlBlock ||
1714 Implementation->readGlobalVariableBlock(Cursor, Scratch)) {
1721 if (!HasValidControlBlock ||
1722 Implementation->readGlobalFunctionBlock(Cursor, Scratch)) {
1729 if (!HasValidControlBlock ||
1730 Implementation->readEnumConstantBlock(Cursor, Scratch)) {
1737 if (!HasValidControlBlock ||
1738 Implementation->readTagBlock(Cursor, Scratch)) {
1745 if (!HasValidControlBlock ||
1746 Implementation->readTypedefBlock(Cursor, Scratch)) {
1755 if (
Cursor.SkipBlock()) {
1763 if (!
Cursor.AtEndOfStream()) {
1771std::unique_ptr<APINotesReader>
1773 llvm::VersionTuple SwiftVersion) {
1774 bool Failed =
false;
1775 std::unique_ptr<APINotesReader> Reader(
1776 new APINotesReader(InputBuffer.release(), SwiftVersion, Failed));
1783template <
typename T>
1785 llvm::VersionTuple Version,
1787 : Results(
std::move(R)) {
1789 assert(!Results.empty());
1790 assert(std::is_sorted(
1791 Results.begin(), Results.end(),
1792 [](
const std::pair<llvm::VersionTuple, T> &left,
1793 const std::pair<llvm::VersionTuple, T> &right) ->
bool {
1794 assert(left.first != right.first &&
"two entries for the same version");
1795 return left.first < right.first;
1798 Selected = std::nullopt;
1799 for (
unsigned i = 0, n = Results.size(); i != n; ++i) {
1800 if (!Version.empty() && Results[i].first >= Version) {
1812 if (!Selected && Results[0].first.empty())
1817 -> std::optional<ContextID> {
1819 return std::nullopt;
1823 return std::nullopt;
1830 return std::nullopt;
1838 return std::nullopt;
1842 return std::nullopt;
1846 return std::nullopt;
1852 -> std::optional<ContextID> {
1854 return std::nullopt;
1858 return std::nullopt;
1865 return std::nullopt;
1873 return std::nullopt;
1877 return std::nullopt;
1881 return std::nullopt;
1890 return std::nullopt;
1894 return std::nullopt;
1897 std::make_tuple(CtxID.Value, *PropertyID, (
char)IsInstance));
1899 return std::nullopt;
1905 bool IsInstanceMethod)
1908 return std::nullopt;
1912 return std::nullopt;
1915 ObjCMethodTableInfo::internal_key_type{CtxID.Value, *SelID,
1918 return std::nullopt;
1924 std::optional<Context> Ctx)
1927 return std::nullopt;
1931 return std::nullopt;
1937 return std::nullopt;
1943 std::optional<Context> Ctx)
1946 return std::nullopt;
1950 return std::nullopt;
1956 return std::nullopt;
1964 return std::nullopt;
1968 return std::nullopt;
1972 return std::nullopt;
1980 return std::nullopt;
1984 return std::nullopt;
1990 return std::nullopt;
1996 std::optional<Context> Ctx)
1999 return std::nullopt;
2003 return std::nullopt;
2009 return std::nullopt;
2015 llvm::StringRef Name, std::optional<ContextID> ParentNamespaceID)
2016 -> std::optional<ContextID> {
2018 return std::nullopt;
2022 return std::nullopt;
2024 uint32_t RawParentNamespaceID =
2025 ParentNamespaceID ? ParentNamespaceID->Value : -1;
2029 return std::nullopt;
static StringRef getIdentifier(const Token &Tok)
Implements an efficient mapping from strings to IdentifierInfo nodes.
iterator find(StringRef Name) const
Smart pointer class that efficiently represents Objective-C method names.
llvm::OnDiskIterableChainedHashTable< ObjCContextIDTableInfo > SerializedObjCContextIDTable
llvm::OnDiskIterableChainedHashTable< GlobalVariableTableInfo > SerializedGlobalVariableTable
bool readEnumConstantBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
std::string ModuleName
The name of the module that we read from the control block.
std::optional< std::pair< off_t, time_t > > SourceFileSizeAndModTime
std::unique_ptr< SerializedIdentifierTable > IdentifierTable
The identifier table.
llvm::OnDiskIterableChainedHashTable< TagTableInfo > SerializedTagTable
std::unique_ptr< SerializedGlobalFunctionTable > GlobalFunctionTable
The global function table.
std::unique_ptr< SerializedObjCPropertyTable > ObjCPropertyTable
The Objective-C property table.
bool readObjCMethodBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
std::unique_ptr< SerializedGlobalVariableTable > GlobalVariableTable
The global variable table.
bool readTagBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
std::unique_ptr< SerializedTypedefTable > TypedefTable
The typedef table.
llvm::OnDiskIterableChainedHashTable< ObjCSelectorTableInfo > SerializedObjCSelectorTable
bool readGlobalFunctionBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
std::unique_ptr< SerializedObjCContextInfoTable > ObjCContextInfoTable
The Objective-C context info table.
bool readTypedefBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
llvm::MemoryBuffer * InputBuffer
The input buffer for the API notes data.
std::unique_ptr< SerializedObjCSelectorTable > ObjCSelectorTable
The Objective-C selector table.
bool readControlBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
bool readObjCPropertyBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
bool readObjCSelectorBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
llvm::OnDiskIterableChainedHashTable< IdentifierTableInfo > SerializedIdentifierTable
std::unique_ptr< SerializedEnumConstantTable > EnumConstantTable
The enumerator table.
std::optional< IdentifierID > getIdentifier(llvm::StringRef Str)
Retrieve the identifier ID for the given string, or an empty optional if the string is unknown.
bool readObjCContextBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
bool readGlobalVariableBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
llvm::OnDiskIterableChainedHashTable< ObjCPropertyTableInfo > SerializedObjCPropertyTable
std::unique_ptr< SerializedTagTable > TagTable
The tag table.
std::optional< SelectorID > getSelector(ObjCSelectorRef Selector)
Retrieve the selector ID for the given selector, or an empty optional if the string is unknown.
llvm::OnDiskIterableChainedHashTable< ObjCMethodTableInfo > SerializedObjCMethodTable
bool readIdentifierBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
llvm::VersionTuple SwiftVersion
The Swift version to use for filtering.
llvm::OnDiskIterableChainedHashTable< EnumConstantTableInfo > SerializedEnumConstantTable
std::unique_ptr< SerializedObjCMethodTable > ObjCMethodTable
The Objective-C method table.
std::unique_ptr< SerializedObjCContextIDTable > ObjCContextIDTable
The Objective-C context ID table.
llvm::OnDiskIterableChainedHashTable< TypedefTableInfo > SerializedTypedefTable
llvm::OnDiskIterableChainedHashTable< ObjCContextInfoTableInfo > SerializedObjCContextInfoTable
llvm::OnDiskIterableChainedHashTable< GlobalFunctionTableInfo > SerializedGlobalFunctionTable
Captures the completed versioned information for a particular part of API notes, including both unver...
VersionedInfo(std::nullopt_t)
Form an empty set of versioned information.
A class that reads API notes data from a binary file that was written by the APINotesWriter.
VersionedInfo< ObjCContextInfo > lookupObjCClassInfo(llvm::StringRef Name)
Look for information regarding the given Objective-C class.
VersionedInfo< TagInfo > lookupTag(llvm::StringRef Name, std::optional< Context > Ctx=std::nullopt)
Look for information regarding the given tag (struct/union/enum/C++ class).
VersionedInfo< GlobalFunctionInfo > lookupGlobalFunction(llvm::StringRef Name, std::optional< Context > Ctx=std::nullopt)
Look for information regarding the given global function.
VersionedInfo< ObjCPropertyInfo > lookupObjCProperty(ContextID CtxID, llvm::StringRef Name, bool IsInstance)
Look for information regarding the given Objective-C property in the given context.
VersionedInfo< ObjCMethodInfo > lookupObjCMethod(ContextID CtxID, ObjCSelectorRef Selector, bool IsInstanceMethod)
Look for information regarding the given Objective-C method in the given context.
VersionedInfo< GlobalVariableInfo > lookupGlobalVariable(llvm::StringRef Name, std::optional< Context > Ctx=std::nullopt)
Look for information regarding the given global variable.
std::optional< ContextID > lookupNamespaceID(llvm::StringRef Name, std::optional< ContextID > ParentNamespaceID=std::nullopt)
Look for the context ID of the given C++ namespace.
VersionedInfo< TypedefInfo > lookupTypedef(llvm::StringRef Name, std::optional< Context > Ctx=std::nullopt)
Look for information regarding the given typedef.
std::optional< ContextID > lookupObjCClassID(llvm::StringRef Name)
Look for the context ID of the given Objective-C class.
static std::unique_ptr< APINotesReader > Create(std::unique_ptr< llvm::MemoryBuffer > InputBuffer, llvm::VersionTuple SwiftVersion)
Create a new API notes reader from the given member buffer, which contains the contents of a binary A...
VersionedInfo< ObjCContextInfo > lookupObjCProtocolInfo(llvm::StringRef Name)
Look for information regarding the given Objective-C protocol.
std::optional< ContextID > lookupObjCProtocolID(llvm::StringRef Name)
Look for the context ID of the given Objective-C protocol.
VersionedInfo< EnumConstantInfo > lookupEnumConstant(llvm::StringRef Name)
Look for information regarding the given enumerator.
Opaque context ID used to refer to an Objective-C class or protocol or a C++ namespace.
llvm::PointerEmbeddedInt< unsigned, 31 > SelectorID
const uint8_t kSwiftCopyable
RetainCountConventionKind
llvm::PointerEmbeddedInt< unsigned, 31 > IdentifierID
SwiftNewTypeKind
The kind of a swift_wrapper/swift_newtype.
const uint8_t kSwiftNonCopyable
EnumExtensibilityKind
The payload for an enum_extensibility attribute.
const uint16_t VERSION_MAJOR
API notes file major version number.
const unsigned char API_NOTES_SIGNATURE[]
Magic number for API notes files.
const uint16_t VERSION_MINOR
API notes file minor version number.
@ OBJC_CONTEXT_BLOCK_ID
The Objective-C context data block, which contains information about Objective-C classes and protocol...
@ TYPEDEF_BLOCK_ID
The typedef data block, which maps typedef names to information about the typedefs.
@ OBJC_PROPERTY_BLOCK_ID
The Objective-C property data block, which maps Objective-C (class name, property name) pairs to info...
@ ENUM_CONSTANT_BLOCK_ID
The enum constant data block, which maps enumerator names to information about the enumerators.
@ TAG_BLOCK_ID
The tag data block, which maps tag names to information about the tags.
@ OBJC_METHOD_BLOCK_ID
The Objective-C property data block, which maps Objective-C (class name, selector,...
@ OBJC_SELECTOR_BLOCK_ID
The Objective-C selector data block, which maps Objective-C selector names (# of pieces,...
@ GLOBAL_FUNCTION_BLOCK_ID
The (global) functions data block, which maps global function names to information about the global f...
@ CONTROL_BLOCK_ID
The control block, which contains all of the information that needs to be validated prior to committi...
@ IDENTIFIER_BLOCK_ID
The identifier data block, which maps identifier strings to IDs.
@ GLOBAL_VARIABLE_BLOCK_ID
The global variables data block, which maps global variable names to information about the global var...
unsigned ComputeHash(Selector Sel)
The JSON file list parser is used to communicate input to InstallAPI.
NullabilityKind
Describes the nullability of a particular type.
@ Result
The result type of a method or function.
hash_code hash_value(const clang::tooling::dependencies::ModuleID &ID)
A stored Objective-C or C++ context, represented by the ID of its parent context, the kind of this co...
A temporary reference to an Objective-C selector, suitable for referencing selector data on the stack...
A stored Objective-C selector.
llvm::SmallVector< IdentifierID, 2 > Identifiers