@@ -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 ,
@@ -630,6 +653,12 @@ class APINotesReader::Implementation {
630
653
// / The Objective-C method table.
631
654
std::unique_ptr<SerializedObjCMethodTable> ObjCMethodTable;
632
655
656
+ using SerializedCXXMethodTable =
657
+ llvm::OnDiskIterableChainedHashTable<CXXMethodTableInfo>;
658
+
659
+ // / The C++ method table.
660
+ std::unique_ptr<SerializedCXXMethodTable> CXXMethodTable;
661
+
633
662
using SerializedObjCSelectorTable =
634
663
llvm::OnDiskIterableChainedHashTable<ObjCSelectorTableInfo>;
635
664
@@ -683,6 +712,8 @@ class APINotesReader::Implementation {
683
712
llvm::SmallVectorImpl<uint64_t > &Scratch);
684
713
bool readObjCMethodBlock (llvm::BitstreamCursor &Cursor,
685
714
llvm::SmallVectorImpl<uint64_t > &Scratch);
715
+ bool readCXXMethodBlock (llvm::BitstreamCursor &Cursor,
716
+ llvm::SmallVectorImpl<uint64_t > &Scratch);
686
717
bool readObjCSelectorBlock (llvm::BitstreamCursor &Cursor,
687
718
llvm::SmallVectorImpl<uint64_t > &Scratch);
688
719
bool readGlobalVariableBlock (llvm::BitstreamCursor &Cursor,
@@ -1140,6 +1171,81 @@ bool APINotesReader::Implementation::readObjCMethodBlock(
1140
1171
return false ;
1141
1172
}
1142
1173
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
+
1143
1249
bool APINotesReader::Implementation::readObjCSelectorBlock (
1144
1250
llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t > &Scratch) {
1145
1251
if (Cursor.EnterSubBlock (OBJC_SELECTOR_BLOCK_ID))
@@ -1692,6 +1798,14 @@ APINotesReader::APINotesReader(llvm::MemoryBuffer *InputBuffer,
1692
1798
}
1693
1799
break ;
1694
1800
1801
+ case CXX_METHOD_BLOCK_ID:
1802
+ if (!HasValidControlBlock ||
1803
+ Implementation->readCXXMethodBlock (Cursor, Scratch)) {
1804
+ Failed = true ;
1805
+ return ;
1806
+ }
1807
+ break ;
1808
+
1695
1809
case OBJC_SELECTOR_BLOCK_ID:
1696
1810
if (!HasValidControlBlock ||
1697
1811
Implementation->readObjCSelectorBlock (Cursor, Scratch)) {
@@ -1911,6 +2025,23 @@ auto APINotesReader::lookupObjCMethod(ContextID CtxID, ObjCSelectorRef Selector,
1911
2025
return {Implementation->SwiftVersion , *Known};
1912
2026
}
1913
2027
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
+
1914
2045
auto APINotesReader::lookupGlobalVariable (llvm::StringRef Name,
1915
2046
std::optional<Context> Ctx)
1916
2047
-> VersionedInfo<GlobalVariableInfo> {
@@ -1965,6 +2096,24 @@ auto APINotesReader::lookupEnumConstant(llvm::StringRef Name)
1965
2096
return {Implementation->SwiftVersion , *Known};
1966
2097
}
1967
2098
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
+
1968
2117
auto APINotesReader::lookupTag (llvm::StringRef Name, std::optional<Context> Ctx)
1969
2118
-> VersionedInfo<TagInfo> {
1970
2119
if (!Implementation->TagTable )
0 commit comments