@@ -749,8 +749,24 @@ namespace {
749
749
// / A class which lays out a witness table in the abstract.
750
750
class WitnessTableLayout : public SILWitnessVisitor <WitnessTableLayout> {
751
751
SmallVector<WitnessTableEntry, 16 > Entries;
752
+ bool requirementSignatureOnly;
752
753
753
754
public:
755
+ explicit WitnessTableLayout (ProtocolInfoKind resultKind) {
756
+ switch (resultKind) {
757
+ case ProtocolInfoKind::RequirementSignature:
758
+ requirementSignatureOnly = true ;
759
+ break ;
760
+ case ProtocolInfoKind::Full:
761
+ requirementSignatureOnly = false ;
762
+ break ;
763
+ }
764
+ }
765
+
766
+ bool shouldVisitRequirementSignatureOnly () {
767
+ return requirementSignatureOnly;
768
+ }
769
+
754
770
void addProtocolConformanceDescriptor () { }
755
771
756
772
// / The next witness is an out-of-line base protocol.
@@ -896,9 +912,11 @@ namespace {
896
912
897
913
// Otherwise, if there isn't a better path through this base,
898
914
// don't accumulate anything in the path.
899
- } else if (!findBetterPath (base, IGM.getProtocolInfo (base),
900
- lengthToBase)) {
901
- continue ;
915
+ } else {
916
+ const ProtocolInfo &baseInfo =
917
+ IGM.getProtocolInfo (base, ProtocolInfoKind::RequirementSignature);
918
+ if (!findBetterPath (base, baseInfo, lengthToBase))
919
+ continue ;
902
920
}
903
921
904
922
// Okay, we've found a better path, and ReversePath contains a
@@ -1210,7 +1228,8 @@ llvm::Value *uniqueForeignWitnessTableRef(IRGenFunction &IGF,
1210
1228
Conformance.getDeclContext())),
1211
1229
SILEntries(SILWT->getEntries ()),
1212
1230
SILConditionalConformances(SILWT->getConditionalConformances ()),
1213
- PI(IGM.getProtocolInfo(SILWT->getConformance ()->getProtocol())) {
1231
+ PI(IGM.getProtocolInfo(SILWT->getConformance ()->getProtocol(),
1232
+ ProtocolInfoKind::Full)) {
1214
1233
// If the conformance is resilient, we require runtime instantiation.
1215
1234
if (isResilientConformance (&Conformance)) {
1216
1235
RequiresSpecialization = true ;
@@ -2079,38 +2098,53 @@ void IRGenModule::ensureRelativeSymbolCollocation(SILWitnessTable &wt) {
2079
2098
}
2080
2099
2081
2100
// / Do a memoized witness-table layout for a protocol.
2082
- const ProtocolInfo &IRGenModule::getProtocolInfo (ProtocolDecl *protocol) {
2083
- return Types.getProtocolInfo (protocol);
2101
+ const ProtocolInfo &IRGenModule::getProtocolInfo (ProtocolDecl *protocol,
2102
+ ProtocolInfoKind kind) {
2103
+ return Types.getProtocolInfo (protocol, kind);
2084
2104
}
2085
2105
2086
2106
// / Do a memoized witness-table layout for a protocol.
2087
- const ProtocolInfo &TypeConverter::getProtocolInfo (ProtocolDecl *protocol) {
2107
+ const ProtocolInfo &TypeConverter::getProtocolInfo (ProtocolDecl *protocol,
2108
+ ProtocolInfoKind kind) {
2088
2109
// Check whether we've already translated this protocol.
2089
2110
auto it = Protocols.find (protocol);
2090
- if (it != Protocols.end ()) return *it->second ;
2111
+ if (it != Protocols.end () && it->second ->getKind () >= kind)
2112
+ return *it->second ;
2091
2113
2092
2114
// If not, lay out the protocol's witness table, if it needs one.
2093
- WitnessTableLayout layout;
2115
+ WitnessTableLayout layout (kind) ;
2094
2116
if (Lowering::TypeConverter::protocolRequiresWitnessTable (protocol))
2095
2117
layout.visitProtocolDecl (protocol);
2096
2118
2097
2119
// Create a ProtocolInfo object from the layout.
2098
- ProtocolInfo *info = ProtocolInfo::create (layout.getEntries ());
2099
- info->NextConverted = FirstProtocol;
2120
+ ProtocolInfo *info = ProtocolInfo::create (layout.getEntries (), kind );
2121
+ info->NextConverted . setPointer ( FirstProtocol) ;
2100
2122
FirstProtocol = info;
2101
2123
2124
+ // Verify that we haven't generated an incompatible layout.
2125
+ if (it != Protocols.end ()) {
2126
+ ArrayRef<WitnessTableEntry> originalEntries =
2127
+ it->second ->getWitnessEntries ();
2128
+ ArrayRef<WitnessTableEntry> newEntries = info->getWitnessEntries ();
2129
+ assert (newEntries.size () >= originalEntries.size ());
2130
+ assert (newEntries.take_front (originalEntries.size ()) == originalEntries);
2131
+ (void )originalEntries;
2132
+ (void )newEntries;
2133
+ }
2134
+
2102
2135
// Memoize.
2103
- Protocols. insert ( std::make_pair ( protocol, info)) ;
2136
+ Protocols[ protocol] = info;
2104
2137
2105
2138
// Done.
2106
2139
return *info;
2107
2140
}
2108
2141
2109
2142
// / Allocate a new ProtocolInfo.
2110
- ProtocolInfo *ProtocolInfo::create (ArrayRef<WitnessTableEntry> table) {
2143
+ ProtocolInfo *ProtocolInfo::create (ArrayRef<WitnessTableEntry> table,
2144
+ ProtocolInfoKind kind) {
2111
2145
size_t bufferSize = totalSizeToAlloc<WitnessTableEntry>(table.size ());
2112
2146
void *buffer = ::operator new (bufferSize);
2113
- return new (buffer) ProtocolInfo (table);
2147
+ return new (buffer) ProtocolInfo (table, kind );
2114
2148
}
2115
2149
2116
2150
// Provide a unique home for the ConformanceInfo vtable.
@@ -2486,7 +2520,8 @@ MetadataResponse MetadataPath::followComponent(IRGenFunction &IGF,
2486
2520
case Component::Kind::OutOfLineBaseProtocol: {
2487
2521
auto conformance = sourceKey.Kind .getProtocolConformance ();
2488
2522
auto protocol = conformance.getRequirement ();
2489
- auto &pi = IGF.IGM .getProtocolInfo (protocol);
2523
+ auto &pi = IGF.IGM .getProtocolInfo (protocol,
2524
+ ProtocolInfoKind::RequirementSignature);
2490
2525
2491
2526
auto &entry = pi.getWitnessEntries ()[component.getPrimaryIndex ()];
2492
2527
assert (entry.isOutOfLineBase ());
@@ -2522,7 +2557,8 @@ MetadataResponse MetadataPath::followComponent(IRGenFunction &IGF,
2522
2557
auto sourceType = sourceKey.Type ;
2523
2558
auto sourceConformance = sourceKey.Kind .getProtocolConformance ();
2524
2559
auto sourceProtocol = sourceConformance.getRequirement ();
2525
- auto &pi = IGF.IGM .getProtocolInfo (sourceProtocol);
2560
+ auto &pi = IGF.IGM .getProtocolInfo (sourceProtocol,
2561
+ ProtocolInfoKind::RequirementSignature);
2526
2562
2527
2563
auto &entry = pi.getWitnessEntries ()[component.getPrimaryIndex ()];
2528
2564
assert (entry.isAssociatedConformance ());
@@ -3243,7 +3279,7 @@ irgen::emitWitnessMethodValue(IRGenFunction &IGF,
3243
3279
assert (!IGF.IGM .isResilient (proto, ResilienceExpansion::Maximal));
3244
3280
3245
3281
// Find the witness we're interested in.
3246
- auto &fnProtoInfo = IGF.IGM .getProtocolInfo (proto);
3282
+ auto &fnProtoInfo = IGF.IGM .getProtocolInfo (proto, ProtocolInfoKind::Full );
3247
3283
auto index = fnProtoInfo.getFunctionIndex (fn);
3248
3284
llvm::Value *witnessFnPtr =
3249
3285
emitInvariantLoadOfOpaqueWitness (IGF, wtable,
@@ -3292,7 +3328,8 @@ irgen::emitAssociatedTypeMetadataRef(IRGenFunction &IGF,
3292
3328
llvm::Value *wtable,
3293
3329
AssociatedType associatedType,
3294
3330
DynamicMetadataRequest request) {
3295
- auto &pi = IGF.IGM .getProtocolInfo (associatedType.getSourceProtocol ());
3331
+ auto &pi = IGF.IGM .getProtocolInfo (associatedType.getSourceProtocol (),
3332
+ ProtocolInfoKind::RequirementSignature);
3296
3333
auto index = pi.getAssociatedTypeIndex (associatedType);
3297
3334
llvm::Value *witness = emitInvariantLoadOfOpaqueWitness (IGF, wtable,
3298
3335
index.forProtocolWitnessTable ());
0 commit comments