@@ -473,6 +473,29 @@ class GlobalFunctionTableInfo
473
473
}
474
474
};
475
475
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
+
476
499
// / Used to deserialize the on-disk enumerator table.
477
500
class EnumConstantTableInfo
478
501
: public VersionedTableInfo<EnumConstantTableInfo, uint32_t ,
@@ -633,6 +656,12 @@ class APINotesReader::Implementation {
633
656
// / The Objective-C method table.
634
657
std::unique_ptr<SerializedObjCMethodTable> ObjCMethodTable;
635
658
659
+ using SerializedCXXMethodTable =
660
+ llvm::OnDiskIterableChainedHashTable<CXXMethodTableInfo>;
661
+
662
+ // / The C++ method table.
663
+ std::unique_ptr<SerializedCXXMethodTable> CXXMethodTable;
664
+
636
665
using SerializedObjCSelectorTable =
637
666
llvm::OnDiskIterableChainedHashTable<ObjCSelectorTableInfo>;
638
667
@@ -686,6 +715,8 @@ class APINotesReader::Implementation {
686
715
llvm::SmallVectorImpl<uint64_t > &Scratch);
687
716
bool readObjCMethodBlock (llvm::BitstreamCursor &Cursor,
688
717
llvm::SmallVectorImpl<uint64_t > &Scratch);
718
+ bool readCXXMethodBlock (llvm::BitstreamCursor &Cursor,
719
+ llvm::SmallVectorImpl<uint64_t > &Scratch);
689
720
bool readObjCSelectorBlock (llvm::BitstreamCursor &Cursor,
690
721
llvm::SmallVectorImpl<uint64_t > &Scratch);
691
722
bool readGlobalVariableBlock (llvm::BitstreamCursor &Cursor,
@@ -1144,6 +1175,81 @@ bool APINotesReader::Implementation::readObjCMethodBlock(
1144
1175
return false ;
1145
1176
}
1146
1177
1178
+ bool APINotesReader::Implementation::readCXXMethodBlock (
1179
+ llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t > &Scratch) {
1180
+ if (Cursor.EnterSubBlock (CXX_METHOD_BLOCK_ID))
1181
+ return true ;
1182
+
1183
+ llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance ();
1184
+ if (!MaybeNext) {
1185
+ // FIXME this drops the error on the floor.
1186
+ consumeError (MaybeNext.takeError ());
1187
+ return false ;
1188
+ }
1189
+ llvm::BitstreamEntry Next = MaybeNext.get ();
1190
+ while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1191
+ if (Next.Kind == llvm::BitstreamEntry::Error)
1192
+ return true ;
1193
+
1194
+ if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1195
+ // Unknown sub-block, possibly for use by a future version of the
1196
+ // API notes format.
1197
+ if (Cursor.SkipBlock ())
1198
+ return true ;
1199
+
1200
+ MaybeNext = Cursor.advance ();
1201
+ if (!MaybeNext) {
1202
+ // FIXME this drops the error on the floor.
1203
+ consumeError (MaybeNext.takeError ());
1204
+ return false ;
1205
+ }
1206
+ Next = MaybeNext.get ();
1207
+ continue ;
1208
+ }
1209
+
1210
+ Scratch.clear ();
1211
+ llvm::StringRef BlobData;
1212
+ llvm::Expected<unsigned > MaybeKind =
1213
+ Cursor.readRecord (Next.ID , Scratch, &BlobData);
1214
+ if (!MaybeKind) {
1215
+ // FIXME this drops the error on the floor.
1216
+ consumeError (MaybeKind.takeError ());
1217
+ return false ;
1218
+ }
1219
+ unsigned Kind = MaybeKind.get ();
1220
+ switch (Kind) {
1221
+ case cxx_method_block::CXX_METHOD_DATA: {
1222
+ // Already saw C++ method table.
1223
+ if (CXXMethodTable)
1224
+ return true ;
1225
+
1226
+ uint32_t tableOffset;
1227
+ cxx_method_block::CXXMethodDataLayout::readRecord (Scratch, tableOffset);
1228
+ auto base = reinterpret_cast <const uint8_t *>(BlobData.data ());
1229
+
1230
+ CXXMethodTable.reset (SerializedCXXMethodTable::Create (
1231
+ base + tableOffset, base + sizeof (uint32_t ), base));
1232
+ break ;
1233
+ }
1234
+
1235
+ default :
1236
+ // Unknown record, possibly for use by a future version of the
1237
+ // module format.
1238
+ break ;
1239
+ }
1240
+
1241
+ MaybeNext = Cursor.advance ();
1242
+ if (!MaybeNext) {
1243
+ // FIXME this drops the error on the floor.
1244
+ consumeError (MaybeNext.takeError ());
1245
+ return false ;
1246
+ }
1247
+ Next = MaybeNext.get ();
1248
+ }
1249
+
1250
+ return false ;
1251
+ }
1252
+
1147
1253
bool APINotesReader::Implementation::readObjCSelectorBlock (
1148
1254
llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t > &Scratch) {
1149
1255
if (Cursor.EnterSubBlock (OBJC_SELECTOR_BLOCK_ID))
@@ -1696,6 +1802,14 @@ APINotesReader::APINotesReader(llvm::MemoryBuffer *InputBuffer,
1696
1802
}
1697
1803
break ;
1698
1804
1805
+ case CXX_METHOD_BLOCK_ID:
1806
+ if (!HasValidControlBlock ||
1807
+ Implementation->readCXXMethodBlock (Cursor, Scratch)) {
1808
+ Failed = true ;
1809
+ return ;
1810
+ }
1811
+ break ;
1812
+
1699
1813
case OBJC_SELECTOR_BLOCK_ID:
1700
1814
if (!HasValidControlBlock ||
1701
1815
Implementation->readObjCSelectorBlock (Cursor, Scratch)) {
@@ -1923,6 +2037,23 @@ auto APINotesReader::lookupObjCMethod(ContextID CtxID, ObjCSelectorRef Selector,
1923
2037
return {Implementation->SwiftVersion , *Known};
1924
2038
}
1925
2039
2040
+ auto APINotesReader::lookupCXXMethod (ContextID CtxID, llvm::StringRef Name)
2041
+ -> VersionedInfo<CXXMethodInfo> {
2042
+ if (!Implementation->CXXMethodTable )
2043
+ return std::nullopt;
2044
+
2045
+ std::optional<IdentifierID> NameID = Implementation->getIdentifier (Name);
2046
+ if (!NameID)
2047
+ return std::nullopt;
2048
+
2049
+ auto Known = Implementation->CXXMethodTable ->find (
2050
+ SingleDeclTableKey (CtxID.Value , *NameID));
2051
+ if (Known == Implementation->CXXMethodTable ->end ())
2052
+ return std::nullopt;
2053
+
2054
+ return {Implementation->SwiftVersion , *Known};
2055
+ }
2056
+
1926
2057
auto APINotesReader::lookupGlobalVariable (llvm::StringRef Name,
1927
2058
std::optional<Context> Ctx)
1928
2059
-> VersionedInfo<GlobalVariableInfo> {
@@ -1977,6 +2108,24 @@ auto APINotesReader::lookupEnumConstant(llvm::StringRef Name)
1977
2108
return {Implementation->SwiftVersion , *Known};
1978
2109
}
1979
2110
2111
+ auto APINotesReader::lookupTagID (llvm::StringRef Name,
2112
+ std::optional<Context> ParentCtx)
2113
+ -> std::optional<ContextID> {
2114
+ if (!Implementation->ContextIDTable )
2115
+ return std::nullopt;
2116
+
2117
+ std::optional<IdentifierID> TagID = Implementation->getIdentifier (Name);
2118
+ if (!TagID)
2119
+ return std::nullopt;
2120
+
2121
+ auto KnownID = Implementation->ContextIDTable ->find (
2122
+ ContextTableKey (ParentCtx, ContextKind::Tag, *TagID));
2123
+ if (KnownID == Implementation->ContextIDTable ->end ())
2124
+ return std::nullopt;
2125
+
2126
+ return ContextID (*KnownID);
2127
+ }
2128
+
1980
2129
auto APINotesReader::lookupTag (llvm::StringRef Name, std::optional<Context> Ctx)
1981
2130
-> VersionedInfo<TagInfo> {
1982
2131
if (!Implementation->TagTable )
0 commit comments