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,7 +56,7 @@ 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.
6162 Normal,
@@ -69,20 +70,54 @@ enum class ProtocolConformanceKind {
6970 Inherited,
7071 // / Builtin conformances are special conformances that the runtime handles
7172 // / and isn't implemented directly in Swift.
72- Builtin
73+ Builtin,
74+
75+ Last_Kind = Builtin
76+ };
77+ enum : unsigned {
78+ NumProtocolConformanceKindBits =
79+ countBitsUsed (static_cast <unsigned >(ProtocolConformanceKind::Last_Kind))
7380};
7481
7582// / Describes the state of a protocol conformance, which may be complete,
7683// / incomplete, or currently being checked.
7784enum class ProtocolConformanceState {
7885 // / The conformance has been fully checked.
79- Complete,
86+ Complete = 0 ,
8087 // / The conformance is known but is not yet complete.
8188 Incomplete,
8289 // / The conformance's type witnesses are currently being resolved.
8390 CheckingTypeWitnesses,
8491 // / The conformance is being checked.
8592 Checking,
93+
94+ Last_State = Checking
95+ };
96+
97+ // / Describes the kind of a builtin conformance.
98+ enum class BuiltinConformanceKind {
99+ // A builtin conformance that has been synthesized by the implementation.
100+ Synthesized = 0 ,
101+ // A missing conformance that we have nonetheless synthesized so that
102+ // we can diagnose it later.
103+ Missing,
104+
105+ Last_Kind = Missing
106+ };
107+
108+ enum : unsigned {
109+ NumProtocolConformanceStateBits =
110+ countBitsUsed (static_cast <unsigned >(ProtocolConformanceState::Last_State))
111+ };
112+
113+ enum : unsigned {
114+ NumConformanceEntryKindBits =
115+ countBitsUsed (static_cast <unsigned >(ConformanceEntryKind::Last_Kind))
116+ };
117+
118+ enum : unsigned {
119+ NumBuiltinConformanceKindBits =
120+ countBitsUsed (static_cast <unsigned >(BuiltinConformanceKind::Last_Kind))
86121};
87122
88123// / Describes how a particular type conforms to a given protocol,
@@ -93,20 +128,73 @@ enum class ProtocolConformanceState {
93128// / for the various kinds of conformance (normal, specialized, inherited).
94129class alignas (1 << DeclAlignInBits) ProtocolConformance
95130 : public ASTAllocated<ProtocolConformance> {
96- // / The kind of protocol conformance.
97- ProtocolConformanceKind Kind;
98-
99131 // / The type that conforms to the protocol, in the context of the
100132 // / conformance definition.
101133 Type ConformingType;
102134
103135protected:
136+ // clang-format off
137+ //
138+ // We format these different than clang-format wishes us to... so turn if off
139+ // for the inline bitfields.
140+ union { uint64_t OpaqueBits;
141+
142+ SWIFT_INLINE_BITFIELD_BASE (ProtocolConformance,
143+ bitmax (NumProtocolConformanceKindBits, 8 ),
144+ // / The kind of protocol conformance.
145+ Kind : bitmax (NumProtocolConformanceKindBits, 8 )
146+ );
147+
148+ SWIFT_INLINE_BITFIELD_EMPTY (RootProtocolConformance, ProtocolConformance);
149+
150+ SWIFT_INLINE_BITFIELD_FULL (NormalProtocolConformance, RootProtocolConformance,
151+ 1 +1 +1 +1 +bitmax (NumProtocolConformanceStateBits,8 )+
152+ bitmax (NumConformanceEntryKindBits,8 ),
153+ // / Indicates whether the conformance is invalid.
154+ IsInvalid : 1 ,
155+ // / The conformance was labeled with @unchecked.
156+ IsUnchecked : 1 ,
157+ // / The conformance was labeled with @preconcurrency.
158+ IsPreconcurrency : 1 ,
159+ // / We have allocated the AssociatedConformances array (but not necessarily
160+ // / populated any of its elements).
161+ HasComputedAssociatedConformances : 1 ,
162+
163+ : NumPadBits,
164+
165+ // / The current state of the conformance.
166+ State : bitmax (NumProtocolConformanceStateBits, 8 ),
167+ // / The reason that this conformance exists.
168+ // /
169+ // / Either Explicit (e.g. 'struct Foo: Protocol {}' or 'extension Foo:
170+ // / Protocol {}'), Synthesized (e.g. RawRepresentable for 'enum Foo: Int {}')
171+ // / or Implied (e.g. 'Foo : Protocol' in 'protocol Other: Protocol {} struct
172+ // / Foo: Other {}'). In only the latter case, the conformance is non-null and
173+ // / points to the conformance that implies this one.
174+ // /
175+ // / This should never be Inherited: that is handled by
176+ // / InheritedProtocolConformance.
177+ SourceKind : bitmax (NumConformanceEntryKindBits, 8 )
178+ );
179+
180+ SWIFT_INLINE_BITFIELD (BuiltinProtocolConformance, RootProtocolConformance,
181+ bitmax (NumBuiltinConformanceKindBits, 8 ),
182+ // / The kind of the builtin conformance
183+ Kind: bitmax (NumBuiltinConformanceKindBits, 8 )
184+ );
185+ } Bits;
186+ // clang-format on
187+
104188 ProtocolConformance (ProtocolConformanceKind kind, Type conformingType)
105- : Kind (kind), ConformingType (conformingType) {}
189+ : ConformingType (conformingType) {
190+ Bits.ProtocolConformance .Kind = unsigned (kind);
191+ }
106192
107193public:
108194 // / Determine the kind of protocol conformance.
109- ProtocolConformanceKind getKind () const { return Kind; }
195+ ProtocolConformanceKind getKind () const {
196+ return static_cast <ProtocolConformanceKind>(Bits.ProtocolConformance .Kind );
197+ }
110198
111199 // / Get the conforming type.
112200 Type getType () const { return ConformingType; }
@@ -435,49 +523,17 @@ class NormalProtocolConformance : public RootProtocolConformance,
435523 friend class ValueWitnessRequest ;
436524 friend class TypeWitnessRequest ;
437525
438- // / The protocol being conformed to and its current state.
439- llvm::PointerIntPair<ProtocolDecl *, 2 , ProtocolConformanceState>
440- ProtocolAndState;
526+ // / The protocol being conformed to.
527+ ProtocolDecl *Protocol;
441528
442529 // / The location of this protocol conformance in the source.
443530 SourceLoc Loc;
444531
445- // Flag bits used in ContextAndBits.
446- enum {
447- // / The conformance was labeled with @unchecked.
448- UncheckedFlag = 0x01 ,
449-
450- // / The conformance was labeled with @preconcurrency.
451- PreconcurrencyFlag = 0x02 ,
452-
453- // / We have allocated the AssociatedConformances array (but not necessarily
454- // / populated any of its elements).
455- HasComputedAssociatedConformancesFlag = 0x04 ,
456- };
457-
458532 // / The declaration context containing the ExtensionDecl or
459533 // / NominalTypeDecl that declared the conformance.
460- // /
461- // / Also stores the "unchecked", "preconcurrency" and "has computed associated
462- // / conformances" bits.
463- llvm::PointerIntPair<DeclContext *, 3 , unsigned > ContextAndBits;
534+ DeclContext *Context;
464535
465- // / Indicates whether the conformance is invalid.
466- bool Invalid : 1 ;
467-
468- // / The reason that this conformance exists.
469- // /
470- // / Either Explicit (e.g. 'struct Foo: Protocol {}' or 'extension Foo:
471- // / Protocol {}'), Synthesized (e.g. RawRepresentable for 'enum Foo: Int {}')
472- // / or Implied (e.g. 'Foo : Protocol' in 'protocol Other: Protocol {} struct
473- // / Foo: Other {}'). In only the latter case, the conformance is non-null and
474- // / points to the conformance that implies this one.
475- // /
476- // / This should never be Inherited: that is handled by
477- // / InheritedProtocolConformance.
478- llvm::PointerIntPair<NormalProtocolConformance *, 3 , ConformanceEntryKind>
479- SourceKindAndImplyingConformance = {nullptr ,
480- ConformanceEntryKind::Explicit};
536+ NormalProtocolConformance *ImplyingConformance = nullptr ;
481537
482538 // / The mapping of individual requirements in the protocol over to
483539 // / the declarations that satisfy those requirements.
@@ -508,25 +564,27 @@ class NormalProtocolConformance : public RootProtocolConformance,
508564 bool isPreconcurrency)
509565 : RootProtocolConformance(ProtocolConformanceKind::Normal,
510566 conformingType),
511- ProtocolAndState (protocol, state), Loc(loc),
512- ContextAndBits(dc, ((isUnchecked ? UncheckedFlag : 0 ) |
513- (isPreconcurrency ? PreconcurrencyFlag : 0 ))),
514- Invalid(false ) {
567+ Protocol (protocol), Loc(loc), Context(dc) {
515568 assert (!conformingType->hasArchetype () &&
516569 " ProtocolConformances should store interface types" );
570+ setState (state);
571+ Bits.NormalProtocolConformance .IsInvalid = false ;
572+ Bits.NormalProtocolConformance .IsUnchecked = isUnchecked;
573+ Bits.NormalProtocolConformance .IsPreconcurrency = isPreconcurrency;
574+ Bits.NormalProtocolConformance .HasComputedAssociatedConformances = false ;
575+ Bits.NormalProtocolConformance .SourceKind =
576+ unsigned (ConformanceEntryKind::Explicit);
517577 }
518578
519579 // / Get the protocol being conformed to.
520- ProtocolDecl *getProtocol () const { return ProtocolAndState. getPointer () ; }
580+ ProtocolDecl *getProtocol () const { return Protocol ; }
521581
522582 // / Retrieve the location of this
523583 SourceLoc getLoc () const { return Loc; }
524584
525585 // / Get the declaration context that contains the conforming extension or
526586 // / nominal type declaration.
527- DeclContext *getDeclContext () const {
528- return ContextAndBits.getPointer ();
529- }
587+ DeclContext *getDeclContext () const { return Context; }
530588
531589 // / Get any additional requirements that are required for this conformance to
532590 // / be satisfied, e.g. for Array<T>: Equatable, T: Equatable also needs
@@ -538,59 +596,59 @@ class NormalProtocolConformance : public RootProtocolConformance,
538596
539597 // / Retrieve the state of this conformance.
540598 ProtocolConformanceState getState () const {
541- return ProtocolAndState.getInt ();
599+ return static_cast <ProtocolConformanceState>(
600+ Bits.NormalProtocolConformance .State );
542601 }
543602
544603 // / Set the state of this conformance.
545604 void setState (ProtocolConformanceState state) {
546- ProtocolAndState. setInt (state);
605+ Bits. NormalProtocolConformance . State = unsigned (state);
547606 }
548607
549608 // / Determine whether this conformance is invalid.
550- bool isInvalid () const {
551- return Invalid;
552- }
609+ bool isInvalid () const { return Bits.NormalProtocolConformance .IsInvalid ; }
553610
554611 // / Mark this conformance as invalid.
555- void setInvalid () {
556- Invalid = true ;
557- }
612+ void setInvalid () { Bits.NormalProtocolConformance .IsInvalid = true ; }
558613
559614 // / Whether this is an "unchecked" conformance.
560615 bool isUnchecked () const {
561- return ContextAndBits. getInt () & UncheckedFlag ;
616+ return Bits. NormalProtocolConformance . IsUnchecked ;
562617 }
563618
564619 // / Mark the conformance as unchecked (equivalent to the @unchecked
565620 // / conformance attribute).
566621 void setUnchecked () {
567622 // OK to mutate because the flags are not part of the folding set node ID.
568- ContextAndBits. setInt (ContextAndBits. getInt () | UncheckedFlag) ;
623+ Bits. NormalProtocolConformance . IsUnchecked = true ;
569624 }
570625
571626 // / Whether this is an preconcurrency conformance.
572- bool isPreconcurrency () const ;
627+ bool isPreconcurrency () const {
628+ return Bits.NormalProtocolConformance .IsPreconcurrency ;
629+ }
573630
574631 // / Determine whether we've lazily computed the associated conformance array
575632 // / already.
576633 bool hasComputedAssociatedConformances () const {
577- return ContextAndBits. getInt () & HasComputedAssociatedConformancesFlag ;
634+ return Bits. NormalProtocolConformance . HasComputedAssociatedConformances ;
578635 }
579636
580637 // / Mark this conformance as having computed the assocaited conformance array.
581638 void setHasComputedAssociatedConformances () {
582- ContextAndBits. setInt (ContextAndBits. getInt () | HasComputedAssociatedConformancesFlag) ;
639+ Bits. NormalProtocolConformance . HasComputedAssociatedConformances = true ;
583640 }
584641
585642 // / Get the kind of source from which this conformance comes.
586643 ConformanceEntryKind getSourceKind () const {
587- return SourceKindAndImplyingConformance.getInt ();
644+ return static_cast <ConformanceEntryKind>(
645+ Bits.NormalProtocolConformance .SourceKind );
588646 }
589647
590648 // / Get the protocol conformance which implied this implied conformance.
591649 NormalProtocolConformance *getImplyingConformance () const {
592650 assert (getSourceKind () == ConformanceEntryKind::Implied);
593- return SourceKindAndImplyingConformance. getPointer () ;
651+ return ImplyingConformance ;
594652 }
595653
596654 void setSourceKindAndImplyingConformance (
@@ -603,7 +661,8 @@ class NormalProtocolConformance : public RootProtocolConformance,
603661 " an implied conformance needs something that implies it" );
604662 assert (sourceKind != ConformanceEntryKind::PreMacroExpansion &&
605663 " cannot create conformance pre-macro-expansion" );
606- SourceKindAndImplyingConformance = {implyingConformance, sourceKind};
664+ Bits.NormalProtocolConformance .SourceKind = unsigned (sourceKind);
665+ ImplyingConformance = implyingConformance;
607666 }
608667
609668 // / Determine whether this conformance is lazily loaded.
@@ -1056,22 +1115,12 @@ class InheritedProtocolConformance : public ProtocolConformance,
10561115 }
10571116};
10581117
1059- // / Describes the kind of a builtin conformance.
1060- enum class BuiltinConformanceKind {
1061- // A builtin conformance that has been synthesized by the implementation.
1062- Synthesized = 0 ,
1063- // A missing conformance that we have nonetheless synthesized so that
1064- // we can diagnose it later.
1065- Missing,
1066- };
1067-
10681118// / A builtin conformance appears when a non-nominal type has a
10691119// / conformance that is synthesized by the implementation.
10701120class BuiltinProtocolConformance final : public RootProtocolConformance {
10711121 friend ASTContext;
10721122
10731123 ProtocolDecl *protocol;
1074- unsigned builtinConformanceKind;
10751124
10761125 BuiltinProtocolConformance (Type conformingType, ProtocolDecl *protocol,
10771126 BuiltinConformanceKind kind);
@@ -1083,7 +1132,8 @@ class BuiltinProtocolConformance final : public RootProtocolConformance {
10831132 }
10841133
10851134 BuiltinConformanceKind getBuiltinConformanceKind () const {
1086- return static_cast <BuiltinConformanceKind>(builtinConformanceKind);
1135+ return static_cast <BuiltinConformanceKind>(
1136+ Bits.BuiltinProtocolConformance .Kind );
10871137 }
10881138
10891139 GenericSignature getGenericSignature () const {
0 commit comments