2424#include " swift/AST/Witness.h"
2525#include " swift/Basic/Compiler.h"
2626#include " swift/Basic/Debug.h"
27+ #include " swift/Basic/InlineBitfield.h"
2728#include " llvm/ADT/ArrayRef.h"
2829#include " llvm/ADT/DenseMap.h"
2930#include " llvm/ADT/FoldingSet.h"
@@ -55,10 +56,10 @@ typedef llvm::DenseMap<AssociatedTypeDecl *, TypeWitnessAndDecl>
5556
5657// / Describes the kind of protocol conformance structure used to encode
5758// / conformance.
58- enum class ProtocolConformanceKind {
59+ enum class ProtocolConformanceKind : unsigned {
5960 // / "Normal" conformance of a (possibly generic) nominal type, which
6061 // / contains complete mappings.
61- Normal = 0 ,
62+ Normal,
6263 // / Self-conformance of a protocol to itself.
6364 Self,
6465 // / Conformance for a specialization of a generic type, which projects the
@@ -82,13 +83,25 @@ enum : unsigned {
8283// / incomplete, or currently being checked.
8384enum class ProtocolConformanceState {
8485 // / The conformance has been fully checked.
85- Complete,
86+ Complete = 0 ,
8687 // / The conformance is known but is not yet complete.
8788 Incomplete,
8889 // / The conformance's type witnesses are currently being resolved.
8990 CheckingTypeWitnesses,
9091 // / The conformance is being checked.
9192 Checking,
93+
94+ Last_State = Checking
95+ };
96+
97+ enum : unsigned {
98+ NumProtocolConformanceStateBits =
99+ countBitsUsed (static_cast <unsigned >(ProtocolConformanceState::Last_State))
100+ };
101+
102+ enum : unsigned {
103+ NumConformanceEntryKindBits =
104+ countBitsUsed (static_cast <unsigned >(ConformanceEntryKind::Last_Kind))
92105};
93106
94107// / Describes how a particular type conforms to a given protocol,
@@ -115,6 +128,38 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance
115128 // / The kind of protocol conformance.
116129 Kind : bitmax (NumProtocolConformanceKindBits, 8 )
117130 );
131+
132+ SWIFT_INLINE_BITFIELD_EMPTY (RootProtocolConformance, ProtocolConformance);
133+
134+ SWIFT_INLINE_BITFIELD_FULL (NormalProtocolConformance, RootProtocolConformance,
135+ 1 +1 +1 +1 +bitmax (NumProtocolConformanceStateBits,8 )+
136+ bitmax (NumConformanceEntryKindBits,8 ),
137+ // / Indicates whether the conformance is invalid.
138+ IsInvalid : 1 ,
139+ // / The conformance was labeled with @unchecked.
140+ IsUnchecked : 1 ,
141+ // / The conformance was labeled with @preconcurrency.
142+ IsPreconcurrency : 1 ,
143+ // / We have allocated the AssociatedConformances array (but not necessarily
144+ // / populated any of its elements).
145+ HasComputedAssociatedConformances : 1 ,
146+
147+ : NumPadBits,
148+
149+ // / The current state of the conformance.
150+ State : bitmax (NumProtocolConformanceStateBits, 8 ),
151+ // / The reason that this conformance exists.
152+ // /
153+ // / Either Explicit (e.g. 'struct Foo: Protocol {}' or 'extension Foo:
154+ // / Protocol {}'), Synthesized (e.g. RawRepresentable for 'enum Foo: Int {}')
155+ // / or Implied (e.g. 'Foo : Protocol' in 'protocol Other: Protocol {} struct
156+ // / Foo: Other {}'). In only the latter case, the conformance is non-null and
157+ // / points to the conformance that implies this one.
158+ // /
159+ // / This should never be Inherited: that is handled by
160+ // / InheritedProtocolConformance.
161+ SourceKind : bitmax (NumConformanceEntryKindBits, 8 )
162+ );
118163 } Bits;
119164 // clang-format on
120165
@@ -456,49 +501,17 @@ class NormalProtocolConformance : public RootProtocolConformance,
456501 friend class ValueWitnessRequest ;
457502 friend class TypeWitnessRequest ;
458503
459- // / The protocol being conformed to and its current state.
460- llvm::PointerIntPair<ProtocolDecl *, 2 , ProtocolConformanceState>
461- ProtocolAndState;
504+ // / The protocol being conformed to.
505+ ProtocolDecl *Protocol;
462506
463507 // / The location of this protocol conformance in the source.
464508 SourceLoc Loc;
465509
466- // Flag bits used in ContextAndBits.
467- enum {
468- // / The conformance was labeled with @unchecked.
469- UncheckedFlag = 0x01 ,
470-
471- // / The conformance was labeled with @preconcurrency.
472- PreconcurrencyFlag = 0x02 ,
473-
474- // / We have allocated the AssociatedConformances array (but not necessarily
475- // / populated any of its elements).
476- HasComputedAssociatedConformancesFlag = 0x04 ,
477- };
478-
479510 // / The declaration context containing the ExtensionDecl or
480511 // / NominalTypeDecl that declared the conformance.
481- // /
482- // / Also stores the "unchecked", "preconcurrency" and "has computed associated
483- // / conformances" bits.
484- llvm::PointerIntPair<DeclContext *, 3 , unsigned > ContextAndBits;
485-
486- // / Indicates whether the conformance is invalid.
487- bool Invalid : 1 ;
512+ DeclContext *Context;
488513
489- // / The reason that this conformance exists.
490- // /
491- // / Either Explicit (e.g. 'struct Foo: Protocol {}' or 'extension Foo:
492- // / Protocol {}'), Synthesized (e.g. RawRepresentable for 'enum Foo: Int {}')
493- // / or Implied (e.g. 'Foo : Protocol' in 'protocol Other: Protocol {} struct
494- // / Foo: Other {}'). In only the latter case, the conformance is non-null and
495- // / points to the conformance that implies this one.
496- // /
497- // / This should never be Inherited: that is handled by
498- // / InheritedProtocolConformance.
499- llvm::PointerIntPair<NormalProtocolConformance *, 3 , ConformanceEntryKind>
500- SourceKindAndImplyingConformance = {nullptr ,
501- ConformanceEntryKind::Explicit};
514+ NormalProtocolConformance *ImplyingConformance = nullptr ;
502515
503516 // / The mapping of individual requirements in the protocol over to
504517 // / the declarations that satisfy those requirements.
@@ -529,25 +542,27 @@ class NormalProtocolConformance : public RootProtocolConformance,
529542 bool isPreconcurrency)
530543 : RootProtocolConformance(ProtocolConformanceKind::Normal,
531544 conformingType),
532- ProtocolAndState (protocol, state), Loc(loc),
533- ContextAndBits(dc, ((isUnchecked ? UncheckedFlag : 0 ) |
534- (isPreconcurrency ? PreconcurrencyFlag : 0 ))),
535- Invalid(false ) {
545+ Protocol (protocol), Loc(loc), Context(dc) {
536546 assert (!conformingType->hasArchetype () &&
537547 " ProtocolConformances should store interface types" );
548+ setState (state);
549+ Bits.NormalProtocolConformance .IsInvalid = false ;
550+ Bits.NormalProtocolConformance .IsUnchecked = isUnchecked;
551+ Bits.NormalProtocolConformance .IsPreconcurrency = isPreconcurrency;
552+ Bits.NormalProtocolConformance .HasComputedAssociatedConformances = false ;
553+ Bits.NormalProtocolConformance .SourceKind =
554+ unsigned (ConformanceEntryKind::Explicit);
538555 }
539556
540557 // / Get the protocol being conformed to.
541- ProtocolDecl *getProtocol () const { return ProtocolAndState. getPointer () ; }
558+ ProtocolDecl *getProtocol () const { return Protocol ; }
542559
543560 // / Retrieve the location of this
544561 SourceLoc getLoc () const { return Loc; }
545562
546563 // / Get the declaration context that contains the conforming extension or
547564 // / nominal type declaration.
548- DeclContext *getDeclContext () const {
549- return ContextAndBits.getPointer ();
550- }
565+ DeclContext *getDeclContext () const { return Context; }
551566
552567 // / Get any additional requirements that are required for this conformance to
553568 // / be satisfied, e.g. for Array<T>: Equatable, T: Equatable also needs
@@ -559,59 +574,59 @@ class NormalProtocolConformance : public RootProtocolConformance,
559574
560575 // / Retrieve the state of this conformance.
561576 ProtocolConformanceState getState () const {
562- return ProtocolAndState.getInt ();
577+ return static_cast <ProtocolConformanceState>(
578+ Bits.NormalProtocolConformance .State );
563579 }
564580
565581 // / Set the state of this conformance.
566582 void setState (ProtocolConformanceState state) {
567- ProtocolAndState. setInt (state);
583+ Bits. NormalProtocolConformance . State = unsigned (state);
568584 }
569585
570586 // / Determine whether this conformance is invalid.
571- bool isInvalid () const {
572- return Invalid;
573- }
587+ bool isInvalid () const { return Bits.NormalProtocolConformance .IsInvalid ; }
574588
575589 // / Mark this conformance as invalid.
576- void setInvalid () {
577- Invalid = true ;
578- }
590+ void setInvalid () { Bits.NormalProtocolConformance .IsInvalid = true ; }
579591
580592 // / Whether this is an "unchecked" conformance.
581593 bool isUnchecked () const {
582- return ContextAndBits. getInt () & UncheckedFlag ;
594+ return Bits. NormalProtocolConformance . IsUnchecked ;
583595 }
584596
585597 // / Mark the conformance as unchecked (equivalent to the @unchecked
586598 // / conformance attribute).
587599 void setUnchecked () {
588600 // OK to mutate because the flags are not part of the folding set node ID.
589- ContextAndBits. setInt (ContextAndBits. getInt () | UncheckedFlag) ;
601+ Bits. NormalProtocolConformance . IsUnchecked = true ;
590602 }
591603
592604 // / Whether this is an preconcurrency conformance.
593- bool isPreconcurrency () const ;
605+ bool isPreconcurrency () const {
606+ return Bits.NormalProtocolConformance .IsPreconcurrency ;
607+ }
594608
595609 // / Determine whether we've lazily computed the associated conformance array
596610 // / already.
597611 bool hasComputedAssociatedConformances () const {
598- return ContextAndBits. getInt () & HasComputedAssociatedConformancesFlag ;
612+ return Bits. NormalProtocolConformance . HasComputedAssociatedConformances ;
599613 }
600614
601615 // / Mark this conformance as having computed the assocaited conformance array.
602616 void setHasComputedAssociatedConformances () {
603- ContextAndBits. setInt (ContextAndBits. getInt () | HasComputedAssociatedConformancesFlag) ;
617+ Bits. NormalProtocolConformance . HasComputedAssociatedConformances = true ;
604618 }
605619
606620 // / Get the kind of source from which this conformance comes.
607621 ConformanceEntryKind getSourceKind () const {
608- return SourceKindAndImplyingConformance.getInt ();
622+ return static_cast <ConformanceEntryKind>(
623+ Bits.NormalProtocolConformance .SourceKind );
609624 }
610625
611626 // / Get the protocol conformance which implied this implied conformance.
612627 NormalProtocolConformance *getImplyingConformance () const {
613628 assert (getSourceKind () == ConformanceEntryKind::Implied);
614- return SourceKindAndImplyingConformance. getPointer () ;
629+ return ImplyingConformance ;
615630 }
616631
617632 void setSourceKindAndImplyingConformance (
@@ -624,7 +639,8 @@ class NormalProtocolConformance : public RootProtocolConformance,
624639 " an implied conformance needs something that implies it" );
625640 assert (sourceKind != ConformanceEntryKind::PreMacroExpansion &&
626641 " cannot create conformance pre-macro-expansion" );
627- SourceKindAndImplyingConformance = {implyingConformance, sourceKind};
642+ Bits.NormalProtocolConformance .SourceKind = unsigned (sourceKind);
643+ ImplyingConformance = implyingConformance;
628644 }
629645
630646 // / Determine whether this conformance is lazily loaded.
0 commit comments