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 for (auto Ident
: Selector
.Identifiers
) {
745 if (auto IdentID
= getIdentifier(Ident
)) {
746 Key
.Identifiers
.push_back(*IdentID
);
752 auto Known
= ObjCSelectorTable
->find(Key
);
753 if (Known
== ObjCSelectorTable
->end())
759 bool APINotesReader::Implementation::readControlBlock(
760 llvm::BitstreamCursor
&Cursor
, llvm::SmallVectorImpl
<uint64_t> &Scratch
) {
761 if (Cursor
.EnterSubBlock(CONTROL_BLOCK_ID
))
764 bool SawMetadata
= false;
766 llvm::Expected
<llvm::BitstreamEntry
> MaybeNext
= Cursor
.advance();
768 // FIXME this drops the error on the floor.
769 consumeError(MaybeNext
.takeError());
772 llvm::BitstreamEntry Next
= MaybeNext
.get();
774 while (Next
.Kind
!= llvm::BitstreamEntry::EndBlock
) {
775 if (Next
.Kind
== llvm::BitstreamEntry::Error
)
778 if (Next
.Kind
== llvm::BitstreamEntry::SubBlock
) {
779 // Unknown metadata sub-block, possibly for use by a future version of the
781 if (Cursor
.SkipBlock())
784 MaybeNext
= Cursor
.advance();
786 // FIXME this drops the error on the floor.
787 consumeError(MaybeNext
.takeError());
790 Next
= MaybeNext
.get();
795 llvm::StringRef BlobData
;
796 llvm::Expected
<unsigned> MaybeKind
=
797 Cursor
.readRecord(Next
.ID
, Scratch
, &BlobData
);
799 // FIXME this drops the error on the floor.
800 consumeError(MaybeKind
.takeError());
803 unsigned Kind
= MaybeKind
.get();
806 case control_block::METADATA
:
807 // Already saw metadata.
811 if (Scratch
[0] != VERSION_MAJOR
|| Scratch
[1] != VERSION_MINOR
)
817 case control_block::MODULE_NAME
:
818 ModuleName
= BlobData
.str();
821 case control_block::MODULE_OPTIONS
:
824 case control_block::SOURCE_FILE
:
825 SourceFileSizeAndModTime
= {Scratch
[0], Scratch
[1]};
829 // Unknown metadata record, possibly for use by a future version of the
834 MaybeNext
= Cursor
.advance();
836 // FIXME this drops the error on the floor.
837 consumeError(MaybeNext
.takeError());
840 Next
= MaybeNext
.get();
846 bool APINotesReader::Implementation::readIdentifierBlock(
847 llvm::BitstreamCursor
&Cursor
, llvm::SmallVectorImpl
<uint64_t> &Scratch
) {
848 if (Cursor
.EnterSubBlock(IDENTIFIER_BLOCK_ID
))
851 llvm::Expected
<llvm::BitstreamEntry
> MaybeNext
= Cursor
.advance();
853 // FIXME this drops the error on the floor.
854 consumeError(MaybeNext
.takeError());
857 llvm::BitstreamEntry Next
= MaybeNext
.get();
859 while (Next
.Kind
!= llvm::BitstreamEntry::EndBlock
) {
860 if (Next
.Kind
== llvm::BitstreamEntry::Error
)
863 if (Next
.Kind
== llvm::BitstreamEntry::SubBlock
) {
864 // Unknown sub-block, possibly for use by a future version of the
866 if (Cursor
.SkipBlock())
869 MaybeNext
= Cursor
.advance();
871 // FIXME this drops the error on the floor.
872 consumeError(MaybeNext
.takeError());
875 Next
= MaybeNext
.get();
880 llvm::StringRef BlobData
;
881 llvm::Expected
<unsigned> MaybeKind
=
882 Cursor
.readRecord(Next
.ID
, Scratch
, &BlobData
);
884 // FIXME this drops the error on the floor.
885 consumeError(MaybeKind
.takeError());
888 unsigned Kind
= MaybeKind
.get();
890 case identifier_block::IDENTIFIER_DATA
: {
891 // Already saw identifier table.
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
));
905 // Unknown record, possibly for use by a future version of the
910 MaybeNext
= Cursor
.advance();
912 // FIXME this drops the error on the floor.
913 consumeError(MaybeNext
.takeError());
916 Next
= MaybeNext
.get();
922 bool APINotesReader::Implementation::readObjCContextBlock(
923 llvm::BitstreamCursor
&Cursor
, llvm::SmallVectorImpl
<uint64_t> &Scratch
) {
924 if (Cursor
.EnterSubBlock(OBJC_CONTEXT_BLOCK_ID
))
927 llvm::Expected
<llvm::BitstreamEntry
> MaybeNext
= Cursor
.advance();
929 // FIXME this drops the error on the floor.
930 consumeError(MaybeNext
.takeError());
933 llvm::BitstreamEntry Next
= MaybeNext
.get();
935 while (Next
.Kind
!= llvm::BitstreamEntry::EndBlock
) {
936 if (Next
.Kind
== llvm::BitstreamEntry::Error
)
939 if (Next
.Kind
== llvm::BitstreamEntry::SubBlock
) {
940 // Unknown sub-block, possibly for use by a future version of the
942 if (Cursor
.SkipBlock())
945 MaybeNext
= Cursor
.advance();
947 // FIXME this drops the error on the floor.
948 consumeError(MaybeNext
.takeError());
951 Next
= MaybeNext
.get();
956 llvm::StringRef BlobData
;
957 llvm::Expected
<unsigned> MaybeKind
=
958 Cursor
.readRecord(Next
.ID
, Scratch
, &BlobData
);
960 // FIXME this drops the error on the floor.
961 consumeError(MaybeKind
.takeError());
964 unsigned Kind
= MaybeKind
.get();
966 case objc_context_block::OBJC_CONTEXT_ID_DATA
: {
967 // Already saw Objective-C context ID table.
968 if (ObjCContextIDTable
)
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
));
980 case objc_context_block::OBJC_CONTEXT_INFO_DATA
: {
981 // Already saw Objective-C context info table.
982 if (ObjCContextInfoTable
)
985 uint32_t tableOffset
;
986 objc_context_block::ObjCContextInfoLayout::readRecord(Scratch
,
988 auto base
= reinterpret_cast<const uint8_t *>(BlobData
.data());
990 ObjCContextInfoTable
.reset(SerializedObjCContextInfoTable::Create(
991 base
+ tableOffset
, base
+ sizeof(uint32_t), base
));
996 // Unknown record, possibly for use by a future version of the
1001 MaybeNext
= Cursor
.advance();
1003 // FIXME this drops the error on the floor.
1004 consumeError(MaybeNext
.takeError());
1007 Next
= MaybeNext
.get();
1013 bool APINotesReader::Implementation::readObjCPropertyBlock(
1014 llvm::BitstreamCursor
&Cursor
, llvm::SmallVectorImpl
<uint64_t> &Scratch
) {
1015 if (Cursor
.EnterSubBlock(OBJC_PROPERTY_BLOCK_ID
))
1018 llvm::Expected
<llvm::BitstreamEntry
> MaybeNext
= Cursor
.advance();
1020 // FIXME this drops the error on the floor.
1021 consumeError(MaybeNext
.takeError());
1024 llvm::BitstreamEntry Next
= MaybeNext
.get();
1026 while (Next
.Kind
!= llvm::BitstreamEntry::EndBlock
) {
1027 if (Next
.Kind
== llvm::BitstreamEntry::Error
)
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())
1036 MaybeNext
= Cursor
.advance();
1038 // FIXME this drops the error on the floor.
1039 consumeError(MaybeNext
.takeError());
1042 Next
= MaybeNext
.get();
1047 llvm::StringRef BlobData
;
1048 llvm::Expected
<unsigned> MaybeKind
=
1049 Cursor
.readRecord(Next
.ID
, Scratch
, &BlobData
);
1051 // FIXME this drops the error on the floor.
1052 consumeError(MaybeKind
.takeError());
1055 unsigned Kind
= MaybeKind
.get();
1057 case objc_property_block::OBJC_PROPERTY_DATA
: {
1058 // Already saw Objective-C property table.
1059 if (ObjCPropertyTable
)
1062 uint32_t tableOffset
;
1063 objc_property_block::ObjCPropertyDataLayout::readRecord(Scratch
,
1065 auto base
= reinterpret_cast<const uint8_t *>(BlobData
.data());
1067 ObjCPropertyTable
.reset(SerializedObjCPropertyTable::Create(
1068 base
+ tableOffset
, base
+ sizeof(uint32_t), base
));
1073 // Unknown record, possibly for use by a future version of the
1078 MaybeNext
= Cursor
.advance();
1080 // FIXME this drops the error on the floor.
1081 consumeError(MaybeNext
.takeError());
1084 Next
= MaybeNext
.get();
1090 bool APINotesReader::Implementation::readObjCMethodBlock(
1091 llvm::BitstreamCursor
&Cursor
, llvm::SmallVectorImpl
<uint64_t> &Scratch
) {
1092 if (Cursor
.EnterSubBlock(OBJC_METHOD_BLOCK_ID
))
1095 llvm::Expected
<llvm::BitstreamEntry
> MaybeNext
= Cursor
.advance();
1097 // FIXME this drops the error on the floor.
1098 consumeError(MaybeNext
.takeError());
1101 llvm::BitstreamEntry Next
= MaybeNext
.get();
1102 while (Next
.Kind
!= llvm::BitstreamEntry::EndBlock
) {
1103 if (Next
.Kind
== llvm::BitstreamEntry::Error
)
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())
1112 MaybeNext
= Cursor
.advance();
1114 // FIXME this drops the error on the floor.
1115 consumeError(MaybeNext
.takeError());
1118 Next
= MaybeNext
.get();
1123 llvm::StringRef BlobData
;
1124 llvm::Expected
<unsigned> MaybeKind
=
1125 Cursor
.readRecord(Next
.ID
, Scratch
, &BlobData
);
1127 // FIXME this drops the error on the floor.
1128 consumeError(MaybeKind
.takeError());
1131 unsigned Kind
= MaybeKind
.get();
1133 case objc_method_block::OBJC_METHOD_DATA
: {
1134 // Already saw Objective-C method table.
1135 if (ObjCMethodTable
)
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
));
1148 // Unknown record, possibly for use by a future version of the
1153 MaybeNext
= Cursor
.advance();
1155 // FIXME this drops the error on the floor.
1156 consumeError(MaybeNext
.takeError());
1159 Next
= MaybeNext
.get();
1165 bool APINotesReader::Implementation::readObjCSelectorBlock(
1166 llvm::BitstreamCursor
&Cursor
, llvm::SmallVectorImpl
<uint64_t> &Scratch
) {
1167 if (Cursor
.EnterSubBlock(OBJC_SELECTOR_BLOCK_ID
))
1170 llvm::Expected
<llvm::BitstreamEntry
> MaybeNext
= Cursor
.advance();
1172 // FIXME this drops the error on the floor.
1173 consumeError(MaybeNext
.takeError());
1176 llvm::BitstreamEntry Next
= MaybeNext
.get();
1177 while (Next
.Kind
!= llvm::BitstreamEntry::EndBlock
) {
1178 if (Next
.Kind
== llvm::BitstreamEntry::Error
)
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())
1187 MaybeNext
= Cursor
.advance();
1189 // FIXME this drops the error on the floor.
1190 consumeError(MaybeNext
.takeError());
1193 Next
= MaybeNext
.get();
1198 llvm::StringRef BlobData
;
1199 llvm::Expected
<unsigned> MaybeKind
=
1200 Cursor
.readRecord(Next
.ID
, Scratch
, &BlobData
);
1202 // FIXME this drops the error on the floor.
1203 consumeError(MaybeKind
.takeError());
1206 unsigned Kind
= MaybeKind
.get();
1208 case objc_selector_block::OBJC_SELECTOR_DATA
: {
1209 // Already saw Objective-C selector table.
1210 if (ObjCSelectorTable
)
1213 uint32_t tableOffset
;
1214 objc_selector_block::ObjCSelectorDataLayout::readRecord(Scratch
,
1216 auto base
= reinterpret_cast<const uint8_t *>(BlobData
.data());
1218 ObjCSelectorTable
.reset(SerializedObjCSelectorTable::Create(
1219 base
+ tableOffset
, base
+ sizeof(uint32_t), base
));
1224 // Unknown record, possibly for use by a future version of the
1229 MaybeNext
= Cursor
.advance();
1231 // FIXME this drops the error on the floor.
1232 consumeError(MaybeNext
.takeError());
1235 Next
= MaybeNext
.get();
1241 bool APINotesReader::Implementation::readGlobalVariableBlock(
1242 llvm::BitstreamCursor
&Cursor
, llvm::SmallVectorImpl
<uint64_t> &Scratch
) {
1243 if (Cursor
.EnterSubBlock(GLOBAL_VARIABLE_BLOCK_ID
))
1246 llvm::Expected
<llvm::BitstreamEntry
> MaybeNext
= Cursor
.advance();
1248 // FIXME this drops the error on the floor.
1249 consumeError(MaybeNext
.takeError());
1252 llvm::BitstreamEntry Next
= MaybeNext
.get();
1253 while (Next
.Kind
!= llvm::BitstreamEntry::EndBlock
) {
1254 if (Next
.Kind
== llvm::BitstreamEntry::Error
)
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())
1263 MaybeNext
= Cursor
.advance();
1265 // FIXME this drops the error on the floor.
1266 consumeError(MaybeNext
.takeError());
1269 Next
= MaybeNext
.get();
1274 llvm::StringRef BlobData
;
1275 llvm::Expected
<unsigned> MaybeKind
=
1276 Cursor
.readRecord(Next
.ID
, Scratch
, &BlobData
);
1278 // FIXME this drops the error on the floor.
1279 consumeError(MaybeKind
.takeError());
1282 unsigned Kind
= MaybeKind
.get();
1284 case global_variable_block::GLOBAL_VARIABLE_DATA
: {
1285 // Already saw global variable table.
1286 if (GlobalVariableTable
)
1289 uint32_t tableOffset
;
1290 global_variable_block::GlobalVariableDataLayout::readRecord(Scratch
,
1292 auto base
= reinterpret_cast<const uint8_t *>(BlobData
.data());
1294 GlobalVariableTable
.reset(SerializedGlobalVariableTable::Create(
1295 base
+ tableOffset
, base
+ sizeof(uint32_t), base
));
1300 // Unknown record, possibly for use by a future version of the
1305 MaybeNext
= Cursor
.advance();
1307 // FIXME this drops the error on the floor.
1308 consumeError(MaybeNext
.takeError());
1311 Next
= MaybeNext
.get();
1317 bool APINotesReader::Implementation::readGlobalFunctionBlock(
1318 llvm::BitstreamCursor
&Cursor
, llvm::SmallVectorImpl
<uint64_t> &Scratch
) {
1319 if (Cursor
.EnterSubBlock(GLOBAL_FUNCTION_BLOCK_ID
))
1322 llvm::Expected
<llvm::BitstreamEntry
> MaybeNext
= Cursor
.advance();
1324 // FIXME this drops the error on the floor.
1325 consumeError(MaybeNext
.takeError());
1328 llvm::BitstreamEntry Next
= MaybeNext
.get();
1329 while (Next
.Kind
!= llvm::BitstreamEntry::EndBlock
) {
1330 if (Next
.Kind
== llvm::BitstreamEntry::Error
)
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())
1339 MaybeNext
= Cursor
.advance();
1341 // FIXME this drops the error on the floor.
1342 consumeError(MaybeNext
.takeError());
1345 Next
= MaybeNext
.get();
1350 llvm::StringRef BlobData
;
1351 llvm::Expected
<unsigned> MaybeKind
=
1352 Cursor
.readRecord(Next
.ID
, Scratch
, &BlobData
);
1354 // FIXME this drops the error on the floor.
1355 consumeError(MaybeKind
.takeError());
1358 unsigned Kind
= MaybeKind
.get();
1360 case global_function_block::GLOBAL_FUNCTION_DATA
: {
1361 // Already saw global function table.
1362 if (GlobalFunctionTable
)
1365 uint32_t tableOffset
;
1366 global_function_block::GlobalFunctionDataLayout::readRecord(Scratch
,
1368 auto base
= reinterpret_cast<const uint8_t *>(BlobData
.data());
1370 GlobalFunctionTable
.reset(SerializedGlobalFunctionTable::Create(
1371 base
+ tableOffset
, base
+ sizeof(uint32_t), base
));
1376 // Unknown record, possibly for use by a future version of the
1381 MaybeNext
= Cursor
.advance();
1383 // FIXME this drops the error on the floor.
1384 consumeError(MaybeNext
.takeError());
1387 Next
= MaybeNext
.get();
1393 bool APINotesReader::Implementation::readEnumConstantBlock(
1394 llvm::BitstreamCursor
&Cursor
, llvm::SmallVectorImpl
<uint64_t> &Scratch
) {
1395 if (Cursor
.EnterSubBlock(ENUM_CONSTANT_BLOCK_ID
))
1398 llvm::Expected
<llvm::BitstreamEntry
> MaybeNext
= Cursor
.advance();
1400 // FIXME this drops the error on the floor.
1401 consumeError(MaybeNext
.takeError());
1404 llvm::BitstreamEntry Next
= MaybeNext
.get();
1405 while (Next
.Kind
!= llvm::BitstreamEntry::EndBlock
) {
1406 if (Next
.Kind
== llvm::BitstreamEntry::Error
)
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())
1415 MaybeNext
= Cursor
.advance();
1417 // FIXME this drops the error on the floor.
1418 consumeError(MaybeNext
.takeError());
1421 Next
= MaybeNext
.get();
1426 llvm::StringRef BlobData
;
1427 llvm::Expected
<unsigned> MaybeKind
=
1428 Cursor
.readRecord(Next
.ID
, Scratch
, &BlobData
);
1430 // FIXME this drops the error on the floor.
1431 consumeError(MaybeKind
.takeError());
1434 unsigned Kind
= MaybeKind
.get();
1436 case enum_constant_block::ENUM_CONSTANT_DATA
: {
1437 // Already saw enumerator table.
1438 if (EnumConstantTable
)
1441 uint32_t tableOffset
;
1442 enum_constant_block::EnumConstantDataLayout::readRecord(Scratch
,
1444 auto base
= reinterpret_cast<const uint8_t *>(BlobData
.data());
1446 EnumConstantTable
.reset(SerializedEnumConstantTable::Create(
1447 base
+ tableOffset
, base
+ sizeof(uint32_t), base
));
1452 // Unknown record, possibly for use by a future version of the
1457 MaybeNext
= Cursor
.advance();
1459 // FIXME this drops the error on the floor.
1460 consumeError(MaybeNext
.takeError());
1463 Next
= MaybeNext
.get();
1469 bool APINotesReader::Implementation::readTagBlock(
1470 llvm::BitstreamCursor
&Cursor
, llvm::SmallVectorImpl
<uint64_t> &Scratch
) {
1471 if (Cursor
.EnterSubBlock(TAG_BLOCK_ID
))
1474 llvm::Expected
<llvm::BitstreamEntry
> MaybeNext
= Cursor
.advance();
1476 // FIXME this drops the error on the floor.
1477 consumeError(MaybeNext
.takeError());
1480 llvm::BitstreamEntry Next
= MaybeNext
.get();
1481 while (Next
.Kind
!= llvm::BitstreamEntry::EndBlock
) {
1482 if (Next
.Kind
== llvm::BitstreamEntry::Error
)
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())
1491 MaybeNext
= Cursor
.advance();
1493 // FIXME this drops the error on the floor.
1494 consumeError(MaybeNext
.takeError());
1497 Next
= MaybeNext
.get();
1502 llvm::StringRef BlobData
;
1503 llvm::Expected
<unsigned> MaybeKind
=
1504 Cursor
.readRecord(Next
.ID
, Scratch
, &BlobData
);
1506 // FIXME this drops the error on the floor.
1507 consumeError(MaybeKind
.takeError());
1510 unsigned Kind
= MaybeKind
.get();
1512 case tag_block::TAG_DATA
: {
1513 // Already saw tag table.
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
));
1527 // Unknown record, possibly for use by a future version of the
1532 MaybeNext
= Cursor
.advance();
1534 // FIXME this drops the error on the floor.
1535 consumeError(MaybeNext
.takeError());
1538 Next
= MaybeNext
.get();
1544 bool APINotesReader::Implementation::readTypedefBlock(
1545 llvm::BitstreamCursor
&Cursor
, llvm::SmallVectorImpl
<uint64_t> &Scratch
) {
1546 if (Cursor
.EnterSubBlock(TYPEDEF_BLOCK_ID
))
1549 llvm::Expected
<llvm::BitstreamEntry
> MaybeNext
= Cursor
.advance();
1551 // FIXME this drops the error on the floor.
1552 consumeError(MaybeNext
.takeError());
1555 llvm::BitstreamEntry Next
= MaybeNext
.get();
1556 while (Next
.Kind
!= llvm::BitstreamEntry::EndBlock
) {
1557 if (Next
.Kind
== llvm::BitstreamEntry::Error
)
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())
1566 MaybeNext
= Cursor
.advance();
1568 // FIXME this drops the error on the floor.
1569 consumeError(MaybeNext
.takeError());
1572 Next
= MaybeNext
.get();
1577 llvm::StringRef BlobData
;
1578 llvm::Expected
<unsigned> MaybeKind
=
1579 Cursor
.readRecord(Next
.ID
, Scratch
, &BlobData
);
1581 // FIXME this drops the error on the floor.
1582 consumeError(MaybeKind
.takeError());
1585 unsigned Kind
= MaybeKind
.get();
1587 case typedef_block::TYPEDEF_DATA
: {
1588 // Already saw typedef table.
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
));
1602 // Unknown record, possibly for use by a future version of the
1607 MaybeNext
= Cursor
.advance();
1609 // FIXME this drops the error on the floor.
1610 consumeError(MaybeNext
.takeError());
1613 Next
= MaybeNext
.get();
1619 APINotesReader::APINotesReader(llvm::MemoryBuffer
*InputBuffer
,
1620 llvm::VersionTuple SwiftVersion
, bool &Failed
)
1621 : Implementation(new class Implementation
) {
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()) {
1635 if (llvm::Expected
<llvm::SimpleBitstreamCursor::word_t
> maybeRead
=
1637 if (maybeRead
.get() != byte
) {
1642 // FIXME this drops the error on the floor.
1643 consumeError(maybeRead
.takeError());
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());
1660 llvm::BitstreamEntry TopLevelEntry
= MaybeTopLevelEntry
.get();
1662 if (TopLevelEntry
.Kind
!= llvm::BitstreamEntry::SubBlock
)
1665 switch (TopLevelEntry
.ID
) {
1666 case llvm::bitc::BLOCKINFO_BLOCK_ID
:
1667 if (!Cursor
.ReadBlockInfoBlock()) {
1673 case CONTROL_BLOCK_ID
:
1674 // Only allow a single control block.
1675 if (HasValidControlBlock
||
1676 Implementation
->readControlBlock(Cursor
, Scratch
)) {
1681 HasValidControlBlock
= true;
1684 case IDENTIFIER_BLOCK_ID
:
1685 if (!HasValidControlBlock
||
1686 Implementation
->readIdentifierBlock(Cursor
, Scratch
)) {
1692 case OBJC_CONTEXT_BLOCK_ID
:
1693 if (!HasValidControlBlock
||
1694 Implementation
->readObjCContextBlock(Cursor
, Scratch
)) {
1701 case OBJC_PROPERTY_BLOCK_ID
:
1702 if (!HasValidControlBlock
||
1703 Implementation
->readObjCPropertyBlock(Cursor
, Scratch
)) {
1709 case OBJC_METHOD_BLOCK_ID
:
1710 if (!HasValidControlBlock
||
1711 Implementation
->readObjCMethodBlock(Cursor
, Scratch
)) {
1717 case OBJC_SELECTOR_BLOCK_ID
:
1718 if (!HasValidControlBlock
||
1719 Implementation
->readObjCSelectorBlock(Cursor
, Scratch
)) {
1725 case GLOBAL_VARIABLE_BLOCK_ID
:
1726 if (!HasValidControlBlock
||
1727 Implementation
->readGlobalVariableBlock(Cursor
, Scratch
)) {
1733 case GLOBAL_FUNCTION_BLOCK_ID
:
1734 if (!HasValidControlBlock
||
1735 Implementation
->readGlobalFunctionBlock(Cursor
, Scratch
)) {
1741 case ENUM_CONSTANT_BLOCK_ID
:
1742 if (!HasValidControlBlock
||
1743 Implementation
->readEnumConstantBlock(Cursor
, Scratch
)) {
1750 if (!HasValidControlBlock
||
1751 Implementation
->readTagBlock(Cursor
, Scratch
)) {
1757 case TYPEDEF_BLOCK_ID
:
1758 if (!HasValidControlBlock
||
1759 Implementation
->readTypedefBlock(Cursor
, Scratch
)) {
1766 // Unknown top-level block, possibly for use by a future version of the
1768 if (Cursor
.SkipBlock()) {
1776 if (!Cursor
.AtEndOfStream()) {
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
));
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
;
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.
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
1825 if (!Selected
&& Results
[0].first
.empty())
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
);
1836 return std::nullopt
;
1838 // ObjC classes can't be declared in C++ namespaces, so use -1 as the global
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
);
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
);
1871 return std::nullopt
;
1873 // ObjC classes can't be declared in C++ namespaces, so use -1 as the global
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
);
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
,
1901 -> VersionedInfo
<ObjCPropertyInfo
> {
1902 if (!Implementation
->ObjCPropertyTable
)
1903 return std::nullopt
;
1905 std::optional
<IdentifierID
> PropertyID
= Implementation
->getIdentifier(Name
);
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
);
1925 return std::nullopt
;
1927 auto Known
= Implementation
->ObjCMethodTable
->find(
1928 ObjCMethodTableInfo::internal_key_type
{CtxID
.Value
, *SelID
,
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
);
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
);
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
);
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
);
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
);
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
);
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