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