1- // ===--- LoadBorrowInvalidationChecker .cpp --------------------------------===//
1+ // ===--- LoadBorrowImmutabilityChecker .cpp --------------------------------===//
22//
33// This source file is part of the Swift.org open source project
44//
1313// / \file
1414// /
1515// / This file defines a verifier that exhaustively validates that there aren't
16- // / any load_borrows in a SIL module that are invalidated by a write to their
16+ // / any load_borrows in a SIL module that have in-scope writes to their
1717// / underlying storage.
1818// /
1919// ===----------------------------------------------------------------------===//
2020
21- #define DEBUG_TYPE " sil-load-borrow-invalidation -checker"
21+ #define DEBUG_TYPE " sil-load-borrow-immutability -checker"
2222#include " VerifierPrivate.h"
2323#include " swift/Basic/Debug.h"
2424#include " swift/Basic/LLVM.h"
@@ -39,26 +39,26 @@ using namespace swift::silverifier;
3939// Write Gatherer
4040// ===----------------------------------------------------------------------===//
4141
42- static bool constructValuesForBuiltinKey (
43- Operand *op, BuiltinInst *bi,
44- SmallVectorImpl<Operand *> &wellBehavedWriteAccumulator ) {
42+ // Helper for gatherAddressWrites.
43+ static bool gatherBuiltinWrites ( Operand *op, BuiltinInst *bi,
44+ SmallVectorImpl<Operand *> &writeAccumulator ) {
4545 // If we definitely do not write to memory, just return true early.
4646 if (!bi->mayWriteToMemory ()) {
4747 return true ;
4848 }
4949
5050 // TODO: Should we make this an exhaustive list so that when new builtins are
5151 // added, they need to actually update this code?
52- wellBehavedWriteAccumulator .push_back (op);
52+ writeAccumulator .push_back (op);
5353 return true ;
5454}
5555
5656// / Returns true if we were able to ascertain that either the initialValue has
5757// / no write uses or all of the write uses were writes that we could understand.
5858static bool
59- constructValuesForKey (SILValue initialValue ,
60- SmallVectorImpl<Operand *> &wellBehavedWriteAccumulator ) {
61- SmallVector<Operand *, 8 > worklist (initialValue ->getUses ());
59+ gatherAddressWrites (SILValue address ,
60+ SmallVectorImpl<Operand *> &writeAccumulator ) {
61+ SmallVector<Operand *, 8 > worklist (address ->getUses ());
6262
6363 while (!worklist.empty ()) {
6464 auto *op = worklist.pop_back_val ();
@@ -81,7 +81,7 @@ constructValuesForKey(SILValue initialValue,
8181 if (auto *oeai = dyn_cast<OpenExistentialAddrInst>(user)) {
8282 // Mutable access!
8383 if (oeai->getAccessKind () != OpenedExistentialAccess::Immutable) {
84- wellBehavedWriteAccumulator .push_back (op);
84+ writeAccumulator .push_back (op);
8585 }
8686
8787 // Otherwise, look through it and continue.
@@ -90,8 +90,8 @@ constructValuesForKey(SILValue initialValue,
9090 }
9191
9292 // Add any destroy_addrs to the resultAccumulator.
93- if (isa<DestroyAddrInst>(user)) {
94- wellBehavedWriteAccumulator .push_back (op);
93+ if (isa<DestroyAddrInst>(user) || isa<DestroyValueInst>(user) ) {
94+ writeAccumulator .push_back (op);
9595 continue ;
9696 }
9797
@@ -103,13 +103,13 @@ constructValuesForKey(SILValue initialValue,
103103
104104 if (auto *mdi = dyn_cast<MarkDependenceInst>(user)) {
105105 if (mdi->getValue () == op->get ()) {
106- wellBehavedWriteAccumulator .push_back (op);
106+ writeAccumulator .push_back (op);
107107 }
108108 continue ;
109109 }
110110
111111 if (isa<InjectEnumAddrInst>(user)) {
112- wellBehavedWriteAccumulator .push_back (op);
112+ writeAccumulator .push_back (op);
113113 continue ;
114114 }
115115
@@ -121,7 +121,7 @@ constructValuesForKey(SILValue initialValue,
121121 if (auto *ccbi = dyn_cast<CheckedCastAddrBranchInst>(user)) {
122122 if (ccbi->getConsumptionKind () == CastConsumptionKind::TakeAlways ||
123123 ccbi->getConsumptionKind () == CastConsumptionKind::TakeOnSuccess) {
124- wellBehavedWriteAccumulator .push_back (op);
124+ writeAccumulator .push_back (op);
125125 continue ;
126126 }
127127 }
@@ -139,7 +139,7 @@ constructValuesForKey(SILValue initialValue,
139139 if (auto *bai = dyn_cast<BeginAccessInst>(user)) {
140140 // If we do not have a read, mark this as a write.
141141 if (bai->getAccessKind () != SILAccessKind::Read) {
142- wellBehavedWriteAccumulator .push_back (op);
142+ writeAccumulator .push_back (op);
143143 }
144144
145145 // Otherwise, add the users to the worklist and continue.
@@ -150,20 +150,20 @@ constructValuesForKey(SILValue initialValue,
150150 // If we have a load, we just need to mark the load [take] as a write.
151151 if (auto *li = dyn_cast<LoadInst>(user)) {
152152 if (li->getOwnershipQualifier () == LoadOwnershipQualifier::Take) {
153- wellBehavedWriteAccumulator .push_back (op);
153+ writeAccumulator .push_back (op);
154154 }
155155 continue ;
156156 }
157157
158158#define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE (Name, name, NAME ) \
159159 if (auto *li = dyn_cast<Load##Name##Inst>(user)) { \
160160 if (li->isTake () == IsTake) { \
161- wellBehavedWriteAccumulator .push_back (op); \
161+ writeAccumulator .push_back (op); \
162162 } \
163163 continue ; \
164164 } \
165165 if (isa<Store##Name##Inst>(user)) { \
166- wellBehavedWriteAccumulator .push_back (op); \
166+ writeAccumulator .push_back (op); \
167167 continue ; \
168168 }
169169#include " swift/AST/ReferenceStorage.def"
@@ -173,7 +173,7 @@ constructValuesForKey(SILValue initialValue,
173173 // interprocedural analysis that we do not perform here.
174174 if (auto fas = FullApplySite::isa (user)) {
175175 if (fas.isIndirectResultOperand (*op)) {
176- wellBehavedWriteAccumulator .push_back (op);
176+ writeAccumulator .push_back (op);
177177 continue ;
178178 }
179179
@@ -191,12 +191,12 @@ constructValuesForKey(SILValue initialValue,
191191 }
192192
193193 if (argConv.isInoutConvention ()) {
194- wellBehavedWriteAccumulator .push_back (op);
194+ writeAccumulator .push_back (op);
195195 continue ;
196196 }
197197
198198 if (argConv.isOwnedConvention ()) {
199- wellBehavedWriteAccumulator .push_back (op);
199+ writeAccumulator .push_back (op);
200200 continue ;
201201 }
202202
@@ -207,22 +207,22 @@ constructValuesForKey(SILValue initialValue,
207207 }
208208
209209 if (auto as = ApplySite::isa (user)) {
210- wellBehavedWriteAccumulator .push_back (op);
210+ writeAccumulator .push_back (op);
211211 continue ;
212212 }
213213
214214 // Copy addr that read are just loads.
215215 if (auto *cai = dyn_cast<CopyAddrInst>(user)) {
216216 // If our value is the destination, this is a write.
217217 if (cai->getDest () == op->get ()) {
218- wellBehavedWriteAccumulator .push_back (op);
218+ writeAccumulator .push_back (op);
219219 continue ;
220220 }
221221
222222 // Ok, so we are Src by process of elimination. Make sure we are not being
223223 // taken.
224224 if (cai->isTakeOfSrc ()) {
225- wellBehavedWriteAccumulator .push_back (op);
225+ writeAccumulator .push_back (op);
226226 continue ;
227227 }
228228
@@ -231,7 +231,7 @@ constructValuesForKey(SILValue initialValue,
231231 }
232232
233233 if (isa<StoreInst>(user) || isa<AssignInst>(user)) {
234- wellBehavedWriteAccumulator .push_back (op);
234+ writeAccumulator .push_back (op);
235235 continue ;
236236 }
237237
@@ -261,7 +261,7 @@ constructValuesForKey(SILValue initialValue,
261261 }
262262
263263 if (info.isIndirectMutating () || info.isConsumed ()) {
264- wellBehavedWriteAccumulator .push_back (op);
264+ writeAccumulator .push_back (op);
265265 continue ;
266266 }
267267 }
@@ -273,19 +273,19 @@ constructValuesForKey(SILValue initialValue,
273273
274274 // unconditional_checked_cast_addr does a take on its input memory.
275275 if (isa<UnconditionalCheckedCastAddrInst>(user)) {
276- wellBehavedWriteAccumulator .push_back (op);
276+ writeAccumulator .push_back (op);
277277 continue ;
278278 }
279279
280280 if (auto *ccabi = dyn_cast<CheckedCastAddrBranchInst>(user)) {
281281 if (ccabi->getConsumptionKind () != CastConsumptionKind::CopyOnSuccess) {
282- wellBehavedWriteAccumulator .push_back (op);
282+ writeAccumulator .push_back (op);
283283 }
284284 continue ;
285285 }
286286
287287 if (auto *bi = dyn_cast<BuiltinInst>(user)) {
288- if (constructValuesForBuiltinKey (op, bi, wellBehavedWriteAccumulator )) {
288+ if (gatherBuiltinWrites (op, bi, writeAccumulator )) {
289289 continue ;
290290 }
291291 }
@@ -304,14 +304,15 @@ constructValuesForKey(SILValue initialValue,
304304}
305305
306306// ===----------------------------------------------------------------------===//
307- // Load Borrow Never Invalidated Analysis
307+ // Load Borrow Immutability Analysis
308308// ===----------------------------------------------------------------------===//
309309
310- LoadBorrowNeverInvalidatedAnalysis::LoadBorrowNeverInvalidatedAnalysis (
310+ LoadBorrowImmutabilityAnalysis::LoadBorrowImmutabilityAnalysis (
311311 DeadEndBlocks &deadEndBlocks)
312- : cache(constructValuesForKey ), deadEndBlocks(deadEndBlocks) {}
312+ : cache(gatherAddressWrites ), deadEndBlocks(deadEndBlocks) {}
313313
314- bool LoadBorrowNeverInvalidatedAnalysis::
314+ // \p address may be an address, pointer, or box type.
315+ bool LoadBorrowImmutabilityAnalysis::
315316 doesAddressHaveWriteThatInvalidatesLoadBorrow (
316317 LoadBorrowInst *lbi, ArrayRef<Operand *> endBorrowUses,
317318 SILValue address) {
@@ -379,7 +380,7 @@ bool LoadBorrowNeverInvalidatedAnalysis::
379380// Top Level Entrypoint
380381// ===----------------------------------------------------------------------===//
381382
382- bool LoadBorrowNeverInvalidatedAnalysis ::
383+ bool LoadBorrowImmutabilityAnalysis ::
383384 doesBoxHaveWritesThatInvalidateLoadBorrow (LoadBorrowInst *lbi,
384385 ArrayRef<Operand *> endBorrowUses,
385386 SILValue originalBox) {
@@ -450,7 +451,7 @@ bool LoadBorrowNeverInvalidatedAnalysis::
450451
451452 return false ;
452453}
453- bool LoadBorrowNeverInvalidatedAnalysis ::isInvalidated (
454+ bool LoadBorrowImmutabilityAnalysis ::isInvalidated (
454455 LoadBorrowInst *lbi) {
455456
456457 // FIXME: To be reenabled separately in a follow-on commit.
0 commit comments