1717#include " swift/SIL/SILFunction.h"
1818#include " swift/SIL/ApplySite.h"
1919#include " swift/SIL/BasicBlockDatastructures.h"
20+ #include " swift/SILOptimizer/Analysis/AliasAnalysis.h"
21+ #include " swift/SILOptimizer/PassManager/PassManager.h"
2022#include " llvm/Support/CommandLine.h"
2123
2224using namespace swift ;
@@ -40,6 +42,7 @@ class MemoryLifetimeVerifier {
4042 using BlockState = BitDataflow::BlockState;
4143
4244 SILFunction *function;
45+ AliasAnalysis *aliasAnalysis;
4346 MemoryLocations locations;
4447
4548 // / alloc_stack memory locations which are used for store_borrow.
@@ -77,6 +80,8 @@ class MemoryLifetimeVerifier {
7780 // / \p addr, are set in \p bits.
7881 void requireBitsSet (const Bits &bits, SILValue addr, SILInstruction *where);
7982
83+ void requireBitsSetForArgument (const Bits &bits, SILValue addr, SILInstruction *applyInst);
84+
8085 bool isStoreBorrowLocation (SILValue addr) {
8186 auto *loc = locations.getLocation (addr);
8287 return loc && storeBorrowLocations.anyCommon (loc->subLocations );
@@ -132,9 +137,12 @@ class MemoryLifetimeVerifier {
132137 }
133138
134139public:
135- MemoryLifetimeVerifier (SILFunction *function) :
136- function (function), locations(/* handleNonTrivialProjections*/ true ,
137- /* handleTrivialLocations*/ true ) {}
140+ MemoryLifetimeVerifier (SILFunction *function, SILPassManager *passManager) :
141+ function (function),
142+ aliasAnalysis (passManager ? passManager->getAnalysis<AliasAnalysis>(function)
143+ : nullptr ),
144+ locations (/* handleNonTrivialProjections*/ true ,
145+ /* handleTrivialLocations*/ true ) {}
138146
139147 // / The main entry point to verify the lifetime of all memory locations in
140148 // / the function.
@@ -274,6 +282,30 @@ void MemoryLifetimeVerifier::requireBitsSet(const Bits &bits, SILValue addr,
274282 }
275283}
276284
285+ void MemoryLifetimeVerifier::requireBitsSetForArgument (const Bits &bits, SILValue addr,
286+ SILInstruction *applyInst) {
287+ // Optimizations can rely on alias analysis to know that an in-argument (or
288+ // parts of it) is not actually read.
289+ // We have to do the same in the verifier: if alias analysis says that an in-
290+ // argument is not read, there is no need that the memory location is initialized.
291+
292+ // Not all calls to the verifier provide the alias analysis.
293+ if (!aliasAnalysis)
294+ return ;
295+
296+ if (auto *loc = locations.getLocation (addr)) {
297+ Bits missingBits = ~bits & loc->subLocations ;
298+ for (int errorLocIdx = missingBits.find_first (); errorLocIdx >= 0 ;
299+ errorLocIdx = missingBits.find_next (errorLocIdx)) {
300+ auto *errorLoc = locations.getLocation (errorLocIdx);
301+ if (aliasAnalysis->mayReadFromMemory (applyInst, errorLoc->representativeValue )) {
302+ reportError (" memory is not initialized, but should be" ,
303+ errorLocIdx, applyInst);
304+ }
305+ }
306+ }
307+ }
308+
277309void MemoryLifetimeVerifier::requireNoStoreBorrowLocation (
278310 SILValue addr, SILInstruction *where) {
279311 if (isa<StoreBorrowInst>(addr)) {
@@ -815,7 +847,7 @@ void MemoryLifetimeVerifier::checkFuncArgument(Bits &bits, Operand &argumentOp,
815847
816848 switch (argumentConvention) {
817849 case SILArgumentConvention::Indirect_In:
818- requireBitsSet (bits, argumentOp.get (), applyInst);
850+ requireBitsSetForArgument (bits, argumentOp.get (), applyInst);
819851 locations.clearBits (bits, argumentOp.get ());
820852 break ;
821853 case SILArgumentConvention::Indirect_Out:
@@ -825,7 +857,7 @@ void MemoryLifetimeVerifier::checkFuncArgument(Bits &bits, Operand &argumentOp,
825857 break ;
826858 case SILArgumentConvention::Indirect_In_Guaranteed:
827859 case SILArgumentConvention::Indirect_Inout:
828- requireBitsSet (bits, argumentOp.get (), applyInst);
860+ requireBitsSetForArgument (bits, argumentOp.get (), applyInst);
829861 break ;
830862 case SILArgumentConvention::Indirect_InoutAliasable:
831863 // We don't require any locations to be initialized for a partial_apply
@@ -834,7 +866,7 @@ void MemoryLifetimeVerifier::checkFuncArgument(Bits &bits, Operand &argumentOp,
834866 // closures capture the whole "self". When this is done in an initializer
835867 // it can happen that not all fields of "self" are initialized, yet.
836868 if (!isa<PartialApplyInst>(applyInst))
837- requireBitsSet (bits, argumentOp.get (), applyInst);
869+ requireBitsSetForArgument (bits, argumentOp.get (), applyInst);
838870 break ;
839871 case SILArgumentConvention::Direct_Owned:
840872 case SILArgumentConvention::Direct_Unowned:
@@ -870,7 +902,7 @@ void MemoryLifetimeVerifier::verify() {
870902
871903} // anonymous namespace
872904
873- void SILFunction::verifyMemoryLifetime () {
874- MemoryLifetimeVerifier verifier (this );
905+ void SILFunction::verifyMemoryLifetime (SILPassManager *passManager ) {
906+ MemoryLifetimeVerifier verifier (this , passManager );
875907 verifier.verify ();
876908}
0 commit comments