@@ -114,6 +114,11 @@ class MemoryLocations {
114114 // / Bit 2 is never set because Inner is completly represented by its
115115 // / sub-locations 3 and 4. But bit 0 is set in location 0 (the "self" bit),
116116 // / 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.
117122 Bits subLocations;
118123
119124 // / The accumulated parent bits, including the "self" bit.
@@ -142,6 +147,12 @@ class MemoryLocations {
142147 // / \endcode
143148 int parentIdx;
144149
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+
145156 private:
146157 friend class MemoryLocations ;
147158
@@ -178,11 +189,18 @@ class MemoryLocations {
178189 // / small. They can be handled separately with handleSingleBlockLocations().
179190 llvm::SmallVector<SingleValueInstruction *, 16 > singleBlockLocations;
180191
192+ // / A Cache for single-payload enums.
193+ llvm::DenseMap<SILType, EnumElementDecl *> singlePayloadEnums;
194+
181195 // / The bit-set of locations for which numNonTrivialFieldsNotCovered is > 0.
182196 Bits nonTrivialLocations;
183197
198+ // / If true, support init_enum_data_addr and unchecked_take_enum_data_addr
199+ bool handleEnumDataProjections;
200+
184201public:
185- MemoryLocations () {}
202+ MemoryLocations (bool handleEnumDataProjections) :
203+ handleEnumDataProjections (handleEnumDataProjections) {}
186204
187205 MemoryLocations (const MemoryLocations &) = delete ;
188206 MemoryLocations &operator =(const MemoryLocations &) = delete ;
@@ -207,6 +225,9 @@ class MemoryLocations {
207225 const Location *getLocation (unsigned index) const {
208226 return &locations[index];
209227 }
228+
229+ // / Returns the root location of \p index.
230+ const Location *getRootLocation (unsigned index) const ;
210231
211232 // / Registers an address projection instruction for a location.
212233 void registerProjection (SingleValueInstruction *projection, unsigned locIdx) {
@@ -262,6 +283,15 @@ class MemoryLocations {
262283 // (locationIdx, fieldNr) -> subLocationIdx
263284 using SubLocationMap = llvm::DenseMap<std::pair<unsigned , unsigned >, unsigned >;
264285
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+
265295 // / Helper function called by analyzeLocation to check all uses of the
266296 // / location recursively.
267297 // /
0 commit comments