24
24
#include " swift/AST/Witness.h"
25
25
#include " swift/Basic/Compiler.h"
26
26
#include " swift/Basic/Debug.h"
27
+ #include " swift/Basic/InlineBitfield.h"
27
28
#include " llvm/ADT/ArrayRef.h"
28
29
#include " llvm/ADT/DenseMap.h"
29
30
#include " llvm/ADT/FoldingSet.h"
@@ -55,7 +56,7 @@ typedef llvm::DenseMap<AssociatedTypeDecl *, TypeWitnessAndDecl>
55
56
56
57
// / Describes the kind of protocol conformance structure used to encode
57
58
// / conformance.
58
- enum class ProtocolConformanceKind {
59
+ enum class ProtocolConformanceKind : unsigned {
59
60
// / "Normal" conformance of a (possibly generic) nominal type, which
60
61
// / contains complete mappings.
61
62
Normal,
@@ -69,20 +70,54 @@ enum class ProtocolConformanceKind {
69
70
Inherited,
70
71
// / Builtin conformances are special conformances that the runtime handles
71
72
// / 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))
73
80
};
74
81
75
82
// / Describes the state of a protocol conformance, which may be complete,
76
83
// / incomplete, or currently being checked.
77
84
enum class ProtocolConformanceState {
78
85
// / The conformance has been fully checked.
79
- Complete,
86
+ Complete = 0 ,
80
87
// / The conformance is known but is not yet complete.
81
88
Incomplete,
82
89
// / The conformance's type witnesses are currently being resolved.
83
90
CheckingTypeWitnesses,
84
91
// / The conformance is being checked.
85
92
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))
86
121
};
87
122
88
123
// / Describes how a particular type conforms to a given protocol,
@@ -93,20 +128,73 @@ enum class ProtocolConformanceState {
93
128
// / for the various kinds of conformance (normal, specialized, inherited).
94
129
class alignas (1 << DeclAlignInBits) ProtocolConformance
95
130
: public ASTAllocated<ProtocolConformance> {
96
- // / The kind of protocol conformance.
97
- ProtocolConformanceKind Kind;
98
-
99
131
// / The type that conforms to the protocol, in the context of the
100
132
// / conformance definition.
101
133
Type ConformingType;
102
134
103
135
protected:
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
+
104
188
ProtocolConformance (ProtocolConformanceKind kind, Type conformingType)
105
- : Kind (kind), ConformingType (conformingType) {}
189
+ : ConformingType (conformingType) {
190
+ Bits.ProtocolConformance .Kind = unsigned (kind);
191
+ }
106
192
107
193
public:
108
194
// / 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
+ }
110
198
111
199
// / Get the conforming type.
112
200
Type getType () const { return ConformingType; }
@@ -435,49 +523,17 @@ class NormalProtocolConformance : public RootProtocolConformance,
435
523
friend class ValueWitnessRequest ;
436
524
friend class TypeWitnessRequest ;
437
525
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;
441
528
442
529
// / The location of this protocol conformance in the source.
443
530
SourceLoc Loc;
444
531
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
-
458
532
// / The declaration context containing the ExtensionDecl or
459
533
// / 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;
464
535
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 ;
481
537
482
538
// / The mapping of individual requirements in the protocol over to
483
539
// / the declarations that satisfy those requirements.
@@ -508,25 +564,27 @@ class NormalProtocolConformance : public RootProtocolConformance,
508
564
bool isPreconcurrency)
509
565
: RootProtocolConformance(ProtocolConformanceKind::Normal,
510
566
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) {
515
568
assert (!conformingType->hasArchetype () &&
516
569
" 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);
517
577
}
518
578
519
579
// / Get the protocol being conformed to.
520
- ProtocolDecl *getProtocol () const { return ProtocolAndState. getPointer () ; }
580
+ ProtocolDecl *getProtocol () const { return Protocol ; }
521
581
522
582
// / Retrieve the location of this
523
583
SourceLoc getLoc () const { return Loc; }
524
584
525
585
// / Get the declaration context that contains the conforming extension or
526
586
// / nominal type declaration.
527
- DeclContext *getDeclContext () const {
528
- return ContextAndBits.getPointer ();
529
- }
587
+ DeclContext *getDeclContext () const { return Context; }
530
588
531
589
// / Get any additional requirements that are required for this conformance to
532
590
// / be satisfied, e.g. for Array<T>: Equatable, T: Equatable also needs
@@ -538,59 +596,59 @@ class NormalProtocolConformance : public RootProtocolConformance,
538
596
539
597
// / Retrieve the state of this conformance.
540
598
ProtocolConformanceState getState () const {
541
- return ProtocolAndState.getInt ();
599
+ return static_cast <ProtocolConformanceState>(
600
+ Bits.NormalProtocolConformance .State );
542
601
}
543
602
544
603
// / Set the state of this conformance.
545
604
void setState (ProtocolConformanceState state) {
546
- ProtocolAndState. setInt (state);
605
+ Bits. NormalProtocolConformance . State = unsigned (state);
547
606
}
548
607
549
608
// / Determine whether this conformance is invalid.
550
- bool isInvalid () const {
551
- return Invalid;
552
- }
609
+ bool isInvalid () const { return Bits.NormalProtocolConformance .IsInvalid ; }
553
610
554
611
// / Mark this conformance as invalid.
555
- void setInvalid () {
556
- Invalid = true ;
557
- }
612
+ void setInvalid () { Bits.NormalProtocolConformance .IsInvalid = true ; }
558
613
559
614
// / Whether this is an "unchecked" conformance.
560
615
bool isUnchecked () const {
561
- return ContextAndBits. getInt () & UncheckedFlag ;
616
+ return Bits. NormalProtocolConformance . IsUnchecked ;
562
617
}
563
618
564
619
// / Mark the conformance as unchecked (equivalent to the @unchecked
565
620
// / conformance attribute).
566
621
void setUnchecked () {
567
622
// 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 ;
569
624
}
570
625
571
626
// / Whether this is an preconcurrency conformance.
572
- bool isPreconcurrency () const ;
627
+ bool isPreconcurrency () const {
628
+ return Bits.NormalProtocolConformance .IsPreconcurrency ;
629
+ }
573
630
574
631
// / Determine whether we've lazily computed the associated conformance array
575
632
// / already.
576
633
bool hasComputedAssociatedConformances () const {
577
- return ContextAndBits. getInt () & HasComputedAssociatedConformancesFlag ;
634
+ return Bits. NormalProtocolConformance . HasComputedAssociatedConformances ;
578
635
}
579
636
580
637
// / Mark this conformance as having computed the assocaited conformance array.
581
638
void setHasComputedAssociatedConformances () {
582
- ContextAndBits. setInt (ContextAndBits. getInt () | HasComputedAssociatedConformancesFlag) ;
639
+ Bits. NormalProtocolConformance . HasComputedAssociatedConformances = true ;
583
640
}
584
641
585
642
// / Get the kind of source from which this conformance comes.
586
643
ConformanceEntryKind getSourceKind () const {
587
- return SourceKindAndImplyingConformance.getInt ();
644
+ return static_cast <ConformanceEntryKind>(
645
+ Bits.NormalProtocolConformance .SourceKind );
588
646
}
589
647
590
648
// / Get the protocol conformance which implied this implied conformance.
591
649
NormalProtocolConformance *getImplyingConformance () const {
592
650
assert (getSourceKind () == ConformanceEntryKind::Implied);
593
- return SourceKindAndImplyingConformance. getPointer () ;
651
+ return ImplyingConformance ;
594
652
}
595
653
596
654
void setSourceKindAndImplyingConformance (
@@ -603,7 +661,8 @@ class NormalProtocolConformance : public RootProtocolConformance,
603
661
" an implied conformance needs something that implies it" );
604
662
assert (sourceKind != ConformanceEntryKind::PreMacroExpansion &&
605
663
" cannot create conformance pre-macro-expansion" );
606
- SourceKindAndImplyingConformance = {implyingConformance, sourceKind};
664
+ Bits.NormalProtocolConformance .SourceKind = unsigned (sourceKind);
665
+ ImplyingConformance = implyingConformance;
607
666
}
608
667
609
668
// / Determine whether this conformance is lazily loaded.
@@ -1056,22 +1115,12 @@ class InheritedProtocolConformance : public ProtocolConformance,
1056
1115
}
1057
1116
};
1058
1117
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
-
1068
1118
// / A builtin conformance appears when a non-nominal type has a
1069
1119
// / conformance that is synthesized by the implementation.
1070
1120
class BuiltinProtocolConformance final : public RootProtocolConformance {
1071
1121
friend ASTContext;
1072
1122
1073
1123
ProtocolDecl *protocol;
1074
- unsigned builtinConformanceKind;
1075
1124
1076
1125
BuiltinProtocolConformance (Type conformingType, ProtocolDecl *protocol,
1077
1126
BuiltinConformanceKind kind);
@@ -1083,7 +1132,8 @@ class BuiltinProtocolConformance final : public RootProtocolConformance {
1083
1132
}
1084
1133
1085
1134
BuiltinConformanceKind getBuiltinConformanceKind () const {
1086
- return static_cast <BuiltinConformanceKind>(builtinConformanceKind);
1135
+ return static_cast <BuiltinConformanceKind>(
1136
+ Bits.BuiltinProtocolConformance .Kind );
1087
1137
}
1088
1138
1089
1139
GenericSignature getGenericSignature () const {
0 commit comments