@@ -473,6 +473,29 @@ class GlobalFunctionTableInfo
473473 }
474474};
475475
476+ // / Used to deserialize the on-disk C++ method table.
477+ class CXXMethodTableInfo
478+ : public VersionedTableInfo<CXXMethodTableInfo, SingleDeclTableKey,
479+ CXXMethodInfo> {
480+ public:
481+ static internal_key_type ReadKey (const uint8_t *Data, unsigned Length) {
482+ auto CtxID = endian::readNext<uint32_t , llvm::endianness::little>(Data);
483+ auto NameID = endian::readNext<uint32_t , llvm::endianness::little>(Data);
484+ return {CtxID, NameID};
485+ }
486+
487+ hash_value_type ComputeHash (internal_key_type Key) {
488+ return static_cast <size_t >(Key.hashValue ());
489+ }
490+
491+ static CXXMethodInfo readUnversioned (internal_key_type Key,
492+ const uint8_t *&Data) {
493+ CXXMethodInfo Info;
494+ ReadFunctionInfo (Data, Info);
495+ return Info;
496+ }
497+ };
498+
476499// / Used to deserialize the on-disk enumerator table.
477500class EnumConstantTableInfo
478501 : public VersionedTableInfo<EnumConstantTableInfo, uint32_t ,
@@ -630,6 +653,12 @@ class APINotesReader::Implementation {
630653 // / The Objective-C method table.
631654 std::unique_ptr<SerializedObjCMethodTable> ObjCMethodTable;
632655
656+ using SerializedCXXMethodTable =
657+ llvm::OnDiskIterableChainedHashTable<CXXMethodTableInfo>;
658+
659+ // / The C++ method table.
660+ std::unique_ptr<SerializedCXXMethodTable> CXXMethodTable;
661+
633662 using SerializedObjCSelectorTable =
634663 llvm::OnDiskIterableChainedHashTable<ObjCSelectorTableInfo>;
635664
@@ -683,6 +712,8 @@ class APINotesReader::Implementation {
683712 llvm::SmallVectorImpl<uint64_t > &Scratch);
684713 bool readObjCMethodBlock (llvm::BitstreamCursor &Cursor,
685714 llvm::SmallVectorImpl<uint64_t > &Scratch);
715+ bool readCXXMethodBlock (llvm::BitstreamCursor &Cursor,
716+ llvm::SmallVectorImpl<uint64_t > &Scratch);
686717 bool readObjCSelectorBlock (llvm::BitstreamCursor &Cursor,
687718 llvm::SmallVectorImpl<uint64_t > &Scratch);
688719 bool readGlobalVariableBlock (llvm::BitstreamCursor &Cursor,
@@ -1140,6 +1171,81 @@ bool APINotesReader::Implementation::readObjCMethodBlock(
11401171 return false ;
11411172}
11421173
1174+ bool APINotesReader::Implementation::readCXXMethodBlock (
1175+ llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t > &Scratch) {
1176+ if (Cursor.EnterSubBlock (CXX_METHOD_BLOCK_ID))
1177+ return true ;
1178+
1179+ llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance ();
1180+ if (!MaybeNext) {
1181+ // FIXME this drops the error on the floor.
1182+ consumeError (MaybeNext.takeError ());
1183+ return false ;
1184+ }
1185+ llvm::BitstreamEntry Next = MaybeNext.get ();
1186+ while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1187+ if (Next.Kind == llvm::BitstreamEntry::Error)
1188+ return true ;
1189+
1190+ if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1191+ // Unknown sub-block, possibly for use by a future version of the
1192+ // API notes format.
1193+ if (Cursor.SkipBlock ())
1194+ return true ;
1195+
1196+ MaybeNext = Cursor.advance ();
1197+ if (!MaybeNext) {
1198+ // FIXME this drops the error on the floor.
1199+ consumeError (MaybeNext.takeError ());
1200+ return false ;
1201+ }
1202+ Next = MaybeNext.get ();
1203+ continue ;
1204+ }
1205+
1206+ Scratch.clear ();
1207+ llvm::StringRef BlobData;
1208+ llvm::Expected<unsigned > MaybeKind =
1209+ Cursor.readRecord (Next.ID , Scratch, &BlobData);
1210+ if (!MaybeKind) {
1211+ // FIXME this drops the error on the floor.
1212+ consumeError (MaybeKind.takeError ());
1213+ return false ;
1214+ }
1215+ unsigned Kind = MaybeKind.get ();
1216+ switch (Kind) {
1217+ case cxx_method_block::CXX_METHOD_DATA: {
1218+ // Already saw C++ method table.
1219+ if (CXXMethodTable)
1220+ return true ;
1221+
1222+ uint32_t tableOffset;
1223+ cxx_method_block::CXXMethodDataLayout::readRecord (Scratch, tableOffset);
1224+ auto base = reinterpret_cast <const uint8_t *>(BlobData.data ());
1225+
1226+ CXXMethodTable.reset (SerializedCXXMethodTable::Create (
1227+ base + tableOffset, base + sizeof (uint32_t ), base));
1228+ break ;
1229+ }
1230+
1231+ default :
1232+ // Unknown record, possibly for use by a future version of the
1233+ // module format.
1234+ break ;
1235+ }
1236+
1237+ MaybeNext = Cursor.advance ();
1238+ if (!MaybeNext) {
1239+ // FIXME this drops the error on the floor.
1240+ consumeError (MaybeNext.takeError ());
1241+ return false ;
1242+ }
1243+ Next = MaybeNext.get ();
1244+ }
1245+
1246+ return false ;
1247+ }
1248+
11431249bool APINotesReader::Implementation::readObjCSelectorBlock (
11441250 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t > &Scratch) {
11451251 if (Cursor.EnterSubBlock (OBJC_SELECTOR_BLOCK_ID))
@@ -1692,6 +1798,14 @@ APINotesReader::APINotesReader(llvm::MemoryBuffer *InputBuffer,
16921798 }
16931799 break ;
16941800
1801+ case CXX_METHOD_BLOCK_ID:
1802+ if (!HasValidControlBlock ||
1803+ Implementation->readCXXMethodBlock (Cursor, Scratch)) {
1804+ Failed = true ;
1805+ return ;
1806+ }
1807+ break ;
1808+
16951809 case OBJC_SELECTOR_BLOCK_ID:
16961810 if (!HasValidControlBlock ||
16971811 Implementation->readObjCSelectorBlock (Cursor, Scratch)) {
@@ -1911,6 +2025,23 @@ auto APINotesReader::lookupObjCMethod(ContextID CtxID, ObjCSelectorRef Selector,
19112025 return {Implementation->SwiftVersion , *Known};
19122026}
19132027
2028+ auto APINotesReader::lookupCXXMethod (ContextID CtxID, llvm::StringRef Name)
2029+ -> VersionedInfo<CXXMethodInfo> {
2030+ if (!Implementation->CXXMethodTable )
2031+ return std::nullopt ;
2032+
2033+ std::optional<IdentifierID> NameID = Implementation->getIdentifier (Name);
2034+ if (!NameID)
2035+ return std::nullopt ;
2036+
2037+ auto Known = Implementation->CXXMethodTable ->find (
2038+ SingleDeclTableKey (CtxID.Value , *NameID));
2039+ if (Known == Implementation->CXXMethodTable ->end ())
2040+ return std::nullopt ;
2041+
2042+ return {Implementation->SwiftVersion , *Known};
2043+ }
2044+
19142045auto APINotesReader::lookupGlobalVariable (llvm::StringRef Name,
19152046 std::optional<Context> Ctx)
19162047 -> VersionedInfo<GlobalVariableInfo> {
@@ -1965,6 +2096,24 @@ auto APINotesReader::lookupEnumConstant(llvm::StringRef Name)
19652096 return {Implementation->SwiftVersion , *Known};
19662097}
19672098
2099+ auto APINotesReader::lookupTagID (llvm::StringRef Name,
2100+ std::optional<Context> ParentCtx)
2101+ -> std::optional<ContextID> {
2102+ if (!Implementation->ContextIDTable )
2103+ return std::nullopt ;
2104+
2105+ std::optional<IdentifierID> TagID = Implementation->getIdentifier (Name);
2106+ if (!TagID)
2107+ return std::nullopt ;
2108+
2109+ auto KnownID = Implementation->ContextIDTable ->find (
2110+ ContextTableKey (ParentCtx, ContextKind::Tag, *TagID));
2111+ if (KnownID == Implementation->ContextIDTable ->end ())
2112+ return std::nullopt ;
2113+
2114+ return ContextID (*KnownID);
2115+ }
2116+
19682117auto APINotesReader::lookupTag (llvm::StringRef Name, std::optional<Context> Ctx)
19692118 -> VersionedInfo<TagInfo> {
19702119 if (!Implementation->TagTable )
0 commit comments