Skip to content

Commit 2f3a946

Browse files
authored
Merge pull request #65300 from slavapestov/serialize-pack-conformance
Serialize pack conformances
2 parents 4ddde6e + 493494f commit 2f3a946

File tree

9 files changed

+210
-62
lines changed

9 files changed

+210
-62
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: 109 additions & 29 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,58 +765,134 @@ 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
765-
ModuleFile::getConformance(ProtocolConformanceID id,
766-
GenericEnvironment *genericEnv) {
767-
auto conformance = getConformanceChecked(id, genericEnv);
828+
ModuleFile::getConformance(ProtocolConformanceID id) {
829+
auto conformance = getConformanceChecked(id);
768830
if (!conformance)
769831
fatal(conformance.takeError());
770832
return conformance.get();
771833
}
772834

773835
Expected<ProtocolConformanceRef>
774-
ModuleFile::getConformanceChecked(ProtocolConformanceID conformanceID,
775-
GenericEnvironment *genericEnv) {
836+
ModuleFile::getConformanceChecked(ProtocolConformanceID conformanceID) {
776837
using namespace decls_block;
777838

778839
if (conformanceID == 0) return ProtocolConformanceRef::forInvalid();
779840

780-
// If the low bit is sit, this is an abstract conformance.
781-
if ((conformanceID & 1) == 0) {
782-
auto protocolID = conformanceID >> 1;
841+
switch (conformanceID & SerializedProtocolConformanceKind::Mask) {
842+
case SerializedProtocolConformanceKind::Abstract: {
843+
auto protocolID = conformanceID >> SerializedProtocolConformanceKind::Shift;
783844
auto maybeProtocol = getDeclChecked(protocolID);
784845
if (!maybeProtocol)
785846
return maybeProtocol.takeError();
786847
auto proto = cast<ProtocolDecl>(maybeProtocol.get());
787848
return ProtocolConformanceRef(proto);
788849
}
789850

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);
851+
case SerializedProtocolConformanceKind::Concrete: {
852+
auto conformanceIndex = (conformanceID >> SerializedProtocolConformanceKind::Shift) - 1;
853+
assert(conformanceIndex < Conformances.size() && "invalid conformance ID");
854+
auto &conformanceOrOffset = Conformances[conformanceIndex];
855+
if (!conformanceOrOffset.isComplete()) {
856+
BCOffsetRAII restoreOffset(DeclTypeCursor);
857+
if (auto error = diagnoseFatalIfNotSuccess(
858+
DeclTypeCursor.JumpToBit(conformanceOrOffset)))
859+
return std::move(error);
799860

800-
auto result =
801-
ProtocolConformanceDeserializer(*this).read(conformanceOrOffset);
802-
if (!result)
803-
return result.takeError();
861+
auto result =
862+
ProtocolConformanceDeserializer(*this).read(conformanceOrOffset);
863+
if (!result)
864+
return result.takeError();
804865

805-
conformanceOrOffset = result.get();
866+
conformanceOrOffset = result.get();
867+
}
868+
auto conformance = conformanceOrOffset.get();
869+
return ProtocolConformanceRef(conformance);
806870
}
807-
auto conformance = conformanceOrOffset.get();
808-
if (!genericEnv || !conformance->getType()->hasTypeParameter())
871+
872+
case SerializedProtocolConformanceKind::Pack: {
873+
auto conformanceIndex = (conformanceID >> SerializedProtocolConformanceKind::Shift) - 1;
874+
assert(conformanceIndex < Conformances.size() && "invalid pack conformance ID");
875+
auto &conformanceOrOffset = Conformances[conformanceIndex];
876+
if (!conformanceOrOffset.isComplete()) {
877+
BCOffsetRAII restoreOffset(DeclTypeCursor);
878+
if (auto error = diagnoseFatalIfNotSuccess(
879+
DeclTypeCursor.JumpToBit(conformanceOrOffset)))
880+
return std::move(error);
881+
882+
auto result =
883+
ProtocolConformanceDeserializer(*this).read(conformanceOrOffset);
884+
if (!result)
885+
return result.takeError();
886+
887+
conformanceOrOffset = result.get();
888+
}
889+
auto conformance = conformanceOrOffset.get();
809890
return ProtocolConformanceRef(conformance);
891+
}
810892

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;
893+
default:
894+
llvm_unreachable("Invalid conformance");
895+
}
816896
}
817897

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

lib/Serialization/ModuleFile.h

Lines changed: 5 additions & 4 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

@@ -986,13 +989,11 @@ class ModuleFile
986989

987990
/// Returns the protocol conformance for the given ID.
988991
ProtocolConformanceRef
989-
getConformance(serialization::ProtocolConformanceID id,
990-
GenericEnvironment *genericEnv = nullptr);
992+
getConformance(serialization::ProtocolConformanceID id);
991993

992994
/// Returns the protocol conformance for the given ID.
993995
llvm::Expected<ProtocolConformanceRef>
994-
getConformanceChecked(serialization::ProtocolConformanceID id,
995-
GenericEnvironment *genericEnv = nullptr);
996+
getConformanceChecked(serialization::ProtocolConformanceID id);
996997

997998
/// Read a SILLayout from the given cursor.
998999
SILLayout *readSILLayout(llvm::BitstreamCursor &Cursor);

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)