1 //===--- APINotesReader.cpp - API Notes Reader ------------------*- C++ -*-===//
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
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"
20 using namespace llvm::support
;
23 /// Deserialize a version tuple.
24 llvm::VersionTuple
ReadVersionTuple(const uint8_t *&Data
) {
25 uint8_t NumVersions
= (*Data
++) & 0x03;
28 endian::readNext
<uint32_t, llvm::endianness::little
, unaligned
>(Data
);
30 return llvm::VersionTuple(Major
);
33 endian::readNext
<uint32_t, llvm::endianness::little
, unaligned
>(Data
);
35 return llvm::VersionTuple(Major
, Minor
);
38 endian::readNext
<uint32_t, llvm::endianness::little
, unaligned
>(Data
);
40 return llvm::VersionTuple(Major
, Minor
, Subminor
);
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
{
51 using internal_key_type
= KeyType
;
52 using external_key_type
= KeyType
;
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
) {
66 static std::pair
<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data
) {
68 endian::readNext
<uint16_t, llvm::endianness::little
, unaligned
>(Data
);
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
,
76 unsigned NumElements
=
77 endian::readNext
<uint16_t, llvm::endianness::little
, unaligned
>(Data
);
79 Result
.reserve(NumElements
);
80 for (unsigned i
= 0; i
!= NumElements
; ++i
) {
81 auto version
= ReadVersionTuple(Data
);
82 const auto *DataBefore
= Data
;
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
});
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));
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
);
108 unsigned SwiftNameLength
=
109 endian::readNext
<uint16_t, llvm::endianness::little
, unaligned
>(Data
);
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
{
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
) {
158 static std::pair
<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data
) {
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
,
172 return endian::readNext
<uint32_t, llvm::endianness::little
, unaligned
>(
177 /// Used to deserialize the on-disk Objective-C class table.
178 class ObjCContextIDTableInfo
{
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
) {
198 static std::pair
<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data
) {
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
) {
208 endian::readNext
<uint32_t, llvm::endianness::little
, unaligned
>(Data
);
210 endian::readNext
<uint8_t, llvm::endianness::little
, unaligned
>(Data
);
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
,
218 return endian::readNext
<uint32_t, llvm::endianness::little
, unaligned
>(
223 /// Used to deserialize the on-disk Objective-C property table.
224 class 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
, unaligned
>(
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
++;
244 Info
.setHasDesignatedInits(true);
245 Payload
= Payload
>> 1;
248 Info
.setDefaultNullability(static_cast<NullabilityKind
>(Payload
& 0x03));
251 if (Payload
& (1 << 1))
252 Info
.setSwiftObjCMembers(Payload
& 1);
255 if (Payload
& (1 << 1))
256 Info
.setSwiftImportAsNonGeneric(Payload
& 1);
262 /// Read serialized VariableInfo.
263 void ReadVariableInfo(const uint8_t *&Data
, VariableInfo
&Info
) {
264 ReadCommonEntityInfo(Data
, Info
);
266 Info
.setNullabilityAudited(static_cast<NullabilityKind
>(*Data
));
271 endian::readNext
<uint16_t, llvm::endianness::little
, unaligned
>(Data
);
272 Info
.setType(std::string(Data
, 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>,
282 static internal_key_type
ReadKey(const uint8_t *Data
, unsigned Length
) {
284 endian::readNext
<uint32_t, llvm::endianness::little
, unaligned
>(Data
);
286 endian::readNext
<uint32_t, llvm::endianness::little
, unaligned
>(Data
);
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));
307 /// Read serialized ParamInfo.
308 void ReadParamInfo(const uint8_t *&Data
, ParamInfo
&Info
) {
309 ReadVariableInfo(Data
, Info
);
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
);
319 Info
.setNoEscape(Payload
& 0x02);
321 assert(Payload
== 0 && "Bad API notes");
324 /// Read serialized FunctionInfo.
325 void ReadFunctionInfo(const uint8_t *&Data
, FunctionInfo
&Info
) {
326 ReadCommonEntityInfo(Data
, Info
);
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
);
335 Info
.NullabilityAudited
= Payload
& 0x1;
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
);
345 endian::readNext
<uint16_t, llvm::endianness::little
, unaligned
>(Data
);
346 while (NumParams
> 0) {
348 ReadParamInfo(Data
, pi
);
349 Info
.Params
.push_back(pi
);
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>,
365 static internal_key_type
ReadKey(const uint8_t *Data
, unsigned Length
) {
367 endian::readNext
<uint32_t, llvm::endianness::little
, unaligned
>(Data
);
369 endian::readNext
<uint32_t, llvm::endianness::little
, unaligned
>(Data
);
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
) {
382 uint8_t Payload
= *Data
++;
383 Info
.RequiredInit
= Payload
& 0x01;
385 Info
.DesignatedInit
= Payload
& 0x01;
388 ReadFunctionInfo(Data
, Info
);
393 /// Used to deserialize the on-disk Objective-C selector table.
394 class ObjCSelectorTableInfo
{
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
) {
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
;
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
>(
435 static data_type
ReadData(internal_key_type Key
, const uint8_t *Data
,
437 return endian::readNext
<uint32_t, llvm::endianness::little
, unaligned
>(
442 /// Used to deserialize the on-disk global variable table.
443 class GlobalVariableTableInfo
444 : public VersionedTableInfo
<GlobalVariableTableInfo
, ContextTableKey
,
445 GlobalVariableInfo
> {
447 static internal_key_type
ReadKey(const uint8_t *Data
, unsigned Length
) {
449 endian::readNext
<uint32_t, llvm::endianness::little
, unaligned
>(Data
);
451 endian::readNext
<uint8_t, llvm::endianness::little
, unaligned
>(Data
);
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
);
469 /// Used to deserialize the on-disk global function table.
470 class GlobalFunctionTableInfo
471 : public VersionedTableInfo
<GlobalFunctionTableInfo
, ContextTableKey
,
472 GlobalFunctionInfo
> {
474 static internal_key_type
ReadKey(const uint8_t *Data
, unsigned Length
) {
476 endian::readNext
<uint32_t, llvm::endianness::little
, unaligned
>(Data
);
478 endian::readNext
<uint8_t, llvm::endianness::little
, unaligned
>(Data
);
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
);
496 /// Used to deserialize the on-disk enumerator table.
497 class EnumConstantTableInfo
498 : public VersionedTableInfo
<EnumConstantTableInfo
, uint32_t,
501 static internal_key_type
ReadKey(const uint8_t *Data
, unsigned Length
) {
503 endian::readNext
<uint32_t, llvm::endianness::little
, unaligned
>(Data
);
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
);
519 /// Used to deserialize the on-disk tag table.
521 : public VersionedTableInfo
<TagTableInfo
, ContextTableKey
, TagInfo
> {
523 static internal_key_type
ReadKey(const uint8_t *Data
, unsigned Length
) {
525 endian::readNext
<uint32_t, llvm::endianness::little
, unaligned
>(Data
);
527 endian::readNext
<uint8_t, llvm::endianness::little
, unaligned
>(Data
);
529 endian::readNext
<IdentifierID
, llvm::endianness::little
, unaligned
>(
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
) {
541 uint8_t Payload
= *Data
++;
543 Info
.setFlagEnum(Payload
& 2);
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) {
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) {
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
);
576 /// Used to deserialize the on-disk typedef table.
577 class TypedefTableInfo
578 : public VersionedTableInfo
<TypedefTableInfo
, ContextTableKey
,
581 static internal_key_type
ReadKey(const uint8_t *Data
, unsigned Length
) {
583 endian::readNext
<uint32_t, llvm::endianness::little
, unaligned
>(Data
);
585 endian::readNext
<uint8_t, llvm::endianness::little
, unaligned
>(Data
);
587 endian::readNext
<IdentifierID
, llvm::endianness::little
, unaligned
>(
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
) {
600 uint8_t Payload
= *Data
++;
602 Info
.SwiftWrapper
= static_cast<SwiftNewTypeKind
>((Payload
& 0x3) - 1);
604 ReadCommonTypeInfo(Data
, Info
);
608 } // end anonymous namespace
610 class APINotesReader::Implementation
{
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
>;
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
)
728 return IdentifierID(0);
730 auto Known
= IdentifierTable
->find(Str
);
731 if (Known
== IdentifierTable
->end())
737 std::optional
<SelectorID
>
738 APINotesReader::Implementation::getSelector(ObjCSelectorRef Selector
) {
739 if (!ObjCSelectorTable
|| !IdentifierTable
)
742 // Translate the identifiers.
743 StoredObjCSelector Key
;
744 Key
.NumArgs
= Selector
.NumArgs
;
745 for (auto Ident
: Selector
.Identifiers
) {
746 if (auto IdentID
= getIdentifier(Ident
)) {
747 Key
.Identifiers
.push_back(*IdentID
);
753 auto Known
= ObjCSelectorTable
->find(Key
);
754 if (Known
== ObjCSelectorTable
->end())
760 bool APINotesReader::Implementation::readControlBlock(
761 llvm::BitstreamCursor
&Cursor
, llvm::SmallVectorImpl
<uint64_t> &Scratch
) {
762 if (Cursor
.EnterSubBlock(CONTROL_BLOCK_ID
))
765 bool SawMetadata
= false;
767 llvm::Expected
<llvm::BitstreamEntry
> MaybeNext
= Cursor
.advance();
769 // FIXME this drops the error on the floor.
770 consumeError(MaybeNext
.takeError());
773 llvm::BitstreamEntry Next
= MaybeNext
.get();
775 while (Next
.Kind
!= llvm::BitstreamEntry::EndBlock
) {
776 if (Next
.Kind
== llvm::BitstreamEntry::Error
)
779 if (Next
.Kind
== llvm::BitstreamEntry::SubBlock
) {
780 // Unknown metadata sub-block, possibly for use by a future version of the
782 if (Cursor
.SkipBlock())
785 MaybeNext
= Cursor
.advance();
787 // FIXME this drops the error on the floor.
788 consumeError(MaybeNext
.takeError());
791 Next
= MaybeNext
.get();
796 llvm::StringRef BlobData
;
797 llvm::Expected
<unsigned> MaybeKind
=
798 Cursor
.readRecord(Next
.ID
, Scratch
, &BlobData
);
800 // FIXME this drops the error on the floor.
801 consumeError(MaybeKind
.takeError());
804 unsigned Kind
= MaybeKind
.get();
807 case control_block::METADATA
:
808 // Already saw metadata.
812 if (Scratch
[0] != VERSION_MAJOR
|| Scratch
[1] != VERSION_MINOR
)
818 case control_block::MODULE_NAME
:
819 ModuleName
= BlobData
.str();
822 case control_block::MODULE_OPTIONS
:
825 case control_block::SOURCE_FILE
:
826 SourceFileSizeAndModTime
= {Scratch
[0], Scratch
[1]};
830 // Unknown metadata record, possibly for use by a future version of the
835 MaybeNext
= Cursor
.advance();
837 // FIXME this drops the error on the floor.
838 consumeError(MaybeNext
.takeError());
841 Next
= MaybeNext
.get();
847 bool APINotesReader::Implementation::readIdentifierBlock(
848 llvm::BitstreamCursor
&Cursor
, llvm::SmallVectorImpl
<uint64_t> &Scratch
) {
849 if (Cursor
.EnterSubBlock(IDENTIFIER_BLOCK_ID
))
852 llvm::Expected
<llvm::BitstreamEntry
> MaybeNext
= Cursor
.advance();
854 // FIXME this drops the error on the floor.
855 consumeError(MaybeNext
.takeError());
858 llvm::BitstreamEntry Next
= MaybeNext
.get();
860 while (Next
.Kind
!= llvm::BitstreamEntry::EndBlock
) {
861 if (Next
.Kind
== llvm::BitstreamEntry::Error
)
864 if (Next
.Kind
== llvm::BitstreamEntry::SubBlock
) {
865 // Unknown sub-block, possibly for use by a future version of the
867 if (Cursor
.SkipBlock())
870 MaybeNext
= Cursor
.advance();
872 // FIXME this drops the error on the floor.
873 consumeError(MaybeNext
.takeError());
876 Next
= MaybeNext
.get();
881 llvm::StringRef BlobData
;
882 llvm::Expected
<unsigned> MaybeKind
=
883 Cursor
.readRecord(Next
.ID
, Scratch
, &BlobData
);
885 // FIXME this drops the error on the floor.
886 consumeError(MaybeKind
.takeError());
889 unsigned Kind
= MaybeKind
.get();
891 case identifier_block::IDENTIFIER_DATA
: {
892 // Already saw identifier table.
896 uint32_t tableOffset
;
897 identifier_block::IdentifierDataLayout::readRecord(Scratch
, tableOffset
);
898 auto base
= reinterpret_cast<const uint8_t *>(BlobData
.data());
900 IdentifierTable
.reset(SerializedIdentifierTable::Create(
901 base
+ tableOffset
, base
+ sizeof(uint32_t), base
));
906 // Unknown record, possibly for use by a future version of the
911 MaybeNext
= Cursor
.advance();
913 // FIXME this drops the error on the floor.
914 consumeError(MaybeNext
.takeError());
917 Next
= MaybeNext
.get();
923 bool APINotesReader::Implementation::readObjCContextBlock(
924 llvm::BitstreamCursor
&Cursor
, llvm::SmallVectorImpl
<uint64_t> &Scratch
) {
925 if (Cursor
.EnterSubBlock(OBJC_CONTEXT_BLOCK_ID
))
928 llvm::Expected
<llvm::BitstreamEntry
> MaybeNext
= Cursor
.advance();
930 // FIXME this drops the error on the floor.
931 consumeError(MaybeNext
.takeError());
934 llvm::BitstreamEntry Next
= MaybeNext
.get();
936 while (Next
.Kind
!= llvm::BitstreamEntry::EndBlock
) {
937 if (Next
.Kind
== llvm::BitstreamEntry::Error
)
940 if (Next
.Kind
== llvm::BitstreamEntry::SubBlock
) {
941 // Unknown sub-block, possibly for use by a future version of the
943 if (Cursor
.SkipBlock())
946 MaybeNext
= Cursor
.advance();
948 // FIXME this drops the error on the floor.
949 consumeError(MaybeNext
.takeError());
952 Next
= MaybeNext
.get();
957 llvm::StringRef BlobData
;
958 llvm::Expected
<unsigned> MaybeKind
=
959 Cursor
.readRecord(Next
.ID
, Scratch
, &BlobData
);
961 // FIXME this drops the error on the floor.
962 consumeError(MaybeKind
.takeError());
965 unsigned Kind
= MaybeKind
.get();
967 case objc_context_block::OBJC_CONTEXT_ID_DATA
: {
968 // Already saw Objective-C context ID table.
969 if (ObjCContextIDTable
)
972 uint32_t tableOffset
;
973 objc_context_block::ObjCContextIDLayout::readRecord(Scratch
, tableOffset
);
974 auto base
= reinterpret_cast<const uint8_t *>(BlobData
.data());
976 ObjCContextIDTable
.reset(SerializedObjCContextIDTable::Create(
977 base
+ tableOffset
, base
+ sizeof(uint32_t), base
));
981 case objc_context_block::OBJC_CONTEXT_INFO_DATA
: {
982 // Already saw Objective-C context info table.
983 if (ObjCContextInfoTable
)
986 uint32_t tableOffset
;
987 objc_context_block::ObjCContextInfoLayout::readRecord(Scratch
,
989 auto base
= reinterpret_cast<const uint8_t *>(BlobData
.data());
991 ObjCContextInfoTable
.reset(SerializedObjCContextInfoTable::Create(
992 base
+ tableOffset
, base
+ sizeof(uint32_t), base
));
997 // Unknown record, possibly for use by a future version of the
1002 MaybeNext
= Cursor
.advance();
1004 // FIXME this drops the error on the floor.
1005 consumeError(MaybeNext
.takeError());
1008 Next
= MaybeNext
.get();
1014 bool APINotesReader::Implementation::readObjCPropertyBlock(
1015 llvm::BitstreamCursor
&Cursor
, llvm::SmallVectorImpl
<uint64_t> &Scratch
) {
1016 if (Cursor
.EnterSubBlock(OBJC_PROPERTY_BLOCK_ID
))
1019 llvm::Expected
<llvm::BitstreamEntry
> MaybeNext
= Cursor
.advance();
1021 // FIXME this drops the error on the floor.
1022 consumeError(MaybeNext
.takeError());
1025 llvm::BitstreamEntry Next
= MaybeNext
.get();
1027 while (Next
.Kind
!= llvm::BitstreamEntry::EndBlock
) {
1028 if (Next
.Kind
== llvm::BitstreamEntry::Error
)
1031 if (Next
.Kind
== llvm::BitstreamEntry::SubBlock
) {
1032 // Unknown sub-block, possibly for use by a future version of the
1033 // API notes format.
1034 if (Cursor
.SkipBlock())
1037 MaybeNext
= Cursor
.advance();
1039 // FIXME this drops the error on the floor.
1040 consumeError(MaybeNext
.takeError());
1043 Next
= MaybeNext
.get();
1048 llvm::StringRef BlobData
;
1049 llvm::Expected
<unsigned> MaybeKind
=
1050 Cursor
.readRecord(Next
.ID
, Scratch
, &BlobData
);
1052 // FIXME this drops the error on the floor.
1053 consumeError(MaybeKind
.takeError());
1056 unsigned Kind
= MaybeKind
.get();
1058 case objc_property_block::OBJC_PROPERTY_DATA
: {
1059 // Already saw Objective-C property table.
1060 if (ObjCPropertyTable
)
1063 uint32_t tableOffset
;
1064 objc_property_block::ObjCPropertyDataLayout::readRecord(Scratch
,
1066 auto base
= reinterpret_cast<const uint8_t *>(BlobData
.data());
1068 ObjCPropertyTable
.reset(SerializedObjCPropertyTable::Create(
1069 base
+ tableOffset
, base
+ sizeof(uint32_t), base
));
1074 // Unknown record, possibly for use by a future version of the
1079 MaybeNext
= Cursor
.advance();
1081 // FIXME this drops the error on the floor.
1082 consumeError(MaybeNext
.takeError());
1085 Next
= MaybeNext
.get();
1091 bool APINotesReader::Implementation::readObjCMethodBlock(
1092 llvm::BitstreamCursor
&Cursor
, llvm::SmallVectorImpl
<uint64_t> &Scratch
) {
1093 if (Cursor
.EnterSubBlock(OBJC_METHOD_BLOCK_ID
))
1096 llvm::Expected
<llvm::BitstreamEntry
> MaybeNext
= Cursor
.advance();
1098 // FIXME this drops the error on the floor.
1099 consumeError(MaybeNext
.takeError());
1102 llvm::BitstreamEntry Next
= MaybeNext
.get();
1103 while (Next
.Kind
!= llvm::BitstreamEntry::EndBlock
) {
1104 if (Next
.Kind
== llvm::BitstreamEntry::Error
)
1107 if (Next
.Kind
== llvm::BitstreamEntry::SubBlock
) {
1108 // Unknown sub-block, possibly for use by a future version of the
1109 // API notes format.
1110 if (Cursor
.SkipBlock())
1113 MaybeNext
= Cursor
.advance();
1115 // FIXME this drops the error on the floor.
1116 consumeError(MaybeNext
.takeError());
1119 Next
= MaybeNext
.get();
1124 llvm::StringRef BlobData
;
1125 llvm::Expected
<unsigned> MaybeKind
=
1126 Cursor
.readRecord(Next
.ID
, Scratch
, &BlobData
);
1128 // FIXME this drops the error on the floor.
1129 consumeError(MaybeKind
.takeError());
1132 unsigned Kind
= MaybeKind
.get();
1134 case objc_method_block::OBJC_METHOD_DATA
: {
1135 // Already saw Objective-C method table.
1136 if (ObjCMethodTable
)
1139 uint32_t tableOffset
;
1140 objc_method_block::ObjCMethodDataLayout::readRecord(Scratch
, tableOffset
);
1141 auto base
= reinterpret_cast<const uint8_t *>(BlobData
.data());
1143 ObjCMethodTable
.reset(SerializedObjCMethodTable::Create(
1144 base
+ tableOffset
, base
+ sizeof(uint32_t), base
));
1149 // Unknown record, possibly for use by a future version of the
1154 MaybeNext
= Cursor
.advance();
1156 // FIXME this drops the error on the floor.
1157 consumeError(MaybeNext
.takeError());
1160 Next
= MaybeNext
.get();
1166 bool APINotesReader::Implementation::readObjCSelectorBlock(
1167 llvm::BitstreamCursor
&Cursor
, llvm::SmallVectorImpl
<uint64_t> &Scratch
) {
1168 if (Cursor
.EnterSubBlock(OBJC_SELECTOR_BLOCK_ID
))
1171 llvm::Expected
<llvm::BitstreamEntry
> MaybeNext
= Cursor
.advance();
1173 // FIXME this drops the error on the floor.
1174 consumeError(MaybeNext
.takeError());
1177 llvm::BitstreamEntry Next
= MaybeNext
.get();
1178 while (Next
.Kind
!= llvm::BitstreamEntry::EndBlock
) {
1179 if (Next
.Kind
== llvm::BitstreamEntry::Error
)
1182 if (Next
.Kind
== llvm::BitstreamEntry::SubBlock
) {
1183 // Unknown sub-block, possibly for use by a future version of the
1184 // API notes format.
1185 if (Cursor
.SkipBlock())
1188 MaybeNext
= Cursor
.advance();
1190 // FIXME this drops the error on the floor.
1191 consumeError(MaybeNext
.takeError());
1194 Next
= MaybeNext
.get();
1199 llvm::StringRef BlobData
;
1200 llvm::Expected
<unsigned> MaybeKind
=
1201 Cursor
.readRecord(Next
.ID
, Scratch
, &BlobData
);
1203 // FIXME this drops the error on the floor.
1204 consumeError(MaybeKind
.takeError());
1207 unsigned Kind
= MaybeKind
.get();
1209 case objc_selector_block::OBJC_SELECTOR_DATA
: {
1210 // Already saw Objective-C selector table.
1211 if (ObjCSelectorTable
)
1214 uint32_t tableOffset
;
1215 objc_selector_block::ObjCSelectorDataLayout::readRecord(Scratch
,
1217 auto base
= reinterpret_cast<const uint8_t *>(BlobData
.data());
1219 ObjCSelectorTable
.reset(SerializedObjCSelectorTable::Create(
1220 base
+ tableOffset
, base
+ sizeof(uint32_t), base
));
1225 // Unknown record, possibly for use by a future version of the
1230 MaybeNext
= Cursor
.advance();
1232 // FIXME this drops the error on the floor.
1233 consumeError(MaybeNext
.takeError());
1236 Next
= MaybeNext
.get();
1242 bool APINotesReader::Implementation::readGlobalVariableBlock(
1243 llvm::BitstreamCursor
&Cursor
, llvm::SmallVectorImpl
<uint64_t> &Scratch
) {
1244 if (Cursor
.EnterSubBlock(GLOBAL_VARIABLE_BLOCK_ID
))
1247 llvm::Expected
<llvm::BitstreamEntry
> MaybeNext
= Cursor
.advance();
1249 // FIXME this drops the error on the floor.
1250 consumeError(MaybeNext
.takeError());
1253 llvm::BitstreamEntry Next
= MaybeNext
.get();
1254 while (Next
.Kind
!= llvm::BitstreamEntry::EndBlock
) {
1255 if (Next
.Kind
== llvm::BitstreamEntry::Error
)
1258 if (Next
.Kind
== llvm::BitstreamEntry::SubBlock
) {
1259 // Unknown sub-block, possibly for use by a future version of the
1260 // API notes format.
1261 if (Cursor
.SkipBlock())
1264 MaybeNext
= Cursor
.advance();
1266 // FIXME this drops the error on the floor.
1267 consumeError(MaybeNext
.takeError());
1270 Next
= MaybeNext
.get();
1275 llvm::StringRef BlobData
;
1276 llvm::Expected
<unsigned> MaybeKind
=
1277 Cursor
.readRecord(Next
.ID
, Scratch
, &BlobData
);
1279 // FIXME this drops the error on the floor.
1280 consumeError(MaybeKind
.takeError());
1283 unsigned Kind
= MaybeKind
.get();
1285 case global_variable_block::GLOBAL_VARIABLE_DATA
: {
1286 // Already saw global variable table.
1287 if (GlobalVariableTable
)
1290 uint32_t tableOffset
;
1291 global_variable_block::GlobalVariableDataLayout::readRecord(Scratch
,
1293 auto base
= reinterpret_cast<const uint8_t *>(BlobData
.data());
1295 GlobalVariableTable
.reset(SerializedGlobalVariableTable::Create(
1296 base
+ tableOffset
, base
+ sizeof(uint32_t), base
));
1301 // Unknown record, possibly for use by a future version of the
1306 MaybeNext
= Cursor
.advance();
1308 // FIXME this drops the error on the floor.
1309 consumeError(MaybeNext
.takeError());
1312 Next
= MaybeNext
.get();
1318 bool APINotesReader::Implementation::readGlobalFunctionBlock(
1319 llvm::BitstreamCursor
&Cursor
, llvm::SmallVectorImpl
<uint64_t> &Scratch
) {
1320 if (Cursor
.EnterSubBlock(GLOBAL_FUNCTION_BLOCK_ID
))
1323 llvm::Expected
<llvm::BitstreamEntry
> MaybeNext
= Cursor
.advance();
1325 // FIXME this drops the error on the floor.
1326 consumeError(MaybeNext
.takeError());
1329 llvm::BitstreamEntry Next
= MaybeNext
.get();
1330 while (Next
.Kind
!= llvm::BitstreamEntry::EndBlock
) {
1331 if (Next
.Kind
== llvm::BitstreamEntry::Error
)
1334 if (Next
.Kind
== llvm::BitstreamEntry::SubBlock
) {
1335 // Unknown sub-block, possibly for use by a future version of the
1336 // API notes format.
1337 if (Cursor
.SkipBlock())
1340 MaybeNext
= Cursor
.advance();
1342 // FIXME this drops the error on the floor.
1343 consumeError(MaybeNext
.takeError());
1346 Next
= MaybeNext
.get();
1351 llvm::StringRef BlobData
;
1352 llvm::Expected
<unsigned> MaybeKind
=
1353 Cursor
.readRecord(Next
.ID
, Scratch
, &BlobData
);
1355 // FIXME this drops the error on the floor.
1356 consumeError(MaybeKind
.takeError());
1359 unsigned Kind
= MaybeKind
.get();
1361 case global_function_block::GLOBAL_FUNCTION_DATA
: {
1362 // Already saw global function table.
1363 if (GlobalFunctionTable
)
1366 uint32_t tableOffset
;
1367 global_function_block::GlobalFunctionDataLayout::readRecord(Scratch
,
1369 auto base
= reinterpret_cast<const uint8_t *>(BlobData
.data());
1371 GlobalFunctionTable
.reset(SerializedGlobalFunctionTable::Create(
1372 base
+ tableOffset
, base
+ sizeof(uint32_t), base
));
1377 // Unknown record, possibly for use by a future version of the
1382 MaybeNext
= Cursor
.advance();
1384 // FIXME this drops the error on the floor.
1385 consumeError(MaybeNext
.takeError());
1388 Next
= MaybeNext
.get();
1394 bool APINotesReader::Implementation::readEnumConstantBlock(
1395 llvm::BitstreamCursor
&Cursor
, llvm::SmallVectorImpl
<uint64_t> &Scratch
) {
1396 if (Cursor
.EnterSubBlock(ENUM_CONSTANT_BLOCK_ID
))
1399 llvm::Expected
<llvm::BitstreamEntry
> MaybeNext
= Cursor
.advance();
1401 // FIXME this drops the error on the floor.
1402 consumeError(MaybeNext
.takeError());
1405 llvm::BitstreamEntry Next
= MaybeNext
.get();
1406 while (Next
.Kind
!= llvm::BitstreamEntry::EndBlock
) {
1407 if (Next
.Kind
== llvm::BitstreamEntry::Error
)
1410 if (Next
.Kind
== llvm::BitstreamEntry::SubBlock
) {
1411 // Unknown sub-block, possibly for use by a future version of the
1412 // API notes format.
1413 if (Cursor
.SkipBlock())
1416 MaybeNext
= Cursor
.advance();
1418 // FIXME this drops the error on the floor.
1419 consumeError(MaybeNext
.takeError());
1422 Next
= MaybeNext
.get();
1427 llvm::StringRef BlobData
;
1428 llvm::Expected
<unsigned> MaybeKind
=
1429 Cursor
.readRecord(Next
.ID
, Scratch
, &BlobData
);
1431 // FIXME this drops the error on the floor.
1432 consumeError(MaybeKind
.takeError());
1435 unsigned Kind
= MaybeKind
.get();
1437 case enum_constant_block::ENUM_CONSTANT_DATA
: {
1438 // Already saw enumerator table.
1439 if (EnumConstantTable
)
1442 uint32_t tableOffset
;
1443 enum_constant_block::EnumConstantDataLayout::readRecord(Scratch
,
1445 auto base
= reinterpret_cast<const uint8_t *>(BlobData
.data());
1447 EnumConstantTable
.reset(SerializedEnumConstantTable::Create(
1448 base
+ tableOffset
, base
+ sizeof(uint32_t), base
));
1453 // Unknown record, possibly for use by a future version of the
1458 MaybeNext
= Cursor
.advance();
1460 // FIXME this drops the error on the floor.
1461 consumeError(MaybeNext
.takeError());
1464 Next
= MaybeNext
.get();
1470 bool APINotesReader::Implementation::readTagBlock(
1471 llvm::BitstreamCursor
&Cursor
, llvm::SmallVectorImpl
<uint64_t> &Scratch
) {
1472 if (Cursor
.EnterSubBlock(TAG_BLOCK_ID
))
1475 llvm::Expected
<llvm::BitstreamEntry
> MaybeNext
= Cursor
.advance();
1477 // FIXME this drops the error on the floor.
1478 consumeError(MaybeNext
.takeError());
1481 llvm::BitstreamEntry Next
= MaybeNext
.get();
1482 while (Next
.Kind
!= llvm::BitstreamEntry::EndBlock
) {
1483 if (Next
.Kind
== llvm::BitstreamEntry::Error
)
1486 if (Next
.Kind
== llvm::BitstreamEntry::SubBlock
) {
1487 // Unknown sub-block, possibly for use by a future version of the
1488 // API notes format.
1489 if (Cursor
.SkipBlock())
1492 MaybeNext
= Cursor
.advance();
1494 // FIXME this drops the error on the floor.
1495 consumeError(MaybeNext
.takeError());
1498 Next
= MaybeNext
.get();
1503 llvm::StringRef BlobData
;
1504 llvm::Expected
<unsigned> MaybeKind
=
1505 Cursor
.readRecord(Next
.ID
, Scratch
, &BlobData
);
1507 // FIXME this drops the error on the floor.
1508 consumeError(MaybeKind
.takeError());
1511 unsigned Kind
= MaybeKind
.get();
1513 case tag_block::TAG_DATA
: {
1514 // Already saw tag table.
1518 uint32_t tableOffset
;
1519 tag_block::TagDataLayout::readRecord(Scratch
, tableOffset
);
1520 auto base
= reinterpret_cast<const uint8_t *>(BlobData
.data());
1522 TagTable
.reset(SerializedTagTable::Create(base
+ tableOffset
,
1523 base
+ sizeof(uint32_t), base
));
1528 // Unknown record, possibly for use by a future version of the
1533 MaybeNext
= Cursor
.advance();
1535 // FIXME this drops the error on the floor.
1536 consumeError(MaybeNext
.takeError());
1539 Next
= MaybeNext
.get();
1545 bool APINotesReader::Implementation::readTypedefBlock(
1546 llvm::BitstreamCursor
&Cursor
, llvm::SmallVectorImpl
<uint64_t> &Scratch
) {
1547 if (Cursor
.EnterSubBlock(TYPEDEF_BLOCK_ID
))
1550 llvm::Expected
<llvm::BitstreamEntry
> MaybeNext
= Cursor
.advance();
1552 // FIXME this drops the error on the floor.
1553 consumeError(MaybeNext
.takeError());
1556 llvm::BitstreamEntry Next
= MaybeNext
.get();
1557 while (Next
.Kind
!= llvm::BitstreamEntry::EndBlock
) {
1558 if (Next
.Kind
== llvm::BitstreamEntry::Error
)
1561 if (Next
.Kind
== llvm::BitstreamEntry::SubBlock
) {
1562 // Unknown sub-block, possibly for use by a future version of the
1563 // API notes format.
1564 if (Cursor
.SkipBlock())
1567 MaybeNext
= Cursor
.advance();
1569 // FIXME this drops the error on the floor.
1570 consumeError(MaybeNext
.takeError());
1573 Next
= MaybeNext
.get();
1578 llvm::StringRef BlobData
;
1579 llvm::Expected
<unsigned> MaybeKind
=
1580 Cursor
.readRecord(Next
.ID
, Scratch
, &BlobData
);
1582 // FIXME this drops the error on the floor.
1583 consumeError(MaybeKind
.takeError());
1586 unsigned Kind
= MaybeKind
.get();
1588 case typedef_block::TYPEDEF_DATA
: {
1589 // Already saw typedef table.
1593 uint32_t tableOffset
;
1594 typedef_block::TypedefDataLayout::readRecord(Scratch
, tableOffset
);
1595 auto base
= reinterpret_cast<const uint8_t *>(BlobData
.data());
1597 TypedefTable
.reset(SerializedTypedefTable::Create(
1598 base
+ tableOffset
, base
+ sizeof(uint32_t), base
));
1603 // Unknown record, possibly for use by a future version of the
1608 MaybeNext
= Cursor
.advance();
1610 // FIXME this drops the error on the floor.
1611 consumeError(MaybeNext
.takeError());
1614 Next
= MaybeNext
.get();
1620 APINotesReader::APINotesReader(llvm::MemoryBuffer
*InputBuffer
,
1621 llvm::VersionTuple SwiftVersion
, bool &Failed
)
1622 : Implementation(new class Implementation
) {
1625 // Initialize the input buffer.
1626 Implementation
->InputBuffer
= InputBuffer
;
1627 Implementation
->SwiftVersion
= SwiftVersion
;
1628 llvm::BitstreamCursor
Cursor(*Implementation
->InputBuffer
);
1630 // Validate signature.
1631 for (auto byte
: API_NOTES_SIGNATURE
) {
1632 if (Cursor
.AtEndOfStream()) {
1636 if (llvm::Expected
<llvm::SimpleBitstreamCursor::word_t
> maybeRead
=
1638 if (maybeRead
.get() != byte
) {
1643 // FIXME this drops the error on the floor.
1644 consumeError(maybeRead
.takeError());
1650 // Look at all of the blocks.
1651 bool HasValidControlBlock
= false;
1652 llvm::SmallVector
<uint64_t, 64> Scratch
;
1653 while (!Cursor
.AtEndOfStream()) {
1654 llvm::Expected
<llvm::BitstreamEntry
> MaybeTopLevelEntry
= Cursor
.advance();
1655 if (!MaybeTopLevelEntry
) {
1656 // FIXME this drops the error on the floor.
1657 consumeError(MaybeTopLevelEntry
.takeError());
1661 llvm::BitstreamEntry TopLevelEntry
= MaybeTopLevelEntry
.get();
1663 if (TopLevelEntry
.Kind
!= llvm::BitstreamEntry::SubBlock
)
1666 switch (TopLevelEntry
.ID
) {
1667 case llvm::bitc::BLOCKINFO_BLOCK_ID
:
1668 if (!Cursor
.ReadBlockInfoBlock()) {
1674 case CONTROL_BLOCK_ID
:
1675 // Only allow a single control block.
1676 if (HasValidControlBlock
||
1677 Implementation
->readControlBlock(Cursor
, Scratch
)) {
1682 HasValidControlBlock
= true;
1685 case IDENTIFIER_BLOCK_ID
:
1686 if (!HasValidControlBlock
||
1687 Implementation
->readIdentifierBlock(Cursor
, Scratch
)) {
1693 case OBJC_CONTEXT_BLOCK_ID
:
1694 if (!HasValidControlBlock
||
1695 Implementation
->readObjCContextBlock(Cursor
, Scratch
)) {
1702 case OBJC_PROPERTY_BLOCK_ID
:
1703 if (!HasValidControlBlock
||
1704 Implementation
->readObjCPropertyBlock(Cursor
, Scratch
)) {
1710 case OBJC_METHOD_BLOCK_ID
:
1711 if (!HasValidControlBlock
||
1712 Implementation
->readObjCMethodBlock(Cursor
, Scratch
)) {
1718 case OBJC_SELECTOR_BLOCK_ID
:
1719 if (!HasValidControlBlock
||
1720 Implementation
->readObjCSelectorBlock(Cursor
, Scratch
)) {
1726 case GLOBAL_VARIABLE_BLOCK_ID
:
1727 if (!HasValidControlBlock
||
1728 Implementation
->readGlobalVariableBlock(Cursor
, Scratch
)) {
1734 case GLOBAL_FUNCTION_BLOCK_ID
:
1735 if (!HasValidControlBlock
||
1736 Implementation
->readGlobalFunctionBlock(Cursor
, Scratch
)) {
1742 case ENUM_CONSTANT_BLOCK_ID
:
1743 if (!HasValidControlBlock
||
1744 Implementation
->readEnumConstantBlock(Cursor
, Scratch
)) {
1751 if (!HasValidControlBlock
||
1752 Implementation
->readTagBlock(Cursor
, Scratch
)) {
1758 case TYPEDEF_BLOCK_ID
:
1759 if (!HasValidControlBlock
||
1760 Implementation
->readTypedefBlock(Cursor
, Scratch
)) {
1767 // Unknown top-level block, possibly for use by a future version of the
1769 if (Cursor
.SkipBlock()) {
1777 if (!Cursor
.AtEndOfStream()) {
1783 APINotesReader::~APINotesReader() { delete Implementation
->InputBuffer
; }
1785 std::unique_ptr
<APINotesReader
>
1786 APINotesReader::Create(std::unique_ptr
<llvm::MemoryBuffer
> InputBuffer
,
1787 llvm::VersionTuple SwiftVersion
) {
1788 bool Failed
= false;
1789 std::unique_ptr
<APINotesReader
> Reader(
1790 new APINotesReader(InputBuffer
.release(), SwiftVersion
, Failed
));
1797 template <typename T
>
1798 APINotesReader::VersionedInfo
<T
>::VersionedInfo(
1799 llvm::VersionTuple Version
,
1800 llvm::SmallVector
<std::pair
<llvm::VersionTuple
, T
>, 1> Results
)
1801 : Results(std::move(Results
)) {
1803 assert(!Results
.empty());
1804 assert(std::is_sorted(
1805 Results
.begin(), Results
.end(),
1806 [](const std::pair
<llvm::VersionTuple
, T
> &left
,
1807 const std::pair
<llvm::VersionTuple
, T
> &right
) -> bool {
1808 assert(left
.first
!= right
.first
&& "two entries for the same version");
1809 return left
.first
< right
.first
;
1812 Selected
= std::nullopt
;
1813 for (unsigned i
= 0, n
= Results
.size(); i
!= n
; ++i
) {
1814 if (!Version
.empty() && Results
[i
].first
>= Version
) {
1815 // If the current version is "4", then entries for 4 are better than
1816 // entries for 5, but both are valid. Because entries are sorted, we get
1817 // that behavior by picking the first match.
1823 // If we didn't find a match but we have an unversioned result, use the
1824 // unversioned result. This will always be the first entry because we encode
1826 if (!Selected
&& Results
[0].first
.empty())
1830 auto APINotesReader::lookupObjCClassID(llvm::StringRef Name
)
1831 -> std::optional
<ContextID
> {
1832 if (!Implementation
->ObjCContextIDTable
)
1833 return std::nullopt
;
1835 std::optional
<IdentifierID
> ClassID
= Implementation
->getIdentifier(Name
);
1837 return std::nullopt
;
1839 // ObjC classes can't be declared in C++ namespaces, so use -1 as the global
1841 auto KnownID
= Implementation
->ObjCContextIDTable
->find(
1842 ContextTableKey(-1, (uint8_t)ContextKind::ObjCClass
, *ClassID
));
1843 if (KnownID
== Implementation
->ObjCContextIDTable
->end())
1844 return std::nullopt
;
1846 return ContextID(*KnownID
);
1849 auto APINotesReader::lookupObjCClassInfo(llvm::StringRef Name
)
1850 -> VersionedInfo
<ObjCContextInfo
> {
1851 if (!Implementation
->ObjCContextInfoTable
)
1852 return std::nullopt
;
1854 std::optional
<ContextID
> CtxID
= lookupObjCClassID(Name
);
1856 return std::nullopt
;
1858 auto KnownInfo
= Implementation
->ObjCContextInfoTable
->find(CtxID
->Value
);
1859 if (KnownInfo
== Implementation
->ObjCContextInfoTable
->end())
1860 return std::nullopt
;
1862 return {Implementation
->SwiftVersion
, *KnownInfo
};
1865 auto APINotesReader::lookupObjCProtocolID(llvm::StringRef Name
)
1866 -> std::optional
<ContextID
> {
1867 if (!Implementation
->ObjCContextIDTable
)
1868 return std::nullopt
;
1870 std::optional
<IdentifierID
> classID
= Implementation
->getIdentifier(Name
);
1872 return std::nullopt
;
1874 // ObjC classes can't be declared in C++ namespaces, so use -1 as the global
1876 auto KnownID
= Implementation
->ObjCContextIDTable
->find(
1877 ContextTableKey(-1, (uint8_t)ContextKind::ObjCProtocol
, *classID
));
1878 if (KnownID
== Implementation
->ObjCContextIDTable
->end())
1879 return std::nullopt
;
1881 return ContextID(*KnownID
);
1884 auto APINotesReader::lookupObjCProtocolInfo(llvm::StringRef Name
)
1885 -> VersionedInfo
<ObjCContextInfo
> {
1886 if (!Implementation
->ObjCContextInfoTable
)
1887 return std::nullopt
;
1889 std::optional
<ContextID
> CtxID
= lookupObjCProtocolID(Name
);
1891 return std::nullopt
;
1893 auto KnownInfo
= Implementation
->ObjCContextInfoTable
->find(CtxID
->Value
);
1894 if (KnownInfo
== Implementation
->ObjCContextInfoTable
->end())
1895 return std::nullopt
;
1897 return {Implementation
->SwiftVersion
, *KnownInfo
};
1900 auto APINotesReader::lookupObjCProperty(ContextID CtxID
, llvm::StringRef Name
,
1902 -> VersionedInfo
<ObjCPropertyInfo
> {
1903 if (!Implementation
->ObjCPropertyTable
)
1904 return std::nullopt
;
1906 std::optional
<IdentifierID
> PropertyID
= Implementation
->getIdentifier(Name
);
1908 return std::nullopt
;
1910 auto Known
= Implementation
->ObjCPropertyTable
->find(
1911 std::make_tuple(CtxID
.Value
, *PropertyID
, (char)IsInstance
));
1912 if (Known
== Implementation
->ObjCPropertyTable
->end())
1913 return std::nullopt
;
1915 return {Implementation
->SwiftVersion
, *Known
};
1918 auto APINotesReader::lookupObjCMethod(ContextID CtxID
, ObjCSelectorRef Selector
,
1919 bool IsInstanceMethod
)
1920 -> VersionedInfo
<ObjCMethodInfo
> {
1921 if (!Implementation
->ObjCMethodTable
)
1922 return std::nullopt
;
1924 std::optional
<SelectorID
> SelID
= Implementation
->getSelector(Selector
);
1926 return std::nullopt
;
1928 auto Known
= Implementation
->ObjCMethodTable
->find(
1929 ObjCMethodTableInfo::internal_key_type
{CtxID
.Value
, *SelID
,
1931 if (Known
== Implementation
->ObjCMethodTable
->end())
1932 return std::nullopt
;
1934 return {Implementation
->SwiftVersion
, *Known
};
1937 auto APINotesReader::lookupGlobalVariable(llvm::StringRef Name
,
1938 std::optional
<Context
> Ctx
)
1939 -> VersionedInfo
<GlobalVariableInfo
> {
1940 if (!Implementation
->GlobalVariableTable
)
1941 return std::nullopt
;
1943 std::optional
<IdentifierID
> NameID
= Implementation
->getIdentifier(Name
);
1945 return std::nullopt
;
1947 ContextTableKey
Key(Ctx
, *NameID
);
1949 auto Known
= Implementation
->GlobalVariableTable
->find(Key
);
1950 if (Known
== Implementation
->GlobalVariableTable
->end())
1951 return std::nullopt
;
1953 return {Implementation
->SwiftVersion
, *Known
};
1956 auto APINotesReader::lookupGlobalFunction(llvm::StringRef Name
,
1957 std::optional
<Context
> Ctx
)
1958 -> VersionedInfo
<GlobalFunctionInfo
> {
1959 if (!Implementation
->GlobalFunctionTable
)
1960 return std::nullopt
;
1962 std::optional
<IdentifierID
> NameID
= Implementation
->getIdentifier(Name
);
1964 return std::nullopt
;
1966 ContextTableKey
Key(Ctx
, *NameID
);
1968 auto Known
= Implementation
->GlobalFunctionTable
->find(Key
);
1969 if (Known
== Implementation
->GlobalFunctionTable
->end())
1970 return std::nullopt
;
1972 return {Implementation
->SwiftVersion
, *Known
};
1975 auto APINotesReader::lookupEnumConstant(llvm::StringRef Name
)
1976 -> VersionedInfo
<EnumConstantInfo
> {
1977 if (!Implementation
->EnumConstantTable
)
1978 return std::nullopt
;
1980 std::optional
<IdentifierID
> NameID
= Implementation
->getIdentifier(Name
);
1982 return std::nullopt
;
1984 auto Known
= Implementation
->EnumConstantTable
->find(*NameID
);
1985 if (Known
== Implementation
->EnumConstantTable
->end())
1986 return std::nullopt
;
1988 return {Implementation
->SwiftVersion
, *Known
};
1991 auto APINotesReader::lookupTag(llvm::StringRef Name
, std::optional
<Context
> Ctx
)
1992 -> VersionedInfo
<TagInfo
> {
1993 if (!Implementation
->TagTable
)
1994 return std::nullopt
;
1996 std::optional
<IdentifierID
> NameID
= Implementation
->getIdentifier(Name
);
1998 return std::nullopt
;
2000 ContextTableKey
Key(Ctx
, *NameID
);
2002 auto Known
= Implementation
->TagTable
->find(Key
);
2003 if (Known
== Implementation
->TagTable
->end())
2004 return std::nullopt
;
2006 return {Implementation
->SwiftVersion
, *Known
};
2009 auto APINotesReader::lookupTypedef(llvm::StringRef Name
,
2010 std::optional
<Context
> Ctx
)
2011 -> VersionedInfo
<TypedefInfo
> {
2012 if (!Implementation
->TypedefTable
)
2013 return std::nullopt
;
2015 std::optional
<IdentifierID
> NameID
= Implementation
->getIdentifier(Name
);
2017 return std::nullopt
;
2019 ContextTableKey
Key(Ctx
, *NameID
);
2021 auto Known
= Implementation
->TypedefTable
->find(Key
);
2022 if (Known
== Implementation
->TypedefTable
->end())
2023 return std::nullopt
;
2025 return {Implementation
->SwiftVersion
, *Known
};
2028 auto APINotesReader::lookupNamespaceID(
2029 llvm::StringRef Name
, std::optional
<ContextID
> ParentNamespaceID
)
2030 -> std::optional
<ContextID
> {
2031 if (!Implementation
->ObjCContextIDTable
)
2032 return std::nullopt
;
2034 std::optional
<IdentifierID
> NamespaceID
= Implementation
->getIdentifier(Name
);
2036 return std::nullopt
;
2038 uint32_t RawParentNamespaceID
=
2039 ParentNamespaceID
? ParentNamespaceID
->Value
: -1;
2040 auto KnownID
= Implementation
->ObjCContextIDTable
->find(
2041 {RawParentNamespaceID
, (uint8_t)ContextKind::Namespace
, *NamespaceID
});
2042 if (KnownID
== Implementation
->ObjCContextIDTable
->end())
2043 return std::nullopt
;
2045 return ContextID(*KnownID
);
2048 } // namespace api_notes
2049 } // namespace clang