Skip to content

Commit 3d0b12e

Browse files
committed
MemoryLifetime: fix a problem where DestroyHoisting moved a destroy_addr before a use of a trivial type.
Even if a destroy_addr of a trivial type is a no-op, we must not end up with using such a value after a destroy_addr. The fix is to also handle aggregate fields of trivial types in MemoryLifetime. rdar://problem/55125020
1 parent c79214c commit 3d0b12e

File tree

7 files changed

+206
-49
lines changed

7 files changed

+206
-49
lines changed

docs/SIL.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2525,7 +2525,9 @@ except that ``destroy_addr`` may be used even if ``%0`` is of an
25252525
address-only type. This does not deallocate memory; it only destroys the
25262526
pointed-to value, leaving the memory uninitialized.
25272527

2528-
If ``T`` is a trivial type, then ``destroy_addr`` is a no-op.
2528+
If ``T`` is a trivial type, then ``destroy_addr`` is a no-op. However, even a
2529+
memory location ``%a`` with a trivial type must not be accessed after a
2530+
``destroy_addr %a``.
25292531

25302532
index_addr
25312533
``````````

include/swift/SIL/MemoryLifetime.h

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,23 @@ class MemoryLocations {
131131
/// \endcode
132132
int parentIdx;
133133

134+
private:
135+
friend class MemoryLocations;
136+
134137
/// Used to decide if a location is completely covered by its sub-locations.
135138
///
136139
/// -1 means: not yet initialized.
137140
int numFieldsNotCoveredBySubfields = -1;
138141

142+
/// The same as ``numFieldsNotCoveredBySubfields``, just for non-trivial
143+
/// fields.
144+
///
145+
/// -1 means: not yet initialized.
146+
int numNonTrivialFieldsNotCovered = -1;
147+
139148
Location(SILValue val, unsigned index, int parentIdx = -1);
149+
150+
void updateFieldCounters(SILType ty, int increment);
140151
};
141152

142153
private:
@@ -156,6 +167,9 @@ class MemoryLocations {
156167
/// small. They can be handled separately with handleSingleBlockLocations().
157168
llvm::SmallVector<SingleValueInstruction *, 16> singleBlockLocations;
158169

170+
/// The bit-set of locations for which numNonTrivialFieldsNotCovered is > 0.
171+
Bits nonTrivialLocations;
172+
159173
public:
160174
MemoryLocations() {}
161175

@@ -220,6 +234,10 @@ class MemoryLocations {
220234
void handleSingleBlockLocations(
221235
std::function<void (SILBasicBlock *block)> handlerFunc);
222236

237+
/// Returns the set of locations for which have non trivial fields which are
238+
/// not covered by sub-fields.
239+
const Bits &getNonTrivialLocations();
240+
223241
/// Debug dump the MemoryLifetime internals.
224242
void dump() const;
225243

@@ -249,11 +267,6 @@ class MemoryLocations {
249267

250268
/// Calculates Location::numFieldsNotCoveredBySubfields
251269
void initFieldsCounter(Location &loc);
252-
253-
/// Only memory locations which store a non-trivial type are considered.
254-
bool shouldTrackLocation(SILType type, SILFunction *inFunction) {
255-
return !type.isTrivial(*inFunction);
256-
}
257270
};
258271

259272
/// The MemoryDataflow utility calculates global dataflow of memory locations.

0 commit comments

Comments
 (0)