@@ -96,35 +96,120 @@ enum IsDependent_t : unsigned {
96
96
IsNotDependent = false ,
97
97
IsDependent = true
98
98
};
99
-
99
+
100
+ // / Is a lowered SIL type trivial? That is, are copies ultimately just
101
+ // / bit-copies, and it takes no work to destroy a value?
102
+ enum IsTrivial_t : bool {
103
+ IsNotTrivial = false ,
104
+ IsTrivial = true
105
+ };
106
+
107
+ // / Is a lowered SIL type fixed-ABI? That is, can the current context
108
+ // / assign it a fixed size and alignment and perform value operations on it
109
+ // / (such as copies, destroys, constructions, and projections) without
110
+ // / metadata?
111
+ // /
112
+ // / Note that a fully concrete type can be non-fixed-ABI without being
113
+ // / itself resilient if it contains a subobject which is not fixed-ABI.
114
+ // /
115
+ // / Also note that we're only concerned with the external value ABI here:
116
+ // / resilient class types are still fixed-ABI, indirect enum cases do not
117
+ // / affect the fixed-ABI-ness of the enum, and so on.
118
+ enum IsFixedABI_t : bool {
119
+ IsNotFixedABI = false ,
120
+ IsFixedABI = true
121
+ };
122
+
123
+ // / Is a lowered SIL type address-only? That is, is the current context
124
+ // / required to keep the value in memory for some reason?
125
+ // /
126
+ // / A type might be address-only because:
127
+ // /
128
+ // / - it is not fixed-size (e.g. because it is a resilient type) and
129
+ // / therefore cannot be loaded into a statically-boundable set of
130
+ // / registers; or
131
+ // /
132
+ // / - it is semantically bound to memory, either because its storage
133
+ // / address is used by the language runtime to implement its semantics
134
+ // / (as with a weak reference) or because its representation is somehow
135
+ // / address-dependent (as with something like a relative pointer).
136
+ // /
137
+ // / An address-only type can be fixed-layout and/or trivial.
138
+ // / A non-fixed-layout type is always address-only.
139
+ enum IsAddressOnly_t : bool {
140
+ IsNotAddressOnly = false ,
141
+ IsAddressOnly = true
142
+ };
143
+
144
+ // / Is this type somewhat like a reference-counted type?
145
+ enum IsReferenceCounted_t : bool {
146
+ IsNotReferenceCounted = false ,
147
+ IsReferenceCounted = true
148
+ };
149
+
100
150
// / Extended type information used by SIL.
101
151
class TypeLowering {
102
152
public:
103
- enum IsTrivial_t : bool { IsNotTrivial, IsTrivial };
104
- enum IsAddressOnly_t : bool { IsNotAddressOnly, IsAddressOnly };
105
- enum IsReferenceCounted_t : bool {
106
- IsNotReferenceCounted,
107
- IsReferenceCounted
153
+ class RecursiveProperties {
154
+ // These are chosen so that bitwise-or merges the flags properly.
155
+ enum : unsigned {
156
+ NonTrivialFlag = 1 << 0 ,
157
+ NonFixedABIFlag = 1 << 1 ,
158
+ AddressOnlyFlag = 1 << 2 ,
159
+ };
160
+
161
+ uint8_t Flags;
162
+ public:
163
+ // / Construct a default RecursiveProperties, which corresponds to
164
+ // / a trivial, loadable, fixed-layout type.
165
+ constexpr RecursiveProperties () : Flags(0 ) {}
166
+
167
+ constexpr RecursiveProperties (IsTrivial_t isTrivial,
168
+ IsFixedABI_t isFixedABI,
169
+ IsAddressOnly_t isAddressOnly)
170
+ : Flags((isTrivial ? 0U : NonTrivialFlag) |
171
+ (isAddressOnly ? AddressOnlyFlag : 0U ) |
172
+ (isFixedABI ? 0U : NonFixedABIFlag)) {}
173
+
174
+ static constexpr RecursiveProperties forReference () {
175
+ return {IsNotTrivial, IsFixedABI, IsNotAddressOnly};
176
+ }
177
+
178
+ static constexpr RecursiveProperties forOpaque () {
179
+ return {IsNotTrivial, IsNotFixedABI, IsAddressOnly};
180
+ }
181
+
182
+ void addSubobject (RecursiveProperties other) {
183
+ Flags |= other.Flags ;
184
+ }
185
+
186
+ IsTrivial_t isTrivial () const {
187
+ return IsTrivial_t ((Flags & NonTrivialFlag) == 0 );
188
+ }
189
+ IsFixedABI_t isFixedABI () const {
190
+ return IsFixedABI_t ((Flags & NonFixedABIFlag) == 0 );
191
+ }
192
+ IsAddressOnly_t isAddressOnly () const {
193
+ return IsAddressOnly_t ((Flags & AddressOnlyFlag) != 0 );
194
+ }
195
+
196
+ void setNonTrivial () { Flags |= NonTrivialFlag; }
197
+ void setNonFixedABI () { Flags |= NonFixedABIFlag; }
198
+ void setAddressOnly () { Flags |= AddressOnlyFlag; }
108
199
};
109
200
110
201
private:
111
202
// / The SIL type of values with this Swift type.
112
203
SILType LoweredType;
113
204
114
- enum : unsigned {
115
- IsTrivialFlag = 0x1 ,
116
- IsAddressOnlyFlag = 0x2 ,
117
- IsReferenceCountedFlag = 0x4 ,
118
- };
119
- unsigned Flags;
205
+ RecursiveProperties Properties;
206
+ unsigned ReferenceCounted : 1 ;
120
207
121
208
protected:
122
- TypeLowering (SILType type, IsTrivial_t isTrivial,
123
- IsAddressOnly_t isAddressOnly,
209
+ TypeLowering (SILType type, RecursiveProperties properties,
124
210
IsReferenceCounted_t isRefCounted)
125
- : LoweredType(type), Flags((isTrivial ? IsTrivialFlag : 0U ) |
126
- (isAddressOnly ? IsAddressOnlyFlag : 0U ) |
127
- (isRefCounted ? IsReferenceCountedFlag : 0U )) {}
211
+ : LoweredType(type), Properties(properties),
212
+ ReferenceCounted (isRefCounted) {}
128
213
129
214
public:
130
215
TypeLowering (const TypeLowering &) = delete;
@@ -143,30 +228,41 @@ class TypeLowering {
143
228
// / This is independent of whether the SIL result is address type.
144
229
bool isFormallyReturnedIndirectly () const { return isAddressOnly (); }
145
230
231
+ RecursiveProperties getRecursiveProperties () const {
232
+ return Properties;
233
+ }
234
+
146
235
// / isAddressOnly - Returns true if the type is an address-only type. A type
147
236
// / is address-only if it is a resilient value type, or if it is a fragile
148
237
// / value type with a resilient member. In either case, the full layout of
149
238
// / values of the type is unavailable to the compiler.
150
239
bool isAddressOnly () const {
151
- return Flags & IsAddressOnlyFlag ;
240
+ return Properties. isAddressOnly () ;
152
241
}
153
242
// / isLoadable - Returns true if the type is loadable, in other words, its
154
243
// / full layout is available to the compiler. This is the inverse of
155
244
// / isAddressOnly.
156
245
bool isLoadable () const {
157
246
return !isAddressOnly ();
158
247
}
248
+
249
+ // / isFixedABI - Returns true if the type has a known fixed layout.
250
+ // / If this is true, value operations on the type can be performed even if
251
+ // / the type is inaccessible.
252
+ bool isFixedABI () const {
253
+ return Properties.isFixedABI ();
254
+ }
159
255
160
256
// / Returns true if the type is trivial, meaning it is a loadable
161
257
// / value type with no reference type members that require releasing.
162
258
bool isTrivial () const {
163
- return Flags & IsTrivialFlag ;
259
+ return Properties. isTrivial () ;
164
260
}
165
261
166
262
// / Returns true if the type is a scalar reference-counted reference, which
167
263
// / can be retained and released.
168
264
bool isReferenceCounted () const {
169
- return Flags & IsReferenceCountedFlag ;
265
+ return ReferenceCounted ;
170
266
}
171
267
172
268
// / getLoweredType - Get the type used to represent values of the Swift type
0 commit comments