@@ -114,6 +114,11 @@ class MemoryLocations {
114
114
// / Bit 2 is never set because Inner is completly represented by its
115
115
// / sub-locations 3 and 4. But bit 0 is set in location 0 (the "self" bit),
116
116
// / because it represents the untracked field ``Outer.z``.
117
+ // /
118
+ // / Single-payload enums are represented by a location with a single sub-
119
+ // / location (the projected payload address, i.e. an ``init_enum_data_addr``
120
+ // / or an ``unchecked_take_enum_data_addr``.
121
+ // / Multi-payload enums are not supported right now.
117
122
Bits subLocations;
118
123
119
124
// / The accumulated parent bits, including the "self" bit.
@@ -142,6 +147,12 @@ class MemoryLocations {
142
147
// / \endcode
143
148
int parentIdx;
144
149
150
+ // / Returns true if the location with index \p idx is this location or a
151
+ // / sub location of this location.
152
+ bool isSubLocation (unsigned idx) const {
153
+ return idx < subLocations.size () && subLocations.test (idx);
154
+ }
155
+
145
156
private:
146
157
friend class MemoryLocations ;
147
158
@@ -178,11 +189,18 @@ class MemoryLocations {
178
189
// / small. They can be handled separately with handleSingleBlockLocations().
179
190
llvm::SmallVector<SingleValueInstruction *, 16 > singleBlockLocations;
180
191
192
+ // / A Cache for single-payload enums.
193
+ llvm::DenseMap<SILType, EnumElementDecl *> singlePayloadEnums;
194
+
181
195
// / The bit-set of locations for which numNonTrivialFieldsNotCovered is > 0.
182
196
Bits nonTrivialLocations;
183
197
198
+ // / If true, support init_enum_data_addr and unchecked_take_enum_data_addr
199
+ bool handleEnumDataProjections;
200
+
184
201
public:
185
- MemoryLocations () {}
202
+ MemoryLocations (bool handleEnumDataProjections) :
203
+ handleEnumDataProjections (handleEnumDataProjections) {}
186
204
187
205
MemoryLocations (const MemoryLocations &) = delete ;
188
206
MemoryLocations &operator =(const MemoryLocations &) = delete ;
@@ -207,6 +225,9 @@ class MemoryLocations {
207
225
const Location *getLocation (unsigned index) const {
208
226
return &locations[index];
209
227
}
228
+
229
+ // / Returns the root location of \p index.
230
+ const Location *getRootLocation (unsigned index) const ;
210
231
211
232
// / Registers an address projection instruction for a location.
212
233
void registerProjection (SingleValueInstruction *projection, unsigned locIdx) {
@@ -262,6 +283,15 @@ class MemoryLocations {
262
283
// (locationIdx, fieldNr) -> subLocationIdx
263
284
using SubLocationMap = llvm::DenseMap<std::pair<unsigned , unsigned >, unsigned >;
264
285
286
+ // / Returns the payload case of a single-payload enum.
287
+ // /
288
+ // / Returns null if \p enumTy is not a single-payload enum.
289
+ // / We are currently only handling enum data projections for single-payload
290
+ // / enums, because it's much simpler to represent them with Locations. We
291
+ // / could also support multi-payload enums, but that gets complicated. Most
292
+ // / importantly, we can handle Swift.Optional.
293
+ EnumElementDecl *getSinglePayloadEnumCase (SILType enumTy);
294
+
265
295
// / Helper function called by analyzeLocation to check all uses of the
266
296
// / location recursively.
267
297
// /
0 commit comments