1313#define DEBUG_TYPE " sil-memory-lifetime-verifier"
1414#include " swift/SIL/MemoryLocations.h"
1515#include " swift/SIL/BitDataflow.h"
16+ #include " swift/SIL/CalleeCache.h"
1617#include " swift/SIL/SILBasicBlock.h"
1718#include " swift/SIL/SILFunction.h"
1819#include " swift/SIL/ApplySite.h"
1920#include " swift/SIL/BasicBlockDatastructures.h"
20- #include " swift/SILOptimizer/Analysis/AliasAnalysis.h"
21- #include " swift/SILOptimizer/PassManager/PassManager.h"
2221#include " llvm/Support/CommandLine.h"
2322
2423using namespace swift ;
@@ -42,7 +41,7 @@ class MemoryLifetimeVerifier {
4241 using BlockState = BitDataflow::BlockState;
4342
4443 SILFunction *function;
45- AliasAnalysis *aliasAnalysis ;
44+ CalleeCache *calleeCache ;
4645 MemoryLocations locations;
4746
4847 // / alloc_stack memory locations which are used for store_borrow.
@@ -80,7 +79,9 @@ class MemoryLifetimeVerifier {
8079 // / \p addr, are set in \p bits.
8180 void requireBitsSet (const Bits &bits, SILValue addr, SILInstruction *where);
8281
83- void requireBitsSetForArgument (const Bits &bits, SILValue addr, SILInstruction *applyInst);
82+ void requireBitsSetForArgument (const Bits &bits, Operand *argOp);
83+
84+ bool applyMayRead (Operand *argOp, SILValue addr);
8485
8586 bool isStoreBorrowLocation (SILValue addr) {
8687 auto *loc = locations.getLocation (addr);
@@ -137,10 +138,9 @@ class MemoryLifetimeVerifier {
137138 }
138139
139140public:
140- MemoryLifetimeVerifier (SILFunction *function, SILPassManager *passManager ) :
141+ MemoryLifetimeVerifier (SILFunction *function, CalleeCache *calleeCache ) :
141142 function (function),
142- aliasAnalysis (passManager ? passManager->getAnalysis<AliasAnalysis>(function)
143- : nullptr ),
143+ calleeCache (calleeCache),
144144 locations (/* handleNonTrivialProjections*/ true ,
145145 /* handleTrivialLocations*/ true ) {}
146146
@@ -277,30 +277,41 @@ void MemoryLifetimeVerifier::requireBitsSet(const Bits &bits, SILValue addr,
277277 }
278278}
279279
280- void MemoryLifetimeVerifier::requireBitsSetForArgument (const Bits &bits, SILValue addr,
281- SILInstruction *applyInst) {
282- // Optimizations can rely on alias analysis to know that an in-argument (or
283- // parts of it) is not actually read.
284- // We have to do the same in the verifier: if alias analysis says that an in-
285- // argument is not read, there is no need that the memory location is initialized.
286-
287- // Not all calls to the verifier provide the alias analysis.
288- if (!aliasAnalysis)
289- return ;
290-
291- if (auto *loc = locations.getLocation (addr)) {
280+ void MemoryLifetimeVerifier::requireBitsSetForArgument (const Bits &bits, Operand *argOp) {
281+ if (auto *loc = locations.getLocation (argOp->get ())) {
292282 Bits missingBits = ~bits & loc->subLocations ;
293283 for (int errorLocIdx = missingBits.find_first (); errorLocIdx >= 0 ;
294284 errorLocIdx = missingBits.find_next (errorLocIdx)) {
295285 auto *errorLoc = locations.getLocation (errorLocIdx);
296- if (aliasAnalysis->mayReadFromMemory (applyInst, errorLoc->representativeValue )) {
286+
287+ if (applyMayRead (argOp, errorLoc->representativeValue )) {
297288 reportError (" memory is not initialized, but should be" ,
298- errorLocIdx, applyInst );
289+ errorLocIdx, argOp-> getUser () );
299290 }
300291 }
301292 }
302293}
303294
295+ bool MemoryLifetimeVerifier::applyMayRead (Operand *argOp, SILValue addr) {
296+ FullApplySite as (argOp->getUser ());
297+ CalleeList callees;
298+ if (calleeCache) {
299+ callees = calleeCache->getCalleeList (as);
300+ if (callees.isIncomplete ())
301+ return true ;
302+ } else if (auto *callee = as.getReferencedFunctionOrNull ()) {
303+ callees = CalleeList (callee);
304+ } else {
305+ return false ;
306+ }
307+
308+ for (SILFunction *callee : callees) {
309+ if (callee->argumentMayRead (argOp, addr))
310+ return true ;
311+ }
312+ return false ;
313+ }
314+
304315void MemoryLifetimeVerifier::requireNoStoreBorrowLocation (
305316 SILValue addr, SILInstruction *where) {
306317 if (isa<StoreBorrowInst>(addr)) {
@@ -864,7 +875,7 @@ void MemoryLifetimeVerifier::checkFuncArgument(Bits &bits, Operand &argumentOp,
864875
865876 switch (argumentConvention) {
866877 case SILArgumentConvention::Indirect_In:
867- requireBitsSetForArgument (bits, argumentOp. get (), applyInst );
878+ requireBitsSetForArgument (bits, & argumentOp);
868879 locations.clearBits (bits, argumentOp.get ());
869880 break ;
870881 case SILArgumentConvention::Indirect_Out:
@@ -874,7 +885,7 @@ void MemoryLifetimeVerifier::checkFuncArgument(Bits &bits, Operand &argumentOp,
874885 break ;
875886 case SILArgumentConvention::Indirect_In_Guaranteed:
876887 case SILArgumentConvention::Indirect_Inout:
877- requireBitsSetForArgument (bits, argumentOp. get (), applyInst );
888+ requireBitsSetForArgument (bits, & argumentOp);
878889 break ;
879890 case SILArgumentConvention::Indirect_InoutAliasable:
880891 // We don't require any locations to be initialized for a partial_apply
@@ -883,7 +894,7 @@ void MemoryLifetimeVerifier::checkFuncArgument(Bits &bits, Operand &argumentOp,
883894 // closures capture the whole "self". When this is done in an initializer
884895 // it can happen that not all fields of "self" are initialized, yet.
885896 if (!isa<PartialApplyInst>(applyInst))
886- requireBitsSetForArgument (bits, argumentOp. get (), applyInst );
897+ requireBitsSetForArgument (bits, & argumentOp);
887898 break ;
888899 case SILArgumentConvention::Direct_Owned:
889900 case SILArgumentConvention::Direct_Unowned:
@@ -919,7 +930,7 @@ void MemoryLifetimeVerifier::verify() {
919930
920931} // anonymous namespace
921932
922- void SILFunction::verifyMemoryLifetime (SILPassManager *passManager ) {
923- MemoryLifetimeVerifier verifier (this , passManager );
933+ void SILFunction::verifyMemoryLifetime (CalleeCache *calleeCache ) {
934+ MemoryLifetimeVerifier verifier (this , calleeCache );
924935 verifier.verify ();
925936}
0 commit comments