xref: /freebsd-src/contrib/llvm-project/clang/lib/APINotes/APINotesReader.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
15f757f3fSDimitry Andric //===--- APINotesReader.cpp - API Notes Reader ------------------*- C++ -*-===//
25f757f3fSDimitry Andric //
35f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65f757f3fSDimitry Andric //
75f757f3fSDimitry Andric //===----------------------------------------------------------------------===//
8*0fca6ea1SDimitry Andric //
9*0fca6ea1SDimitry Andric // This file implements the \c APINotesReader class that reads source
10*0fca6ea1SDimitry Andric // API notes data providing additional information about source code as
11*0fca6ea1SDimitry Andric // a separate input, such as the non-nil/nilable annotations for
12*0fca6ea1SDimitry Andric // method parameters.
13*0fca6ea1SDimitry Andric //
14*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
155f757f3fSDimitry Andric #include "clang/APINotes/APINotesReader.h"
165f757f3fSDimitry Andric #include "APINotesFormat.h"
175f757f3fSDimitry Andric #include "llvm/ADT/Hashing.h"
185f757f3fSDimitry Andric #include "llvm/ADT/StringExtras.h"
195f757f3fSDimitry Andric #include "llvm/Bitstream/BitstreamReader.h"
205f757f3fSDimitry Andric #include "llvm/Support/DJB.h"
215f757f3fSDimitry Andric #include "llvm/Support/EndianStream.h"
225f757f3fSDimitry Andric #include "llvm/Support/OnDiskHashTable.h"
235f757f3fSDimitry Andric 
245f757f3fSDimitry Andric namespace clang {
255f757f3fSDimitry Andric namespace api_notes {
265f757f3fSDimitry Andric using namespace llvm::support;
275f757f3fSDimitry Andric 
285f757f3fSDimitry Andric namespace {
295f757f3fSDimitry Andric /// Deserialize a version tuple.
305f757f3fSDimitry Andric llvm::VersionTuple ReadVersionTuple(const uint8_t *&Data) {
315f757f3fSDimitry Andric   uint8_t NumVersions = (*Data++) & 0x03;
325f757f3fSDimitry Andric 
33*0fca6ea1SDimitry Andric   unsigned Major = endian::readNext<uint32_t, llvm::endianness::little>(Data);
345f757f3fSDimitry Andric   if (NumVersions == 0)
355f757f3fSDimitry Andric     return llvm::VersionTuple(Major);
365f757f3fSDimitry Andric 
37*0fca6ea1SDimitry Andric   unsigned Minor = endian::readNext<uint32_t, llvm::endianness::little>(Data);
385f757f3fSDimitry Andric   if (NumVersions == 1)
395f757f3fSDimitry Andric     return llvm::VersionTuple(Major, Minor);
405f757f3fSDimitry Andric 
415f757f3fSDimitry Andric   unsigned Subminor =
42*0fca6ea1SDimitry Andric       endian::readNext<uint32_t, llvm::endianness::little>(Data);
435f757f3fSDimitry Andric   if (NumVersions == 2)
445f757f3fSDimitry Andric     return llvm::VersionTuple(Major, Minor, Subminor);
455f757f3fSDimitry Andric 
46*0fca6ea1SDimitry Andric   unsigned Build = endian::readNext<uint32_t, llvm::endianness::little>(Data);
475f757f3fSDimitry Andric   return llvm::VersionTuple(Major, Minor, Subminor, Build);
485f757f3fSDimitry Andric }
495f757f3fSDimitry Andric 
505f757f3fSDimitry Andric /// An on-disk hash table whose data is versioned based on the Swift version.
515f757f3fSDimitry Andric template <typename Derived, typename KeyType, typename UnversionedDataType>
525f757f3fSDimitry Andric class VersionedTableInfo {
535f757f3fSDimitry Andric public:
545f757f3fSDimitry Andric   using internal_key_type = KeyType;
555f757f3fSDimitry Andric   using external_key_type = KeyType;
565f757f3fSDimitry Andric   using data_type =
575f757f3fSDimitry Andric       llvm::SmallVector<std::pair<llvm::VersionTuple, UnversionedDataType>, 1>;
585f757f3fSDimitry Andric   using hash_value_type = size_t;
595f757f3fSDimitry Andric   using offset_type = unsigned;
605f757f3fSDimitry Andric 
615f757f3fSDimitry Andric   internal_key_type GetInternalKey(external_key_type Key) { return Key; }
625f757f3fSDimitry Andric 
635f757f3fSDimitry Andric   external_key_type GetExternalKey(internal_key_type Key) { return Key; }
645f757f3fSDimitry Andric 
655f757f3fSDimitry Andric   static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
665f757f3fSDimitry Andric     return LHS == RHS;
675f757f3fSDimitry Andric   }
685f757f3fSDimitry Andric 
695f757f3fSDimitry Andric   static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {
705f757f3fSDimitry Andric     unsigned KeyLength =
71*0fca6ea1SDimitry Andric         endian::readNext<uint16_t, llvm::endianness::little>(Data);
725f757f3fSDimitry Andric     unsigned DataLength =
73*0fca6ea1SDimitry Andric         endian::readNext<uint16_t, llvm::endianness::little>(Data);
745f757f3fSDimitry Andric     return {KeyLength, DataLength};
755f757f3fSDimitry Andric   }
765f757f3fSDimitry Andric 
775f757f3fSDimitry Andric   static data_type ReadData(internal_key_type Key, const uint8_t *Data,
785f757f3fSDimitry Andric                             unsigned Length) {
795f757f3fSDimitry Andric     unsigned NumElements =
80*0fca6ea1SDimitry Andric         endian::readNext<uint16_t, llvm::endianness::little>(Data);
815f757f3fSDimitry Andric     data_type Result;
825f757f3fSDimitry Andric     Result.reserve(NumElements);
835f757f3fSDimitry Andric     for (unsigned i = 0; i != NumElements; ++i) {
845f757f3fSDimitry Andric       auto version = ReadVersionTuple(Data);
855f757f3fSDimitry Andric       const auto *DataBefore = Data;
865f757f3fSDimitry Andric       (void)DataBefore;
87*0fca6ea1SDimitry Andric       auto UnversionedData = Derived::readUnversioned(Key, Data);
885f757f3fSDimitry Andric       assert(Data != DataBefore &&
895f757f3fSDimitry Andric              "Unversioned data reader didn't move pointer");
905f757f3fSDimitry Andric       Result.push_back({version, UnversionedData});
915f757f3fSDimitry Andric     }
925f757f3fSDimitry Andric     return Result;
935f757f3fSDimitry Andric   }
945f757f3fSDimitry Andric };
955f757f3fSDimitry Andric 
965f757f3fSDimitry Andric /// Read serialized CommonEntityInfo.
975f757f3fSDimitry Andric void ReadCommonEntityInfo(const uint8_t *&Data, CommonEntityInfo &Info) {
985f757f3fSDimitry Andric   uint8_t UnavailableBits = *Data++;
995f757f3fSDimitry Andric   Info.Unavailable = (UnavailableBits >> 1) & 0x01;
1005f757f3fSDimitry Andric   Info.UnavailableInSwift = UnavailableBits & 0x01;
1015f757f3fSDimitry Andric   if ((UnavailableBits >> 2) & 0x01)
1025f757f3fSDimitry Andric     Info.setSwiftPrivate(static_cast<bool>((UnavailableBits >> 3) & 0x01));
1035f757f3fSDimitry Andric 
1045f757f3fSDimitry Andric   unsigned MsgLength =
105*0fca6ea1SDimitry Andric       endian::readNext<uint16_t, llvm::endianness::little>(Data);
1065f757f3fSDimitry Andric   Info.UnavailableMsg =
1075f757f3fSDimitry Andric       std::string(reinterpret_cast<const char *>(Data),
1085f757f3fSDimitry Andric                   reinterpret_cast<const char *>(Data) + MsgLength);
1095f757f3fSDimitry Andric   Data += MsgLength;
1105f757f3fSDimitry Andric 
1115f757f3fSDimitry Andric   unsigned SwiftNameLength =
112*0fca6ea1SDimitry Andric       endian::readNext<uint16_t, llvm::endianness::little>(Data);
1135f757f3fSDimitry Andric   Info.SwiftName =
1145f757f3fSDimitry Andric       std::string(reinterpret_cast<const char *>(Data),
1155f757f3fSDimitry Andric                   reinterpret_cast<const char *>(Data) + SwiftNameLength);
1165f757f3fSDimitry Andric   Data += SwiftNameLength;
1175f757f3fSDimitry Andric }
1185f757f3fSDimitry Andric 
1195f757f3fSDimitry Andric /// Read serialized CommonTypeInfo.
1205f757f3fSDimitry Andric void ReadCommonTypeInfo(const uint8_t *&Data, CommonTypeInfo &Info) {
1215f757f3fSDimitry Andric   ReadCommonEntityInfo(Data, Info);
1225f757f3fSDimitry Andric 
1235f757f3fSDimitry Andric   unsigned SwiftBridgeLength =
124*0fca6ea1SDimitry Andric       endian::readNext<uint16_t, llvm::endianness::little>(Data);
1255f757f3fSDimitry Andric   if (SwiftBridgeLength > 0) {
1265f757f3fSDimitry Andric     Info.setSwiftBridge(std::string(reinterpret_cast<const char *>(Data),
1275f757f3fSDimitry Andric                                     SwiftBridgeLength - 1));
1285f757f3fSDimitry Andric     Data += SwiftBridgeLength - 1;
1295f757f3fSDimitry Andric   }
1305f757f3fSDimitry Andric 
1315f757f3fSDimitry Andric   unsigned ErrorDomainLength =
132*0fca6ea1SDimitry Andric       endian::readNext<uint16_t, llvm::endianness::little>(Data);
1335f757f3fSDimitry Andric   if (ErrorDomainLength > 0) {
1345f757f3fSDimitry Andric     Info.setNSErrorDomain(std::optional<std::string>(std::string(
1355f757f3fSDimitry Andric         reinterpret_cast<const char *>(Data), ErrorDomainLength - 1)));
1365f757f3fSDimitry Andric     Data += ErrorDomainLength - 1;
1375f757f3fSDimitry Andric   }
1385f757f3fSDimitry Andric }
1395f757f3fSDimitry Andric 
1405f757f3fSDimitry Andric /// Used to deserialize the on-disk identifier table.
1415f757f3fSDimitry Andric class IdentifierTableInfo {
1425f757f3fSDimitry Andric public:
1435f757f3fSDimitry Andric   using internal_key_type = llvm::StringRef;
1445f757f3fSDimitry Andric   using external_key_type = llvm::StringRef;
1455f757f3fSDimitry Andric   using data_type = IdentifierID;
1465f757f3fSDimitry Andric   using hash_value_type = uint32_t;
1475f757f3fSDimitry Andric   using offset_type = unsigned;
1485f757f3fSDimitry Andric 
1495f757f3fSDimitry Andric   internal_key_type GetInternalKey(external_key_type Key) { return Key; }
1505f757f3fSDimitry Andric 
1515f757f3fSDimitry Andric   external_key_type GetExternalKey(internal_key_type Key) { return Key; }
1525f757f3fSDimitry Andric 
1535f757f3fSDimitry Andric   hash_value_type ComputeHash(internal_key_type Key) {
154*0fca6ea1SDimitry Andric     return llvm::djbHash(Key);
1555f757f3fSDimitry Andric   }
1565f757f3fSDimitry Andric 
1575f757f3fSDimitry Andric   static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
1585f757f3fSDimitry Andric     return LHS == RHS;
1595f757f3fSDimitry Andric   }
1605f757f3fSDimitry Andric 
1615f757f3fSDimitry Andric   static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {
1625f757f3fSDimitry Andric     unsigned KeyLength =
163*0fca6ea1SDimitry Andric         endian::readNext<uint16_t, llvm::endianness::little>(Data);
1645f757f3fSDimitry Andric     unsigned DataLength =
165*0fca6ea1SDimitry Andric         endian::readNext<uint16_t, llvm::endianness::little>(Data);
1665f757f3fSDimitry Andric     return {KeyLength, DataLength};
1675f757f3fSDimitry Andric   }
1685f757f3fSDimitry Andric 
1695f757f3fSDimitry Andric   static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
1705f757f3fSDimitry Andric     return llvm::StringRef(reinterpret_cast<const char *>(Data), Length);
1715f757f3fSDimitry Andric   }
1725f757f3fSDimitry Andric 
1735f757f3fSDimitry Andric   static data_type ReadData(internal_key_type key, const uint8_t *Data,
1745f757f3fSDimitry Andric                             unsigned Length) {
175*0fca6ea1SDimitry Andric     return endian::readNext<uint32_t, llvm::endianness::little>(Data);
1765f757f3fSDimitry Andric   }
1775f757f3fSDimitry Andric };
1785f757f3fSDimitry Andric 
179*0fca6ea1SDimitry Andric /// Used to deserialize the on-disk table of Objective-C classes and C++
180*0fca6ea1SDimitry Andric /// namespaces.
181*0fca6ea1SDimitry Andric class ContextIDTableInfo {
1825f757f3fSDimitry Andric public:
1835f757f3fSDimitry Andric   using internal_key_type = ContextTableKey;
1845f757f3fSDimitry Andric   using external_key_type = internal_key_type;
1855f757f3fSDimitry Andric   using data_type = unsigned;
1865f757f3fSDimitry Andric   using hash_value_type = size_t;
1875f757f3fSDimitry Andric   using offset_type = unsigned;
1885f757f3fSDimitry Andric 
1895f757f3fSDimitry Andric   internal_key_type GetInternalKey(external_key_type Key) { return Key; }
1905f757f3fSDimitry Andric 
1915f757f3fSDimitry Andric   external_key_type GetExternalKey(internal_key_type Key) { return Key; }
1925f757f3fSDimitry Andric 
1935f757f3fSDimitry Andric   hash_value_type ComputeHash(internal_key_type Key) {
1945f757f3fSDimitry Andric     return static_cast<size_t>(Key.hashValue());
1955f757f3fSDimitry Andric   }
1965f757f3fSDimitry Andric 
1975f757f3fSDimitry Andric   static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
1985f757f3fSDimitry Andric     return LHS == RHS;
1995f757f3fSDimitry Andric   }
2005f757f3fSDimitry Andric 
2015f757f3fSDimitry Andric   static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {
2025f757f3fSDimitry Andric     unsigned KeyLength =
203*0fca6ea1SDimitry Andric         endian::readNext<uint16_t, llvm::endianness::little>(Data);
2045f757f3fSDimitry Andric     unsigned DataLength =
205*0fca6ea1SDimitry Andric         endian::readNext<uint16_t, llvm::endianness::little>(Data);
2065f757f3fSDimitry Andric     return {KeyLength, DataLength};
2075f757f3fSDimitry Andric   }
2085f757f3fSDimitry Andric 
2095f757f3fSDimitry Andric   static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
2105f757f3fSDimitry Andric     auto ParentCtxID =
211*0fca6ea1SDimitry Andric         endian::readNext<uint32_t, llvm::endianness::little>(Data);
2125f757f3fSDimitry Andric     auto ContextKind =
213*0fca6ea1SDimitry Andric         endian::readNext<uint8_t, llvm::endianness::little>(Data);
214*0fca6ea1SDimitry Andric     auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
2155f757f3fSDimitry Andric     return {ParentCtxID, ContextKind, NameID};
2165f757f3fSDimitry Andric   }
2175f757f3fSDimitry Andric 
2185f757f3fSDimitry Andric   static data_type ReadData(internal_key_type Key, const uint8_t *Data,
2195f757f3fSDimitry Andric                             unsigned Length) {
220*0fca6ea1SDimitry Andric     return endian::readNext<uint32_t, llvm::endianness::little>(Data);
2215f757f3fSDimitry Andric   }
2225f757f3fSDimitry Andric };
2235f757f3fSDimitry Andric 
2245f757f3fSDimitry Andric /// Used to deserialize the on-disk Objective-C property table.
225*0fca6ea1SDimitry Andric class ContextInfoTableInfo
226*0fca6ea1SDimitry Andric     : public VersionedTableInfo<ContextInfoTableInfo, unsigned, ContextInfo> {
2275f757f3fSDimitry Andric public:
2285f757f3fSDimitry Andric   static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
229*0fca6ea1SDimitry Andric     return endian::readNext<uint32_t, llvm::endianness::little>(Data);
2305f757f3fSDimitry Andric   }
2315f757f3fSDimitry Andric 
2325f757f3fSDimitry Andric   hash_value_type ComputeHash(internal_key_type Key) {
2335f757f3fSDimitry Andric     return static_cast<size_t>(llvm::hash_value(Key));
2345f757f3fSDimitry Andric   }
2355f757f3fSDimitry Andric 
236*0fca6ea1SDimitry Andric   static ContextInfo readUnversioned(internal_key_type Key,
2375f757f3fSDimitry Andric                                      const uint8_t *&Data) {
238*0fca6ea1SDimitry Andric     ContextInfo Info;
2395f757f3fSDimitry Andric     ReadCommonTypeInfo(Data, Info);
2405f757f3fSDimitry Andric     uint8_t Payload = *Data++;
2415f757f3fSDimitry Andric 
2425f757f3fSDimitry Andric     if (Payload & 0x01)
2435f757f3fSDimitry Andric       Info.setHasDesignatedInits(true);
2445f757f3fSDimitry Andric     Payload = Payload >> 1;
2455f757f3fSDimitry Andric 
2465f757f3fSDimitry Andric     if (Payload & 0x4)
2475f757f3fSDimitry Andric       Info.setDefaultNullability(static_cast<NullabilityKind>(Payload & 0x03));
2485f757f3fSDimitry Andric     Payload >>= 3;
2495f757f3fSDimitry Andric 
2505f757f3fSDimitry Andric     if (Payload & (1 << 1))
2515f757f3fSDimitry Andric       Info.setSwiftObjCMembers(Payload & 1);
2525f757f3fSDimitry Andric     Payload >>= 2;
2535f757f3fSDimitry Andric 
2545f757f3fSDimitry Andric     if (Payload & (1 << 1))
2555f757f3fSDimitry Andric       Info.setSwiftImportAsNonGeneric(Payload & 1);
2565f757f3fSDimitry Andric 
2575f757f3fSDimitry Andric     return Info;
2585f757f3fSDimitry Andric   }
2595f757f3fSDimitry Andric };
2605f757f3fSDimitry Andric 
2615f757f3fSDimitry Andric /// Read serialized VariableInfo.
2625f757f3fSDimitry Andric void ReadVariableInfo(const uint8_t *&Data, VariableInfo &Info) {
2635f757f3fSDimitry Andric   ReadCommonEntityInfo(Data, Info);
2645f757f3fSDimitry Andric   if (*Data++) {
2655f757f3fSDimitry Andric     Info.setNullabilityAudited(static_cast<NullabilityKind>(*Data));
2665f757f3fSDimitry Andric   }
2675f757f3fSDimitry Andric   ++Data;
2685f757f3fSDimitry Andric 
269*0fca6ea1SDimitry Andric   auto TypeLen = endian::readNext<uint16_t, llvm::endianness::little>(Data);
2705f757f3fSDimitry Andric   Info.setType(std::string(Data, Data + TypeLen));
2715f757f3fSDimitry Andric   Data += TypeLen;
2725f757f3fSDimitry Andric }
2735f757f3fSDimitry Andric 
2745f757f3fSDimitry Andric /// Used to deserialize the on-disk Objective-C property table.
2755f757f3fSDimitry Andric class ObjCPropertyTableInfo
2765f757f3fSDimitry Andric     : public VersionedTableInfo<ObjCPropertyTableInfo,
2775f757f3fSDimitry Andric                                 std::tuple<uint32_t, uint32_t, uint8_t>,
2785f757f3fSDimitry Andric                                 ObjCPropertyInfo> {
2795f757f3fSDimitry Andric public:
2805f757f3fSDimitry Andric   static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
281*0fca6ea1SDimitry Andric     auto ClassID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
282*0fca6ea1SDimitry Andric     auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
283*0fca6ea1SDimitry Andric     char IsInstance = endian::readNext<uint8_t, llvm::endianness::little>(Data);
2845f757f3fSDimitry Andric     return {ClassID, NameID, IsInstance};
2855f757f3fSDimitry Andric   }
2865f757f3fSDimitry Andric 
2875f757f3fSDimitry Andric   hash_value_type ComputeHash(internal_key_type Key) {
2885f757f3fSDimitry Andric     return static_cast<size_t>(llvm::hash_value(Key));
2895f757f3fSDimitry Andric   }
2905f757f3fSDimitry Andric 
2915f757f3fSDimitry Andric   static ObjCPropertyInfo readUnversioned(internal_key_type Key,
2925f757f3fSDimitry Andric                                           const uint8_t *&Data) {
2935f757f3fSDimitry Andric     ObjCPropertyInfo Info;
2945f757f3fSDimitry Andric     ReadVariableInfo(Data, Info);
2955f757f3fSDimitry Andric     uint8_t Flags = *Data++;
2965f757f3fSDimitry Andric     if (Flags & (1 << 0))
2975f757f3fSDimitry Andric       Info.setSwiftImportAsAccessors(Flags & (1 << 1));
2985f757f3fSDimitry Andric     return Info;
2995f757f3fSDimitry Andric   }
3005f757f3fSDimitry Andric };
3015f757f3fSDimitry Andric 
3025f757f3fSDimitry Andric /// Read serialized ParamInfo.
3035f757f3fSDimitry Andric void ReadParamInfo(const uint8_t *&Data, ParamInfo &Info) {
3045f757f3fSDimitry Andric   ReadVariableInfo(Data, Info);
3055f757f3fSDimitry Andric 
306*0fca6ea1SDimitry Andric   uint8_t Payload = endian::readNext<uint8_t, llvm::endianness::little>(Data);
3075f757f3fSDimitry Andric   if (auto RawConvention = Payload & 0x7) {
3085f757f3fSDimitry Andric     auto Convention = static_cast<RetainCountConventionKind>(RawConvention - 1);
3095f757f3fSDimitry Andric     Info.setRetainCountConvention(Convention);
3105f757f3fSDimitry Andric   }
3115f757f3fSDimitry Andric   Payload >>= 3;
3125f757f3fSDimitry Andric   if (Payload & 0x01)
3135f757f3fSDimitry Andric     Info.setNoEscape(Payload & 0x02);
3145f757f3fSDimitry Andric   Payload >>= 2;
3155f757f3fSDimitry Andric   assert(Payload == 0 && "Bad API notes");
3165f757f3fSDimitry Andric }
3175f757f3fSDimitry Andric 
3185f757f3fSDimitry Andric /// Read serialized FunctionInfo.
3195f757f3fSDimitry Andric void ReadFunctionInfo(const uint8_t *&Data, FunctionInfo &Info) {
3205f757f3fSDimitry Andric   ReadCommonEntityInfo(Data, Info);
3215f757f3fSDimitry Andric 
322*0fca6ea1SDimitry Andric   uint8_t Payload = endian::readNext<uint8_t, llvm::endianness::little>(Data);
3235f757f3fSDimitry Andric   if (auto RawConvention = Payload & 0x7) {
3245f757f3fSDimitry Andric     auto Convention = static_cast<RetainCountConventionKind>(RawConvention - 1);
3255f757f3fSDimitry Andric     Info.setRetainCountConvention(Convention);
3265f757f3fSDimitry Andric   }
3275f757f3fSDimitry Andric   Payload >>= 3;
3285f757f3fSDimitry Andric   Info.NullabilityAudited = Payload & 0x1;
3295f757f3fSDimitry Andric   Payload >>= 1;
3305f757f3fSDimitry Andric   assert(Payload == 0 && "Bad API notes");
3315f757f3fSDimitry Andric 
3325f757f3fSDimitry Andric   Info.NumAdjustedNullable =
333*0fca6ea1SDimitry Andric       endian::readNext<uint8_t, llvm::endianness::little>(Data);
3345f757f3fSDimitry Andric   Info.NullabilityPayload =
335*0fca6ea1SDimitry Andric       endian::readNext<uint64_t, llvm::endianness::little>(Data);
3365f757f3fSDimitry Andric 
3375f757f3fSDimitry Andric   unsigned NumParams =
338*0fca6ea1SDimitry Andric       endian::readNext<uint16_t, llvm::endianness::little>(Data);
3395f757f3fSDimitry Andric   while (NumParams > 0) {
3405f757f3fSDimitry Andric     ParamInfo pi;
3415f757f3fSDimitry Andric     ReadParamInfo(Data, pi);
3425f757f3fSDimitry Andric     Info.Params.push_back(pi);
3435f757f3fSDimitry Andric     --NumParams;
3445f757f3fSDimitry Andric   }
3455f757f3fSDimitry Andric 
3465f757f3fSDimitry Andric   unsigned ResultTypeLen =
347*0fca6ea1SDimitry Andric       endian::readNext<uint16_t, llvm::endianness::little>(Data);
3485f757f3fSDimitry Andric   Info.ResultType = std::string(Data, Data + ResultTypeLen);
3495f757f3fSDimitry Andric   Data += ResultTypeLen;
3505f757f3fSDimitry Andric }
3515f757f3fSDimitry Andric 
3525f757f3fSDimitry Andric /// Used to deserialize the on-disk Objective-C method table.
3535f757f3fSDimitry Andric class ObjCMethodTableInfo
3545f757f3fSDimitry Andric     : public VersionedTableInfo<ObjCMethodTableInfo,
3555f757f3fSDimitry Andric                                 std::tuple<uint32_t, uint32_t, uint8_t>,
3565f757f3fSDimitry Andric                                 ObjCMethodInfo> {
3575f757f3fSDimitry Andric public:
3585f757f3fSDimitry Andric   static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
359*0fca6ea1SDimitry Andric     auto ClassID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
3605f757f3fSDimitry Andric     auto SelectorID =
361*0fca6ea1SDimitry Andric         endian::readNext<uint32_t, llvm::endianness::little>(Data);
362*0fca6ea1SDimitry Andric     auto IsInstance = endian::readNext<uint8_t, llvm::endianness::little>(Data);
3635f757f3fSDimitry Andric     return {ClassID, SelectorID, IsInstance};
3645f757f3fSDimitry Andric   }
3655f757f3fSDimitry Andric 
3665f757f3fSDimitry Andric   hash_value_type ComputeHash(internal_key_type Key) {
3675f757f3fSDimitry Andric     return static_cast<size_t>(llvm::hash_value(Key));
3685f757f3fSDimitry Andric   }
3695f757f3fSDimitry Andric 
3705f757f3fSDimitry Andric   static ObjCMethodInfo readUnversioned(internal_key_type Key,
3715f757f3fSDimitry Andric                                         const uint8_t *&Data) {
3725f757f3fSDimitry Andric     ObjCMethodInfo Info;
3735f757f3fSDimitry Andric     uint8_t Payload = *Data++;
3745f757f3fSDimitry Andric     Info.RequiredInit = Payload & 0x01;
3755f757f3fSDimitry Andric     Payload >>= 1;
3765f757f3fSDimitry Andric     Info.DesignatedInit = Payload & 0x01;
3775f757f3fSDimitry Andric     Payload >>= 1;
3785f757f3fSDimitry Andric 
3795f757f3fSDimitry Andric     ReadFunctionInfo(Data, Info);
3805f757f3fSDimitry Andric     return Info;
3815f757f3fSDimitry Andric   }
3825f757f3fSDimitry Andric };
3835f757f3fSDimitry Andric 
3845f757f3fSDimitry Andric /// Used to deserialize the on-disk Objective-C selector table.
3855f757f3fSDimitry Andric class ObjCSelectorTableInfo {
3865f757f3fSDimitry Andric public:
3875f757f3fSDimitry Andric   using internal_key_type = StoredObjCSelector;
3885f757f3fSDimitry Andric   using external_key_type = internal_key_type;
3895f757f3fSDimitry Andric   using data_type = SelectorID;
3905f757f3fSDimitry Andric   using hash_value_type = unsigned;
3915f757f3fSDimitry Andric   using offset_type = unsigned;
3925f757f3fSDimitry Andric 
3935f757f3fSDimitry Andric   internal_key_type GetInternalKey(external_key_type Key) { return Key; }
3945f757f3fSDimitry Andric 
3955f757f3fSDimitry Andric   external_key_type GetExternalKey(internal_key_type Key) { return Key; }
3965f757f3fSDimitry Andric 
3975f757f3fSDimitry Andric   hash_value_type ComputeHash(internal_key_type Key) {
3985f757f3fSDimitry Andric     return llvm::DenseMapInfo<StoredObjCSelector>::getHashValue(Key);
3995f757f3fSDimitry Andric   }
4005f757f3fSDimitry Andric 
4015f757f3fSDimitry Andric   static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
4025f757f3fSDimitry Andric     return llvm::DenseMapInfo<StoredObjCSelector>::isEqual(LHS, RHS);
4035f757f3fSDimitry Andric   }
4045f757f3fSDimitry Andric 
4055f757f3fSDimitry Andric   static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {
4065f757f3fSDimitry Andric     unsigned KeyLength =
407*0fca6ea1SDimitry Andric         endian::readNext<uint16_t, llvm::endianness::little>(Data);
4085f757f3fSDimitry Andric     unsigned DataLength =
409*0fca6ea1SDimitry Andric         endian::readNext<uint16_t, llvm::endianness::little>(Data);
4105f757f3fSDimitry Andric     return {KeyLength, DataLength};
4115f757f3fSDimitry Andric   }
4125f757f3fSDimitry Andric 
4135f757f3fSDimitry Andric   static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
4145f757f3fSDimitry Andric     internal_key_type Key;
415*0fca6ea1SDimitry Andric     Key.NumArgs = endian::readNext<uint16_t, llvm::endianness::little>(Data);
4165f757f3fSDimitry Andric     unsigned NumIdents = (Length - sizeof(uint16_t)) / sizeof(uint32_t);
4175f757f3fSDimitry Andric     for (unsigned i = 0; i != NumIdents; ++i) {
4185f757f3fSDimitry Andric       Key.Identifiers.push_back(
419*0fca6ea1SDimitry Andric           endian::readNext<uint32_t, llvm::endianness::little>(Data));
4205f757f3fSDimitry Andric     }
4215f757f3fSDimitry Andric     return Key;
4225f757f3fSDimitry Andric   }
4235f757f3fSDimitry Andric 
4245f757f3fSDimitry Andric   static data_type ReadData(internal_key_type Key, const uint8_t *Data,
4255f757f3fSDimitry Andric                             unsigned Length) {
426*0fca6ea1SDimitry Andric     return endian::readNext<uint32_t, llvm::endianness::little>(Data);
4275f757f3fSDimitry Andric   }
4285f757f3fSDimitry Andric };
4295f757f3fSDimitry Andric 
4305f757f3fSDimitry Andric /// Used to deserialize the on-disk global variable table.
4315f757f3fSDimitry Andric class GlobalVariableTableInfo
432*0fca6ea1SDimitry Andric     : public VersionedTableInfo<GlobalVariableTableInfo, SingleDeclTableKey,
4335f757f3fSDimitry Andric                                 GlobalVariableInfo> {
4345f757f3fSDimitry Andric public:
4355f757f3fSDimitry Andric   static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
436*0fca6ea1SDimitry Andric     auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
437*0fca6ea1SDimitry Andric     auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
438*0fca6ea1SDimitry Andric     return {CtxID, NameID};
4395f757f3fSDimitry Andric   }
4405f757f3fSDimitry Andric 
4415f757f3fSDimitry Andric   hash_value_type ComputeHash(internal_key_type Key) {
4425f757f3fSDimitry Andric     return static_cast<size_t>(Key.hashValue());
4435f757f3fSDimitry Andric   }
4445f757f3fSDimitry Andric 
4455f757f3fSDimitry Andric   static GlobalVariableInfo readUnversioned(internal_key_type Key,
4465f757f3fSDimitry Andric                                             const uint8_t *&Data) {
4475f757f3fSDimitry Andric     GlobalVariableInfo Info;
4485f757f3fSDimitry Andric     ReadVariableInfo(Data, Info);
4495f757f3fSDimitry Andric     return Info;
4505f757f3fSDimitry Andric   }
4515f757f3fSDimitry Andric };
4525f757f3fSDimitry Andric 
4535f757f3fSDimitry Andric /// Used to deserialize the on-disk global function table.
4545f757f3fSDimitry Andric class GlobalFunctionTableInfo
455*0fca6ea1SDimitry Andric     : public VersionedTableInfo<GlobalFunctionTableInfo, SingleDeclTableKey,
4565f757f3fSDimitry Andric                                 GlobalFunctionInfo> {
4575f757f3fSDimitry Andric public:
4585f757f3fSDimitry Andric   static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
459*0fca6ea1SDimitry Andric     auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
460*0fca6ea1SDimitry Andric     auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
461*0fca6ea1SDimitry Andric     return {CtxID, NameID};
4625f757f3fSDimitry Andric   }
4635f757f3fSDimitry Andric 
4645f757f3fSDimitry Andric   hash_value_type ComputeHash(internal_key_type Key) {
4655f757f3fSDimitry Andric     return static_cast<size_t>(Key.hashValue());
4665f757f3fSDimitry Andric   }
4675f757f3fSDimitry Andric 
4685f757f3fSDimitry Andric   static GlobalFunctionInfo readUnversioned(internal_key_type Key,
4695f757f3fSDimitry Andric                                             const uint8_t *&Data) {
4705f757f3fSDimitry Andric     GlobalFunctionInfo Info;
4715f757f3fSDimitry Andric     ReadFunctionInfo(Data, Info);
4725f757f3fSDimitry Andric     return Info;
4735f757f3fSDimitry Andric   }
4745f757f3fSDimitry Andric };
4755f757f3fSDimitry Andric 
476*0fca6ea1SDimitry Andric /// Used to deserialize the on-disk C++ method table.
477*0fca6ea1SDimitry Andric class CXXMethodTableInfo
478*0fca6ea1SDimitry Andric     : public VersionedTableInfo<CXXMethodTableInfo, SingleDeclTableKey,
479*0fca6ea1SDimitry Andric                                 CXXMethodInfo> {
480*0fca6ea1SDimitry Andric public:
481*0fca6ea1SDimitry Andric   static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
482*0fca6ea1SDimitry Andric     auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
483*0fca6ea1SDimitry Andric     auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
484*0fca6ea1SDimitry Andric     return {CtxID, NameID};
485*0fca6ea1SDimitry Andric   }
486*0fca6ea1SDimitry Andric 
487*0fca6ea1SDimitry Andric   hash_value_type ComputeHash(internal_key_type Key) {
488*0fca6ea1SDimitry Andric     return static_cast<size_t>(Key.hashValue());
489*0fca6ea1SDimitry Andric   }
490*0fca6ea1SDimitry Andric 
491*0fca6ea1SDimitry Andric   static CXXMethodInfo readUnversioned(internal_key_type Key,
492*0fca6ea1SDimitry Andric                                        const uint8_t *&Data) {
493*0fca6ea1SDimitry Andric     CXXMethodInfo Info;
494*0fca6ea1SDimitry Andric     ReadFunctionInfo(Data, Info);
495*0fca6ea1SDimitry Andric     return Info;
496*0fca6ea1SDimitry Andric   }
497*0fca6ea1SDimitry Andric };
498*0fca6ea1SDimitry Andric 
4995f757f3fSDimitry Andric /// Used to deserialize the on-disk enumerator table.
5005f757f3fSDimitry Andric class EnumConstantTableInfo
5015f757f3fSDimitry Andric     : public VersionedTableInfo<EnumConstantTableInfo, uint32_t,
5025f757f3fSDimitry Andric                                 EnumConstantInfo> {
5035f757f3fSDimitry Andric public:
5045f757f3fSDimitry Andric   static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
505*0fca6ea1SDimitry Andric     auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
5065f757f3fSDimitry Andric     return NameID;
5075f757f3fSDimitry Andric   }
5085f757f3fSDimitry Andric 
5095f757f3fSDimitry Andric   hash_value_type ComputeHash(internal_key_type Key) {
5105f757f3fSDimitry Andric     return static_cast<size_t>(llvm::hash_value(Key));
5115f757f3fSDimitry Andric   }
5125f757f3fSDimitry Andric 
5135f757f3fSDimitry Andric   static EnumConstantInfo readUnversioned(internal_key_type Key,
5145f757f3fSDimitry Andric                                           const uint8_t *&Data) {
5155f757f3fSDimitry Andric     EnumConstantInfo Info;
5165f757f3fSDimitry Andric     ReadCommonEntityInfo(Data, Info);
5175f757f3fSDimitry Andric     return Info;
5185f757f3fSDimitry Andric   }
5195f757f3fSDimitry Andric };
5205f757f3fSDimitry Andric 
5215f757f3fSDimitry Andric /// Used to deserialize the on-disk tag table.
5225f757f3fSDimitry Andric class TagTableInfo
523*0fca6ea1SDimitry Andric     : public VersionedTableInfo<TagTableInfo, SingleDeclTableKey, TagInfo> {
5245f757f3fSDimitry Andric public:
5255f757f3fSDimitry Andric   static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
526*0fca6ea1SDimitry Andric     auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
5275f757f3fSDimitry Andric     auto NameID =
528*0fca6ea1SDimitry Andric         endian::readNext<IdentifierID, llvm::endianness::little>(Data);
529*0fca6ea1SDimitry Andric     return {CtxID, NameID};
5305f757f3fSDimitry Andric   }
5315f757f3fSDimitry Andric 
5325f757f3fSDimitry Andric   hash_value_type ComputeHash(internal_key_type Key) {
5335f757f3fSDimitry Andric     return static_cast<size_t>(Key.hashValue());
5345f757f3fSDimitry Andric   }
5355f757f3fSDimitry Andric 
5365f757f3fSDimitry Andric   static TagInfo readUnversioned(internal_key_type Key, const uint8_t *&Data) {
5375f757f3fSDimitry Andric     TagInfo Info;
5385f757f3fSDimitry Andric 
5395f757f3fSDimitry Andric     uint8_t Payload = *Data++;
5405f757f3fSDimitry Andric     if (Payload & 1)
5415f757f3fSDimitry Andric       Info.setFlagEnum(Payload & 2);
5425f757f3fSDimitry Andric     Payload >>= 2;
5435f757f3fSDimitry Andric     if (Payload > 0)
5445f757f3fSDimitry Andric       Info.EnumExtensibility =
5455f757f3fSDimitry Andric           static_cast<EnumExtensibilityKind>((Payload & 0x3) - 1);
5465f757f3fSDimitry Andric 
547*0fca6ea1SDimitry Andric     uint8_t Copyable =
548*0fca6ea1SDimitry Andric         endian::readNext<uint8_t, llvm::endianness::little>(Data);
549*0fca6ea1SDimitry Andric     if (Copyable == kSwiftNonCopyable)
550*0fca6ea1SDimitry Andric       Info.setSwiftCopyable(std::optional(false));
551*0fca6ea1SDimitry Andric     else if (Copyable == kSwiftCopyable)
552*0fca6ea1SDimitry Andric       Info.setSwiftCopyable(std::optional(true));
553*0fca6ea1SDimitry Andric 
5545f757f3fSDimitry Andric     unsigned ImportAsLength =
555*0fca6ea1SDimitry Andric         endian::readNext<uint16_t, llvm::endianness::little>(Data);
5565f757f3fSDimitry Andric     if (ImportAsLength > 0) {
5575f757f3fSDimitry Andric       Info.SwiftImportAs =
5585f757f3fSDimitry Andric           std::string(reinterpret_cast<const char *>(Data), ImportAsLength - 1);
5595f757f3fSDimitry Andric       Data += ImportAsLength - 1;
5605f757f3fSDimitry Andric     }
5615f757f3fSDimitry Andric     unsigned RetainOpLength =
562*0fca6ea1SDimitry Andric         endian::readNext<uint16_t, llvm::endianness::little>(Data);
5635f757f3fSDimitry Andric     if (RetainOpLength > 0) {
5645f757f3fSDimitry Andric       Info.SwiftRetainOp =
5655f757f3fSDimitry Andric           std::string(reinterpret_cast<const char *>(Data), RetainOpLength - 1);
5665f757f3fSDimitry Andric       Data += RetainOpLength - 1;
5675f757f3fSDimitry Andric     }
5685f757f3fSDimitry Andric     unsigned ReleaseOpLength =
569*0fca6ea1SDimitry Andric         endian::readNext<uint16_t, llvm::endianness::little>(Data);
5705f757f3fSDimitry Andric     if (ReleaseOpLength > 0) {
5715f757f3fSDimitry Andric       Info.SwiftReleaseOp = std::string(reinterpret_cast<const char *>(Data),
5725f757f3fSDimitry Andric                                         ReleaseOpLength - 1);
5735f757f3fSDimitry Andric       Data += ReleaseOpLength - 1;
5745f757f3fSDimitry Andric     }
5755f757f3fSDimitry Andric 
5765f757f3fSDimitry Andric     ReadCommonTypeInfo(Data, Info);
5775f757f3fSDimitry Andric     return Info;
5785f757f3fSDimitry Andric   }
5795f757f3fSDimitry Andric };
5805f757f3fSDimitry Andric 
5815f757f3fSDimitry Andric /// Used to deserialize the on-disk typedef table.
5825f757f3fSDimitry Andric class TypedefTableInfo
583*0fca6ea1SDimitry Andric     : public VersionedTableInfo<TypedefTableInfo, SingleDeclTableKey,
5845f757f3fSDimitry Andric                                 TypedefInfo> {
5855f757f3fSDimitry Andric public:
5865f757f3fSDimitry Andric   static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
587*0fca6ea1SDimitry Andric     auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
5885f757f3fSDimitry Andric     auto nameID =
589*0fca6ea1SDimitry Andric         endian::readNext<IdentifierID, llvm::endianness::little>(Data);
590*0fca6ea1SDimitry Andric     return {CtxID, nameID};
5915f757f3fSDimitry Andric   }
5925f757f3fSDimitry Andric 
5935f757f3fSDimitry Andric   hash_value_type ComputeHash(internal_key_type Key) {
5945f757f3fSDimitry Andric     return static_cast<size_t>(Key.hashValue());
5955f757f3fSDimitry Andric   }
5965f757f3fSDimitry Andric 
5975f757f3fSDimitry Andric   static TypedefInfo readUnversioned(internal_key_type Key,
5985f757f3fSDimitry Andric                                      const uint8_t *&Data) {
5995f757f3fSDimitry Andric     TypedefInfo Info;
6005f757f3fSDimitry Andric 
6015f757f3fSDimitry Andric     uint8_t Payload = *Data++;
6025f757f3fSDimitry Andric     if (Payload > 0)
6035f757f3fSDimitry Andric       Info.SwiftWrapper = static_cast<SwiftNewTypeKind>((Payload & 0x3) - 1);
6045f757f3fSDimitry Andric 
6055f757f3fSDimitry Andric     ReadCommonTypeInfo(Data, Info);
6065f757f3fSDimitry Andric     return Info;
6075f757f3fSDimitry Andric   }
6085f757f3fSDimitry Andric };
6095f757f3fSDimitry Andric } // end anonymous namespace
6105f757f3fSDimitry Andric 
6115f757f3fSDimitry Andric class APINotesReader::Implementation {
6125f757f3fSDimitry Andric public:
6135f757f3fSDimitry Andric   /// The input buffer for the API notes data.
6145f757f3fSDimitry Andric   llvm::MemoryBuffer *InputBuffer;
6155f757f3fSDimitry Andric 
6165f757f3fSDimitry Andric   /// The Swift version to use for filtering.
6175f757f3fSDimitry Andric   llvm::VersionTuple SwiftVersion;
6185f757f3fSDimitry Andric 
6195f757f3fSDimitry Andric   /// The name of the module that we read from the control block.
6205f757f3fSDimitry Andric   std::string ModuleName;
6215f757f3fSDimitry Andric 
6225f757f3fSDimitry Andric   // The size and modification time of the source file from
6235f757f3fSDimitry Andric   // which this API notes file was created, if known.
6245f757f3fSDimitry Andric   std::optional<std::pair<off_t, time_t>> SourceFileSizeAndModTime;
6255f757f3fSDimitry Andric 
6265f757f3fSDimitry Andric   using SerializedIdentifierTable =
6275f757f3fSDimitry Andric       llvm::OnDiskIterableChainedHashTable<IdentifierTableInfo>;
6285f757f3fSDimitry Andric 
6295f757f3fSDimitry Andric   /// The identifier table.
6305f757f3fSDimitry Andric   std::unique_ptr<SerializedIdentifierTable> IdentifierTable;
6315f757f3fSDimitry Andric 
632*0fca6ea1SDimitry Andric   using SerializedContextIDTable =
633*0fca6ea1SDimitry Andric       llvm::OnDiskIterableChainedHashTable<ContextIDTableInfo>;
6345f757f3fSDimitry Andric 
635*0fca6ea1SDimitry Andric   /// The Objective-C / C++ context ID table.
636*0fca6ea1SDimitry Andric   std::unique_ptr<SerializedContextIDTable> ContextIDTable;
6375f757f3fSDimitry Andric 
638*0fca6ea1SDimitry Andric   using SerializedContextInfoTable =
639*0fca6ea1SDimitry Andric       llvm::OnDiskIterableChainedHashTable<ContextInfoTableInfo>;
6405f757f3fSDimitry Andric 
6415f757f3fSDimitry Andric   /// The Objective-C context info table.
642*0fca6ea1SDimitry Andric   std::unique_ptr<SerializedContextInfoTable> ContextInfoTable;
6435f757f3fSDimitry Andric 
6445f757f3fSDimitry Andric   using SerializedObjCPropertyTable =
6455f757f3fSDimitry Andric       llvm::OnDiskIterableChainedHashTable<ObjCPropertyTableInfo>;
6465f757f3fSDimitry Andric 
6475f757f3fSDimitry Andric   /// The Objective-C property table.
6485f757f3fSDimitry Andric   std::unique_ptr<SerializedObjCPropertyTable> ObjCPropertyTable;
6495f757f3fSDimitry Andric 
6505f757f3fSDimitry Andric   using SerializedObjCMethodTable =
6515f757f3fSDimitry Andric       llvm::OnDiskIterableChainedHashTable<ObjCMethodTableInfo>;
6525f757f3fSDimitry Andric 
6535f757f3fSDimitry Andric   /// The Objective-C method table.
6545f757f3fSDimitry Andric   std::unique_ptr<SerializedObjCMethodTable> ObjCMethodTable;
6555f757f3fSDimitry Andric 
656*0fca6ea1SDimitry Andric   using SerializedCXXMethodTable =
657*0fca6ea1SDimitry Andric       llvm::OnDiskIterableChainedHashTable<CXXMethodTableInfo>;
658*0fca6ea1SDimitry Andric 
659*0fca6ea1SDimitry Andric   /// The C++ method table.
660*0fca6ea1SDimitry Andric   std::unique_ptr<SerializedCXXMethodTable> CXXMethodTable;
661*0fca6ea1SDimitry Andric 
6625f757f3fSDimitry Andric   using SerializedObjCSelectorTable =
6635f757f3fSDimitry Andric       llvm::OnDiskIterableChainedHashTable<ObjCSelectorTableInfo>;
6645f757f3fSDimitry Andric 
6655f757f3fSDimitry Andric   /// The Objective-C selector table.
6665f757f3fSDimitry Andric   std::unique_ptr<SerializedObjCSelectorTable> ObjCSelectorTable;
6675f757f3fSDimitry Andric 
6685f757f3fSDimitry Andric   using SerializedGlobalVariableTable =
6695f757f3fSDimitry Andric       llvm::OnDiskIterableChainedHashTable<GlobalVariableTableInfo>;
6705f757f3fSDimitry Andric 
6715f757f3fSDimitry Andric   /// The global variable table.
6725f757f3fSDimitry Andric   std::unique_ptr<SerializedGlobalVariableTable> GlobalVariableTable;
6735f757f3fSDimitry Andric 
6745f757f3fSDimitry Andric   using SerializedGlobalFunctionTable =
6755f757f3fSDimitry Andric       llvm::OnDiskIterableChainedHashTable<GlobalFunctionTableInfo>;
6765f757f3fSDimitry Andric 
6775f757f3fSDimitry Andric   /// The global function table.
6785f757f3fSDimitry Andric   std::unique_ptr<SerializedGlobalFunctionTable> GlobalFunctionTable;
6795f757f3fSDimitry Andric 
6805f757f3fSDimitry Andric   using SerializedEnumConstantTable =
6815f757f3fSDimitry Andric       llvm::OnDiskIterableChainedHashTable<EnumConstantTableInfo>;
6825f757f3fSDimitry Andric 
6835f757f3fSDimitry Andric   /// The enumerator table.
6845f757f3fSDimitry Andric   std::unique_ptr<SerializedEnumConstantTable> EnumConstantTable;
6855f757f3fSDimitry Andric 
6865f757f3fSDimitry Andric   using SerializedTagTable = llvm::OnDiskIterableChainedHashTable<TagTableInfo>;
6875f757f3fSDimitry Andric 
6885f757f3fSDimitry Andric   /// The tag table.
6895f757f3fSDimitry Andric   std::unique_ptr<SerializedTagTable> TagTable;
6905f757f3fSDimitry Andric 
6915f757f3fSDimitry Andric   using SerializedTypedefTable =
6925f757f3fSDimitry Andric       llvm::OnDiskIterableChainedHashTable<TypedefTableInfo>;
6935f757f3fSDimitry Andric 
6945f757f3fSDimitry Andric   /// The typedef table.
6955f757f3fSDimitry Andric   std::unique_ptr<SerializedTypedefTable> TypedefTable;
6965f757f3fSDimitry Andric 
6975f757f3fSDimitry Andric   /// Retrieve the identifier ID for the given string, or an empty
6985f757f3fSDimitry Andric   /// optional if the string is unknown.
6995f757f3fSDimitry Andric   std::optional<IdentifierID> getIdentifier(llvm::StringRef Str);
7005f757f3fSDimitry Andric 
7015f757f3fSDimitry Andric   /// Retrieve the selector ID for the given selector, or an empty
7025f757f3fSDimitry Andric   /// optional if the string is unknown.
7035f757f3fSDimitry Andric   std::optional<SelectorID> getSelector(ObjCSelectorRef Selector);
7045f757f3fSDimitry Andric 
7055f757f3fSDimitry Andric   bool readControlBlock(llvm::BitstreamCursor &Cursor,
7065f757f3fSDimitry Andric                         llvm::SmallVectorImpl<uint64_t> &Scratch);
7075f757f3fSDimitry Andric   bool readIdentifierBlock(llvm::BitstreamCursor &Cursor,
7085f757f3fSDimitry Andric                            llvm::SmallVectorImpl<uint64_t> &Scratch);
709*0fca6ea1SDimitry Andric   bool readContextBlock(llvm::BitstreamCursor &Cursor,
7105f757f3fSDimitry Andric                         llvm::SmallVectorImpl<uint64_t> &Scratch);
7115f757f3fSDimitry Andric   bool readObjCPropertyBlock(llvm::BitstreamCursor &Cursor,
7125f757f3fSDimitry Andric                              llvm::SmallVectorImpl<uint64_t> &Scratch);
7135f757f3fSDimitry Andric   bool readObjCMethodBlock(llvm::BitstreamCursor &Cursor,
7145f757f3fSDimitry Andric                            llvm::SmallVectorImpl<uint64_t> &Scratch);
715*0fca6ea1SDimitry Andric   bool readCXXMethodBlock(llvm::BitstreamCursor &Cursor,
716*0fca6ea1SDimitry Andric                           llvm::SmallVectorImpl<uint64_t> &Scratch);
7175f757f3fSDimitry Andric   bool readObjCSelectorBlock(llvm::BitstreamCursor &Cursor,
7185f757f3fSDimitry Andric                              llvm::SmallVectorImpl<uint64_t> &Scratch);
7195f757f3fSDimitry Andric   bool readGlobalVariableBlock(llvm::BitstreamCursor &Cursor,
7205f757f3fSDimitry Andric                                llvm::SmallVectorImpl<uint64_t> &Scratch);
7215f757f3fSDimitry Andric   bool readGlobalFunctionBlock(llvm::BitstreamCursor &Cursor,
7225f757f3fSDimitry Andric                                llvm::SmallVectorImpl<uint64_t> &Scratch);
7235f757f3fSDimitry Andric   bool readEnumConstantBlock(llvm::BitstreamCursor &Cursor,
7245f757f3fSDimitry Andric                              llvm::SmallVectorImpl<uint64_t> &Scratch);
7255f757f3fSDimitry Andric   bool readTagBlock(llvm::BitstreamCursor &Cursor,
7265f757f3fSDimitry Andric                     llvm::SmallVectorImpl<uint64_t> &Scratch);
7275f757f3fSDimitry Andric   bool readTypedefBlock(llvm::BitstreamCursor &Cursor,
7285f757f3fSDimitry Andric                         llvm::SmallVectorImpl<uint64_t> &Scratch);
7295f757f3fSDimitry Andric };
7305f757f3fSDimitry Andric 
7315f757f3fSDimitry Andric std::optional<IdentifierID>
7325f757f3fSDimitry Andric APINotesReader::Implementation::getIdentifier(llvm::StringRef Str) {
7335f757f3fSDimitry Andric   if (!IdentifierTable)
7345f757f3fSDimitry Andric     return std::nullopt;
7355f757f3fSDimitry Andric 
7365f757f3fSDimitry Andric   if (Str.empty())
7375f757f3fSDimitry Andric     return IdentifierID(0);
7385f757f3fSDimitry Andric 
7395f757f3fSDimitry Andric   auto Known = IdentifierTable->find(Str);
7405f757f3fSDimitry Andric   if (Known == IdentifierTable->end())
7415f757f3fSDimitry Andric     return std::nullopt;
7425f757f3fSDimitry Andric 
7435f757f3fSDimitry Andric   return *Known;
7445f757f3fSDimitry Andric }
7455f757f3fSDimitry Andric 
7465f757f3fSDimitry Andric std::optional<SelectorID>
7475f757f3fSDimitry Andric APINotesReader::Implementation::getSelector(ObjCSelectorRef Selector) {
7485f757f3fSDimitry Andric   if (!ObjCSelectorTable || !IdentifierTable)
7495f757f3fSDimitry Andric     return std::nullopt;
7505f757f3fSDimitry Andric 
7515f757f3fSDimitry Andric   // Translate the identifiers.
7525f757f3fSDimitry Andric   StoredObjCSelector Key;
7535f757f3fSDimitry Andric   Key.NumArgs = Selector.NumArgs;
7545f757f3fSDimitry Andric   for (auto Ident : Selector.Identifiers) {
7555f757f3fSDimitry Andric     if (auto IdentID = getIdentifier(Ident)) {
7565f757f3fSDimitry Andric       Key.Identifiers.push_back(*IdentID);
7575f757f3fSDimitry Andric     } else {
7585f757f3fSDimitry Andric       return std::nullopt;
7595f757f3fSDimitry Andric     }
7605f757f3fSDimitry Andric   }
7615f757f3fSDimitry Andric 
7625f757f3fSDimitry Andric   auto Known = ObjCSelectorTable->find(Key);
7635f757f3fSDimitry Andric   if (Known == ObjCSelectorTable->end())
7645f757f3fSDimitry Andric     return std::nullopt;
7655f757f3fSDimitry Andric 
7665f757f3fSDimitry Andric   return *Known;
7675f757f3fSDimitry Andric }
7685f757f3fSDimitry Andric 
7695f757f3fSDimitry Andric bool APINotesReader::Implementation::readControlBlock(
7705f757f3fSDimitry Andric     llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
7715f757f3fSDimitry Andric   if (Cursor.EnterSubBlock(CONTROL_BLOCK_ID))
7725f757f3fSDimitry Andric     return true;
7735f757f3fSDimitry Andric 
7745f757f3fSDimitry Andric   bool SawMetadata = false;
7755f757f3fSDimitry Andric 
7765f757f3fSDimitry Andric   llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
7775f757f3fSDimitry Andric   if (!MaybeNext) {
7785f757f3fSDimitry Andric     // FIXME this drops the error on the floor.
7795f757f3fSDimitry Andric     consumeError(MaybeNext.takeError());
7805f757f3fSDimitry Andric     return false;
7815f757f3fSDimitry Andric   }
7825f757f3fSDimitry Andric   llvm::BitstreamEntry Next = MaybeNext.get();
7835f757f3fSDimitry Andric 
7845f757f3fSDimitry Andric   while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
7855f757f3fSDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::Error)
7865f757f3fSDimitry Andric       return true;
7875f757f3fSDimitry Andric 
7885f757f3fSDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
7895f757f3fSDimitry Andric       // Unknown metadata sub-block, possibly for use by a future version of the
7905f757f3fSDimitry Andric       // API notes format.
7915f757f3fSDimitry Andric       if (Cursor.SkipBlock())
7925f757f3fSDimitry Andric         return true;
7935f757f3fSDimitry Andric 
7945f757f3fSDimitry Andric       MaybeNext = Cursor.advance();
7955f757f3fSDimitry Andric       if (!MaybeNext) {
7965f757f3fSDimitry Andric         // FIXME this drops the error on the floor.
7975f757f3fSDimitry Andric         consumeError(MaybeNext.takeError());
7985f757f3fSDimitry Andric         return false;
7995f757f3fSDimitry Andric       }
8005f757f3fSDimitry Andric       Next = MaybeNext.get();
8015f757f3fSDimitry Andric       continue;
8025f757f3fSDimitry Andric     }
8035f757f3fSDimitry Andric 
8045f757f3fSDimitry Andric     Scratch.clear();
8055f757f3fSDimitry Andric     llvm::StringRef BlobData;
8065f757f3fSDimitry Andric     llvm::Expected<unsigned> MaybeKind =
8075f757f3fSDimitry Andric         Cursor.readRecord(Next.ID, Scratch, &BlobData);
8085f757f3fSDimitry Andric     if (!MaybeKind) {
8095f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
8105f757f3fSDimitry Andric       consumeError(MaybeKind.takeError());
8115f757f3fSDimitry Andric       return false;
8125f757f3fSDimitry Andric     }
8135f757f3fSDimitry Andric     unsigned Kind = MaybeKind.get();
8145f757f3fSDimitry Andric 
8155f757f3fSDimitry Andric     switch (Kind) {
8165f757f3fSDimitry Andric     case control_block::METADATA:
8175f757f3fSDimitry Andric       // Already saw metadata.
8185f757f3fSDimitry Andric       if (SawMetadata)
8195f757f3fSDimitry Andric         return true;
8205f757f3fSDimitry Andric 
8215f757f3fSDimitry Andric       if (Scratch[0] != VERSION_MAJOR || Scratch[1] != VERSION_MINOR)
8225f757f3fSDimitry Andric         return true;
8235f757f3fSDimitry Andric 
8245f757f3fSDimitry Andric       SawMetadata = true;
8255f757f3fSDimitry Andric       break;
8265f757f3fSDimitry Andric 
8275f757f3fSDimitry Andric     case control_block::MODULE_NAME:
8285f757f3fSDimitry Andric       ModuleName = BlobData.str();
8295f757f3fSDimitry Andric       break;
8305f757f3fSDimitry Andric 
8315f757f3fSDimitry Andric     case control_block::MODULE_OPTIONS:
8325f757f3fSDimitry Andric       break;
8335f757f3fSDimitry Andric 
8345f757f3fSDimitry Andric     case control_block::SOURCE_FILE:
8355f757f3fSDimitry Andric       SourceFileSizeAndModTime = {Scratch[0], Scratch[1]};
8365f757f3fSDimitry Andric       break;
8375f757f3fSDimitry Andric 
8385f757f3fSDimitry Andric     default:
8395f757f3fSDimitry Andric       // Unknown metadata record, possibly for use by a future version of the
8405f757f3fSDimitry Andric       // module format.
8415f757f3fSDimitry Andric       break;
8425f757f3fSDimitry Andric     }
8435f757f3fSDimitry Andric 
8445f757f3fSDimitry Andric     MaybeNext = Cursor.advance();
8455f757f3fSDimitry Andric     if (!MaybeNext) {
8465f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
8475f757f3fSDimitry Andric       consumeError(MaybeNext.takeError());
8485f757f3fSDimitry Andric       return false;
8495f757f3fSDimitry Andric     }
8505f757f3fSDimitry Andric     Next = MaybeNext.get();
8515f757f3fSDimitry Andric   }
8525f757f3fSDimitry Andric 
8535f757f3fSDimitry Andric   return !SawMetadata;
8545f757f3fSDimitry Andric }
8555f757f3fSDimitry Andric 
8565f757f3fSDimitry Andric bool APINotesReader::Implementation::readIdentifierBlock(
8575f757f3fSDimitry Andric     llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
8585f757f3fSDimitry Andric   if (Cursor.EnterSubBlock(IDENTIFIER_BLOCK_ID))
8595f757f3fSDimitry Andric     return true;
8605f757f3fSDimitry Andric 
8615f757f3fSDimitry Andric   llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
8625f757f3fSDimitry Andric   if (!MaybeNext) {
8635f757f3fSDimitry Andric     // FIXME this drops the error on the floor.
8645f757f3fSDimitry Andric     consumeError(MaybeNext.takeError());
8655f757f3fSDimitry Andric     return false;
8665f757f3fSDimitry Andric   }
8675f757f3fSDimitry Andric   llvm::BitstreamEntry Next = MaybeNext.get();
8685f757f3fSDimitry Andric 
8695f757f3fSDimitry Andric   while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
8705f757f3fSDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::Error)
8715f757f3fSDimitry Andric       return true;
8725f757f3fSDimitry Andric 
8735f757f3fSDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
8745f757f3fSDimitry Andric       // Unknown sub-block, possibly for use by a future version of the
8755f757f3fSDimitry Andric       // API notes format.
8765f757f3fSDimitry Andric       if (Cursor.SkipBlock())
8775f757f3fSDimitry Andric         return true;
8785f757f3fSDimitry Andric 
8795f757f3fSDimitry Andric       MaybeNext = Cursor.advance();
8805f757f3fSDimitry Andric       if (!MaybeNext) {
8815f757f3fSDimitry Andric         // FIXME this drops the error on the floor.
8825f757f3fSDimitry Andric         consumeError(MaybeNext.takeError());
8835f757f3fSDimitry Andric         return false;
8845f757f3fSDimitry Andric       }
8855f757f3fSDimitry Andric       Next = MaybeNext.get();
8865f757f3fSDimitry Andric       continue;
8875f757f3fSDimitry Andric     }
8885f757f3fSDimitry Andric 
8895f757f3fSDimitry Andric     Scratch.clear();
8905f757f3fSDimitry Andric     llvm::StringRef BlobData;
8915f757f3fSDimitry Andric     llvm::Expected<unsigned> MaybeKind =
8925f757f3fSDimitry Andric         Cursor.readRecord(Next.ID, Scratch, &BlobData);
8935f757f3fSDimitry Andric     if (!MaybeKind) {
8945f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
8955f757f3fSDimitry Andric       consumeError(MaybeKind.takeError());
8965f757f3fSDimitry Andric       return false;
8975f757f3fSDimitry Andric     }
8985f757f3fSDimitry Andric     unsigned Kind = MaybeKind.get();
8995f757f3fSDimitry Andric     switch (Kind) {
9005f757f3fSDimitry Andric     case identifier_block::IDENTIFIER_DATA: {
9015f757f3fSDimitry Andric       // Already saw identifier table.
9025f757f3fSDimitry Andric       if (IdentifierTable)
9035f757f3fSDimitry Andric         return true;
9045f757f3fSDimitry Andric 
9055f757f3fSDimitry Andric       uint32_t tableOffset;
9065f757f3fSDimitry Andric       identifier_block::IdentifierDataLayout::readRecord(Scratch, tableOffset);
9075f757f3fSDimitry Andric       auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
9085f757f3fSDimitry Andric 
9095f757f3fSDimitry Andric       IdentifierTable.reset(SerializedIdentifierTable::Create(
9105f757f3fSDimitry Andric           base + tableOffset, base + sizeof(uint32_t), base));
9115f757f3fSDimitry Andric       break;
9125f757f3fSDimitry Andric     }
9135f757f3fSDimitry Andric 
9145f757f3fSDimitry Andric     default:
9155f757f3fSDimitry Andric       // Unknown record, possibly for use by a future version of the
9165f757f3fSDimitry Andric       // module format.
9175f757f3fSDimitry Andric       break;
9185f757f3fSDimitry Andric     }
9195f757f3fSDimitry Andric 
9205f757f3fSDimitry Andric     MaybeNext = Cursor.advance();
9215f757f3fSDimitry Andric     if (!MaybeNext) {
9225f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
9235f757f3fSDimitry Andric       consumeError(MaybeNext.takeError());
9245f757f3fSDimitry Andric       return false;
9255f757f3fSDimitry Andric     }
9265f757f3fSDimitry Andric     Next = MaybeNext.get();
9275f757f3fSDimitry Andric   }
9285f757f3fSDimitry Andric 
9295f757f3fSDimitry Andric   return false;
9305f757f3fSDimitry Andric }
9315f757f3fSDimitry Andric 
932*0fca6ea1SDimitry Andric bool APINotesReader::Implementation::readContextBlock(
9335f757f3fSDimitry Andric     llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
9345f757f3fSDimitry Andric   if (Cursor.EnterSubBlock(OBJC_CONTEXT_BLOCK_ID))
9355f757f3fSDimitry Andric     return true;
9365f757f3fSDimitry Andric 
9375f757f3fSDimitry Andric   llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
9385f757f3fSDimitry Andric   if (!MaybeNext) {
9395f757f3fSDimitry Andric     // FIXME this drops the error on the floor.
9405f757f3fSDimitry Andric     consumeError(MaybeNext.takeError());
9415f757f3fSDimitry Andric     return false;
9425f757f3fSDimitry Andric   }
9435f757f3fSDimitry Andric   llvm::BitstreamEntry Next = MaybeNext.get();
9445f757f3fSDimitry Andric 
9455f757f3fSDimitry Andric   while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
9465f757f3fSDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::Error)
9475f757f3fSDimitry Andric       return true;
9485f757f3fSDimitry Andric 
9495f757f3fSDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
9505f757f3fSDimitry Andric       // Unknown sub-block, possibly for use by a future version of the
9515f757f3fSDimitry Andric       // API notes format.
9525f757f3fSDimitry Andric       if (Cursor.SkipBlock())
9535f757f3fSDimitry Andric         return true;
9545f757f3fSDimitry Andric 
9555f757f3fSDimitry Andric       MaybeNext = Cursor.advance();
9565f757f3fSDimitry Andric       if (!MaybeNext) {
9575f757f3fSDimitry Andric         // FIXME this drops the error on the floor.
9585f757f3fSDimitry Andric         consumeError(MaybeNext.takeError());
9595f757f3fSDimitry Andric         return false;
9605f757f3fSDimitry Andric       }
9615f757f3fSDimitry Andric       Next = MaybeNext.get();
9625f757f3fSDimitry Andric       continue;
9635f757f3fSDimitry Andric     }
9645f757f3fSDimitry Andric 
9655f757f3fSDimitry Andric     Scratch.clear();
9665f757f3fSDimitry Andric     llvm::StringRef BlobData;
9675f757f3fSDimitry Andric     llvm::Expected<unsigned> MaybeKind =
9685f757f3fSDimitry Andric         Cursor.readRecord(Next.ID, Scratch, &BlobData);
9695f757f3fSDimitry Andric     if (!MaybeKind) {
9705f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
9715f757f3fSDimitry Andric       consumeError(MaybeKind.takeError());
9725f757f3fSDimitry Andric       return false;
9735f757f3fSDimitry Andric     }
9745f757f3fSDimitry Andric     unsigned Kind = MaybeKind.get();
9755f757f3fSDimitry Andric     switch (Kind) {
976*0fca6ea1SDimitry Andric     case context_block::CONTEXT_ID_DATA: {
977*0fca6ea1SDimitry Andric       // Already saw Objective-C / C++ context ID table.
978*0fca6ea1SDimitry Andric       if (ContextIDTable)
9795f757f3fSDimitry Andric         return true;
9805f757f3fSDimitry Andric 
9815f757f3fSDimitry Andric       uint32_t tableOffset;
982*0fca6ea1SDimitry Andric       context_block::ContextIDLayout::readRecord(Scratch, tableOffset);
9835f757f3fSDimitry Andric       auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
9845f757f3fSDimitry Andric 
985*0fca6ea1SDimitry Andric       ContextIDTable.reset(SerializedContextIDTable::Create(
9865f757f3fSDimitry Andric           base + tableOffset, base + sizeof(uint32_t), base));
9875f757f3fSDimitry Andric       break;
9885f757f3fSDimitry Andric     }
9895f757f3fSDimitry Andric 
990*0fca6ea1SDimitry Andric     case context_block::CONTEXT_INFO_DATA: {
991*0fca6ea1SDimitry Andric       // Already saw Objective-C / C++ context info table.
992*0fca6ea1SDimitry Andric       if (ContextInfoTable)
9935f757f3fSDimitry Andric         return true;
9945f757f3fSDimitry Andric 
9955f757f3fSDimitry Andric       uint32_t tableOffset;
996*0fca6ea1SDimitry Andric       context_block::ContextInfoLayout::readRecord(Scratch, tableOffset);
9975f757f3fSDimitry Andric       auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
9985f757f3fSDimitry Andric 
999*0fca6ea1SDimitry Andric       ContextInfoTable.reset(SerializedContextInfoTable::Create(
10005f757f3fSDimitry Andric           base + tableOffset, base + sizeof(uint32_t), base));
10015f757f3fSDimitry Andric       break;
10025f757f3fSDimitry Andric     }
10035f757f3fSDimitry Andric 
10045f757f3fSDimitry Andric     default:
10055f757f3fSDimitry Andric       // Unknown record, possibly for use by a future version of the
10065f757f3fSDimitry Andric       // module format.
10075f757f3fSDimitry Andric       break;
10085f757f3fSDimitry Andric     }
10095f757f3fSDimitry Andric 
10105f757f3fSDimitry Andric     MaybeNext = Cursor.advance();
10115f757f3fSDimitry Andric     if (!MaybeNext) {
10125f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
10135f757f3fSDimitry Andric       consumeError(MaybeNext.takeError());
10145f757f3fSDimitry Andric       return false;
10155f757f3fSDimitry Andric     }
10165f757f3fSDimitry Andric     Next = MaybeNext.get();
10175f757f3fSDimitry Andric   }
10185f757f3fSDimitry Andric 
10195f757f3fSDimitry Andric   return false;
10205f757f3fSDimitry Andric }
10215f757f3fSDimitry Andric 
10225f757f3fSDimitry Andric bool APINotesReader::Implementation::readObjCPropertyBlock(
10235f757f3fSDimitry Andric     llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
10245f757f3fSDimitry Andric   if (Cursor.EnterSubBlock(OBJC_PROPERTY_BLOCK_ID))
10255f757f3fSDimitry Andric     return true;
10265f757f3fSDimitry Andric 
10275f757f3fSDimitry Andric   llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
10285f757f3fSDimitry Andric   if (!MaybeNext) {
10295f757f3fSDimitry Andric     // FIXME this drops the error on the floor.
10305f757f3fSDimitry Andric     consumeError(MaybeNext.takeError());
10315f757f3fSDimitry Andric     return false;
10325f757f3fSDimitry Andric   }
10335f757f3fSDimitry Andric   llvm::BitstreamEntry Next = MaybeNext.get();
10345f757f3fSDimitry Andric 
10355f757f3fSDimitry Andric   while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
10365f757f3fSDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::Error)
10375f757f3fSDimitry Andric       return true;
10385f757f3fSDimitry Andric 
10395f757f3fSDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
10405f757f3fSDimitry Andric       // Unknown sub-block, possibly for use by a future version of the
10415f757f3fSDimitry Andric       // API notes format.
10425f757f3fSDimitry Andric       if (Cursor.SkipBlock())
10435f757f3fSDimitry Andric         return true;
10445f757f3fSDimitry Andric 
10455f757f3fSDimitry Andric       MaybeNext = Cursor.advance();
10465f757f3fSDimitry Andric       if (!MaybeNext) {
10475f757f3fSDimitry Andric         // FIXME this drops the error on the floor.
10485f757f3fSDimitry Andric         consumeError(MaybeNext.takeError());
10495f757f3fSDimitry Andric         return false;
10505f757f3fSDimitry Andric       }
10515f757f3fSDimitry Andric       Next = MaybeNext.get();
10525f757f3fSDimitry Andric       continue;
10535f757f3fSDimitry Andric     }
10545f757f3fSDimitry Andric 
10555f757f3fSDimitry Andric     Scratch.clear();
10565f757f3fSDimitry Andric     llvm::StringRef BlobData;
10575f757f3fSDimitry Andric     llvm::Expected<unsigned> MaybeKind =
10585f757f3fSDimitry Andric         Cursor.readRecord(Next.ID, Scratch, &BlobData);
10595f757f3fSDimitry Andric     if (!MaybeKind) {
10605f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
10615f757f3fSDimitry Andric       consumeError(MaybeKind.takeError());
10625f757f3fSDimitry Andric       return false;
10635f757f3fSDimitry Andric     }
10645f757f3fSDimitry Andric     unsigned Kind = MaybeKind.get();
10655f757f3fSDimitry Andric     switch (Kind) {
10665f757f3fSDimitry Andric     case objc_property_block::OBJC_PROPERTY_DATA: {
10675f757f3fSDimitry Andric       // Already saw Objective-C property table.
10685f757f3fSDimitry Andric       if (ObjCPropertyTable)
10695f757f3fSDimitry Andric         return true;
10705f757f3fSDimitry Andric 
10715f757f3fSDimitry Andric       uint32_t tableOffset;
10725f757f3fSDimitry Andric       objc_property_block::ObjCPropertyDataLayout::readRecord(Scratch,
10735f757f3fSDimitry Andric                                                               tableOffset);
10745f757f3fSDimitry Andric       auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
10755f757f3fSDimitry Andric 
10765f757f3fSDimitry Andric       ObjCPropertyTable.reset(SerializedObjCPropertyTable::Create(
10775f757f3fSDimitry Andric           base + tableOffset, base + sizeof(uint32_t), base));
10785f757f3fSDimitry Andric       break;
10795f757f3fSDimitry Andric     }
10805f757f3fSDimitry Andric 
10815f757f3fSDimitry Andric     default:
10825f757f3fSDimitry Andric       // Unknown record, possibly for use by a future version of the
10835f757f3fSDimitry Andric       // module format.
10845f757f3fSDimitry Andric       break;
10855f757f3fSDimitry Andric     }
10865f757f3fSDimitry Andric 
10875f757f3fSDimitry Andric     MaybeNext = Cursor.advance();
10885f757f3fSDimitry Andric     if (!MaybeNext) {
10895f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
10905f757f3fSDimitry Andric       consumeError(MaybeNext.takeError());
10915f757f3fSDimitry Andric       return false;
10925f757f3fSDimitry Andric     }
10935f757f3fSDimitry Andric     Next = MaybeNext.get();
10945f757f3fSDimitry Andric   }
10955f757f3fSDimitry Andric 
10965f757f3fSDimitry Andric   return false;
10975f757f3fSDimitry Andric }
10985f757f3fSDimitry Andric 
10995f757f3fSDimitry Andric bool APINotesReader::Implementation::readObjCMethodBlock(
11005f757f3fSDimitry Andric     llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
11015f757f3fSDimitry Andric   if (Cursor.EnterSubBlock(OBJC_METHOD_BLOCK_ID))
11025f757f3fSDimitry Andric     return true;
11035f757f3fSDimitry Andric 
11045f757f3fSDimitry Andric   llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
11055f757f3fSDimitry Andric   if (!MaybeNext) {
11065f757f3fSDimitry Andric     // FIXME this drops the error on the floor.
11075f757f3fSDimitry Andric     consumeError(MaybeNext.takeError());
11085f757f3fSDimitry Andric     return false;
11095f757f3fSDimitry Andric   }
11105f757f3fSDimitry Andric   llvm::BitstreamEntry Next = MaybeNext.get();
11115f757f3fSDimitry Andric   while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
11125f757f3fSDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::Error)
11135f757f3fSDimitry Andric       return true;
11145f757f3fSDimitry Andric 
11155f757f3fSDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
11165f757f3fSDimitry Andric       // Unknown sub-block, possibly for use by a future version of the
11175f757f3fSDimitry Andric       // API notes format.
11185f757f3fSDimitry Andric       if (Cursor.SkipBlock())
11195f757f3fSDimitry Andric         return true;
11205f757f3fSDimitry Andric 
11215f757f3fSDimitry Andric       MaybeNext = Cursor.advance();
11225f757f3fSDimitry Andric       if (!MaybeNext) {
11235f757f3fSDimitry Andric         // FIXME this drops the error on the floor.
11245f757f3fSDimitry Andric         consumeError(MaybeNext.takeError());
11255f757f3fSDimitry Andric         return false;
11265f757f3fSDimitry Andric       }
11275f757f3fSDimitry Andric       Next = MaybeNext.get();
11285f757f3fSDimitry Andric       continue;
11295f757f3fSDimitry Andric     }
11305f757f3fSDimitry Andric 
11315f757f3fSDimitry Andric     Scratch.clear();
11325f757f3fSDimitry Andric     llvm::StringRef BlobData;
11335f757f3fSDimitry Andric     llvm::Expected<unsigned> MaybeKind =
11345f757f3fSDimitry Andric         Cursor.readRecord(Next.ID, Scratch, &BlobData);
11355f757f3fSDimitry Andric     if (!MaybeKind) {
11365f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
11375f757f3fSDimitry Andric       consumeError(MaybeKind.takeError());
11385f757f3fSDimitry Andric       return false;
11395f757f3fSDimitry Andric     }
11405f757f3fSDimitry Andric     unsigned Kind = MaybeKind.get();
11415f757f3fSDimitry Andric     switch (Kind) {
11425f757f3fSDimitry Andric     case objc_method_block::OBJC_METHOD_DATA: {
11435f757f3fSDimitry Andric       // Already saw Objective-C method table.
11445f757f3fSDimitry Andric       if (ObjCMethodTable)
11455f757f3fSDimitry Andric         return true;
11465f757f3fSDimitry Andric 
11475f757f3fSDimitry Andric       uint32_t tableOffset;
11485f757f3fSDimitry Andric       objc_method_block::ObjCMethodDataLayout::readRecord(Scratch, tableOffset);
11495f757f3fSDimitry Andric       auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
11505f757f3fSDimitry Andric 
11515f757f3fSDimitry Andric       ObjCMethodTable.reset(SerializedObjCMethodTable::Create(
11525f757f3fSDimitry Andric           base + tableOffset, base + sizeof(uint32_t), base));
11535f757f3fSDimitry Andric       break;
11545f757f3fSDimitry Andric     }
11555f757f3fSDimitry Andric 
11565f757f3fSDimitry Andric     default:
11575f757f3fSDimitry Andric       // Unknown record, possibly for use by a future version of the
11585f757f3fSDimitry Andric       // module format.
11595f757f3fSDimitry Andric       break;
11605f757f3fSDimitry Andric     }
11615f757f3fSDimitry Andric 
11625f757f3fSDimitry Andric     MaybeNext = Cursor.advance();
11635f757f3fSDimitry Andric     if (!MaybeNext) {
11645f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
11655f757f3fSDimitry Andric       consumeError(MaybeNext.takeError());
11665f757f3fSDimitry Andric       return false;
11675f757f3fSDimitry Andric     }
11685f757f3fSDimitry Andric     Next = MaybeNext.get();
11695f757f3fSDimitry Andric   }
11705f757f3fSDimitry Andric 
11715f757f3fSDimitry Andric   return false;
11725f757f3fSDimitry Andric }
11735f757f3fSDimitry Andric 
1174*0fca6ea1SDimitry Andric bool APINotesReader::Implementation::readCXXMethodBlock(
1175*0fca6ea1SDimitry Andric     llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1176*0fca6ea1SDimitry Andric   if (Cursor.EnterSubBlock(CXX_METHOD_BLOCK_ID))
1177*0fca6ea1SDimitry Andric     return true;
1178*0fca6ea1SDimitry Andric 
1179*0fca6ea1SDimitry Andric   llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1180*0fca6ea1SDimitry Andric   if (!MaybeNext) {
1181*0fca6ea1SDimitry Andric     // FIXME this drops the error on the floor.
1182*0fca6ea1SDimitry Andric     consumeError(MaybeNext.takeError());
1183*0fca6ea1SDimitry Andric     return false;
1184*0fca6ea1SDimitry Andric   }
1185*0fca6ea1SDimitry Andric   llvm::BitstreamEntry Next = MaybeNext.get();
1186*0fca6ea1SDimitry Andric   while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1187*0fca6ea1SDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::Error)
1188*0fca6ea1SDimitry Andric       return true;
1189*0fca6ea1SDimitry Andric 
1190*0fca6ea1SDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1191*0fca6ea1SDimitry Andric       // Unknown sub-block, possibly for use by a future version of the
1192*0fca6ea1SDimitry Andric       // API notes format.
1193*0fca6ea1SDimitry Andric       if (Cursor.SkipBlock())
1194*0fca6ea1SDimitry Andric         return true;
1195*0fca6ea1SDimitry Andric 
1196*0fca6ea1SDimitry Andric       MaybeNext = Cursor.advance();
1197*0fca6ea1SDimitry Andric       if (!MaybeNext) {
1198*0fca6ea1SDimitry Andric         // FIXME this drops the error on the floor.
1199*0fca6ea1SDimitry Andric         consumeError(MaybeNext.takeError());
1200*0fca6ea1SDimitry Andric         return false;
1201*0fca6ea1SDimitry Andric       }
1202*0fca6ea1SDimitry Andric       Next = MaybeNext.get();
1203*0fca6ea1SDimitry Andric       continue;
1204*0fca6ea1SDimitry Andric     }
1205*0fca6ea1SDimitry Andric 
1206*0fca6ea1SDimitry Andric     Scratch.clear();
1207*0fca6ea1SDimitry Andric     llvm::StringRef BlobData;
1208*0fca6ea1SDimitry Andric     llvm::Expected<unsigned> MaybeKind =
1209*0fca6ea1SDimitry Andric         Cursor.readRecord(Next.ID, Scratch, &BlobData);
1210*0fca6ea1SDimitry Andric     if (!MaybeKind) {
1211*0fca6ea1SDimitry Andric       // FIXME this drops the error on the floor.
1212*0fca6ea1SDimitry Andric       consumeError(MaybeKind.takeError());
1213*0fca6ea1SDimitry Andric       return false;
1214*0fca6ea1SDimitry Andric     }
1215*0fca6ea1SDimitry Andric     unsigned Kind = MaybeKind.get();
1216*0fca6ea1SDimitry Andric     switch (Kind) {
1217*0fca6ea1SDimitry Andric     case cxx_method_block::CXX_METHOD_DATA: {
1218*0fca6ea1SDimitry Andric       // Already saw C++ method table.
1219*0fca6ea1SDimitry Andric       if (CXXMethodTable)
1220*0fca6ea1SDimitry Andric         return true;
1221*0fca6ea1SDimitry Andric 
1222*0fca6ea1SDimitry Andric       uint32_t tableOffset;
1223*0fca6ea1SDimitry Andric       cxx_method_block::CXXMethodDataLayout::readRecord(Scratch, tableOffset);
1224*0fca6ea1SDimitry Andric       auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1225*0fca6ea1SDimitry Andric 
1226*0fca6ea1SDimitry Andric       CXXMethodTable.reset(SerializedCXXMethodTable::Create(
1227*0fca6ea1SDimitry Andric           base + tableOffset, base + sizeof(uint32_t), base));
1228*0fca6ea1SDimitry Andric       break;
1229*0fca6ea1SDimitry Andric     }
1230*0fca6ea1SDimitry Andric 
1231*0fca6ea1SDimitry Andric     default:
1232*0fca6ea1SDimitry Andric       // Unknown record, possibly for use by a future version of the
1233*0fca6ea1SDimitry Andric       // module format.
1234*0fca6ea1SDimitry Andric       break;
1235*0fca6ea1SDimitry Andric     }
1236*0fca6ea1SDimitry Andric 
1237*0fca6ea1SDimitry Andric     MaybeNext = Cursor.advance();
1238*0fca6ea1SDimitry Andric     if (!MaybeNext) {
1239*0fca6ea1SDimitry Andric       // FIXME this drops the error on the floor.
1240*0fca6ea1SDimitry Andric       consumeError(MaybeNext.takeError());
1241*0fca6ea1SDimitry Andric       return false;
1242*0fca6ea1SDimitry Andric     }
1243*0fca6ea1SDimitry Andric     Next = MaybeNext.get();
1244*0fca6ea1SDimitry Andric   }
1245*0fca6ea1SDimitry Andric 
1246*0fca6ea1SDimitry Andric   return false;
1247*0fca6ea1SDimitry Andric }
1248*0fca6ea1SDimitry Andric 
12495f757f3fSDimitry Andric bool APINotesReader::Implementation::readObjCSelectorBlock(
12505f757f3fSDimitry Andric     llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
12515f757f3fSDimitry Andric   if (Cursor.EnterSubBlock(OBJC_SELECTOR_BLOCK_ID))
12525f757f3fSDimitry Andric     return true;
12535f757f3fSDimitry Andric 
12545f757f3fSDimitry Andric   llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
12555f757f3fSDimitry Andric   if (!MaybeNext) {
12565f757f3fSDimitry Andric     // FIXME this drops the error on the floor.
12575f757f3fSDimitry Andric     consumeError(MaybeNext.takeError());
12585f757f3fSDimitry Andric     return false;
12595f757f3fSDimitry Andric   }
12605f757f3fSDimitry Andric   llvm::BitstreamEntry Next = MaybeNext.get();
12615f757f3fSDimitry Andric   while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
12625f757f3fSDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::Error)
12635f757f3fSDimitry Andric       return true;
12645f757f3fSDimitry Andric 
12655f757f3fSDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
12665f757f3fSDimitry Andric       // Unknown sub-block, possibly for use by a future version of the
12675f757f3fSDimitry Andric       // API notes format.
12685f757f3fSDimitry Andric       if (Cursor.SkipBlock())
12695f757f3fSDimitry Andric         return true;
12705f757f3fSDimitry Andric 
12715f757f3fSDimitry Andric       MaybeNext = Cursor.advance();
12725f757f3fSDimitry Andric       if (!MaybeNext) {
12735f757f3fSDimitry Andric         // FIXME this drops the error on the floor.
12745f757f3fSDimitry Andric         consumeError(MaybeNext.takeError());
12755f757f3fSDimitry Andric         return false;
12765f757f3fSDimitry Andric       }
12775f757f3fSDimitry Andric       Next = MaybeNext.get();
12785f757f3fSDimitry Andric       continue;
12795f757f3fSDimitry Andric     }
12805f757f3fSDimitry Andric 
12815f757f3fSDimitry Andric     Scratch.clear();
12825f757f3fSDimitry Andric     llvm::StringRef BlobData;
12835f757f3fSDimitry Andric     llvm::Expected<unsigned> MaybeKind =
12845f757f3fSDimitry Andric         Cursor.readRecord(Next.ID, Scratch, &BlobData);
12855f757f3fSDimitry Andric     if (!MaybeKind) {
12865f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
12875f757f3fSDimitry Andric       consumeError(MaybeKind.takeError());
12885f757f3fSDimitry Andric       return false;
12895f757f3fSDimitry Andric     }
12905f757f3fSDimitry Andric     unsigned Kind = MaybeKind.get();
12915f757f3fSDimitry Andric     switch (Kind) {
12925f757f3fSDimitry Andric     case objc_selector_block::OBJC_SELECTOR_DATA: {
12935f757f3fSDimitry Andric       // Already saw Objective-C selector table.
12945f757f3fSDimitry Andric       if (ObjCSelectorTable)
12955f757f3fSDimitry Andric         return true;
12965f757f3fSDimitry Andric 
12975f757f3fSDimitry Andric       uint32_t tableOffset;
12985f757f3fSDimitry Andric       objc_selector_block::ObjCSelectorDataLayout::readRecord(Scratch,
12995f757f3fSDimitry Andric                                                               tableOffset);
13005f757f3fSDimitry Andric       auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
13015f757f3fSDimitry Andric 
13025f757f3fSDimitry Andric       ObjCSelectorTable.reset(SerializedObjCSelectorTable::Create(
13035f757f3fSDimitry Andric           base + tableOffset, base + sizeof(uint32_t), base));
13045f757f3fSDimitry Andric       break;
13055f757f3fSDimitry Andric     }
13065f757f3fSDimitry Andric 
13075f757f3fSDimitry Andric     default:
13085f757f3fSDimitry Andric       // Unknown record, possibly for use by a future version of the
13095f757f3fSDimitry Andric       // module format.
13105f757f3fSDimitry Andric       break;
13115f757f3fSDimitry Andric     }
13125f757f3fSDimitry Andric 
13135f757f3fSDimitry Andric     MaybeNext = Cursor.advance();
13145f757f3fSDimitry Andric     if (!MaybeNext) {
13155f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
13165f757f3fSDimitry Andric       consumeError(MaybeNext.takeError());
13175f757f3fSDimitry Andric       return false;
13185f757f3fSDimitry Andric     }
13195f757f3fSDimitry Andric     Next = MaybeNext.get();
13205f757f3fSDimitry Andric   }
13215f757f3fSDimitry Andric 
13225f757f3fSDimitry Andric   return false;
13235f757f3fSDimitry Andric }
13245f757f3fSDimitry Andric 
13255f757f3fSDimitry Andric bool APINotesReader::Implementation::readGlobalVariableBlock(
13265f757f3fSDimitry Andric     llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
13275f757f3fSDimitry Andric   if (Cursor.EnterSubBlock(GLOBAL_VARIABLE_BLOCK_ID))
13285f757f3fSDimitry Andric     return true;
13295f757f3fSDimitry Andric 
13305f757f3fSDimitry Andric   llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
13315f757f3fSDimitry Andric   if (!MaybeNext) {
13325f757f3fSDimitry Andric     // FIXME this drops the error on the floor.
13335f757f3fSDimitry Andric     consumeError(MaybeNext.takeError());
13345f757f3fSDimitry Andric     return false;
13355f757f3fSDimitry Andric   }
13365f757f3fSDimitry Andric   llvm::BitstreamEntry Next = MaybeNext.get();
13375f757f3fSDimitry Andric   while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
13385f757f3fSDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::Error)
13395f757f3fSDimitry Andric       return true;
13405f757f3fSDimitry Andric 
13415f757f3fSDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
13425f757f3fSDimitry Andric       // Unknown sub-block, possibly for use by a future version of the
13435f757f3fSDimitry Andric       // API notes format.
13445f757f3fSDimitry Andric       if (Cursor.SkipBlock())
13455f757f3fSDimitry Andric         return true;
13465f757f3fSDimitry Andric 
13475f757f3fSDimitry Andric       MaybeNext = Cursor.advance();
13485f757f3fSDimitry Andric       if (!MaybeNext) {
13495f757f3fSDimitry Andric         // FIXME this drops the error on the floor.
13505f757f3fSDimitry Andric         consumeError(MaybeNext.takeError());
13515f757f3fSDimitry Andric         return false;
13525f757f3fSDimitry Andric       }
13535f757f3fSDimitry Andric       Next = MaybeNext.get();
13545f757f3fSDimitry Andric       continue;
13555f757f3fSDimitry Andric     }
13565f757f3fSDimitry Andric 
13575f757f3fSDimitry Andric     Scratch.clear();
13585f757f3fSDimitry Andric     llvm::StringRef BlobData;
13595f757f3fSDimitry Andric     llvm::Expected<unsigned> MaybeKind =
13605f757f3fSDimitry Andric         Cursor.readRecord(Next.ID, Scratch, &BlobData);
13615f757f3fSDimitry Andric     if (!MaybeKind) {
13625f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
13635f757f3fSDimitry Andric       consumeError(MaybeKind.takeError());
13645f757f3fSDimitry Andric       return false;
13655f757f3fSDimitry Andric     }
13665f757f3fSDimitry Andric     unsigned Kind = MaybeKind.get();
13675f757f3fSDimitry Andric     switch (Kind) {
13685f757f3fSDimitry Andric     case global_variable_block::GLOBAL_VARIABLE_DATA: {
13695f757f3fSDimitry Andric       // Already saw global variable table.
13705f757f3fSDimitry Andric       if (GlobalVariableTable)
13715f757f3fSDimitry Andric         return true;
13725f757f3fSDimitry Andric 
13735f757f3fSDimitry Andric       uint32_t tableOffset;
13745f757f3fSDimitry Andric       global_variable_block::GlobalVariableDataLayout::readRecord(Scratch,
13755f757f3fSDimitry Andric                                                                   tableOffset);
13765f757f3fSDimitry Andric       auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
13775f757f3fSDimitry Andric 
13785f757f3fSDimitry Andric       GlobalVariableTable.reset(SerializedGlobalVariableTable::Create(
13795f757f3fSDimitry Andric           base + tableOffset, base + sizeof(uint32_t), base));
13805f757f3fSDimitry Andric       break;
13815f757f3fSDimitry Andric     }
13825f757f3fSDimitry Andric 
13835f757f3fSDimitry Andric     default:
13845f757f3fSDimitry Andric       // Unknown record, possibly for use by a future version of the
13855f757f3fSDimitry Andric       // module format.
13865f757f3fSDimitry Andric       break;
13875f757f3fSDimitry Andric     }
13885f757f3fSDimitry Andric 
13895f757f3fSDimitry Andric     MaybeNext = Cursor.advance();
13905f757f3fSDimitry Andric     if (!MaybeNext) {
13915f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
13925f757f3fSDimitry Andric       consumeError(MaybeNext.takeError());
13935f757f3fSDimitry Andric       return false;
13945f757f3fSDimitry Andric     }
13955f757f3fSDimitry Andric     Next = MaybeNext.get();
13965f757f3fSDimitry Andric   }
13975f757f3fSDimitry Andric 
13985f757f3fSDimitry Andric   return false;
13995f757f3fSDimitry Andric }
14005f757f3fSDimitry Andric 
14015f757f3fSDimitry Andric bool APINotesReader::Implementation::readGlobalFunctionBlock(
14025f757f3fSDimitry Andric     llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
14035f757f3fSDimitry Andric   if (Cursor.EnterSubBlock(GLOBAL_FUNCTION_BLOCK_ID))
14045f757f3fSDimitry Andric     return true;
14055f757f3fSDimitry Andric 
14065f757f3fSDimitry Andric   llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
14075f757f3fSDimitry Andric   if (!MaybeNext) {
14085f757f3fSDimitry Andric     // FIXME this drops the error on the floor.
14095f757f3fSDimitry Andric     consumeError(MaybeNext.takeError());
14105f757f3fSDimitry Andric     return false;
14115f757f3fSDimitry Andric   }
14125f757f3fSDimitry Andric   llvm::BitstreamEntry Next = MaybeNext.get();
14135f757f3fSDimitry Andric   while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
14145f757f3fSDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::Error)
14155f757f3fSDimitry Andric       return true;
14165f757f3fSDimitry Andric 
14175f757f3fSDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
14185f757f3fSDimitry Andric       // Unknown sub-block, possibly for use by a future version of the
14195f757f3fSDimitry Andric       // API notes format.
14205f757f3fSDimitry Andric       if (Cursor.SkipBlock())
14215f757f3fSDimitry Andric         return true;
14225f757f3fSDimitry Andric 
14235f757f3fSDimitry Andric       MaybeNext = Cursor.advance();
14245f757f3fSDimitry Andric       if (!MaybeNext) {
14255f757f3fSDimitry Andric         // FIXME this drops the error on the floor.
14265f757f3fSDimitry Andric         consumeError(MaybeNext.takeError());
14275f757f3fSDimitry Andric         return false;
14285f757f3fSDimitry Andric       }
14295f757f3fSDimitry Andric       Next = MaybeNext.get();
14305f757f3fSDimitry Andric       continue;
14315f757f3fSDimitry Andric     }
14325f757f3fSDimitry Andric 
14335f757f3fSDimitry Andric     Scratch.clear();
14345f757f3fSDimitry Andric     llvm::StringRef BlobData;
14355f757f3fSDimitry Andric     llvm::Expected<unsigned> MaybeKind =
14365f757f3fSDimitry Andric         Cursor.readRecord(Next.ID, Scratch, &BlobData);
14375f757f3fSDimitry Andric     if (!MaybeKind) {
14385f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
14395f757f3fSDimitry Andric       consumeError(MaybeKind.takeError());
14405f757f3fSDimitry Andric       return false;
14415f757f3fSDimitry Andric     }
14425f757f3fSDimitry Andric     unsigned Kind = MaybeKind.get();
14435f757f3fSDimitry Andric     switch (Kind) {
14445f757f3fSDimitry Andric     case global_function_block::GLOBAL_FUNCTION_DATA: {
14455f757f3fSDimitry Andric       // Already saw global function table.
14465f757f3fSDimitry Andric       if (GlobalFunctionTable)
14475f757f3fSDimitry Andric         return true;
14485f757f3fSDimitry Andric 
14495f757f3fSDimitry Andric       uint32_t tableOffset;
14505f757f3fSDimitry Andric       global_function_block::GlobalFunctionDataLayout::readRecord(Scratch,
14515f757f3fSDimitry Andric                                                                   tableOffset);
14525f757f3fSDimitry Andric       auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
14535f757f3fSDimitry Andric 
14545f757f3fSDimitry Andric       GlobalFunctionTable.reset(SerializedGlobalFunctionTable::Create(
14555f757f3fSDimitry Andric           base + tableOffset, base + sizeof(uint32_t), base));
14565f757f3fSDimitry Andric       break;
14575f757f3fSDimitry Andric     }
14585f757f3fSDimitry Andric 
14595f757f3fSDimitry Andric     default:
14605f757f3fSDimitry Andric       // Unknown record, possibly for use by a future version of the
14615f757f3fSDimitry Andric       // module format.
14625f757f3fSDimitry Andric       break;
14635f757f3fSDimitry Andric     }
14645f757f3fSDimitry Andric 
14655f757f3fSDimitry Andric     MaybeNext = Cursor.advance();
14665f757f3fSDimitry Andric     if (!MaybeNext) {
14675f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
14685f757f3fSDimitry Andric       consumeError(MaybeNext.takeError());
14695f757f3fSDimitry Andric       return false;
14705f757f3fSDimitry Andric     }
14715f757f3fSDimitry Andric     Next = MaybeNext.get();
14725f757f3fSDimitry Andric   }
14735f757f3fSDimitry Andric 
14745f757f3fSDimitry Andric   return false;
14755f757f3fSDimitry Andric }
14765f757f3fSDimitry Andric 
14775f757f3fSDimitry Andric bool APINotesReader::Implementation::readEnumConstantBlock(
14785f757f3fSDimitry Andric     llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
14795f757f3fSDimitry Andric   if (Cursor.EnterSubBlock(ENUM_CONSTANT_BLOCK_ID))
14805f757f3fSDimitry Andric     return true;
14815f757f3fSDimitry Andric 
14825f757f3fSDimitry Andric   llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
14835f757f3fSDimitry Andric   if (!MaybeNext) {
14845f757f3fSDimitry Andric     // FIXME this drops the error on the floor.
14855f757f3fSDimitry Andric     consumeError(MaybeNext.takeError());
14865f757f3fSDimitry Andric     return false;
14875f757f3fSDimitry Andric   }
14885f757f3fSDimitry Andric   llvm::BitstreamEntry Next = MaybeNext.get();
14895f757f3fSDimitry Andric   while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
14905f757f3fSDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::Error)
14915f757f3fSDimitry Andric       return true;
14925f757f3fSDimitry Andric 
14935f757f3fSDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
14945f757f3fSDimitry Andric       // Unknown sub-block, possibly for use by a future version of the
14955f757f3fSDimitry Andric       // API notes format.
14965f757f3fSDimitry Andric       if (Cursor.SkipBlock())
14975f757f3fSDimitry Andric         return true;
14985f757f3fSDimitry Andric 
14995f757f3fSDimitry Andric       MaybeNext = Cursor.advance();
15005f757f3fSDimitry Andric       if (!MaybeNext) {
15015f757f3fSDimitry Andric         // FIXME this drops the error on the floor.
15025f757f3fSDimitry Andric         consumeError(MaybeNext.takeError());
15035f757f3fSDimitry Andric         return false;
15045f757f3fSDimitry Andric       }
15055f757f3fSDimitry Andric       Next = MaybeNext.get();
15065f757f3fSDimitry Andric       continue;
15075f757f3fSDimitry Andric     }
15085f757f3fSDimitry Andric 
15095f757f3fSDimitry Andric     Scratch.clear();
15105f757f3fSDimitry Andric     llvm::StringRef BlobData;
15115f757f3fSDimitry Andric     llvm::Expected<unsigned> MaybeKind =
15125f757f3fSDimitry Andric         Cursor.readRecord(Next.ID, Scratch, &BlobData);
15135f757f3fSDimitry Andric     if (!MaybeKind) {
15145f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
15155f757f3fSDimitry Andric       consumeError(MaybeKind.takeError());
15165f757f3fSDimitry Andric       return false;
15175f757f3fSDimitry Andric     }
15185f757f3fSDimitry Andric     unsigned Kind = MaybeKind.get();
15195f757f3fSDimitry Andric     switch (Kind) {
15205f757f3fSDimitry Andric     case enum_constant_block::ENUM_CONSTANT_DATA: {
15215f757f3fSDimitry Andric       // Already saw enumerator table.
15225f757f3fSDimitry Andric       if (EnumConstantTable)
15235f757f3fSDimitry Andric         return true;
15245f757f3fSDimitry Andric 
15255f757f3fSDimitry Andric       uint32_t tableOffset;
15265f757f3fSDimitry Andric       enum_constant_block::EnumConstantDataLayout::readRecord(Scratch,
15275f757f3fSDimitry Andric                                                               tableOffset);
15285f757f3fSDimitry Andric       auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
15295f757f3fSDimitry Andric 
15305f757f3fSDimitry Andric       EnumConstantTable.reset(SerializedEnumConstantTable::Create(
15315f757f3fSDimitry Andric           base + tableOffset, base + sizeof(uint32_t), base));
15325f757f3fSDimitry Andric       break;
15335f757f3fSDimitry Andric     }
15345f757f3fSDimitry Andric 
15355f757f3fSDimitry Andric     default:
15365f757f3fSDimitry Andric       // Unknown record, possibly for use by a future version of the
15375f757f3fSDimitry Andric       // module format.
15385f757f3fSDimitry Andric       break;
15395f757f3fSDimitry Andric     }
15405f757f3fSDimitry Andric 
15415f757f3fSDimitry Andric     MaybeNext = Cursor.advance();
15425f757f3fSDimitry Andric     if (!MaybeNext) {
15435f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
15445f757f3fSDimitry Andric       consumeError(MaybeNext.takeError());
15455f757f3fSDimitry Andric       return false;
15465f757f3fSDimitry Andric     }
15475f757f3fSDimitry Andric     Next = MaybeNext.get();
15485f757f3fSDimitry Andric   }
15495f757f3fSDimitry Andric 
15505f757f3fSDimitry Andric   return false;
15515f757f3fSDimitry Andric }
15525f757f3fSDimitry Andric 
15535f757f3fSDimitry Andric bool APINotesReader::Implementation::readTagBlock(
15545f757f3fSDimitry Andric     llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
15555f757f3fSDimitry Andric   if (Cursor.EnterSubBlock(TAG_BLOCK_ID))
15565f757f3fSDimitry Andric     return true;
15575f757f3fSDimitry Andric 
15585f757f3fSDimitry Andric   llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
15595f757f3fSDimitry Andric   if (!MaybeNext) {
15605f757f3fSDimitry Andric     // FIXME this drops the error on the floor.
15615f757f3fSDimitry Andric     consumeError(MaybeNext.takeError());
15625f757f3fSDimitry Andric     return false;
15635f757f3fSDimitry Andric   }
15645f757f3fSDimitry Andric   llvm::BitstreamEntry Next = MaybeNext.get();
15655f757f3fSDimitry Andric   while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
15665f757f3fSDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::Error)
15675f757f3fSDimitry Andric       return true;
15685f757f3fSDimitry Andric 
15695f757f3fSDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
15705f757f3fSDimitry Andric       // Unknown sub-block, possibly for use by a future version of the
15715f757f3fSDimitry Andric       // API notes format.
15725f757f3fSDimitry Andric       if (Cursor.SkipBlock())
15735f757f3fSDimitry Andric         return true;
15745f757f3fSDimitry Andric 
15755f757f3fSDimitry Andric       MaybeNext = Cursor.advance();
15765f757f3fSDimitry Andric       if (!MaybeNext) {
15775f757f3fSDimitry Andric         // FIXME this drops the error on the floor.
15785f757f3fSDimitry Andric         consumeError(MaybeNext.takeError());
15795f757f3fSDimitry Andric         return false;
15805f757f3fSDimitry Andric       }
15815f757f3fSDimitry Andric       Next = MaybeNext.get();
15825f757f3fSDimitry Andric       continue;
15835f757f3fSDimitry Andric     }
15845f757f3fSDimitry Andric 
15855f757f3fSDimitry Andric     Scratch.clear();
15865f757f3fSDimitry Andric     llvm::StringRef BlobData;
15875f757f3fSDimitry Andric     llvm::Expected<unsigned> MaybeKind =
15885f757f3fSDimitry Andric         Cursor.readRecord(Next.ID, Scratch, &BlobData);
15895f757f3fSDimitry Andric     if (!MaybeKind) {
15905f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
15915f757f3fSDimitry Andric       consumeError(MaybeKind.takeError());
15925f757f3fSDimitry Andric       return false;
15935f757f3fSDimitry Andric     }
15945f757f3fSDimitry Andric     unsigned Kind = MaybeKind.get();
15955f757f3fSDimitry Andric     switch (Kind) {
15965f757f3fSDimitry Andric     case tag_block::TAG_DATA: {
15975f757f3fSDimitry Andric       // Already saw tag table.
15985f757f3fSDimitry Andric       if (TagTable)
15995f757f3fSDimitry Andric         return true;
16005f757f3fSDimitry Andric 
16015f757f3fSDimitry Andric       uint32_t tableOffset;
16025f757f3fSDimitry Andric       tag_block::TagDataLayout::readRecord(Scratch, tableOffset);
16035f757f3fSDimitry Andric       auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
16045f757f3fSDimitry Andric 
16055f757f3fSDimitry Andric       TagTable.reset(SerializedTagTable::Create(base + tableOffset,
16065f757f3fSDimitry Andric                                                 base + sizeof(uint32_t), base));
16075f757f3fSDimitry Andric       break;
16085f757f3fSDimitry Andric     }
16095f757f3fSDimitry Andric 
16105f757f3fSDimitry Andric     default:
16115f757f3fSDimitry Andric       // Unknown record, possibly for use by a future version of the
16125f757f3fSDimitry Andric       // module format.
16135f757f3fSDimitry Andric       break;
16145f757f3fSDimitry Andric     }
16155f757f3fSDimitry Andric 
16165f757f3fSDimitry Andric     MaybeNext = Cursor.advance();
16175f757f3fSDimitry Andric     if (!MaybeNext) {
16185f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
16195f757f3fSDimitry Andric       consumeError(MaybeNext.takeError());
16205f757f3fSDimitry Andric       return false;
16215f757f3fSDimitry Andric     }
16225f757f3fSDimitry Andric     Next = MaybeNext.get();
16235f757f3fSDimitry Andric   }
16245f757f3fSDimitry Andric 
16255f757f3fSDimitry Andric   return false;
16265f757f3fSDimitry Andric }
16275f757f3fSDimitry Andric 
16285f757f3fSDimitry Andric bool APINotesReader::Implementation::readTypedefBlock(
16295f757f3fSDimitry Andric     llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
16305f757f3fSDimitry Andric   if (Cursor.EnterSubBlock(TYPEDEF_BLOCK_ID))
16315f757f3fSDimitry Andric     return true;
16325f757f3fSDimitry Andric 
16335f757f3fSDimitry Andric   llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
16345f757f3fSDimitry Andric   if (!MaybeNext) {
16355f757f3fSDimitry Andric     // FIXME this drops the error on the floor.
16365f757f3fSDimitry Andric     consumeError(MaybeNext.takeError());
16375f757f3fSDimitry Andric     return false;
16385f757f3fSDimitry Andric   }
16395f757f3fSDimitry Andric   llvm::BitstreamEntry Next = MaybeNext.get();
16405f757f3fSDimitry Andric   while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
16415f757f3fSDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::Error)
16425f757f3fSDimitry Andric       return true;
16435f757f3fSDimitry Andric 
16445f757f3fSDimitry Andric     if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
16455f757f3fSDimitry Andric       // Unknown sub-block, possibly for use by a future version of the
16465f757f3fSDimitry Andric       // API notes format.
16475f757f3fSDimitry Andric       if (Cursor.SkipBlock())
16485f757f3fSDimitry Andric         return true;
16495f757f3fSDimitry Andric 
16505f757f3fSDimitry Andric       MaybeNext = Cursor.advance();
16515f757f3fSDimitry Andric       if (!MaybeNext) {
16525f757f3fSDimitry Andric         // FIXME this drops the error on the floor.
16535f757f3fSDimitry Andric         consumeError(MaybeNext.takeError());
16545f757f3fSDimitry Andric         return false;
16555f757f3fSDimitry Andric       }
16565f757f3fSDimitry Andric       Next = MaybeNext.get();
16575f757f3fSDimitry Andric       continue;
16585f757f3fSDimitry Andric     }
16595f757f3fSDimitry Andric 
16605f757f3fSDimitry Andric     Scratch.clear();
16615f757f3fSDimitry Andric     llvm::StringRef BlobData;
16625f757f3fSDimitry Andric     llvm::Expected<unsigned> MaybeKind =
16635f757f3fSDimitry Andric         Cursor.readRecord(Next.ID, Scratch, &BlobData);
16645f757f3fSDimitry Andric     if (!MaybeKind) {
16655f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
16665f757f3fSDimitry Andric       consumeError(MaybeKind.takeError());
16675f757f3fSDimitry Andric       return false;
16685f757f3fSDimitry Andric     }
16695f757f3fSDimitry Andric     unsigned Kind = MaybeKind.get();
16705f757f3fSDimitry Andric     switch (Kind) {
16715f757f3fSDimitry Andric     case typedef_block::TYPEDEF_DATA: {
16725f757f3fSDimitry Andric       // Already saw typedef table.
16735f757f3fSDimitry Andric       if (TypedefTable)
16745f757f3fSDimitry Andric         return true;
16755f757f3fSDimitry Andric 
16765f757f3fSDimitry Andric       uint32_t tableOffset;
16775f757f3fSDimitry Andric       typedef_block::TypedefDataLayout::readRecord(Scratch, tableOffset);
16785f757f3fSDimitry Andric       auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
16795f757f3fSDimitry Andric 
16805f757f3fSDimitry Andric       TypedefTable.reset(SerializedTypedefTable::Create(
16815f757f3fSDimitry Andric           base + tableOffset, base + sizeof(uint32_t), base));
16825f757f3fSDimitry Andric       break;
16835f757f3fSDimitry Andric     }
16845f757f3fSDimitry Andric 
16855f757f3fSDimitry Andric     default:
16865f757f3fSDimitry Andric       // Unknown record, possibly for use by a future version of the
16875f757f3fSDimitry Andric       // module format.
16885f757f3fSDimitry Andric       break;
16895f757f3fSDimitry Andric     }
16905f757f3fSDimitry Andric 
16915f757f3fSDimitry Andric     MaybeNext = Cursor.advance();
16925f757f3fSDimitry Andric     if (!MaybeNext) {
16935f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
16945f757f3fSDimitry Andric       consumeError(MaybeNext.takeError());
16955f757f3fSDimitry Andric       return false;
16965f757f3fSDimitry Andric     }
16975f757f3fSDimitry Andric     Next = MaybeNext.get();
16985f757f3fSDimitry Andric   }
16995f757f3fSDimitry Andric 
17005f757f3fSDimitry Andric   return false;
17015f757f3fSDimitry Andric }
17025f757f3fSDimitry Andric 
17035f757f3fSDimitry Andric APINotesReader::APINotesReader(llvm::MemoryBuffer *InputBuffer,
17045f757f3fSDimitry Andric                                llvm::VersionTuple SwiftVersion, bool &Failed)
17055f757f3fSDimitry Andric     : Implementation(new class Implementation) {
17065f757f3fSDimitry Andric   Failed = false;
17075f757f3fSDimitry Andric 
17085f757f3fSDimitry Andric   // Initialize the input buffer.
17095f757f3fSDimitry Andric   Implementation->InputBuffer = InputBuffer;
17105f757f3fSDimitry Andric   Implementation->SwiftVersion = SwiftVersion;
17115f757f3fSDimitry Andric   llvm::BitstreamCursor Cursor(*Implementation->InputBuffer);
17125f757f3fSDimitry Andric 
17135f757f3fSDimitry Andric   // Validate signature.
17145f757f3fSDimitry Andric   for (auto byte : API_NOTES_SIGNATURE) {
17155f757f3fSDimitry Andric     if (Cursor.AtEndOfStream()) {
17165f757f3fSDimitry Andric       Failed = true;
17175f757f3fSDimitry Andric       return;
17185f757f3fSDimitry Andric     }
17195f757f3fSDimitry Andric     if (llvm::Expected<llvm::SimpleBitstreamCursor::word_t> maybeRead =
17205f757f3fSDimitry Andric             Cursor.Read(8)) {
17215f757f3fSDimitry Andric       if (maybeRead.get() != byte) {
17225f757f3fSDimitry Andric         Failed = true;
17235f757f3fSDimitry Andric         return;
17245f757f3fSDimitry Andric       }
17255f757f3fSDimitry Andric     } else {
17265f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
17275f757f3fSDimitry Andric       consumeError(maybeRead.takeError());
17285f757f3fSDimitry Andric       Failed = true;
17295f757f3fSDimitry Andric       return;
17305f757f3fSDimitry Andric     }
17315f757f3fSDimitry Andric   }
17325f757f3fSDimitry Andric 
17335f757f3fSDimitry Andric   // Look at all of the blocks.
17345f757f3fSDimitry Andric   bool HasValidControlBlock = false;
17355f757f3fSDimitry Andric   llvm::SmallVector<uint64_t, 64> Scratch;
17365f757f3fSDimitry Andric   while (!Cursor.AtEndOfStream()) {
17375f757f3fSDimitry Andric     llvm::Expected<llvm::BitstreamEntry> MaybeTopLevelEntry = Cursor.advance();
17385f757f3fSDimitry Andric     if (!MaybeTopLevelEntry) {
17395f757f3fSDimitry Andric       // FIXME this drops the error on the floor.
17405f757f3fSDimitry Andric       consumeError(MaybeTopLevelEntry.takeError());
17415f757f3fSDimitry Andric       Failed = true;
17425f757f3fSDimitry Andric       return;
17435f757f3fSDimitry Andric     }
17445f757f3fSDimitry Andric     llvm::BitstreamEntry TopLevelEntry = MaybeTopLevelEntry.get();
17455f757f3fSDimitry Andric 
17465f757f3fSDimitry Andric     if (TopLevelEntry.Kind != llvm::BitstreamEntry::SubBlock)
17475f757f3fSDimitry Andric       break;
17485f757f3fSDimitry Andric 
17495f757f3fSDimitry Andric     switch (TopLevelEntry.ID) {
17505f757f3fSDimitry Andric     case llvm::bitc::BLOCKINFO_BLOCK_ID:
17515f757f3fSDimitry Andric       if (!Cursor.ReadBlockInfoBlock()) {
17525f757f3fSDimitry Andric         Failed = true;
17535f757f3fSDimitry Andric         break;
17545f757f3fSDimitry Andric       }
17555f757f3fSDimitry Andric       break;
17565f757f3fSDimitry Andric 
17575f757f3fSDimitry Andric     case CONTROL_BLOCK_ID:
17585f757f3fSDimitry Andric       // Only allow a single control block.
17595f757f3fSDimitry Andric       if (HasValidControlBlock ||
17605f757f3fSDimitry Andric           Implementation->readControlBlock(Cursor, Scratch)) {
17615f757f3fSDimitry Andric         Failed = true;
17625f757f3fSDimitry Andric         return;
17635f757f3fSDimitry Andric       }
17645f757f3fSDimitry Andric 
17655f757f3fSDimitry Andric       HasValidControlBlock = true;
17665f757f3fSDimitry Andric       break;
17675f757f3fSDimitry Andric 
17685f757f3fSDimitry Andric     case IDENTIFIER_BLOCK_ID:
17695f757f3fSDimitry Andric       if (!HasValidControlBlock ||
17705f757f3fSDimitry Andric           Implementation->readIdentifierBlock(Cursor, Scratch)) {
17715f757f3fSDimitry Andric         Failed = true;
17725f757f3fSDimitry Andric         return;
17735f757f3fSDimitry Andric       }
17745f757f3fSDimitry Andric       break;
17755f757f3fSDimitry Andric 
17765f757f3fSDimitry Andric     case OBJC_CONTEXT_BLOCK_ID:
17775f757f3fSDimitry Andric       if (!HasValidControlBlock ||
1778*0fca6ea1SDimitry Andric           Implementation->readContextBlock(Cursor, Scratch)) {
17795f757f3fSDimitry Andric         Failed = true;
17805f757f3fSDimitry Andric         return;
17815f757f3fSDimitry Andric       }
17825f757f3fSDimitry Andric 
17835f757f3fSDimitry Andric       break;
17845f757f3fSDimitry Andric 
17855f757f3fSDimitry Andric     case OBJC_PROPERTY_BLOCK_ID:
17865f757f3fSDimitry Andric       if (!HasValidControlBlock ||
17875f757f3fSDimitry Andric           Implementation->readObjCPropertyBlock(Cursor, Scratch)) {
17885f757f3fSDimitry Andric         Failed = true;
17895f757f3fSDimitry Andric         return;
17905f757f3fSDimitry Andric       }
17915f757f3fSDimitry Andric       break;
17925f757f3fSDimitry Andric 
17935f757f3fSDimitry Andric     case OBJC_METHOD_BLOCK_ID:
17945f757f3fSDimitry Andric       if (!HasValidControlBlock ||
17955f757f3fSDimitry Andric           Implementation->readObjCMethodBlock(Cursor, Scratch)) {
17965f757f3fSDimitry Andric         Failed = true;
17975f757f3fSDimitry Andric         return;
17985f757f3fSDimitry Andric       }
17995f757f3fSDimitry Andric       break;
18005f757f3fSDimitry Andric 
1801*0fca6ea1SDimitry Andric     case CXX_METHOD_BLOCK_ID:
1802*0fca6ea1SDimitry Andric       if (!HasValidControlBlock ||
1803*0fca6ea1SDimitry Andric           Implementation->readCXXMethodBlock(Cursor, Scratch)) {
1804*0fca6ea1SDimitry Andric         Failed = true;
1805*0fca6ea1SDimitry Andric         return;
1806*0fca6ea1SDimitry Andric       }
1807*0fca6ea1SDimitry Andric       break;
1808*0fca6ea1SDimitry Andric 
18095f757f3fSDimitry Andric     case OBJC_SELECTOR_BLOCK_ID:
18105f757f3fSDimitry Andric       if (!HasValidControlBlock ||
18115f757f3fSDimitry Andric           Implementation->readObjCSelectorBlock(Cursor, Scratch)) {
18125f757f3fSDimitry Andric         Failed = true;
18135f757f3fSDimitry Andric         return;
18145f757f3fSDimitry Andric       }
18155f757f3fSDimitry Andric       break;
18165f757f3fSDimitry Andric 
18175f757f3fSDimitry Andric     case GLOBAL_VARIABLE_BLOCK_ID:
18185f757f3fSDimitry Andric       if (!HasValidControlBlock ||
18195f757f3fSDimitry Andric           Implementation->readGlobalVariableBlock(Cursor, Scratch)) {
18205f757f3fSDimitry Andric         Failed = true;
18215f757f3fSDimitry Andric         return;
18225f757f3fSDimitry Andric       }
18235f757f3fSDimitry Andric       break;
18245f757f3fSDimitry Andric 
18255f757f3fSDimitry Andric     case GLOBAL_FUNCTION_BLOCK_ID:
18265f757f3fSDimitry Andric       if (!HasValidControlBlock ||
18275f757f3fSDimitry Andric           Implementation->readGlobalFunctionBlock(Cursor, Scratch)) {
18285f757f3fSDimitry Andric         Failed = true;
18295f757f3fSDimitry Andric         return;
18305f757f3fSDimitry Andric       }
18315f757f3fSDimitry Andric       break;
18325f757f3fSDimitry Andric 
18335f757f3fSDimitry Andric     case ENUM_CONSTANT_BLOCK_ID:
18345f757f3fSDimitry Andric       if (!HasValidControlBlock ||
18355f757f3fSDimitry Andric           Implementation->readEnumConstantBlock(Cursor, Scratch)) {
18365f757f3fSDimitry Andric         Failed = true;
18375f757f3fSDimitry Andric         return;
18385f757f3fSDimitry Andric       }
18395f757f3fSDimitry Andric       break;
18405f757f3fSDimitry Andric 
18415f757f3fSDimitry Andric     case TAG_BLOCK_ID:
18425f757f3fSDimitry Andric       if (!HasValidControlBlock ||
18435f757f3fSDimitry Andric           Implementation->readTagBlock(Cursor, Scratch)) {
18445f757f3fSDimitry Andric         Failed = true;
18455f757f3fSDimitry Andric         return;
18465f757f3fSDimitry Andric       }
18475f757f3fSDimitry Andric       break;
18485f757f3fSDimitry Andric 
18495f757f3fSDimitry Andric     case TYPEDEF_BLOCK_ID:
18505f757f3fSDimitry Andric       if (!HasValidControlBlock ||
18515f757f3fSDimitry Andric           Implementation->readTypedefBlock(Cursor, Scratch)) {
18525f757f3fSDimitry Andric         Failed = true;
18535f757f3fSDimitry Andric         return;
18545f757f3fSDimitry Andric       }
18555f757f3fSDimitry Andric       break;
18565f757f3fSDimitry Andric 
18575f757f3fSDimitry Andric     default:
18585f757f3fSDimitry Andric       // Unknown top-level block, possibly for use by a future version of the
18595f757f3fSDimitry Andric       // module format.
18605f757f3fSDimitry Andric       if (Cursor.SkipBlock()) {
18615f757f3fSDimitry Andric         Failed = true;
18625f757f3fSDimitry Andric         return;
18635f757f3fSDimitry Andric       }
18645f757f3fSDimitry Andric       break;
18655f757f3fSDimitry Andric     }
18665f757f3fSDimitry Andric   }
18675f757f3fSDimitry Andric 
18685f757f3fSDimitry Andric   if (!Cursor.AtEndOfStream()) {
18695f757f3fSDimitry Andric     Failed = true;
18705f757f3fSDimitry Andric     return;
18715f757f3fSDimitry Andric   }
18725f757f3fSDimitry Andric }
18735f757f3fSDimitry Andric 
18745f757f3fSDimitry Andric APINotesReader::~APINotesReader() { delete Implementation->InputBuffer; }
18755f757f3fSDimitry Andric 
18765f757f3fSDimitry Andric std::unique_ptr<APINotesReader>
18775f757f3fSDimitry Andric APINotesReader::Create(std::unique_ptr<llvm::MemoryBuffer> InputBuffer,
18785f757f3fSDimitry Andric                        llvm::VersionTuple SwiftVersion) {
18795f757f3fSDimitry Andric   bool Failed = false;
18805f757f3fSDimitry Andric   std::unique_ptr<APINotesReader> Reader(
18815f757f3fSDimitry Andric       new APINotesReader(InputBuffer.release(), SwiftVersion, Failed));
18825f757f3fSDimitry Andric   if (Failed)
18835f757f3fSDimitry Andric     return nullptr;
18845f757f3fSDimitry Andric 
18855f757f3fSDimitry Andric   return Reader;
18865f757f3fSDimitry Andric }
18875f757f3fSDimitry Andric 
18885f757f3fSDimitry Andric template <typename T>
18895f757f3fSDimitry Andric APINotesReader::VersionedInfo<T>::VersionedInfo(
18905f757f3fSDimitry Andric     llvm::VersionTuple Version,
1891*0fca6ea1SDimitry Andric     llvm::SmallVector<std::pair<llvm::VersionTuple, T>, 1> R)
1892*0fca6ea1SDimitry Andric     : Results(std::move(R)) {
18935f757f3fSDimitry Andric 
18945f757f3fSDimitry Andric   assert(!Results.empty());
18955f757f3fSDimitry Andric   assert(std::is_sorted(
18965f757f3fSDimitry Andric       Results.begin(), Results.end(),
18975f757f3fSDimitry Andric       [](const std::pair<llvm::VersionTuple, T> &left,
18985f757f3fSDimitry Andric          const std::pair<llvm::VersionTuple, T> &right) -> bool {
18995f757f3fSDimitry Andric         assert(left.first != right.first && "two entries for the same version");
19005f757f3fSDimitry Andric         return left.first < right.first;
19015f757f3fSDimitry Andric       }));
19025f757f3fSDimitry Andric 
19035f757f3fSDimitry Andric   Selected = std::nullopt;
19045f757f3fSDimitry Andric   for (unsigned i = 0, n = Results.size(); i != n; ++i) {
19055f757f3fSDimitry Andric     if (!Version.empty() && Results[i].first >= Version) {
19065f757f3fSDimitry Andric       // If the current version is "4", then entries for 4 are better than
19075f757f3fSDimitry Andric       // entries for 5, but both are valid. Because entries are sorted, we get
19085f757f3fSDimitry Andric       // that behavior by picking the first match.
19095f757f3fSDimitry Andric       Selected = i;
19105f757f3fSDimitry Andric       break;
19115f757f3fSDimitry Andric     }
19125f757f3fSDimitry Andric   }
19135f757f3fSDimitry Andric 
19145f757f3fSDimitry Andric   // If we didn't find a match but we have an unversioned result, use the
19155f757f3fSDimitry Andric   // unversioned result. This will always be the first entry because we encode
19165f757f3fSDimitry Andric   // it as version 0.
19175f757f3fSDimitry Andric   if (!Selected && Results[0].first.empty())
19185f757f3fSDimitry Andric     Selected = 0;
19195f757f3fSDimitry Andric }
19205f757f3fSDimitry Andric 
19215f757f3fSDimitry Andric auto APINotesReader::lookupObjCClassID(llvm::StringRef Name)
19225f757f3fSDimitry Andric     -> std::optional<ContextID> {
1923*0fca6ea1SDimitry Andric   if (!Implementation->ContextIDTable)
19245f757f3fSDimitry Andric     return std::nullopt;
19255f757f3fSDimitry Andric 
19265f757f3fSDimitry Andric   std::optional<IdentifierID> ClassID = Implementation->getIdentifier(Name);
19275f757f3fSDimitry Andric   if (!ClassID)
19285f757f3fSDimitry Andric     return std::nullopt;
19295f757f3fSDimitry Andric 
19305f757f3fSDimitry Andric   // ObjC classes can't be declared in C++ namespaces, so use -1 as the global
19315f757f3fSDimitry Andric   // context.
1932*0fca6ea1SDimitry Andric   auto KnownID = Implementation->ContextIDTable->find(
19335f757f3fSDimitry Andric       ContextTableKey(-1, (uint8_t)ContextKind::ObjCClass, *ClassID));
1934*0fca6ea1SDimitry Andric   if (KnownID == Implementation->ContextIDTable->end())
19355f757f3fSDimitry Andric     return std::nullopt;
19365f757f3fSDimitry Andric 
19375f757f3fSDimitry Andric   return ContextID(*KnownID);
19385f757f3fSDimitry Andric }
19395f757f3fSDimitry Andric 
19405f757f3fSDimitry Andric auto APINotesReader::lookupObjCClassInfo(llvm::StringRef Name)
1941*0fca6ea1SDimitry Andric     -> VersionedInfo<ContextInfo> {
1942*0fca6ea1SDimitry Andric   if (!Implementation->ContextInfoTable)
19435f757f3fSDimitry Andric     return std::nullopt;
19445f757f3fSDimitry Andric 
19455f757f3fSDimitry Andric   std::optional<ContextID> CtxID = lookupObjCClassID(Name);
19465f757f3fSDimitry Andric   if (!CtxID)
19475f757f3fSDimitry Andric     return std::nullopt;
19485f757f3fSDimitry Andric 
1949*0fca6ea1SDimitry Andric   auto KnownInfo = Implementation->ContextInfoTable->find(CtxID->Value);
1950*0fca6ea1SDimitry Andric   if (KnownInfo == Implementation->ContextInfoTable->end())
19515f757f3fSDimitry Andric     return std::nullopt;
19525f757f3fSDimitry Andric 
19535f757f3fSDimitry Andric   return {Implementation->SwiftVersion, *KnownInfo};
19545f757f3fSDimitry Andric }
19555f757f3fSDimitry Andric 
19565f757f3fSDimitry Andric auto APINotesReader::lookupObjCProtocolID(llvm::StringRef Name)
19575f757f3fSDimitry Andric     -> std::optional<ContextID> {
1958*0fca6ea1SDimitry Andric   if (!Implementation->ContextIDTable)
19595f757f3fSDimitry Andric     return std::nullopt;
19605f757f3fSDimitry Andric 
19615f757f3fSDimitry Andric   std::optional<IdentifierID> classID = Implementation->getIdentifier(Name);
19625f757f3fSDimitry Andric   if (!classID)
19635f757f3fSDimitry Andric     return std::nullopt;
19645f757f3fSDimitry Andric 
19655f757f3fSDimitry Andric   // ObjC classes can't be declared in C++ namespaces, so use -1 as the global
19665f757f3fSDimitry Andric   // context.
1967*0fca6ea1SDimitry Andric   auto KnownID = Implementation->ContextIDTable->find(
19685f757f3fSDimitry Andric       ContextTableKey(-1, (uint8_t)ContextKind::ObjCProtocol, *classID));
1969*0fca6ea1SDimitry Andric   if (KnownID == Implementation->ContextIDTable->end())
19705f757f3fSDimitry Andric     return std::nullopt;
19715f757f3fSDimitry Andric 
19725f757f3fSDimitry Andric   return ContextID(*KnownID);
19735f757f3fSDimitry Andric }
19745f757f3fSDimitry Andric 
19755f757f3fSDimitry Andric auto APINotesReader::lookupObjCProtocolInfo(llvm::StringRef Name)
1976*0fca6ea1SDimitry Andric     -> VersionedInfo<ContextInfo> {
1977*0fca6ea1SDimitry Andric   if (!Implementation->ContextInfoTable)
19785f757f3fSDimitry Andric     return std::nullopt;
19795f757f3fSDimitry Andric 
19805f757f3fSDimitry Andric   std::optional<ContextID> CtxID = lookupObjCProtocolID(Name);
19815f757f3fSDimitry Andric   if (!CtxID)
19825f757f3fSDimitry Andric     return std::nullopt;
19835f757f3fSDimitry Andric 
1984*0fca6ea1SDimitry Andric   auto KnownInfo = Implementation->ContextInfoTable->find(CtxID->Value);
1985*0fca6ea1SDimitry Andric   if (KnownInfo == Implementation->ContextInfoTable->end())
19865f757f3fSDimitry Andric     return std::nullopt;
19875f757f3fSDimitry Andric 
19885f757f3fSDimitry Andric   return {Implementation->SwiftVersion, *KnownInfo};
19895f757f3fSDimitry Andric }
19905f757f3fSDimitry Andric 
19915f757f3fSDimitry Andric auto APINotesReader::lookupObjCProperty(ContextID CtxID, llvm::StringRef Name,
19925f757f3fSDimitry Andric                                         bool IsInstance)
19935f757f3fSDimitry Andric     -> VersionedInfo<ObjCPropertyInfo> {
19945f757f3fSDimitry Andric   if (!Implementation->ObjCPropertyTable)
19955f757f3fSDimitry Andric     return std::nullopt;
19965f757f3fSDimitry Andric 
19975f757f3fSDimitry Andric   std::optional<IdentifierID> PropertyID = Implementation->getIdentifier(Name);
19985f757f3fSDimitry Andric   if (!PropertyID)
19995f757f3fSDimitry Andric     return std::nullopt;
20005f757f3fSDimitry Andric 
20015f757f3fSDimitry Andric   auto Known = Implementation->ObjCPropertyTable->find(
20025f757f3fSDimitry Andric       std::make_tuple(CtxID.Value, *PropertyID, (char)IsInstance));
20035f757f3fSDimitry Andric   if (Known == Implementation->ObjCPropertyTable->end())
20045f757f3fSDimitry Andric     return std::nullopt;
20055f757f3fSDimitry Andric 
20065f757f3fSDimitry Andric   return {Implementation->SwiftVersion, *Known};
20075f757f3fSDimitry Andric }
20085f757f3fSDimitry Andric 
20095f757f3fSDimitry Andric auto APINotesReader::lookupObjCMethod(ContextID CtxID, ObjCSelectorRef Selector,
20105f757f3fSDimitry Andric                                       bool IsInstanceMethod)
20115f757f3fSDimitry Andric     -> VersionedInfo<ObjCMethodInfo> {
20125f757f3fSDimitry Andric   if (!Implementation->ObjCMethodTable)
20135f757f3fSDimitry Andric     return std::nullopt;
20145f757f3fSDimitry Andric 
20155f757f3fSDimitry Andric   std::optional<SelectorID> SelID = Implementation->getSelector(Selector);
20165f757f3fSDimitry Andric   if (!SelID)
20175f757f3fSDimitry Andric     return std::nullopt;
20185f757f3fSDimitry Andric 
20195f757f3fSDimitry Andric   auto Known = Implementation->ObjCMethodTable->find(
20205f757f3fSDimitry Andric       ObjCMethodTableInfo::internal_key_type{CtxID.Value, *SelID,
20215f757f3fSDimitry Andric                                              IsInstanceMethod});
20225f757f3fSDimitry Andric   if (Known == Implementation->ObjCMethodTable->end())
20235f757f3fSDimitry Andric     return std::nullopt;
20245f757f3fSDimitry Andric 
20255f757f3fSDimitry Andric   return {Implementation->SwiftVersion, *Known};
20265f757f3fSDimitry Andric }
20275f757f3fSDimitry Andric 
2028*0fca6ea1SDimitry Andric auto APINotesReader::lookupCXXMethod(ContextID CtxID, llvm::StringRef Name)
2029*0fca6ea1SDimitry Andric     -> VersionedInfo<CXXMethodInfo> {
2030*0fca6ea1SDimitry Andric   if (!Implementation->CXXMethodTable)
2031*0fca6ea1SDimitry Andric     return std::nullopt;
2032*0fca6ea1SDimitry Andric 
2033*0fca6ea1SDimitry Andric   std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2034*0fca6ea1SDimitry Andric   if (!NameID)
2035*0fca6ea1SDimitry Andric     return std::nullopt;
2036*0fca6ea1SDimitry Andric 
2037*0fca6ea1SDimitry Andric   auto Known = Implementation->CXXMethodTable->find(
2038*0fca6ea1SDimitry Andric       SingleDeclTableKey(CtxID.Value, *NameID));
2039*0fca6ea1SDimitry Andric   if (Known == Implementation->CXXMethodTable->end())
2040*0fca6ea1SDimitry Andric     return std::nullopt;
2041*0fca6ea1SDimitry Andric 
2042*0fca6ea1SDimitry Andric   return {Implementation->SwiftVersion, *Known};
2043*0fca6ea1SDimitry Andric }
2044*0fca6ea1SDimitry Andric 
20455f757f3fSDimitry Andric auto APINotesReader::lookupGlobalVariable(llvm::StringRef Name,
20465f757f3fSDimitry Andric                                           std::optional<Context> Ctx)
20475f757f3fSDimitry Andric     -> VersionedInfo<GlobalVariableInfo> {
20485f757f3fSDimitry Andric   if (!Implementation->GlobalVariableTable)
20495f757f3fSDimitry Andric     return std::nullopt;
20505f757f3fSDimitry Andric 
20515f757f3fSDimitry Andric   std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
20525f757f3fSDimitry Andric   if (!NameID)
20535f757f3fSDimitry Andric     return std::nullopt;
20545f757f3fSDimitry Andric 
2055*0fca6ea1SDimitry Andric   SingleDeclTableKey Key(Ctx, *NameID);
20565f757f3fSDimitry Andric 
20575f757f3fSDimitry Andric   auto Known = Implementation->GlobalVariableTable->find(Key);
20585f757f3fSDimitry Andric   if (Known == Implementation->GlobalVariableTable->end())
20595f757f3fSDimitry Andric     return std::nullopt;
20605f757f3fSDimitry Andric 
20615f757f3fSDimitry Andric   return {Implementation->SwiftVersion, *Known};
20625f757f3fSDimitry Andric }
20635f757f3fSDimitry Andric 
20645f757f3fSDimitry Andric auto APINotesReader::lookupGlobalFunction(llvm::StringRef Name,
20655f757f3fSDimitry Andric                                           std::optional<Context> Ctx)
20665f757f3fSDimitry Andric     -> VersionedInfo<GlobalFunctionInfo> {
20675f757f3fSDimitry Andric   if (!Implementation->GlobalFunctionTable)
20685f757f3fSDimitry Andric     return std::nullopt;
20695f757f3fSDimitry Andric 
20705f757f3fSDimitry Andric   std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
20715f757f3fSDimitry Andric   if (!NameID)
20725f757f3fSDimitry Andric     return std::nullopt;
20735f757f3fSDimitry Andric 
2074*0fca6ea1SDimitry Andric   SingleDeclTableKey Key(Ctx, *NameID);
20755f757f3fSDimitry Andric 
20765f757f3fSDimitry Andric   auto Known = Implementation->GlobalFunctionTable->find(Key);
20775f757f3fSDimitry Andric   if (Known == Implementation->GlobalFunctionTable->end())
20785f757f3fSDimitry Andric     return std::nullopt;
20795f757f3fSDimitry Andric 
20805f757f3fSDimitry Andric   return {Implementation->SwiftVersion, *Known};
20815f757f3fSDimitry Andric }
20825f757f3fSDimitry Andric 
20835f757f3fSDimitry Andric auto APINotesReader::lookupEnumConstant(llvm::StringRef Name)
20845f757f3fSDimitry Andric     -> VersionedInfo<EnumConstantInfo> {
20855f757f3fSDimitry Andric   if (!Implementation->EnumConstantTable)
20865f757f3fSDimitry Andric     return std::nullopt;
20875f757f3fSDimitry Andric 
20885f757f3fSDimitry Andric   std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
20895f757f3fSDimitry Andric   if (!NameID)
20905f757f3fSDimitry Andric     return std::nullopt;
20915f757f3fSDimitry Andric 
20925f757f3fSDimitry Andric   auto Known = Implementation->EnumConstantTable->find(*NameID);
20935f757f3fSDimitry Andric   if (Known == Implementation->EnumConstantTable->end())
20945f757f3fSDimitry Andric     return std::nullopt;
20955f757f3fSDimitry Andric 
20965f757f3fSDimitry Andric   return {Implementation->SwiftVersion, *Known};
20975f757f3fSDimitry Andric }
20985f757f3fSDimitry Andric 
2099*0fca6ea1SDimitry Andric auto APINotesReader::lookupTagID(llvm::StringRef Name,
2100*0fca6ea1SDimitry Andric                                  std::optional<Context> ParentCtx)
2101*0fca6ea1SDimitry Andric     -> std::optional<ContextID> {
2102*0fca6ea1SDimitry Andric   if (!Implementation->ContextIDTable)
2103*0fca6ea1SDimitry Andric     return std::nullopt;
2104*0fca6ea1SDimitry Andric 
2105*0fca6ea1SDimitry Andric   std::optional<IdentifierID> TagID = Implementation->getIdentifier(Name);
2106*0fca6ea1SDimitry Andric   if (!TagID)
2107*0fca6ea1SDimitry Andric     return std::nullopt;
2108*0fca6ea1SDimitry Andric 
2109*0fca6ea1SDimitry Andric   auto KnownID = Implementation->ContextIDTable->find(
2110*0fca6ea1SDimitry Andric       ContextTableKey(ParentCtx, ContextKind::Tag, *TagID));
2111*0fca6ea1SDimitry Andric   if (KnownID == Implementation->ContextIDTable->end())
2112*0fca6ea1SDimitry Andric     return std::nullopt;
2113*0fca6ea1SDimitry Andric 
2114*0fca6ea1SDimitry Andric   return ContextID(*KnownID);
2115*0fca6ea1SDimitry Andric }
2116*0fca6ea1SDimitry Andric 
21175f757f3fSDimitry Andric auto APINotesReader::lookupTag(llvm::StringRef Name, std::optional<Context> Ctx)
21185f757f3fSDimitry Andric     -> VersionedInfo<TagInfo> {
21195f757f3fSDimitry Andric   if (!Implementation->TagTable)
21205f757f3fSDimitry Andric     return std::nullopt;
21215f757f3fSDimitry Andric 
21225f757f3fSDimitry Andric   std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
21235f757f3fSDimitry Andric   if (!NameID)
21245f757f3fSDimitry Andric     return std::nullopt;
21255f757f3fSDimitry Andric 
2126*0fca6ea1SDimitry Andric   SingleDeclTableKey Key(Ctx, *NameID);
21275f757f3fSDimitry Andric 
21285f757f3fSDimitry Andric   auto Known = Implementation->TagTable->find(Key);
21295f757f3fSDimitry Andric   if (Known == Implementation->TagTable->end())
21305f757f3fSDimitry Andric     return std::nullopt;
21315f757f3fSDimitry Andric 
21325f757f3fSDimitry Andric   return {Implementation->SwiftVersion, *Known};
21335f757f3fSDimitry Andric }
21345f757f3fSDimitry Andric 
21355f757f3fSDimitry Andric auto APINotesReader::lookupTypedef(llvm::StringRef Name,
21365f757f3fSDimitry Andric                                    std::optional<Context> Ctx)
21375f757f3fSDimitry Andric     -> VersionedInfo<TypedefInfo> {
21385f757f3fSDimitry Andric   if (!Implementation->TypedefTable)
21395f757f3fSDimitry Andric     return std::nullopt;
21405f757f3fSDimitry Andric 
21415f757f3fSDimitry Andric   std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
21425f757f3fSDimitry Andric   if (!NameID)
21435f757f3fSDimitry Andric     return std::nullopt;
21445f757f3fSDimitry Andric 
2145*0fca6ea1SDimitry Andric   SingleDeclTableKey Key(Ctx, *NameID);
21465f757f3fSDimitry Andric 
21475f757f3fSDimitry Andric   auto Known = Implementation->TypedefTable->find(Key);
21485f757f3fSDimitry Andric   if (Known == Implementation->TypedefTable->end())
21495f757f3fSDimitry Andric     return std::nullopt;
21505f757f3fSDimitry Andric 
21515f757f3fSDimitry Andric   return {Implementation->SwiftVersion, *Known};
21525f757f3fSDimitry Andric }
21535f757f3fSDimitry Andric 
21545f757f3fSDimitry Andric auto APINotesReader::lookupNamespaceID(
21555f757f3fSDimitry Andric     llvm::StringRef Name, std::optional<ContextID> ParentNamespaceID)
21565f757f3fSDimitry Andric     -> std::optional<ContextID> {
2157*0fca6ea1SDimitry Andric   if (!Implementation->ContextIDTable)
21585f757f3fSDimitry Andric     return std::nullopt;
21595f757f3fSDimitry Andric 
21605f757f3fSDimitry Andric   std::optional<IdentifierID> NamespaceID = Implementation->getIdentifier(Name);
21615f757f3fSDimitry Andric   if (!NamespaceID)
21625f757f3fSDimitry Andric     return std::nullopt;
21635f757f3fSDimitry Andric 
21645f757f3fSDimitry Andric   uint32_t RawParentNamespaceID =
21655f757f3fSDimitry Andric       ParentNamespaceID ? ParentNamespaceID->Value : -1;
2166*0fca6ea1SDimitry Andric   auto KnownID = Implementation->ContextIDTable->find(
21675f757f3fSDimitry Andric       {RawParentNamespaceID, (uint8_t)ContextKind::Namespace, *NamespaceID});
2168*0fca6ea1SDimitry Andric   if (KnownID == Implementation->ContextIDTable->end())
21695f757f3fSDimitry Andric     return std::nullopt;
21705f757f3fSDimitry Andric 
21715f757f3fSDimitry Andric   return ContextID(*KnownID);
21725f757f3fSDimitry Andric }
21735f757f3fSDimitry Andric 
21745f757f3fSDimitry Andric } // namespace api_notes
21755f757f3fSDimitry Andric } // namespace clang
2176