Skip to content

Commit 1affb47

Browse files
authored
Merge pull request #36054 from eeckstein/memory-lifetime-for-enums
MemoryLifetimeVerifier: support verifying enum memory locations.
2 parents 8e0d3ba + 65a6d9a commit 1affb47

File tree

13 files changed

+450
-63
lines changed

13 files changed

+450
-63
lines changed

docs/SIL.rst

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2320,6 +2320,54 @@ The current list of interior pointer SIL instructions are:
23202320
(*) We still need to finish adding support for project_box, but all other
23212321
interior pointers are guarded already.
23222322

2323+
Memory Lifetime
2324+
~~~~~~~~~~~~~~~
2325+
2326+
Similar to Ownership SSA, there are also lifetime rules for values in memory.
2327+
With "memory" we refer to memory which is addressed by SIL instruction with
2328+
address-type operands, like ``load``, ``store``, ``switch_enum_addr``, etc.
2329+
2330+
Each memory location which holds a non-trivial value is either uninitialized
2331+
or initialized. A memory location gets initialized by storing values into it
2332+
(except assignment, which expects a location to be already initialized).
2333+
A memory location gets de-initialized by "taking" from it or destroying it, e.g.
2334+
with ``destroy_addr``. It is illegal to re-initialize a memory location or to
2335+
use a location after it was de-initialized.
2336+
2337+
If a memory location holds a trivial value (e.g. an ``Int``), it is not
2338+
required to de-initialize the location.
2339+
2340+
The SIL verifier checks this rule for memory locations which can be uniquely
2341+
identified, for example and ``alloc_stack`` or an indirect parameter. The
2342+
verifier cannot check memory locations which are potentially aliased, e.g.
2343+
a ``ref_element_addr`` (a stored class property).
2344+
2345+
Lifetime of Enums in Memory
2346+
```````````````````````````
2347+
2348+
The situation is a bit more complicated with enums, because an enum can have
2349+
both, cases with non-trivial payloads and cases with no payload or trivial
2350+
payloads.
2351+
2352+
Even if an enum itself is not trivial (because it has at least on case with a
2353+
non-trivial payload), it is not required to de-initialize such an enum memory
2354+
location on paths where it's statically provable that the enum contains a
2355+
trivial or non-payload case.
2356+
2357+
That's the case if the destroy point is jointly dominated by:
2358+
2359+
* a ``store [trivial]`` to the enum memory location.
2360+
2361+
or
2362+
2363+
* an ``inject_enum_addr`` to the enum memory location with a non-trivial or
2364+
non-payload case.
2365+
2366+
or
2367+
2368+
* a successor of a ``switch_enum`` or ``switch_enum_addr`` for a non-trivial
2369+
or non-payload case.
2370+
23232371
Dead End Blocks
23242372
~~~~~~~~~~~~~~~
23252373

include/swift/SIL/MemoryLifetime.h

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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+
184201
public:
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

Comments
 (0)