@@ -299,6 +299,28 @@ class ObjCPropertyTableInfo
299299 }
300300};
301301
302+ // / Used to deserialize the on-disk C record field table.
303+ class FieldTableInfo
304+ : public VersionedTableInfo<FieldTableInfo, SingleDeclTableKey, FieldInfo> {
305+ public:
306+ static internal_key_type ReadKey (const uint8_t *Data, unsigned Length) {
307+ auto CtxID = endian::readNext<uint32_t , llvm::endianness::little>(Data);
308+ auto NameID = endian::readNext<uint32_t , llvm::endianness::little>(Data);
309+ return {CtxID, NameID};
310+ }
311+
312+ hash_value_type ComputeHash (internal_key_type Key) {
313+ return static_cast <size_t >(Key.hashValue ());
314+ }
315+
316+ static FieldInfo readUnversioned (internal_key_type Key,
317+ const uint8_t *&Data) {
318+ FieldInfo Info;
319+ ReadVariableInfo (Data, Info);
320+ return Info;
321+ }
322+ };
323+
302324// / Read serialized ParamInfo.
303325void ReadParamInfo (const uint8_t *&Data, ParamInfo &Info) {
304326 ReadVariableInfo (Data, Info);
@@ -653,6 +675,12 @@ class APINotesReader::Implementation {
653675 // / The Objective-C property table.
654676 std::unique_ptr<SerializedObjCPropertyTable> ObjCPropertyTable;
655677
678+ using SerializedFieldTable =
679+ llvm::OnDiskIterableChainedHashTable<FieldTableInfo>;
680+
681+ // / The C record field table.
682+ std::unique_ptr<SerializedFieldTable> FieldTable;
683+
656684 using SerializedObjCMethodTable =
657685 llvm::OnDiskIterableChainedHashTable<ObjCMethodTableInfo>;
658686
@@ -720,6 +748,8 @@ class APINotesReader::Implementation {
720748 llvm::SmallVectorImpl<uint64_t > &Scratch);
721749 bool readCXXMethodBlock (llvm::BitstreamCursor &Cursor,
722750 llvm::SmallVectorImpl<uint64_t > &Scratch);
751+ bool readFieldBlock (llvm::BitstreamCursor &Cursor,
752+ llvm::SmallVectorImpl<uint64_t > &Scratch);
723753 bool readObjCSelectorBlock (llvm::BitstreamCursor &Cursor,
724754 llvm::SmallVectorImpl<uint64_t > &Scratch);
725755 bool readGlobalVariableBlock (llvm::BitstreamCursor &Cursor,
@@ -1252,6 +1282,81 @@ bool APINotesReader::Implementation::readCXXMethodBlock(
12521282 return false ;
12531283}
12541284
1285+ bool APINotesReader::Implementation::readFieldBlock (
1286+ llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t > &Scratch) {
1287+ if (Cursor.EnterSubBlock (FIELD_BLOCK_ID))
1288+ return true ;
1289+
1290+ llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance ();
1291+ if (!MaybeNext) {
1292+ // FIXME this drops the error on the floor.
1293+ consumeError (MaybeNext.takeError ());
1294+ return false ;
1295+ }
1296+ llvm::BitstreamEntry Next = MaybeNext.get ();
1297+ while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1298+ if (Next.Kind == llvm::BitstreamEntry::Error)
1299+ return true ;
1300+
1301+ if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1302+ // Unknown sub-block, possibly for use by a future version of the
1303+ // API notes format.
1304+ if (Cursor.SkipBlock ())
1305+ return true ;
1306+
1307+ MaybeNext = Cursor.advance ();
1308+ if (!MaybeNext) {
1309+ // FIXME this drops the error on the floor.
1310+ consumeError (MaybeNext.takeError ());
1311+ return false ;
1312+ }
1313+ Next = MaybeNext.get ();
1314+ continue ;
1315+ }
1316+
1317+ Scratch.clear ();
1318+ llvm::StringRef BlobData;
1319+ llvm::Expected<unsigned > MaybeKind =
1320+ Cursor.readRecord (Next.ID , Scratch, &BlobData);
1321+ if (!MaybeKind) {
1322+ // FIXME this drops the error on the floor.
1323+ consumeError (MaybeKind.takeError ());
1324+ return false ;
1325+ }
1326+ unsigned Kind = MaybeKind.get ();
1327+ switch (Kind) {
1328+ case field_block::FIELD_DATA: {
1329+ // Already saw field table.
1330+ if (FieldTable)
1331+ return true ;
1332+
1333+ uint32_t tableOffset;
1334+ field_block::FieldDataLayout::readRecord (Scratch, tableOffset);
1335+ auto base = reinterpret_cast <const uint8_t *>(BlobData.data ());
1336+
1337+ FieldTable.reset (SerializedFieldTable::Create (
1338+ base + tableOffset, base + sizeof (uint32_t ), base));
1339+ break ;
1340+ }
1341+
1342+ default :
1343+ // Unknown record, possibly for use by a future version of the
1344+ // module format.
1345+ break ;
1346+ }
1347+
1348+ MaybeNext = Cursor.advance ();
1349+ if (!MaybeNext) {
1350+ // FIXME this drops the error on the floor.
1351+ consumeError (MaybeNext.takeError ());
1352+ return false ;
1353+ }
1354+ Next = MaybeNext.get ();
1355+ }
1356+
1357+ return false ;
1358+ }
1359+
12551360bool APINotesReader::Implementation::readObjCSelectorBlock (
12561361 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t > &Scratch) {
12571362 if (Cursor.EnterSubBlock (OBJC_SELECTOR_BLOCK_ID))
@@ -1812,6 +1917,14 @@ APINotesReader::APINotesReader(llvm::MemoryBuffer *InputBuffer,
18121917 }
18131918 break ;
18141919
1920+ case FIELD_BLOCK_ID:
1921+ if (!HasValidControlBlock ||
1922+ Implementation->readFieldBlock (Cursor, Scratch)) {
1923+ Failed = true ;
1924+ return ;
1925+ }
1926+ break ;
1927+
18151928 case OBJC_SELECTOR_BLOCK_ID:
18161929 if (!HasValidControlBlock ||
18171930 Implementation->readObjCSelectorBlock (Cursor, Scratch)) {
@@ -2031,6 +2144,23 @@ auto APINotesReader::lookupObjCMethod(ContextID CtxID, ObjCSelectorRef Selector,
20312144 return {Implementation->SwiftVersion , *Known};
20322145}
20332146
2147+ auto APINotesReader::lookupField (ContextID CtxID, llvm::StringRef Name)
2148+ -> VersionedInfo<FieldInfo> {
2149+ if (!Implementation->FieldTable )
2150+ return std::nullopt ;
2151+
2152+ std::optional<IdentifierID> NameID = Implementation->getIdentifier (Name);
2153+ if (!NameID)
2154+ return std::nullopt ;
2155+
2156+ auto Known = Implementation->FieldTable ->find (
2157+ SingleDeclTableKey (CtxID.Value , *NameID));
2158+ if (Known == Implementation->FieldTable ->end ())
2159+ return std::nullopt ;
2160+
2161+ return {Implementation->SwiftVersion , *Known};
2162+ }
2163+
20342164auto APINotesReader::lookupCXXMethod (ContextID CtxID, llvm::StringRef Name)
20352165 -> VersionedInfo<CXXMethodInfo> {
20362166 if (!Implementation->CXXMethodTable )
0 commit comments