13
13
#define DEBUG_TYPE " sil-access-utils"
14
14
15
15
#include " swift/SIL/MemAccessUtils.h"
16
+ #include " swift/SIL/SILUndef.h"
16
17
17
18
using namespace swift ;
18
19
@@ -115,6 +116,30 @@ static void checkSwitchEnumBlockArg(SILPHIArgument *arg) {
115
116
}
116
117
}
117
118
119
+ // / Return true if the given address value is produced by a special address
120
+ // / producer that is only used for local initialization, not formal access.
121
+ static bool isAddressForLocalInitOnly (SILValue sourceAddr) {
122
+ switch (sourceAddr->getKind ()) {
123
+ default :
124
+ return false ;
125
+
126
+ // Value to address conversions: the operand is the non-address source
127
+ // value. These allow local mutation of the value but should never be used
128
+ // for formal access of an lvalue.
129
+ case ValueKind::OpenExistentialBoxInst:
130
+ case ValueKind::ProjectExistentialBoxInst:
131
+ return true ;
132
+
133
+ // Self-evident local initialization.
134
+ case ValueKind::InitEnumDataAddrInst:
135
+ case ValueKind::InitExistentialAddrInst:
136
+ case ValueKind::AllocExistentialBoxInst:
137
+ case ValueKind::AllocValueBufferInst:
138
+ case ValueKind::ProjectValueBufferInst:
139
+ return true ;
140
+ }
141
+ }
142
+
118
143
AccessedStorage swift::findAccessedStorage (SILValue sourceAddr) {
119
144
SILValue address = sourceAddr;
120
145
while (true ) {
@@ -127,9 +152,12 @@ AccessedStorage swift::findAccessedStorage(SILValue sourceAddr) {
127
152
// Handle other unidentified address sources.
128
153
switch (address->getKind ()) {
129
154
default :
155
+ if (isAddressForLocalInitOnly (address))
156
+ return AccessedStorage (address, AccessedStorage::Unidentified);
130
157
return AccessedStorage ();
131
158
132
159
case ValueKind::PointerToAddressInst:
160
+ case ValueKind::SILUndef:
133
161
return AccessedStorage (address, AccessedStorage::Unidentified);
134
162
135
163
// A block argument may be a box value projected out of
@@ -181,22 +209,6 @@ AccessedStorage swift::findAccessedStorage(SILValue sourceAddr) {
181
209
case ValueKind::IndexAddrInst:
182
210
address = cast<SingleValueInstruction>(address)->getOperand (0 );
183
211
continue ;
184
-
185
- // Value to address conversions: the operand is the non-address source
186
- // value. These allow local mutation of the value but should never be used
187
- // for formal access of an lvalue.
188
- case ValueKind::OpenExistentialBoxInst:
189
- case ValueKind::ProjectExistentialBoxInst:
190
- case ValueKind::ProjectValueBufferInst:
191
- return AccessedStorage (address, AccessedStorage::Unidentified);
192
-
193
- // Local initialization: these cases are skipped.
194
- case ValueKind::InitEnumDataAddrInst:
195
- case ValueKind::InitExistentialAddrInst:
196
- case ValueKind::AllocExistentialBoxInst:
197
- case ValueKind::AllocValueBufferInst:
198
- case ValueKind::SILUndef:
199
- return AccessedStorage (address, AccessedStorage::Unidentified);
200
212
}
201
213
}
202
214
}
@@ -231,6 +243,35 @@ static bool isScratchBuffer(SILValue value) {
231
243
value->getType ().getSwiftRValueType ());
232
244
}
233
245
246
+ bool swift::memInstMustInitialize (Operand *memOper) {
247
+ SILValue address = memOper->get ();
248
+ SILInstruction *memInst = memOper->getUser ();
249
+
250
+ switch (memInst->getKind ()) {
251
+ default :
252
+ return false ;
253
+
254
+ case SILInstructionKind::CopyAddrInst: {
255
+ auto *CAI = cast<CopyAddrInst>(memInst);
256
+ return CAI->getDest () == address && CAI->isInitializationOfDest ();
257
+ }
258
+ case SILInstructionKind::InitExistentialAddrInst:
259
+ case SILInstructionKind::InitEnumDataAddrInst:
260
+ case SILInstructionKind::InjectEnumAddrInst:
261
+ return true ;
262
+
263
+ case SILInstructionKind::StoreInst:
264
+ return cast<StoreInst>(memInst)->getOwnershipQualifier ()
265
+ == StoreOwnershipQualifier::Init;
266
+
267
+ case SILInstructionKind::StoreWeakInst:
268
+ return cast<StoreWeakInst>(memInst)->isInitializationOfDest ();
269
+
270
+ case SILInstructionKind::StoreUnownedInst:
271
+ return cast<StoreUnownedInst>(memInst)->isInitializationOfDest ();
272
+ }
273
+ }
274
+
234
275
bool swift::isPossibleFormalAccessBase (const AccessedStorage &storage,
235
276
SILFunction *F) {
236
277
switch (storage.getKind ()) {
@@ -259,6 +300,9 @@ bool swift::isPossibleFormalAccessBase(const AccessedStorage &storage,
259
300
return isPossibleFormalAccessBase (nestedStorage, F);
260
301
}
261
302
case AccessedStorage::Unidentified:
303
+ if (isAddressForLocalInitOnly (storage.getValue ()))
304
+ return false ;
305
+
262
306
if (isa<SILPHIArgument>(storage.getValue ())) {
263
307
checkSwitchEnumBlockArg (cast<SILPHIArgument>(storage.getValue ()));
264
308
return false ;
@@ -268,12 +312,7 @@ bool swift::isPossibleFormalAccessBase(const AccessedStorage &storage,
268
312
if (isa<PointerToAddressInst>(storage.getValue ()))
269
313
return false ;
270
314
271
- // Existential initialization is just initialization.
272
- if (isa<InitExistentialAddrInst>(storage.getValue ()))
273
- return false ;
274
-
275
- // Enum initialization is just initialization.
276
- if (isa<InitEnumDataAddrInst>(storage.getValue ()))
315
+ if (isa<SILUndef>(storage.getValue ()))
277
316
return false ;
278
317
279
318
if (isScratchBuffer (storage.getValue ()))
0 commit comments