@@ -541,16 +541,19 @@ void UseState::initializeLiveness(
541541 FieldSensitiveMultiDefPrunedLiveRange &liveness) {
542542 // We begin by initializing all of our init uses.
543543 for (auto initInstAndValue : initInsts) {
544+ LLVM_DEBUG (llvm::dbgs () << " Found def: " << *initInstAndValue.first );
544545 liveness.initializeDef (initInstAndValue.first , initInstAndValue.second );
545546 }
546547
547548 // If we have a reinitInstAndValue that we are going to be able to convert
548549 // into a simple init, add it as an init. We are going to consider the rest of
549550 // our reinit uses to be liveness uses.
550551 for (auto reinitInstAndValue : reinitInsts) {
551- if (isReinitToInitConvertibleInst (reinitInstAndValue.first ))
552+ if (isReinitToInitConvertibleInst (reinitInstAndValue.first )) {
553+ LLVM_DEBUG (llvm::dbgs () << " Found def: " << *reinitInstAndValue.first );
552554 liveness.initializeDef (reinitInstAndValue.first ,
553555 reinitInstAndValue.second );
556+ }
554557 }
555558
556559 // Then check if our markedValue is from an argument that is in,
@@ -603,6 +606,24 @@ void UseState::initializeLiveness(
603606 }
604607 }
605608
609+ // Check if our address is from a ref_element_addr. In such a case, we treat
610+ // the mark_must_check as the initialization.
611+ if (auto *refEltAddr = dyn_cast<RefElementAddrInst>(address->getOperand ())) {
612+ LLVM_DEBUG (llvm::dbgs () << " Found ref_element_addr use... "
613+ " adding mark_must_check as init!\n " );
614+ initInsts.insert ({address, liveness.getTopLevelSpan ()});
615+ liveness.initializeDef (address, liveness.getTopLevelSpan ());
616+ }
617+
618+ // Check if our address is from a global_addr. In such a case, we treat the
619+ // mark_must_check as the initialization.
620+ if (auto *globalAddr = dyn_cast<GlobalAddrInst>(address->getOperand ())) {
621+ LLVM_DEBUG (llvm::dbgs () << " Found global_addr use... "
622+ " adding mark_must_check as init!\n " );
623+ initInsts.insert ({address, liveness.getTopLevelSpan ()});
624+ liveness.initializeDef (address, liveness.getTopLevelSpan ());
625+ }
626+
606627 // Now that we have finished initialization of defs, change our multi-maps
607628 // from their array form to their map form.
608629 liveness.finishedInitializationOfDefs ();
@@ -1157,15 +1178,17 @@ bool GatherUsesVisitor::visitUse(Operand *op, AccessUseType useTy) {
11571178 // Canonicalize the lifetime of the load [take], load [copy].
11581179 moveChecker.changed |= moveChecker.canonicalizer .canonicalize (li);
11591180
1160- // If we are asked to perform guaranteed checking, emit an error if we
1161- // have /any/ consuming uses. This is a case that can always be converted
1162- // to a load_borrow if we pass the check .
1181+ // If we are asked to perform no_consume_or_assign checking or
1182+ // assignable_but_not_consumable checking, if we found any consumes of our
1183+ // load, then we need to emit an error .
11631184 if (markedValue->getCheckKind () ==
1164- MarkMustCheckInst::CheckKind::NoConsumeOrAssign) {
1165- if (!moveChecker.canonicalizer .foundAnyConsumingUses ()) {
1185+ MarkMustCheckInst::CheckKind::NoConsumeOrAssign ||
1186+ markedValue->getCheckKind () ==
1187+ MarkMustCheckInst::CheckKind::AssignableButNotConsumable) {
1188+ if (moveChecker.canonicalizer .foundAnyConsumingUses ()) {
11661189 LLVM_DEBUG (llvm::dbgs ()
11671190 << " Found mark must check [nocopy] error: " << *user);
1168- moveChecker.diagnosticEmitter .emitObjectGuaranteedDiagnostic (
1191+ moveChecker.diagnosticEmitter .emitAddressInstLoadedAndConsumed (
11691192 markedValue);
11701193 emittedEarlyDiagnostic = true ;
11711194 return true ;
@@ -1856,14 +1879,18 @@ void MoveOnlyChecker::rewriteUses(
18561879 // destroy_value and use then to create a new load_borrow scope.
18571880 SILBuilderWithScope builder (li);
18581881 auto *lbi = builder.createLoadBorrow (li->getLoc (), li->getOperand ());
1859-
1882+ // We use this auxillary list to avoid iterator invalidation of
1883+ // li->getConsumingUse();
1884+ StackList<DestroyValueInst *> toDelete (lbi->getFunction ());
18601885 for (auto *consumeUse : li->getConsumingUses ()) {
18611886 auto *dvi = cast<DestroyValueInst>(consumeUse->getUser ());
18621887 SILBuilderWithScope destroyBuilder (dvi);
18631888 destroyBuilder.createEndBorrow (dvi->getLoc (), lbi);
1864- dvi-> eraseFromParent ( );
1889+ toDelete. push_back (dvi );
18651890 changed = true ;
18661891 }
1892+ while (!toDelete.empty ())
1893+ toDelete.pop_back_val ()->eraseFromParent ();
18671894
18681895 li->replaceAllUsesWith (lbi);
18691896 li->eraseFromParent ();
@@ -1903,7 +1930,7 @@ bool MoveOnlyChecker::performSingleCheck(MarkMustCheckInst *markedAddress) {
19031930 diagnosticEmitter, gatherUsesLiveness);
19041931 SWIFT_DEFER { visitor.clear (); };
19051932 visitor.reset (markedAddress);
1906- if (!visitAccessPathUses (visitor, accessPath , fn)) {
1933+ if (!visitAccessPathBaseUses (visitor, accessPathWithBase , fn)) {
19071934 LLVM_DEBUG (llvm::dbgs () << " Failed access path visit: " << *markedAddress);
19081935 return false ;
19091936 }
0 commit comments