Skip to content

Commit 1e26137

Browse files
committed
Serialization: Serialize PackConformance
1 parent df5d531 commit 1e26137

File tree

9 files changed

+219
-42
lines changed

9 files changed

+219
-42
lines changed

lib/Serialization/DeclTypeRecordNodes.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ OTHER(EXPANDED_MACRO_REPLACEMENTS, 132)
190190
OTHER(NORMAL_PROTOCOL_CONFORMANCE, 141)
191191
OTHER(SPECIALIZED_PROTOCOL_CONFORMANCE, 142)
192192
OTHER(INHERITED_PROTOCOL_CONFORMANCE, 143)
193-
// 144 is unused; was INVALID_PROTOCOL_CONFORMANCE
193+
OTHER(PACK_CONFORMANCE, 144)
194194

195195
OTHER(SIL_LAYOUT, 145)
196196
// 146 is unused; was NORMAL_PROTOCOL_CONFORMANCE_ID

lib/Serialization/Deserialization.cpp

Lines changed: 116 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "swift/AST/Initializer.h"
2727
#include "swift/AST/MacroDefinition.h"
2828
#include "swift/AST/NameLookupRequests.h"
29+
#include "swift/AST/PackConformance.h"
2930
#include "swift/AST/ParameterList.h"
3031
#include "swift/AST/Pattern.h"
3132
#include "swift/AST/PrettyStackTrace.h"
@@ -498,6 +499,9 @@ class ProtocolConformanceDeserializer {
498499
ModuleFile::Serialized<ProtocolConformance *> &entry);
499500
Expected<ProtocolConformance *>
500501
readNormalProtocolConformanceXRef(ArrayRef<uint64_t> data);
502+
503+
Expected<PackConformance *>
504+
read(ModuleFile::Serialized<PackConformance *> &entry);
501505
};
502506
} // end namespace swift
503507

@@ -761,6 +765,65 @@ ProtocolConformanceDeserializer::readNormalProtocolConformance(
761765
return conformance;
762766
}
763767

768+
Expected<PackConformance*>
769+
ProtocolConformanceDeserializer::read(
770+
ModuleFile::Serialized<PackConformance *> &conformanceEntry) {
771+
using namespace decls_block;
772+
773+
SmallVector<uint64_t, 16> scratch;
774+
775+
llvm::BitstreamEntry entry =
776+
MF.fatalIfUnexpected(MF.DeclTypeCursor.advance());
777+
778+
if (entry.Kind != llvm::BitstreamEntry::Record) {
779+
// We don't know how to serialize types represented by sub-blocks.
780+
return MF.diagnoseFatal();
781+
}
782+
783+
StringRef blobData;
784+
unsigned kind = MF.fatalIfUnexpected(
785+
MF.DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));
786+
assert(blobData.empty());
787+
788+
if (kind != decls_block::PACK_CONFORMANCE)
789+
return MF.diagnoseFatal(llvm::make_error<InvalidRecordKindError>(kind));
790+
791+
TypeID patternTypeID;
792+
DeclID protocolID;
793+
ArrayRef<uint64_t> patternConformanceIDs;
794+
PackConformanceLayout::readRecord(scratch,
795+
patternTypeID, protocolID,
796+
patternConformanceIDs);
797+
798+
auto patternTypeOrError = MF.getTypeChecked(patternTypeID);
799+
if (!patternTypeOrError)
800+
return patternTypeOrError.takeError();
801+
auto patternType = patternTypeOrError.get();
802+
803+
auto protocolOrError = MF.getDeclChecked(protocolID);
804+
if (!protocolOrError)
805+
return protocolOrError.takeError();
806+
auto *protocol = protocolOrError.get();
807+
808+
PrettyStackTraceType trace(MF.getAssociatedModule()->getASTContext(),
809+
"reading pack conformance for",
810+
patternType);
811+
812+
SmallVector<ProtocolConformanceRef, 4> patternConformances;
813+
for (auto confID : patternConformanceIDs) {
814+
auto confOrError = MF.getConformanceChecked(confID);
815+
if (!confOrError)
816+
return confOrError.takeError();
817+
patternConformances.push_back(confOrError.get());
818+
}
819+
820+
auto conformance =
821+
PackConformance::get(patternType->castTo<PackType>(),
822+
cast<ProtocolDecl>(protocol),
823+
patternConformances);
824+
return conformance;
825+
}
826+
764827
ProtocolConformanceRef
765828
ModuleFile::getConformance(ProtocolConformanceID id,
766829
GenericEnvironment *genericEnv) {
@@ -777,42 +840,68 @@ ModuleFile::getConformanceChecked(ProtocolConformanceID conformanceID,
777840

778841
if (conformanceID == 0) return ProtocolConformanceRef::forInvalid();
779842

780-
// If the low bit is sit, this is an abstract conformance.
781-
if ((conformanceID & 1) == 0) {
782-
auto protocolID = conformanceID >> 1;
843+
switch (conformanceID & SerializedProtocolConformanceKind::Mask) {
844+
case SerializedProtocolConformanceKind::Abstract: {
845+
auto protocolID = conformanceID >> SerializedProtocolConformanceKind::Shift;
783846
auto maybeProtocol = getDeclChecked(protocolID);
784847
if (!maybeProtocol)
785848
return maybeProtocol.takeError();
786849
auto proto = cast<ProtocolDecl>(maybeProtocol.get());
787850
return ProtocolConformanceRef(proto);
788851
}
789852

790-
// Otherwise, it's a concrete conformance.
791-
auto conformanceIndex = (conformanceID >> 1) - 1;
792-
assert(conformanceIndex < Conformances.size() && "invalid conformance ID");
793-
auto &conformanceOrOffset = Conformances[conformanceIndex];
794-
if (!conformanceOrOffset.isComplete()) {
795-
BCOffsetRAII restoreOffset(DeclTypeCursor);
796-
if (auto error = diagnoseFatalIfNotSuccess(
797-
DeclTypeCursor.JumpToBit(conformanceOrOffset)))
798-
return std::move(error);
799-
800-
auto result =
801-
ProtocolConformanceDeserializer(*this).read(conformanceOrOffset);
802-
if (!result)
803-
return result.takeError();
804-
805-
conformanceOrOffset = result.get();
806-
}
807-
auto conformance = conformanceOrOffset.get();
808-
if (!genericEnv || !conformance->getType()->hasTypeParameter())
853+
case SerializedProtocolConformanceKind::Concrete: {
854+
auto conformanceIndex = (conformanceID >> SerializedProtocolConformanceKind::Shift) - 1;
855+
assert(conformanceIndex < Conformances.size() && "invalid conformance ID");
856+
auto &conformanceOrOffset = Conformances[conformanceIndex];
857+
if (!conformanceOrOffset.isComplete()) {
858+
BCOffsetRAII restoreOffset(DeclTypeCursor);
859+
if (auto error = diagnoseFatalIfNotSuccess(
860+
DeclTypeCursor.JumpToBit(conformanceOrOffset)))
861+
return std::move(error);
862+
863+
auto result =
864+
ProtocolConformanceDeserializer(*this).read(conformanceOrOffset);
865+
if (!result)
866+
return result.takeError();
867+
868+
conformanceOrOffset = result.get();
869+
}
870+
auto conformance = conformanceOrOffset.get();
871+
if (!genericEnv || !conformance->getType()->hasTypeParameter())
872+
return ProtocolConformanceRef(conformance);
873+
874+
// If we have a generic environment, map the conformance into context.
875+
auto mappedConformance =
876+
genericEnv->mapConformanceRefIntoContext(conformance->getType(),
877+
ProtocolConformanceRef(conformance));
878+
return mappedConformance.second;
879+
}
880+
881+
case SerializedProtocolConformanceKind::Pack: {
882+
auto conformanceIndex = (conformanceID >> SerializedProtocolConformanceKind::Shift) - 1;
883+
assert(conformanceIndex < Conformances.size() && "invalid pack conformance ID");
884+
auto &conformanceOrOffset = Conformances[conformanceIndex];
885+
if (!conformanceOrOffset.isComplete()) {
886+
BCOffsetRAII restoreOffset(DeclTypeCursor);
887+
if (auto error = diagnoseFatalIfNotSuccess(
888+
DeclTypeCursor.JumpToBit(conformanceOrOffset)))
889+
return std::move(error);
890+
891+
auto result =
892+
ProtocolConformanceDeserializer(*this).read(conformanceOrOffset);
893+
if (!result)
894+
return result.takeError();
895+
896+
conformanceOrOffset = result.get();
897+
}
898+
auto conformance = conformanceOrOffset.get();
809899
return ProtocolConformanceRef(conformance);
900+
}
810901

811-
// If we have a generic environment, map the conformance into context.
812-
auto mappedConformance =
813-
genericEnv->mapConformanceRefIntoContext(conformance->getType(),
814-
ProtocolConformanceRef(conformance));
815-
return mappedConformance.second;
902+
default:
903+
llvm_unreachable("Invalid conformance");
904+
}
816905
}
817906

818907
GenericParamList *ModuleFile::maybeReadGenericParams(DeclContext *DC) {

lib/Serialization/ModuleFile.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,9 @@ class ModuleFile
254254
/// Protocol conformances referenced by this module.
255255
MutableArrayRef<Serialized<ProtocolConformance *>> Conformances;
256256

257+
/// Pack conformances referenced by this module.
258+
MutableArrayRef<Serialized<PackConformance *>> PackConformances;
259+
257260
/// SILLayouts referenced by this module.
258261
MutableArrayRef<Serialized<SILLayout *>> SILLayouts;
259262

lib/Serialization/ModuleFileSharedCore.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,10 @@ bool ModuleFileSharedCore::readIndexBlock(llvm::BitstreamCursor &cursor) {
890890
assert(blobData.empty());
891891
allocateBuffer(Conformances, scratch);
892892
break;
893+
case index_block::PACK_CONFORMANCE_OFFSETS:
894+
assert(blobData.empty());
895+
allocateBuffer(PackConformances, scratch);
896+
break;
893897
case index_block::SIL_LAYOUT_OFFSETS:
894898
assert(blobData.empty());
895899
allocateBuffer(SILLayouts, scratch);

lib/Serialization/ModuleFileSharedCore.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,9 @@ class ModuleFileSharedCore {
229229
/// Protocol conformances referenced by this module.
230230
ArrayRef<RawBitOffset> Conformances;
231231

232+
/// Pack conformances referenced by this module.
233+
ArrayRef<RawBitOffset> PackConformances;
234+
232235
/// SILLayouts referenced by this module.
233236
ArrayRef<RawBitOffset> SILLayouts;
234237

lib/Serialization/ModuleFormat.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5858
/// describe what change you made. The content of this comment isn't important;
5959
/// it just ensures a conflict if two people change the module format.
6060
/// Don't worry about adhering to the 80-column limit for this line.
61-
const uint16_t SWIFTMODULE_VERSION_MINOR = 759; // change PackType
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 780; // serialize PackConformance
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///
@@ -140,6 +140,21 @@ class DeclContextIDField : public BCFixed<32> {
140140
using ProtocolConformanceID = DeclID;
141141
using ProtocolConformanceIDField = DeclIDField;
142142

143+
// The low two bits of the ProtocolConformanceID determine the kind:
144+
// 00 -- abstract conformance
145+
// 01 -- concrete conformance
146+
// 10 -- pack conformance
147+
struct SerializedProtocolConformanceKind {
148+
enum {
149+
Abstract = 0,
150+
Concrete = 1,
151+
Pack = 2,
152+
153+
Shift = 2,
154+
Mask = 3
155+
};
156+
};
157+
143158
// GenericSignatureID must be the same as DeclID because it is stored in the
144159
// same way.
145160
using GenericSignatureID = DeclID;
@@ -1910,6 +1925,13 @@ namespace decls_block {
19101925
BCArray<BCVBR<6>> // conditional requirements
19111926
>;
19121927

1928+
using PackConformanceLayout = BCRecordLayout<
1929+
PACK_CONFORMANCE,
1930+
TypeIDField, // pattern type
1931+
DeclIDField, // the protocol
1932+
BCArray<ProtocolConformanceIDField> // pattern conformances
1933+
>;
1934+
19131935
using ProtocolConformanceXrefLayout = BCRecordLayout<
19141936
PROTOCOL_CONFORMANCE_XREF,
19151937
DeclIDField, // the protocol being conformed to
@@ -2344,6 +2366,7 @@ namespace index_block {
23442366
GENERIC_SIGNATURE_OFFSETS,
23452367
GENERIC_ENVIRONMENT_OFFSETS,
23462368
PROTOCOL_CONFORMANCE_OFFSETS,
2369+
PACK_CONFORMANCE_OFFSETS,
23472370
SIL_LAYOUT_OFFSETS,
23482371

23492372
PRECEDENCE_GROUPS,

0 commit comments

Comments
 (0)