Serialization: Round-trip primary associated type list

This commit is contained in:
Slava Pestov
2022-04-16 22:35:57 -04:00
parent d52dddc7c8
commit 6982b90c6e
14 changed files with 193 additions and 71 deletions

View File

@@ -991,70 +991,84 @@ void ModuleFile::readAssociatedTypes(
}
}
void ModuleFile::readPrimaryAssociatedTypes(
SmallVectorImpl<AssociatedTypeDecl *> &assocTypes,
llvm::BitstreamCursor &Cursor) {
using namespace decls_block;
BCOffsetRAII lastRecordOffset(Cursor);
SmallVector<uint64_t, 8> scratch;
StringRef blobData;
while (true) {
lastRecordOffset.reset();
llvm::BitstreamEntry entry =
fatalIfUnexpected(Cursor.advance(AF_DontPopBlockAtEnd));
if (entry.Kind != llvm::BitstreamEntry::Record)
break;
scratch.clear();
unsigned recordID = fatalIfUnexpected(
Cursor.readRecord(entry.ID, scratch, &blobData));
if (recordID != PRIMARY_ASSOCIATED_TYPE)
break;
DeclID declID;
PrimaryAssociatedTypeLayout::readRecord(scratch, declID);
assocTypes.push_back(cast<AssociatedTypeDecl>(getDecl(declID)));
}
}
static llvm::Error skipRecords(llvm::BitstreamCursor &Cursor, unsigned kind) {
using namespace decls_block;
BCOffsetRAII lastRecordOffset(Cursor);
while (true) {
Expected<llvm::BitstreamEntry> maybeEntry =
Cursor.advance(AF_DontPopBlockAtEnd);
if (!maybeEntry)
return maybeEntry.takeError();
llvm::BitstreamEntry entry = maybeEntry.get();
if (entry.Kind != llvm::BitstreamEntry::Record)
break;
Expected<unsigned> maybeRecordID = Cursor.skipRecord(entry.ID);
if (!maybeRecordID)
return maybeRecordID.takeError();
if (maybeRecordID.get() != kind)
return llvm::Error::success();
lastRecordOffset.reset();
}
return llvm::Error::success();
}
/// Advances past any records that might be part of a protocol requirement
/// signature, which consists of generic requirements together with protocol
/// typealias records.
static llvm::Error skipRequirementSignature(llvm::BitstreamCursor &Cursor) {
using namespace decls_block;
BCOffsetRAII lastRecordOffset(Cursor);
while (true) {
Expected<llvm::BitstreamEntry> maybeEntry =
Cursor.advance(AF_DontPopBlockAtEnd);
if (!maybeEntry)
return maybeEntry.takeError();
llvm::BitstreamEntry entry = maybeEntry.get();
if (entry.Kind != llvm::BitstreamEntry::Record)
break;
Expected<unsigned> maybeRecordID = Cursor.skipRecord(entry.ID);
if (!maybeRecordID)
return maybeRecordID.takeError();
switch (maybeRecordID.get()) {
case REQUIREMENT_SIGNATURE:
break;
default:
// This record is not a generic requirement.
return llvm::Error::success();
}
lastRecordOffset.reset();
}
return llvm::Error::success();
return skipRecords(Cursor, REQUIREMENT_SIGNATURE);
}
/// Advances past any lazy associated type member records.
static llvm::Error skipAssociatedTypeMembers(llvm::BitstreamCursor &Cursor) {
using namespace decls_block;
BCOffsetRAII lastRecordOffset(Cursor);
return skipRecords(Cursor, ASSOCIATED_TYPE);
}
while (true) {
Expected<llvm::BitstreamEntry> maybeEntry =
Cursor.advance(AF_DontPopBlockAtEnd);
if (!maybeEntry)
return maybeEntry.takeError();
llvm::BitstreamEntry entry = maybeEntry.get();
if (entry.Kind != llvm::BitstreamEntry::Record)
break;
/// Advances past any lazy primary associated type member records.
static llvm::Error skipPrimaryAssociatedTypeMembers(
llvm::BitstreamCursor &Cursor) {
using namespace decls_block;
Expected<unsigned> maybeRecordID = Cursor.skipRecord(entry.ID);
if (!maybeRecordID)
return maybeRecordID.takeError();
switch (maybeRecordID.get()) {
case ASSOCIATED_TYPE:
break;
default:
// This record is not an associated type.
return llvm::Error::success();
}
lastRecordOffset.reset();
}
return llvm::Error::success();
return skipRecords(Cursor, PRIMARY_ASSOCIATED_TYPE);
}
GenericSignature ModuleFile::getGenericSignature(
@@ -3749,16 +3763,21 @@ public:
proto->setImplicit();
proto->setIsObjC(isObjC);
proto->setLazyRequirementSignature(&MF,
MF.DeclTypeCursor.GetCurrentBitNo());
proto->setLazyRequirementSignature(
&MF, MF.DeclTypeCursor.GetCurrentBitNo());
if (llvm::Error Err = skipRequirementSignature(MF.DeclTypeCursor))
MF.fatal(std::move(Err));
proto->setLazyAssociatedTypeMembers(&MF,
MF.DeclTypeCursor.GetCurrentBitNo());
proto->setLazyAssociatedTypeMembers(
&MF, MF.DeclTypeCursor.GetCurrentBitNo());
if (llvm::Error Err = skipAssociatedTypeMembers(MF.DeclTypeCursor))
MF.fatal(std::move(Err));
proto->setLazyPrimaryAssociatedTypeMembers(
&MF, MF.DeclTypeCursor.GetCurrentBitNo());
if (llvm::Error Err = skipPrimaryAssociatedTypeMembers(MF.DeclTypeCursor))
MF.fatal(std::move(Err));
proto->setMemberLoader(&MF, MF.DeclTypeCursor.GetCurrentBitNo());
return proto;
@@ -6987,6 +7006,14 @@ void ModuleFile::loadAssociatedTypes(const ProtocolDecl *decl,
readAssociatedTypes(assocTypes, DeclTypeCursor);
}
void ModuleFile::loadPrimaryAssociatedTypes(const ProtocolDecl *decl,
uint64_t contextData,
SmallVectorImpl<AssociatedTypeDecl *> &assocTypes) {
BCOffsetRAII restoreOffset(DeclTypeCursor);
fatalIfNotSuccess(DeclTypeCursor.JumpToBit(contextData));
readPrimaryAssociatedTypes(assocTypes, DeclTypeCursor);
}
static Optional<ForeignErrorConvention::Kind>
decodeRawStableForeignErrorConventionKind(uint8_t kind) {
switch (kind) {