Skip to content

Commit bbfdf7b

Browse files
authored
Merge pull request #72470 from DougGregor/dynamic-suppressible-protocols
Metadata and runtime support for suppressible protocol requirements
2 parents a63078f + 3339edb commit bbfdf7b

23 files changed

+1443
-105
lines changed

include/swift/ABI/GenericContext.h

Lines changed: 166 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "swift/ABI/TargetLayout.h"
2222
#include "swift/ABI/MetadataValues.h"
2323
#include "swift/ABI/MetadataRef.h"
24+
#include "swift/ABI/SuppressibleProtocols.h"
2425
#include "swift/ABI/TrailingObjects.h"
2526
#include "swift/Demangling/Demangle.h"
2627

@@ -103,6 +104,10 @@ struct TargetGenericContextDescriptorHeader {
103104
bool hasArguments() const {
104105
return getNumArguments() > 0;
105106
}
107+
108+
bool hasConditionalSuppressedProtocols() const {
109+
return Flags.hasConditionalSuppressedProtocols();
110+
}
106111
};
107112
using GenericContextDescriptorHeader =
108113
TargetGenericContextDescriptorHeader<InProcess>;
@@ -137,6 +142,20 @@ class TargetGenericRequirementDescriptor {
137142
///
138143
/// Only valid if the requirement has Layout kind.
139144
GenericRequirementLayoutKind Layout;
145+
146+
/// The set of suppressible protocols whose check is suppressed, along
147+
/// with the index of the generic parameter being suppressed.
148+
///
149+
/// The index is technically redundant with the subject type, but its
150+
/// storage is effectively free because this union is 32 bits anyway. The
151+
/// index 0xFFFF is reserved for "not a generic parameter", in case we
152+
/// need to use that in the future.
153+
///
154+
/// Only valid if the requirement has SuppressedProtocols kind.
155+
struct {
156+
uint16_t GenericParamIndex;
157+
SuppressibleProtocolSet Protocols;
158+
} SuppressedProtocols;
140159
};
141160

142161
constexpr GenericRequirementFlags getFlags() const {
@@ -204,6 +223,18 @@ class TargetGenericRequirementDescriptor {
204223
return Layout;
205224
}
206225

226+
/// Retrieve the set of suppressed protocols.
227+
SuppressibleProtocolSet getSuppressedProtocols() const {
228+
assert(getKind() == GenericRequirementKind::SuppressedProtocols);
229+
return SuppressedProtocols.Protocols;
230+
}
231+
232+
/// Retrieve the suppressible protocol kind.
233+
uint16_t getSuppressedProtocolsGenericParamIndex() const {
234+
assert(getKind() == GenericRequirementKind::SuppressedProtocols);
235+
return SuppressedProtocols.GenericParamIndex;
236+
}
237+
207238
/// Determine whether this generic requirement has a known kind.
208239
///
209240
/// \returns \c false for any future generic requirement kinds.
@@ -215,6 +246,7 @@ class TargetGenericRequirementDescriptor {
215246
case GenericRequirementKind::SameConformance:
216247
case GenericRequirementKind::SameType:
217248
case GenericRequirementKind::SameShape:
249+
case GenericRequirementKind::SuppressedProtocols:
218250
return true;
219251
}
220252

@@ -266,6 +298,26 @@ struct GenericPackShapeDescriptor {
266298
uint16_t Unused;
267299
};
268300

301+
/// A count for the number of requirements for the number of requirements
302+
/// for a given conditional conformance to a suppressible protocols.
303+
struct ConditionalSuppressibleProtocolsRequirementCount {
304+
uint16_t count;
305+
};
306+
307+
/// A suppressible protocol set used for the conditional conformances in a
308+
/// generic context.
309+
struct ConditionalSuppressibleProtocolSet: SuppressibleProtocolSet {
310+
using SuppressibleProtocolSet::SuppressibleProtocolSet;
311+
};
312+
313+
/// A generic requirement for describing a conditional conformance to a
314+
/// suppressible protocol.
315+
///
316+
/// This type is equivalent to a `TargetGenericRequirementDescriptor`, and
317+
/// differs only because it needs to occur alongside
318+
template<typename Runtime>
319+
struct TargetConditionalSuppressibleProtocolRequirement: TargetGenericRequirementDescriptor<Runtime> { };
320+
269321
/// An array of generic parameter descriptors, all
270322
/// GenericParamDescriptor::implicit(), which is by far
271323
/// the most common case. Some generic context storage can
@@ -306,7 +358,8 @@ class RuntimeGenericSignature {
306358

307359
public:
308360
RuntimeGenericSignature()
309-
: Header{0, 0, 0, 0}, Params(nullptr), Requirements(nullptr),
361+
: Header{0, 0, 0, GenericContextDescriptorFlags(false, false)},
362+
Params(nullptr), Requirements(nullptr),
310363
PackShapeHeader{0, 0}, PackShapeDescriptors(nullptr) {}
311364

312365
RuntimeGenericSignature(const TargetGenericContextDescriptorHeader<Runtime> &header,
@@ -425,20 +478,27 @@ class TrailingGenericContextObjects<TargetSelf<Runtime>,
425478
TargetGenericRequirementDescriptor<Runtime>,
426479
GenericPackShapeHeader,
427480
GenericPackShapeDescriptor,
481+
ConditionalSuppressibleProtocolSet,
482+
ConditionalSuppressibleProtocolsRequirementCount,
483+
TargetConditionalSuppressibleProtocolRequirement<Runtime>,
428484
FollowingTrailingObjects...>
429485
{
430486
protected:
431487
using Self = TargetSelf<Runtime>;
432488
using GenericContextHeaderType = TargetGenericContextHeaderType<Runtime>;
433489
using GenericRequirementDescriptor =
434490
TargetGenericRequirementDescriptor<Runtime>;
435-
491+
using GenericConditionalSuppressibleProtocolRequirement =
492+
TargetConditionalSuppressibleProtocolRequirement<Runtime>;
436493
using TrailingObjects = swift::ABI::TrailingObjects<Self,
437494
GenericContextHeaderType,
438495
GenericParamDescriptor,
439496
GenericRequirementDescriptor,
440497
GenericPackShapeHeader,
441498
GenericPackShapeDescriptor,
499+
ConditionalSuppressibleProtocolSet,
500+
ConditionalSuppressibleProtocolsRequirementCount,
501+
GenericConditionalSuppressibleProtocolRequirement,
442502
FollowingTrailingObjects...>;
443503
friend TrailingObjects;
444504

@@ -467,7 +527,84 @@ class TrailingGenericContextObjects<TargetSelf<Runtime>,
467527
/// HeaderType ought to be convertible to GenericContextDescriptorHeader.
468528
return getFullGenericContextHeader();
469529
}
470-
530+
531+
bool hasConditionalSuppressedProtocols() const {
532+
if (!asSelf()->isGeneric())
533+
return false;
534+
535+
return getGenericContextHeader().hasConditionalSuppressedProtocols();
536+
}
537+
538+
const SuppressibleProtocolSet &
539+
getConditionalSuppressedProtocols() const {
540+
assert(hasConditionalSuppressedProtocols());
541+
return *this->template
542+
getTrailingObjects<ConditionalSuppressibleProtocolSet>();
543+
}
544+
545+
/// Retrieve the counts for # of conditional suppressible protocols for each
546+
/// conditional conformance to a suppressible protocol.
547+
///
548+
/// The counts are cumulative, so the first entry in the array is the
549+
/// number of requirements for the first conditional conformance. The
550+
/// second entry in the array is the number of requirements in the first
551+
/// and second conditional conformances. The last entry is, therefore, the
552+
/// total count of requirements in the structure.
553+
llvm::ArrayRef<ConditionalSuppressibleProtocolsRequirementCount>
554+
getConditionalSuppressibleProtocolRequirementCounts() const {
555+
if (!asSelf()->hasConditionalSuppressedProtocols())
556+
return {};
557+
558+
return {
559+
this->template
560+
getTrailingObjects<ConditionalSuppressibleProtocolsRequirementCount>(),
561+
getNumConditionalSuppressibleProtocolsRequirementCounts()
562+
};
563+
}
564+
565+
/// Retrieve the array of requirements for conditional conformances to
566+
/// the ith conditional conformance to a suppressible protocol.
567+
llvm::ArrayRef<GenericConditionalSuppressibleProtocolRequirement>
568+
getConditionalSuppressibleProtocolRequirementsAt(unsigned i) const {
569+
auto counts = getConditionalSuppressibleProtocolRequirementCounts();
570+
assert(i < counts.size());
571+
572+
unsigned startIndex = (i == 0) ? 0 : counts[i-1].count;
573+
unsigned endIndex = counts[i].count;
574+
575+
auto basePtr =
576+
this->template
577+
getTrailingObjects<GenericConditionalSuppressibleProtocolRequirement>();
578+
return { basePtr + startIndex, basePtr + endIndex };
579+
}
580+
581+
/// Retrieve the array of requirements for conditional conformances to
582+
/// the ith conditional conformance to a suppressible protocol.
583+
llvm::ArrayRef<GenericConditionalSuppressibleProtocolRequirement>
584+
getConditionalSuppressibleProtocolRequirementsFor(
585+
SuppressibleProtocolKind kind
586+
) const {
587+
if (!asSelf()->hasConditionalSuppressedProtocols())
588+
return { };
589+
590+
auto conditionallySuppressed = getConditionalSuppressedProtocols();
591+
if (!conditionallySuppressed.contains(kind))
592+
return { };
593+
594+
// Count the number of "set" bits up to (but not including) the
595+
// bit we're looking at.
596+
unsigned targetBit = static_cast<uint8_t>(kind);
597+
auto suppressedBits = conditionallySuppressed.rawBits();
598+
unsigned priorBits = 0;
599+
for (unsigned i = 0; i != targetBit; ++i) {
600+
if (suppressedBits & 0x01)
601+
++priorBits;
602+
suppressedBits = suppressedBits >> 1;
603+
}
604+
605+
return getConditionalSuppressibleProtocolRequirementsAt(priorBits);
606+
}
607+
471608
const TargetGenericContext<Runtime> *getGenericContext() const {
472609
if (!asSelf()->isGeneric())
473610
return nullptr;
@@ -549,6 +686,32 @@ class TrailingGenericContextObjects<TargetSelf<Runtime>,
549686
return getGenericPackShapeHeader().NumPacks;
550687
}
551688

689+
size_t numTrailingObjects(
690+
OverloadToken<ConditionalSuppressibleProtocolSet>
691+
) const {
692+
return asSelf()->hasConditionalSuppressedProtocols() ? 1 : 0;
693+
}
694+
695+
unsigned getNumConditionalSuppressibleProtocolsRequirementCounts() const {
696+
if (!asSelf()->hasConditionalSuppressedProtocols())
697+
return 0;
698+
699+
return countBitsUsed(getConditionalSuppressedProtocols().rawBits());
700+
}
701+
702+
size_t numTrailingObjects(
703+
OverloadToken<ConditionalSuppressibleProtocolsRequirementCount>
704+
) const {
705+
return getNumConditionalSuppressibleProtocolsRequirementCounts();
706+
}
707+
708+
size_t numTrailingObjects(
709+
OverloadToken<GenericConditionalSuppressibleProtocolRequirement>
710+
) const {
711+
auto counts = getConditionalSuppressibleProtocolRequirementCounts();
712+
return counts.empty() ? 0 : counts.back().count;
713+
}
714+
552715
#if defined(_MSC_VER) && _MSC_VER < 1920
553716
#undef OverloadToken
554717
#endif

0 commit comments

Comments
 (0)