@@ -541,16 +541,19 @@ void UseState::initializeLiveness(
541
541
FieldSensitiveMultiDefPrunedLiveRange &liveness) {
542
542
// We begin by initializing all of our init uses.
543
543
for (auto initInstAndValue : initInsts) {
544
+ LLVM_DEBUG (llvm::dbgs () << " Found def: " << *initInstAndValue.first );
544
545
liveness.initializeDef (initInstAndValue.first , initInstAndValue.second );
545
546
}
546
547
547
548
// If we have a reinitInstAndValue that we are going to be able to convert
548
549
// into a simple init, add it as an init. We are going to consider the rest of
549
550
// our reinit uses to be liveness uses.
550
551
for (auto reinitInstAndValue : reinitInsts) {
551
- if (isReinitToInitConvertibleInst (reinitInstAndValue.first ))
552
+ if (isReinitToInitConvertibleInst (reinitInstAndValue.first )) {
553
+ LLVM_DEBUG (llvm::dbgs () << " Found def: " << *reinitInstAndValue.first );
552
554
liveness.initializeDef (reinitInstAndValue.first ,
553
555
reinitInstAndValue.second );
556
+ }
554
557
}
555
558
556
559
// Then check if our markedValue is from an argument that is in,
@@ -603,6 +606,24 @@ void UseState::initializeLiveness(
603
606
}
604
607
}
605
608
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
+
606
627
// Now that we have finished initialization of defs, change our multi-maps
607
628
// from their array form to their map form.
608
629
liveness.finishedInitializationOfDefs ();
@@ -1157,15 +1178,17 @@ bool GatherUsesVisitor::visitUse(Operand *op, AccessUseType useTy) {
1157
1178
// Canonicalize the lifetime of the load [take], load [copy].
1158
1179
moveChecker.changed |= moveChecker.canonicalizer .canonicalize (li);
1159
1180
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 .
1163
1184
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 ()) {
1166
1189
LLVM_DEBUG (llvm::dbgs ()
1167
1190
<< " Found mark must check [nocopy] error: " << *user);
1168
- moveChecker.diagnosticEmitter .emitObjectGuaranteedDiagnostic (
1191
+ moveChecker.diagnosticEmitter .emitAddressInstLoadedAndConsumed (
1169
1192
markedValue);
1170
1193
emittedEarlyDiagnostic = true ;
1171
1194
return true ;
@@ -1856,14 +1879,18 @@ void MoveOnlyChecker::rewriteUses(
1856
1879
// destroy_value and use then to create a new load_borrow scope.
1857
1880
SILBuilderWithScope builder (li);
1858
1881
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 ());
1860
1885
for (auto *consumeUse : li->getConsumingUses ()) {
1861
1886
auto *dvi = cast<DestroyValueInst>(consumeUse->getUser ());
1862
1887
SILBuilderWithScope destroyBuilder (dvi);
1863
1888
destroyBuilder.createEndBorrow (dvi->getLoc (), lbi);
1864
- dvi-> eraseFromParent ( );
1889
+ toDelete. push_back (dvi );
1865
1890
changed = true ;
1866
1891
}
1892
+ while (!toDelete.empty ())
1893
+ toDelete.pop_back_val ()->eraseFromParent ();
1867
1894
1868
1895
li->replaceAllUsesWith (lbi);
1869
1896
li->eraseFromParent ();
@@ -1903,7 +1930,7 @@ bool MoveOnlyChecker::performSingleCheck(MarkMustCheckInst *markedAddress) {
1903
1930
diagnosticEmitter, gatherUsesLiveness);
1904
1931
SWIFT_DEFER { visitor.clear (); };
1905
1932
visitor.reset (markedAddress);
1906
- if (!visitAccessPathUses (visitor, accessPath , fn)) {
1933
+ if (!visitAccessPathBaseUses (visitor, accessPathWithBase , fn)) {
1907
1934
LLVM_DEBUG (llvm::dbgs () << " Failed access path visit: " << *markedAddress);
1908
1935
return false ;
1909
1936
}
0 commit comments