[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / clang / lib / APINotes / APINotesReader.cpp
blob2cbf5fd3bf50301fd28b21c0fecca875230ba53b
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 //===----------------------------------------------------------------------===//
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"
18 namespace clang {
19 namespace api_notes {
20 using namespace llvm::support;
22 namespace {
23 /// Deserialize a version tuple.
24 llvm::VersionTuple ReadVersionTuple(const uint8_t *&Data) {
25 uint8_t NumVersions = (*Data++) & 0x03;
27 unsigned Major =
28 endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data);
29 if (NumVersions == 0)
30 return llvm::VersionTuple(Major);
32 unsigned Minor =
33 endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data);
34 if (NumVersions == 1)
35 return llvm::VersionTuple(Major, Minor);
37 unsigned Subminor =
38 endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data);
39 if (NumVersions == 2)
40 return llvm::VersionTuple(Major, Minor, Subminor);
42 unsigned Build =
43 endian::readNext<uint32_t, llvm::endianness::little, unaligned>(Data);
44 return llvm::VersionTuple(Major, Minor, Subminor, Build);
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;
58 internal_key_type GetInternalKey(external_key_type Key) { return Key; }
60 external_key_type GetExternalKey(internal_key_type Key) { return Key; }
62 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
63 return LHS == RHS;
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};
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});
89 return Result;
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));
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;
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;
116 /// Read serialized CommonTypeInfo.
117 void ReadCommonTypeInfo(const uint8_t *&Data, CommonTypeInfo &Info) {
118 ReadCommonEntityInfo(Data, Info);
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;
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;
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;
146 internal_key_type GetInternalKey(external_key_type Key) { return Key; }
148 external_key_type GetExternalKey(internal_key_type Key) { return Key; }
150 hash_value_type ComputeHash(internal_key_type Key) {
151 return llvm::hash_value(Key);
154 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
155 return LHS == RHS;
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};
166 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
167 return llvm::StringRef(reinterpret_cast<const char *>(Data), Length);
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);
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;
186 internal_key_type GetInternalKey(external_key_type Key) { return Key; }
188 external_key_type GetExternalKey(internal_key_type Key) { return Key; }
190 hash_value_type ComputeHash(internal_key_type Key) {
191 return static_cast<size_t>(Key.hashValue());
194 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
195 return LHS == RHS;
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};
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};
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);
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);
233 hash_value_type ComputeHash(internal_key_type Key) {
234 return static_cast<size_t>(llvm::hash_value(Key));
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++;
243 if (Payload & 0x01)
244 Info.setHasDesignatedInits(true);
245 Payload = Payload >> 1;
247 if (Payload & 0x4)
248 Info.setDefaultNullability(static_cast<NullabilityKind>(Payload & 0x03));
249 Payload >>= 3;
251 if (Payload & (1 << 1))
252 Info.setSwiftObjCMembers(Payload & 1);
253 Payload >>= 2;
255 if (Payload & (1 << 1))
256 Info.setSwiftImportAsNonGeneric(Payload & 1);
258 return Info;
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));
268 ++Data;
270 auto TypeLen =
271 endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data);
272 Info.setType(std::string(Data, Data + TypeLen));
273 Data += TypeLen;
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};
292 hash_value_type ComputeHash(internal_key_type Key) {
293 return static_cast<size_t>(llvm::hash_value(Key));
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;
307 /// Read serialized ParamInfo.
308 void ReadParamInfo(const uint8_t *&Data, ParamInfo &Info) {
309 ReadVariableInfo(Data, Info);
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);
317 Payload >>= 3;
318 if (Payload & 0x01)
319 Info.setNoEscape(Payload & 0x02);
320 Payload >>= 2;
321 assert(Payload == 0 && "Bad API notes");
324 /// Read serialized FunctionInfo.
325 void ReadFunctionInfo(const uint8_t *&Data, FunctionInfo &Info) {
326 ReadCommonEntityInfo(Data, Info);
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);
334 Payload >>= 3;
335 Info.NullabilityAudited = Payload & 0x1;
336 Payload >>= 1;
337 assert(Payload == 0 && "Bad API notes");
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);
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;
353 unsigned ResultTypeLen =
354 endian::readNext<uint16_t, llvm::endianness::little, unaligned>(Data);
355 Info.ResultType = std::string(Data, Data + ResultTypeLen);
356 Data += ResultTypeLen;
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};
375 hash_value_type ComputeHash(internal_key_type Key) {
376 return static_cast<size_t>(llvm::hash_value(Key));
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;
388 ReadFunctionInfo(Data, Info);
389 return Info;
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;
402 internal_key_type GetInternalKey(external_key_type Key) { return Key; }
404 external_key_type GetExternalKey(internal_key_type Key) { return Key; }
406 hash_value_type ComputeHash(internal_key_type Key) {
407 return llvm::DenseMapInfo<StoredObjCSelector>::getHashValue(Key);
410 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
411 return llvm::DenseMapInfo<StoredObjCSelector>::isEqual(LHS, RHS);
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};
422 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
423 internal_key_type Key;
424 Key.NumPieces =
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));
432 return Key;
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);
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};
457 hash_value_type ComputeHash(internal_key_type Key) {
458 return static_cast<size_t>(Key.hashValue());
461 static GlobalVariableInfo readUnversioned(internal_key_type Key,
462 const uint8_t *&Data) {
463 GlobalVariableInfo Info;
464 ReadVariableInfo(Data, Info);
465 return Info;
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};
484 hash_value_type ComputeHash(internal_key_type Key) {
485 return static_cast<size_t>(Key.hashValue());
488 static GlobalFunctionInfo readUnversioned(internal_key_type Key,
489 const uint8_t *&Data) {
490 GlobalFunctionInfo Info;
491 ReadFunctionInfo(Data, Info);
492 return Info;
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;
507 hash_value_type ComputeHash(internal_key_type Key) {
508 return static_cast<size_t>(llvm::hash_value(Key));
511 static EnumConstantInfo readUnversioned(internal_key_type Key,
512 const uint8_t *&Data) {
513 EnumConstantInfo Info;
514 ReadCommonEntityInfo(Data, Info);
515 return Info;
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};
534 hash_value_type ComputeHash(internal_key_type Key) {
535 return static_cast<size_t>(Key.hashValue());
538 static TagInfo readUnversioned(internal_key_type Key, const uint8_t *&Data) {
539 TagInfo Info;
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);
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;
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;
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;
571 ReadCommonTypeInfo(Data, Info);
572 return Info;
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};
592 hash_value_type ComputeHash(internal_key_type Key) {
593 return static_cast<size_t>(Key.hashValue());
596 static TypedefInfo readUnversioned(internal_key_type Key,
597 const uint8_t *&Data) {
598 TypedefInfo Info;
600 uint8_t Payload = *Data++;
601 if (Payload > 0)
602 Info.SwiftWrapper = static_cast<SwiftNewTypeKind>((Payload & 0x3) - 1);
604 ReadCommonTypeInfo(Data, Info);
605 return Info;
608 } // end anonymous namespace
610 class APINotesReader::Implementation {
611 public:
612 /// The input buffer for the API notes data.
613 llvm::MemoryBuffer *InputBuffer;
615 /// The Swift version to use for filtering.
616 llvm::VersionTuple SwiftVersion;
618 /// The name of the module that we read from the control block.
619 std::string ModuleName;
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;
625 using SerializedIdentifierTable =
626 llvm::OnDiskIterableChainedHashTable<IdentifierTableInfo>;
628 /// The identifier table.
629 std::unique_ptr<SerializedIdentifierTable> IdentifierTable;
631 using SerializedObjCContextIDTable =
632 llvm::OnDiskIterableChainedHashTable<ObjCContextIDTableInfo>;
634 /// The Objective-C context ID table.
635 std::unique_ptr<SerializedObjCContextIDTable> ObjCContextIDTable;
637 using SerializedObjCContextInfoTable =
638 llvm::OnDiskIterableChainedHashTable<ObjCContextInfoTableInfo>;
640 /// The Objective-C context info table.
641 std::unique_ptr<SerializedObjCContextInfoTable> ObjCContextInfoTable;
643 using SerializedObjCPropertyTable =
644 llvm::OnDiskIterableChainedHashTable<ObjCPropertyTableInfo>;
646 /// The Objective-C property table.
647 std::unique_ptr<SerializedObjCPropertyTable> ObjCPropertyTable;
649 using SerializedObjCMethodTable =
650 llvm::OnDiskIterableChainedHashTable<ObjCMethodTableInfo>;
652 /// The Objective-C method table.
653 std::unique_ptr<SerializedObjCMethodTable> ObjCMethodTable;
655 using SerializedObjCSelectorTable =
656 llvm::OnDiskIterableChainedHashTable<ObjCSelectorTableInfo>;
658 /// The Objective-C selector table.
659 std::unique_ptr<SerializedObjCSelectorTable> ObjCSelectorTable;
661 using SerializedGlobalVariableTable =
662 llvm::OnDiskIterableChainedHashTable<GlobalVariableTableInfo>;
664 /// The global variable table.
665 std::unique_ptr<SerializedGlobalVariableTable> GlobalVariableTable;
667 using SerializedGlobalFunctionTable =
668 llvm::OnDiskIterableChainedHashTable<GlobalFunctionTableInfo>;
670 /// The global function table.
671 std::unique_ptr<SerializedGlobalFunctionTable> GlobalFunctionTable;
673 using SerializedEnumConstantTable =
674 llvm::OnDiskIterableChainedHashTable<EnumConstantTableInfo>;
676 /// The enumerator table.
677 std::unique_ptr<SerializedEnumConstantTable> EnumConstantTable;
679 using SerializedTagTable = llvm::OnDiskIterableChainedHashTable<TagTableInfo>;
681 /// The tag table.
682 std::unique_ptr<SerializedTagTable> TagTable;
684 using SerializedTypedefTable =
685 llvm::OnDiskIterableChainedHashTable<TypedefTableInfo>;
687 /// The typedef table.
688 std::unique_ptr<SerializedTypedefTable> TypedefTable;
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);
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);
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);
722 std::optional<IdentifierID>
723 APINotesReader::Implementation::getIdentifier(llvm::StringRef Str) {
724 if (!IdentifierTable)
725 return std::nullopt;
727 if (Str.empty())
728 return IdentifierID(0);
730 auto Known = IdentifierTable->find(Str);
731 if (Known == IdentifierTable->end())
732 return std::nullopt;
734 return *Known;
737 std::optional<SelectorID>
738 APINotesReader::Implementation::getSelector(ObjCSelectorRef Selector) {
739 if (!ObjCSelectorTable || !IdentifierTable)
740 return std::nullopt;
742 // Translate the identifiers.
743 StoredObjCSelector Key;
744 for (auto Ident : Selector.Identifiers) {
745 if (auto IdentID = getIdentifier(Ident)) {
746 Key.Identifiers.push_back(*IdentID);
747 } else {
748 return std::nullopt;
752 auto Known = ObjCSelectorTable->find(Key);
753 if (Known == ObjCSelectorTable->end())
754 return std::nullopt;
756 return *Known;
759 bool APINotesReader::Implementation::readControlBlock(
760 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
761 if (Cursor.EnterSubBlock(CONTROL_BLOCK_ID))
762 return true;
764 bool SawMetadata = false;
766 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
767 if (!MaybeNext) {
768 // FIXME this drops the error on the floor.
769 consumeError(MaybeNext.takeError());
770 return false;
772 llvm::BitstreamEntry Next = MaybeNext.get();
774 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
775 if (Next.Kind == llvm::BitstreamEntry::Error)
776 return true;
778 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
779 // Unknown metadata sub-block, possibly for use by a future version of the
780 // API notes format.
781 if (Cursor.SkipBlock())
782 return true;
784 MaybeNext = Cursor.advance();
785 if (!MaybeNext) {
786 // FIXME this drops the error on the floor.
787 consumeError(MaybeNext.takeError());
788 return false;
790 Next = MaybeNext.get();
791 continue;
794 Scratch.clear();
795 llvm::StringRef BlobData;
796 llvm::Expected<unsigned> MaybeKind =
797 Cursor.readRecord(Next.ID, Scratch, &BlobData);
798 if (!MaybeKind) {
799 // FIXME this drops the error on the floor.
800 consumeError(MaybeKind.takeError());
801 return false;
803 unsigned Kind = MaybeKind.get();
805 switch (Kind) {
806 case control_block::METADATA:
807 // Already saw metadata.
808 if (SawMetadata)
809 return true;
811 if (Scratch[0] != VERSION_MAJOR || Scratch[1] != VERSION_MINOR)
812 return true;
814 SawMetadata = true;
815 break;
817 case control_block::MODULE_NAME:
818 ModuleName = BlobData.str();
819 break;
821 case control_block::MODULE_OPTIONS:
822 break;
824 case control_block::SOURCE_FILE:
825 SourceFileSizeAndModTime = {Scratch[0], Scratch[1]};
826 break;
828 default:
829 // Unknown metadata record, possibly for use by a future version of the
830 // module format.
831 break;
834 MaybeNext = Cursor.advance();
835 if (!MaybeNext) {
836 // FIXME this drops the error on the floor.
837 consumeError(MaybeNext.takeError());
838 return false;
840 Next = MaybeNext.get();
843 return !SawMetadata;
846 bool APINotesReader::Implementation::readIdentifierBlock(
847 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
848 if (Cursor.EnterSubBlock(IDENTIFIER_BLOCK_ID))
849 return true;
851 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
852 if (!MaybeNext) {
853 // FIXME this drops the error on the floor.
854 consumeError(MaybeNext.takeError());
855 return false;
857 llvm::BitstreamEntry Next = MaybeNext.get();
859 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
860 if (Next.Kind == llvm::BitstreamEntry::Error)
861 return true;
863 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
864 // Unknown sub-block, possibly for use by a future version of the
865 // API notes format.
866 if (Cursor.SkipBlock())
867 return true;
869 MaybeNext = Cursor.advance();
870 if (!MaybeNext) {
871 // FIXME this drops the error on the floor.
872 consumeError(MaybeNext.takeError());
873 return false;
875 Next = MaybeNext.get();
876 continue;
879 Scratch.clear();
880 llvm::StringRef BlobData;
881 llvm::Expected<unsigned> MaybeKind =
882 Cursor.readRecord(Next.ID, Scratch, &BlobData);
883 if (!MaybeKind) {
884 // FIXME this drops the error on the floor.
885 consumeError(MaybeKind.takeError());
886 return false;
888 unsigned Kind = MaybeKind.get();
889 switch (Kind) {
890 case identifier_block::IDENTIFIER_DATA: {
891 // Already saw identifier table.
892 if (IdentifierTable)
893 return true;
895 uint32_t tableOffset;
896 identifier_block::IdentifierDataLayout::readRecord(Scratch, tableOffset);
897 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
899 IdentifierTable.reset(SerializedIdentifierTable::Create(
900 base + tableOffset, base + sizeof(uint32_t), base));
901 break;
904 default:
905 // Unknown record, possibly for use by a future version of the
906 // module format.
907 break;
910 MaybeNext = Cursor.advance();
911 if (!MaybeNext) {
912 // FIXME this drops the error on the floor.
913 consumeError(MaybeNext.takeError());
914 return false;
916 Next = MaybeNext.get();
919 return false;
922 bool APINotesReader::Implementation::readObjCContextBlock(
923 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
924 if (Cursor.EnterSubBlock(OBJC_CONTEXT_BLOCK_ID))
925 return true;
927 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
928 if (!MaybeNext) {
929 // FIXME this drops the error on the floor.
930 consumeError(MaybeNext.takeError());
931 return false;
933 llvm::BitstreamEntry Next = MaybeNext.get();
935 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
936 if (Next.Kind == llvm::BitstreamEntry::Error)
937 return true;
939 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
940 // Unknown sub-block, possibly for use by a future version of the
941 // API notes format.
942 if (Cursor.SkipBlock())
943 return true;
945 MaybeNext = Cursor.advance();
946 if (!MaybeNext) {
947 // FIXME this drops the error on the floor.
948 consumeError(MaybeNext.takeError());
949 return false;
951 Next = MaybeNext.get();
952 continue;
955 Scratch.clear();
956 llvm::StringRef BlobData;
957 llvm::Expected<unsigned> MaybeKind =
958 Cursor.readRecord(Next.ID, Scratch, &BlobData);
959 if (!MaybeKind) {
960 // FIXME this drops the error on the floor.
961 consumeError(MaybeKind.takeError());
962 return false;
964 unsigned Kind = MaybeKind.get();
965 switch (Kind) {
966 case objc_context_block::OBJC_CONTEXT_ID_DATA: {
967 // Already saw Objective-C context ID table.
968 if (ObjCContextIDTable)
969 return true;
971 uint32_t tableOffset;
972 objc_context_block::ObjCContextIDLayout::readRecord(Scratch, tableOffset);
973 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
975 ObjCContextIDTable.reset(SerializedObjCContextIDTable::Create(
976 base + tableOffset, base + sizeof(uint32_t), base));
977 break;
980 case objc_context_block::OBJC_CONTEXT_INFO_DATA: {
981 // Already saw Objective-C context info table.
982 if (ObjCContextInfoTable)
983 return true;
985 uint32_t tableOffset;
986 objc_context_block::ObjCContextInfoLayout::readRecord(Scratch,
987 tableOffset);
988 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
990 ObjCContextInfoTable.reset(SerializedObjCContextInfoTable::Create(
991 base + tableOffset, base + sizeof(uint32_t), base));
992 break;
995 default:
996 // Unknown record, possibly for use by a future version of the
997 // module format.
998 break;
1001 MaybeNext = Cursor.advance();
1002 if (!MaybeNext) {
1003 // FIXME this drops the error on the floor.
1004 consumeError(MaybeNext.takeError());
1005 return false;
1007 Next = MaybeNext.get();
1010 return false;
1013 bool APINotesReader::Implementation::readObjCPropertyBlock(
1014 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1015 if (Cursor.EnterSubBlock(OBJC_PROPERTY_BLOCK_ID))
1016 return true;
1018 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1019 if (!MaybeNext) {
1020 // FIXME this drops the error on the floor.
1021 consumeError(MaybeNext.takeError());
1022 return false;
1024 llvm::BitstreamEntry Next = MaybeNext.get();
1026 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1027 if (Next.Kind == llvm::BitstreamEntry::Error)
1028 return true;
1030 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1031 // Unknown sub-block, possibly for use by a future version of the
1032 // API notes format.
1033 if (Cursor.SkipBlock())
1034 return true;
1036 MaybeNext = Cursor.advance();
1037 if (!MaybeNext) {
1038 // FIXME this drops the error on the floor.
1039 consumeError(MaybeNext.takeError());
1040 return false;
1042 Next = MaybeNext.get();
1043 continue;
1046 Scratch.clear();
1047 llvm::StringRef BlobData;
1048 llvm::Expected<unsigned> MaybeKind =
1049 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1050 if (!MaybeKind) {
1051 // FIXME this drops the error on the floor.
1052 consumeError(MaybeKind.takeError());
1053 return false;
1055 unsigned Kind = MaybeKind.get();
1056 switch (Kind) {
1057 case objc_property_block::OBJC_PROPERTY_DATA: {
1058 // Already saw Objective-C property table.
1059 if (ObjCPropertyTable)
1060 return true;
1062 uint32_t tableOffset;
1063 objc_property_block::ObjCPropertyDataLayout::readRecord(Scratch,
1064 tableOffset);
1065 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1067 ObjCPropertyTable.reset(SerializedObjCPropertyTable::Create(
1068 base + tableOffset, base + sizeof(uint32_t), base));
1069 break;
1072 default:
1073 // Unknown record, possibly for use by a future version of the
1074 // module format.
1075 break;
1078 MaybeNext = Cursor.advance();
1079 if (!MaybeNext) {
1080 // FIXME this drops the error on the floor.
1081 consumeError(MaybeNext.takeError());
1082 return false;
1084 Next = MaybeNext.get();
1087 return false;
1090 bool APINotesReader::Implementation::readObjCMethodBlock(
1091 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1092 if (Cursor.EnterSubBlock(OBJC_METHOD_BLOCK_ID))
1093 return true;
1095 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1096 if (!MaybeNext) {
1097 // FIXME this drops the error on the floor.
1098 consumeError(MaybeNext.takeError());
1099 return false;
1101 llvm::BitstreamEntry Next = MaybeNext.get();
1102 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1103 if (Next.Kind == llvm::BitstreamEntry::Error)
1104 return true;
1106 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1107 // Unknown sub-block, possibly for use by a future version of the
1108 // API notes format.
1109 if (Cursor.SkipBlock())
1110 return true;
1112 MaybeNext = Cursor.advance();
1113 if (!MaybeNext) {
1114 // FIXME this drops the error on the floor.
1115 consumeError(MaybeNext.takeError());
1116 return false;
1118 Next = MaybeNext.get();
1119 continue;
1122 Scratch.clear();
1123 llvm::StringRef BlobData;
1124 llvm::Expected<unsigned> MaybeKind =
1125 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1126 if (!MaybeKind) {
1127 // FIXME this drops the error on the floor.
1128 consumeError(MaybeKind.takeError());
1129 return false;
1131 unsigned Kind = MaybeKind.get();
1132 switch (Kind) {
1133 case objc_method_block::OBJC_METHOD_DATA: {
1134 // Already saw Objective-C method table.
1135 if (ObjCMethodTable)
1136 return true;
1138 uint32_t tableOffset;
1139 objc_method_block::ObjCMethodDataLayout::readRecord(Scratch, tableOffset);
1140 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1142 ObjCMethodTable.reset(SerializedObjCMethodTable::Create(
1143 base + tableOffset, base + sizeof(uint32_t), base));
1144 break;
1147 default:
1148 // Unknown record, possibly for use by a future version of the
1149 // module format.
1150 break;
1153 MaybeNext = Cursor.advance();
1154 if (!MaybeNext) {
1155 // FIXME this drops the error on the floor.
1156 consumeError(MaybeNext.takeError());
1157 return false;
1159 Next = MaybeNext.get();
1162 return false;
1165 bool APINotesReader::Implementation::readObjCSelectorBlock(
1166 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1167 if (Cursor.EnterSubBlock(OBJC_SELECTOR_BLOCK_ID))
1168 return true;
1170 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1171 if (!MaybeNext) {
1172 // FIXME this drops the error on the floor.
1173 consumeError(MaybeNext.takeError());
1174 return false;
1176 llvm::BitstreamEntry Next = MaybeNext.get();
1177 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1178 if (Next.Kind == llvm::BitstreamEntry::Error)
1179 return true;
1181 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1182 // Unknown sub-block, possibly for use by a future version of the
1183 // API notes format.
1184 if (Cursor.SkipBlock())
1185 return true;
1187 MaybeNext = Cursor.advance();
1188 if (!MaybeNext) {
1189 // FIXME this drops the error on the floor.
1190 consumeError(MaybeNext.takeError());
1191 return false;
1193 Next = MaybeNext.get();
1194 continue;
1197 Scratch.clear();
1198 llvm::StringRef BlobData;
1199 llvm::Expected<unsigned> MaybeKind =
1200 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1201 if (!MaybeKind) {
1202 // FIXME this drops the error on the floor.
1203 consumeError(MaybeKind.takeError());
1204 return false;
1206 unsigned Kind = MaybeKind.get();
1207 switch (Kind) {
1208 case objc_selector_block::OBJC_SELECTOR_DATA: {
1209 // Already saw Objective-C selector table.
1210 if (ObjCSelectorTable)
1211 return true;
1213 uint32_t tableOffset;
1214 objc_selector_block::ObjCSelectorDataLayout::readRecord(Scratch,
1215 tableOffset);
1216 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1218 ObjCSelectorTable.reset(SerializedObjCSelectorTable::Create(
1219 base + tableOffset, base + sizeof(uint32_t), base));
1220 break;
1223 default:
1224 // Unknown record, possibly for use by a future version of the
1225 // module format.
1226 break;
1229 MaybeNext = Cursor.advance();
1230 if (!MaybeNext) {
1231 // FIXME this drops the error on the floor.
1232 consumeError(MaybeNext.takeError());
1233 return false;
1235 Next = MaybeNext.get();
1238 return false;
1241 bool APINotesReader::Implementation::readGlobalVariableBlock(
1242 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1243 if (Cursor.EnterSubBlock(GLOBAL_VARIABLE_BLOCK_ID))
1244 return true;
1246 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1247 if (!MaybeNext) {
1248 // FIXME this drops the error on the floor.
1249 consumeError(MaybeNext.takeError());
1250 return false;
1252 llvm::BitstreamEntry Next = MaybeNext.get();
1253 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1254 if (Next.Kind == llvm::BitstreamEntry::Error)
1255 return true;
1257 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1258 // Unknown sub-block, possibly for use by a future version of the
1259 // API notes format.
1260 if (Cursor.SkipBlock())
1261 return true;
1263 MaybeNext = Cursor.advance();
1264 if (!MaybeNext) {
1265 // FIXME this drops the error on the floor.
1266 consumeError(MaybeNext.takeError());
1267 return false;
1269 Next = MaybeNext.get();
1270 continue;
1273 Scratch.clear();
1274 llvm::StringRef BlobData;
1275 llvm::Expected<unsigned> MaybeKind =
1276 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1277 if (!MaybeKind) {
1278 // FIXME this drops the error on the floor.
1279 consumeError(MaybeKind.takeError());
1280 return false;
1282 unsigned Kind = MaybeKind.get();
1283 switch (Kind) {
1284 case global_variable_block::GLOBAL_VARIABLE_DATA: {
1285 // Already saw global variable table.
1286 if (GlobalVariableTable)
1287 return true;
1289 uint32_t tableOffset;
1290 global_variable_block::GlobalVariableDataLayout::readRecord(Scratch,
1291 tableOffset);
1292 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1294 GlobalVariableTable.reset(SerializedGlobalVariableTable::Create(
1295 base + tableOffset, base + sizeof(uint32_t), base));
1296 break;
1299 default:
1300 // Unknown record, possibly for use by a future version of the
1301 // module format.
1302 break;
1305 MaybeNext = Cursor.advance();
1306 if (!MaybeNext) {
1307 // FIXME this drops the error on the floor.
1308 consumeError(MaybeNext.takeError());
1309 return false;
1311 Next = MaybeNext.get();
1314 return false;
1317 bool APINotesReader::Implementation::readGlobalFunctionBlock(
1318 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1319 if (Cursor.EnterSubBlock(GLOBAL_FUNCTION_BLOCK_ID))
1320 return true;
1322 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1323 if (!MaybeNext) {
1324 // FIXME this drops the error on the floor.
1325 consumeError(MaybeNext.takeError());
1326 return false;
1328 llvm::BitstreamEntry Next = MaybeNext.get();
1329 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1330 if (Next.Kind == llvm::BitstreamEntry::Error)
1331 return true;
1333 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1334 // Unknown sub-block, possibly for use by a future version of the
1335 // API notes format.
1336 if (Cursor.SkipBlock())
1337 return true;
1339 MaybeNext = Cursor.advance();
1340 if (!MaybeNext) {
1341 // FIXME this drops the error on the floor.
1342 consumeError(MaybeNext.takeError());
1343 return false;
1345 Next = MaybeNext.get();
1346 continue;
1349 Scratch.clear();
1350 llvm::StringRef BlobData;
1351 llvm::Expected<unsigned> MaybeKind =
1352 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1353 if (!MaybeKind) {
1354 // FIXME this drops the error on the floor.
1355 consumeError(MaybeKind.takeError());
1356 return false;
1358 unsigned Kind = MaybeKind.get();
1359 switch (Kind) {
1360 case global_function_block::GLOBAL_FUNCTION_DATA: {
1361 // Already saw global function table.
1362 if (GlobalFunctionTable)
1363 return true;
1365 uint32_t tableOffset;
1366 global_function_block::GlobalFunctionDataLayout::readRecord(Scratch,
1367 tableOffset);
1368 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1370 GlobalFunctionTable.reset(SerializedGlobalFunctionTable::Create(
1371 base + tableOffset, base + sizeof(uint32_t), base));
1372 break;
1375 default:
1376 // Unknown record, possibly for use by a future version of the
1377 // module format.
1378 break;
1381 MaybeNext = Cursor.advance();
1382 if (!MaybeNext) {
1383 // FIXME this drops the error on the floor.
1384 consumeError(MaybeNext.takeError());
1385 return false;
1387 Next = MaybeNext.get();
1390 return false;
1393 bool APINotesReader::Implementation::readEnumConstantBlock(
1394 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1395 if (Cursor.EnterSubBlock(ENUM_CONSTANT_BLOCK_ID))
1396 return true;
1398 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1399 if (!MaybeNext) {
1400 // FIXME this drops the error on the floor.
1401 consumeError(MaybeNext.takeError());
1402 return false;
1404 llvm::BitstreamEntry Next = MaybeNext.get();
1405 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1406 if (Next.Kind == llvm::BitstreamEntry::Error)
1407 return true;
1409 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1410 // Unknown sub-block, possibly for use by a future version of the
1411 // API notes format.
1412 if (Cursor.SkipBlock())
1413 return true;
1415 MaybeNext = Cursor.advance();
1416 if (!MaybeNext) {
1417 // FIXME this drops the error on the floor.
1418 consumeError(MaybeNext.takeError());
1419 return false;
1421 Next = MaybeNext.get();
1422 continue;
1425 Scratch.clear();
1426 llvm::StringRef BlobData;
1427 llvm::Expected<unsigned> MaybeKind =
1428 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1429 if (!MaybeKind) {
1430 // FIXME this drops the error on the floor.
1431 consumeError(MaybeKind.takeError());
1432 return false;
1434 unsigned Kind = MaybeKind.get();
1435 switch (Kind) {
1436 case enum_constant_block::ENUM_CONSTANT_DATA: {
1437 // Already saw enumerator table.
1438 if (EnumConstantTable)
1439 return true;
1441 uint32_t tableOffset;
1442 enum_constant_block::EnumConstantDataLayout::readRecord(Scratch,
1443 tableOffset);
1444 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1446 EnumConstantTable.reset(SerializedEnumConstantTable::Create(
1447 base + tableOffset, base + sizeof(uint32_t), base));
1448 break;
1451 default:
1452 // Unknown record, possibly for use by a future version of the
1453 // module format.
1454 break;
1457 MaybeNext = Cursor.advance();
1458 if (!MaybeNext) {
1459 // FIXME this drops the error on the floor.
1460 consumeError(MaybeNext.takeError());
1461 return false;
1463 Next = MaybeNext.get();
1466 return false;
1469 bool APINotesReader::Implementation::readTagBlock(
1470 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1471 if (Cursor.EnterSubBlock(TAG_BLOCK_ID))
1472 return true;
1474 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1475 if (!MaybeNext) {
1476 // FIXME this drops the error on the floor.
1477 consumeError(MaybeNext.takeError());
1478 return false;
1480 llvm::BitstreamEntry Next = MaybeNext.get();
1481 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1482 if (Next.Kind == llvm::BitstreamEntry::Error)
1483 return true;
1485 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1486 // Unknown sub-block, possibly for use by a future version of the
1487 // API notes format.
1488 if (Cursor.SkipBlock())
1489 return true;
1491 MaybeNext = Cursor.advance();
1492 if (!MaybeNext) {
1493 // FIXME this drops the error on the floor.
1494 consumeError(MaybeNext.takeError());
1495 return false;
1497 Next = MaybeNext.get();
1498 continue;
1501 Scratch.clear();
1502 llvm::StringRef BlobData;
1503 llvm::Expected<unsigned> MaybeKind =
1504 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1505 if (!MaybeKind) {
1506 // FIXME this drops the error on the floor.
1507 consumeError(MaybeKind.takeError());
1508 return false;
1510 unsigned Kind = MaybeKind.get();
1511 switch (Kind) {
1512 case tag_block::TAG_DATA: {
1513 // Already saw tag table.
1514 if (TagTable)
1515 return true;
1517 uint32_t tableOffset;
1518 tag_block::TagDataLayout::readRecord(Scratch, tableOffset);
1519 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1521 TagTable.reset(SerializedTagTable::Create(base + tableOffset,
1522 base + sizeof(uint32_t), base));
1523 break;
1526 default:
1527 // Unknown record, possibly for use by a future version of the
1528 // module format.
1529 break;
1532 MaybeNext = Cursor.advance();
1533 if (!MaybeNext) {
1534 // FIXME this drops the error on the floor.
1535 consumeError(MaybeNext.takeError());
1536 return false;
1538 Next = MaybeNext.get();
1541 return false;
1544 bool APINotesReader::Implementation::readTypedefBlock(
1545 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1546 if (Cursor.EnterSubBlock(TYPEDEF_BLOCK_ID))
1547 return true;
1549 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1550 if (!MaybeNext) {
1551 // FIXME this drops the error on the floor.
1552 consumeError(MaybeNext.takeError());
1553 return false;
1555 llvm::BitstreamEntry Next = MaybeNext.get();
1556 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1557 if (Next.Kind == llvm::BitstreamEntry::Error)
1558 return true;
1560 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1561 // Unknown sub-block, possibly for use by a future version of the
1562 // API notes format.
1563 if (Cursor.SkipBlock())
1564 return true;
1566 MaybeNext = Cursor.advance();
1567 if (!MaybeNext) {
1568 // FIXME this drops the error on the floor.
1569 consumeError(MaybeNext.takeError());
1570 return false;
1572 Next = MaybeNext.get();
1573 continue;
1576 Scratch.clear();
1577 llvm::StringRef BlobData;
1578 llvm::Expected<unsigned> MaybeKind =
1579 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1580 if (!MaybeKind) {
1581 // FIXME this drops the error on the floor.
1582 consumeError(MaybeKind.takeError());
1583 return false;
1585 unsigned Kind = MaybeKind.get();
1586 switch (Kind) {
1587 case typedef_block::TYPEDEF_DATA: {
1588 // Already saw typedef table.
1589 if (TypedefTable)
1590 return true;
1592 uint32_t tableOffset;
1593 typedef_block::TypedefDataLayout::readRecord(Scratch, tableOffset);
1594 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1596 TypedefTable.reset(SerializedTypedefTable::Create(
1597 base + tableOffset, base + sizeof(uint32_t), base));
1598 break;
1601 default:
1602 // Unknown record, possibly for use by a future version of the
1603 // module format.
1604 break;
1607 MaybeNext = Cursor.advance();
1608 if (!MaybeNext) {
1609 // FIXME this drops the error on the floor.
1610 consumeError(MaybeNext.takeError());
1611 return false;
1613 Next = MaybeNext.get();
1616 return false;
1619 APINotesReader::APINotesReader(llvm::MemoryBuffer *InputBuffer,
1620 llvm::VersionTuple SwiftVersion, bool &Failed)
1621 : Implementation(new class Implementation) {
1622 Failed = false;
1624 // Initialize the input buffer.
1625 Implementation->InputBuffer = InputBuffer;
1626 Implementation->SwiftVersion = SwiftVersion;
1627 llvm::BitstreamCursor Cursor(*Implementation->InputBuffer);
1629 // Validate signature.
1630 for (auto byte : API_NOTES_SIGNATURE) {
1631 if (Cursor.AtEndOfStream()) {
1632 Failed = true;
1633 return;
1635 if (llvm::Expected<llvm::SimpleBitstreamCursor::word_t> maybeRead =
1636 Cursor.Read(8)) {
1637 if (maybeRead.get() != byte) {
1638 Failed = true;
1639 return;
1641 } else {
1642 // FIXME this drops the error on the floor.
1643 consumeError(maybeRead.takeError());
1644 Failed = true;
1645 return;
1649 // Look at all of the blocks.
1650 bool HasValidControlBlock = false;
1651 llvm::SmallVector<uint64_t, 64> Scratch;
1652 while (!Cursor.AtEndOfStream()) {
1653 llvm::Expected<llvm::BitstreamEntry> MaybeTopLevelEntry = Cursor.advance();
1654 if (!MaybeTopLevelEntry) {
1655 // FIXME this drops the error on the floor.
1656 consumeError(MaybeTopLevelEntry.takeError());
1657 Failed = true;
1658 return;
1660 llvm::BitstreamEntry TopLevelEntry = MaybeTopLevelEntry.get();
1662 if (TopLevelEntry.Kind != llvm::BitstreamEntry::SubBlock)
1663 break;
1665 switch (TopLevelEntry.ID) {
1666 case llvm::bitc::BLOCKINFO_BLOCK_ID:
1667 if (!Cursor.ReadBlockInfoBlock()) {
1668 Failed = true;
1669 break;
1671 break;
1673 case CONTROL_BLOCK_ID:
1674 // Only allow a single control block.
1675 if (HasValidControlBlock ||
1676 Implementation->readControlBlock(Cursor, Scratch)) {
1677 Failed = true;
1678 return;
1681 HasValidControlBlock = true;
1682 break;
1684 case IDENTIFIER_BLOCK_ID:
1685 if (!HasValidControlBlock ||
1686 Implementation->readIdentifierBlock(Cursor, Scratch)) {
1687 Failed = true;
1688 return;
1690 break;
1692 case OBJC_CONTEXT_BLOCK_ID:
1693 if (!HasValidControlBlock ||
1694 Implementation->readObjCContextBlock(Cursor, Scratch)) {
1695 Failed = true;
1696 return;
1699 break;
1701 case OBJC_PROPERTY_BLOCK_ID:
1702 if (!HasValidControlBlock ||
1703 Implementation->readObjCPropertyBlock(Cursor, Scratch)) {
1704 Failed = true;
1705 return;
1707 break;
1709 case OBJC_METHOD_BLOCK_ID:
1710 if (!HasValidControlBlock ||
1711 Implementation->readObjCMethodBlock(Cursor, Scratch)) {
1712 Failed = true;
1713 return;
1715 break;
1717 case OBJC_SELECTOR_BLOCK_ID:
1718 if (!HasValidControlBlock ||
1719 Implementation->readObjCSelectorBlock(Cursor, Scratch)) {
1720 Failed = true;
1721 return;
1723 break;
1725 case GLOBAL_VARIABLE_BLOCK_ID:
1726 if (!HasValidControlBlock ||
1727 Implementation->readGlobalVariableBlock(Cursor, Scratch)) {
1728 Failed = true;
1729 return;
1731 break;
1733 case GLOBAL_FUNCTION_BLOCK_ID:
1734 if (!HasValidControlBlock ||
1735 Implementation->readGlobalFunctionBlock(Cursor, Scratch)) {
1736 Failed = true;
1737 return;
1739 break;
1741 case ENUM_CONSTANT_BLOCK_ID:
1742 if (!HasValidControlBlock ||
1743 Implementation->readEnumConstantBlock(Cursor, Scratch)) {
1744 Failed = true;
1745 return;
1747 break;
1749 case TAG_BLOCK_ID:
1750 if (!HasValidControlBlock ||
1751 Implementation->readTagBlock(Cursor, Scratch)) {
1752 Failed = true;
1753 return;
1755 break;
1757 case TYPEDEF_BLOCK_ID:
1758 if (!HasValidControlBlock ||
1759 Implementation->readTypedefBlock(Cursor, Scratch)) {
1760 Failed = true;
1761 return;
1763 break;
1765 default:
1766 // Unknown top-level block, possibly for use by a future version of the
1767 // module format.
1768 if (Cursor.SkipBlock()) {
1769 Failed = true;
1770 return;
1772 break;
1776 if (!Cursor.AtEndOfStream()) {
1777 Failed = true;
1778 return;
1782 APINotesReader::~APINotesReader() { delete Implementation->InputBuffer; }
1784 std::unique_ptr<APINotesReader>
1785 APINotesReader::Create(std::unique_ptr<llvm::MemoryBuffer> InputBuffer,
1786 llvm::VersionTuple SwiftVersion) {
1787 bool Failed = false;
1788 std::unique_ptr<APINotesReader> Reader(
1789 new APINotesReader(InputBuffer.release(), SwiftVersion, Failed));
1790 if (Failed)
1791 return nullptr;
1793 return Reader;
1796 template <typename T>
1797 APINotesReader::VersionedInfo<T>::VersionedInfo(
1798 llvm::VersionTuple Version,
1799 llvm::SmallVector<std::pair<llvm::VersionTuple, T>, 1> Results)
1800 : Results(std::move(Results)) {
1802 assert(!Results.empty());
1803 assert(std::is_sorted(
1804 Results.begin(), Results.end(),
1805 [](const std::pair<llvm::VersionTuple, T> &left,
1806 const std::pair<llvm::VersionTuple, T> &right) -> bool {
1807 assert(left.first != right.first && "two entries for the same version");
1808 return left.first < right.first;
1809 }));
1811 Selected = std::nullopt;
1812 for (unsigned i = 0, n = Results.size(); i != n; ++i) {
1813 if (!Version.empty() && Results[i].first >= Version) {
1814 // If the current version is "4", then entries for 4 are better than
1815 // entries for 5, but both are valid. Because entries are sorted, we get
1816 // that behavior by picking the first match.
1817 Selected = i;
1818 break;
1822 // If we didn't find a match but we have an unversioned result, use the
1823 // unversioned result. This will always be the first entry because we encode
1824 // it as version 0.
1825 if (!Selected && Results[0].first.empty())
1826 Selected = 0;
1829 auto APINotesReader::lookupObjCClassID(llvm::StringRef Name)
1830 -> std::optional<ContextID> {
1831 if (!Implementation->ObjCContextIDTable)
1832 return std::nullopt;
1834 std::optional<IdentifierID> ClassID = Implementation->getIdentifier(Name);
1835 if (!ClassID)
1836 return std::nullopt;
1838 // ObjC classes can't be declared in C++ namespaces, so use -1 as the global
1839 // context.
1840 auto KnownID = Implementation->ObjCContextIDTable->find(
1841 ContextTableKey(-1, (uint8_t)ContextKind::ObjCClass, *ClassID));
1842 if (KnownID == Implementation->ObjCContextIDTable->end())
1843 return std::nullopt;
1845 return ContextID(*KnownID);
1848 auto APINotesReader::lookupObjCClassInfo(llvm::StringRef Name)
1849 -> VersionedInfo<ObjCContextInfo> {
1850 if (!Implementation->ObjCContextInfoTable)
1851 return std::nullopt;
1853 std::optional<ContextID> CtxID = lookupObjCClassID(Name);
1854 if (!CtxID)
1855 return std::nullopt;
1857 auto KnownInfo = Implementation->ObjCContextInfoTable->find(CtxID->Value);
1858 if (KnownInfo == Implementation->ObjCContextInfoTable->end())
1859 return std::nullopt;
1861 return {Implementation->SwiftVersion, *KnownInfo};
1864 auto APINotesReader::lookupObjCProtocolID(llvm::StringRef Name)
1865 -> std::optional<ContextID> {
1866 if (!Implementation->ObjCContextIDTable)
1867 return std::nullopt;
1869 std::optional<IdentifierID> classID = Implementation->getIdentifier(Name);
1870 if (!classID)
1871 return std::nullopt;
1873 // ObjC classes can't be declared in C++ namespaces, so use -1 as the global
1874 // context.
1875 auto KnownID = Implementation->ObjCContextIDTable->find(
1876 ContextTableKey(-1, (uint8_t)ContextKind::ObjCProtocol, *classID));
1877 if (KnownID == Implementation->ObjCContextIDTable->end())
1878 return std::nullopt;
1880 return ContextID(*KnownID);
1883 auto APINotesReader::lookupObjCProtocolInfo(llvm::StringRef Name)
1884 -> VersionedInfo<ObjCContextInfo> {
1885 if (!Implementation->ObjCContextInfoTable)
1886 return std::nullopt;
1888 std::optional<ContextID> CtxID = lookupObjCProtocolID(Name);
1889 if (!CtxID)
1890 return std::nullopt;
1892 auto KnownInfo = Implementation->ObjCContextInfoTable->find(CtxID->Value);
1893 if (KnownInfo == Implementation->ObjCContextInfoTable->end())
1894 return std::nullopt;
1896 return {Implementation->SwiftVersion, *KnownInfo};
1899 auto APINotesReader::lookupObjCProperty(ContextID CtxID, llvm::StringRef Name,
1900 bool IsInstance)
1901 -> VersionedInfo<ObjCPropertyInfo> {
1902 if (!Implementation->ObjCPropertyTable)
1903 return std::nullopt;
1905 std::optional<IdentifierID> PropertyID = Implementation->getIdentifier(Name);
1906 if (!PropertyID)
1907 return std::nullopt;
1909 auto Known = Implementation->ObjCPropertyTable->find(
1910 std::make_tuple(CtxID.Value, *PropertyID, (char)IsInstance));
1911 if (Known == Implementation->ObjCPropertyTable->end())
1912 return std::nullopt;
1914 return {Implementation->SwiftVersion, *Known};
1917 auto APINotesReader::lookupObjCMethod(ContextID CtxID, ObjCSelectorRef Selector,
1918 bool IsInstanceMethod)
1919 -> VersionedInfo<ObjCMethodInfo> {
1920 if (!Implementation->ObjCMethodTable)
1921 return std::nullopt;
1923 std::optional<SelectorID> SelID = Implementation->getSelector(Selector);
1924 if (!SelID)
1925 return std::nullopt;
1927 auto Known = Implementation->ObjCMethodTable->find(
1928 ObjCMethodTableInfo::internal_key_type{CtxID.Value, *SelID,
1929 IsInstanceMethod});
1930 if (Known == Implementation->ObjCMethodTable->end())
1931 return std::nullopt;
1933 return {Implementation->SwiftVersion, *Known};
1936 auto APINotesReader::lookupGlobalVariable(llvm::StringRef Name,
1937 std::optional<Context> Ctx)
1938 -> VersionedInfo<GlobalVariableInfo> {
1939 if (!Implementation->GlobalVariableTable)
1940 return std::nullopt;
1942 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
1943 if (!NameID)
1944 return std::nullopt;
1946 ContextTableKey Key(Ctx, *NameID);
1948 auto Known = Implementation->GlobalVariableTable->find(Key);
1949 if (Known == Implementation->GlobalVariableTable->end())
1950 return std::nullopt;
1952 return {Implementation->SwiftVersion, *Known};
1955 auto APINotesReader::lookupGlobalFunction(llvm::StringRef Name,
1956 std::optional<Context> Ctx)
1957 -> VersionedInfo<GlobalFunctionInfo> {
1958 if (!Implementation->GlobalFunctionTable)
1959 return std::nullopt;
1961 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
1962 if (!NameID)
1963 return std::nullopt;
1965 ContextTableKey Key(Ctx, *NameID);
1967 auto Known = Implementation->GlobalFunctionTable->find(Key);
1968 if (Known == Implementation->GlobalFunctionTable->end())
1969 return std::nullopt;
1971 return {Implementation->SwiftVersion, *Known};
1974 auto APINotesReader::lookupEnumConstant(llvm::StringRef Name)
1975 -> VersionedInfo<EnumConstantInfo> {
1976 if (!Implementation->EnumConstantTable)
1977 return std::nullopt;
1979 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
1980 if (!NameID)
1981 return std::nullopt;
1983 auto Known = Implementation->EnumConstantTable->find(*NameID);
1984 if (Known == Implementation->EnumConstantTable->end())
1985 return std::nullopt;
1987 return {Implementation->SwiftVersion, *Known};
1990 auto APINotesReader::lookupTag(llvm::StringRef Name, std::optional<Context> Ctx)
1991 -> VersionedInfo<TagInfo> {
1992 if (!Implementation->TagTable)
1993 return std::nullopt;
1995 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
1996 if (!NameID)
1997 return std::nullopt;
1999 ContextTableKey Key(Ctx, *NameID);
2001 auto Known = Implementation->TagTable->find(Key);
2002 if (Known == Implementation->TagTable->end())
2003 return std::nullopt;
2005 return {Implementation->SwiftVersion, *Known};
2008 auto APINotesReader::lookupTypedef(llvm::StringRef Name,
2009 std::optional<Context> Ctx)
2010 -> VersionedInfo<TypedefInfo> {
2011 if (!Implementation->TypedefTable)
2012 return std::nullopt;
2014 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2015 if (!NameID)
2016 return std::nullopt;
2018 ContextTableKey Key(Ctx, *NameID);
2020 auto Known = Implementation->TypedefTable->find(Key);
2021 if (Known == Implementation->TypedefTable->end())
2022 return std::nullopt;
2024 return {Implementation->SwiftVersion, *Known};
2027 auto APINotesReader::lookupNamespaceID(
2028 llvm::StringRef Name, std::optional<ContextID> ParentNamespaceID)
2029 -> std::optional<ContextID> {
2030 if (!Implementation->ObjCContextIDTable)
2031 return std::nullopt;
2033 std::optional<IdentifierID> NamespaceID = Implementation->getIdentifier(Name);
2034 if (!NamespaceID)
2035 return std::nullopt;
2037 uint32_t RawParentNamespaceID =
2038 ParentNamespaceID ? ParentNamespaceID->Value : -1;
2039 auto KnownID = Implementation->ObjCContextIDTable->find(
2040 {RawParentNamespaceID, (uint8_t)ContextKind::Namespace, *NamespaceID});
2041 if (KnownID == Implementation->ObjCContextIDTable->end())
2042 return std::nullopt;
2044 return ContextID(*KnownID);
2047 } // namespace api_notes
2048 } // namespace clang