@@ -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,15 @@ 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
+
606
618
// Now that we have finished initialization of defs, change our multi-maps
607
619
// from their array form to their map form.
608
620
liveness.finishedInitializationOfDefs ();
@@ -1157,15 +1169,17 @@ bool GatherUsesVisitor::visitUse(Operand *op, AccessUseType useTy) {
1157
1169
// Canonicalize the lifetime of the load [take], load [copy].
1158
1170
moveChecker.changed |= moveChecker.canonicalizer .canonicalize (li);
1159
1171
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 .
1172
+ // If we are asked to perform no_consume_or_assign checking or
1173
+ // assignable_but_not_consumable checking, if we found any consumes of our
1174
+ // load, then we need to emit an error .
1163
1175
if (markedValue->getCheckKind () ==
1164
- MarkMustCheckInst::CheckKind::NoConsumeOrAssign) {
1165
- if (!moveChecker.canonicalizer .foundAnyConsumingUses ()) {
1176
+ MarkMustCheckInst::CheckKind::NoConsumeOrAssign ||
1177
+ markedValue->getCheckKind () ==
1178
+ MarkMustCheckInst::CheckKind::AssignableButNotConsumable) {
1179
+ if (moveChecker.canonicalizer .foundAnyConsumingUses ()) {
1166
1180
LLVM_DEBUG (llvm::dbgs ()
1167
1181
<< " Found mark must check [nocopy] error: " << *user);
1168
- moveChecker.diagnosticEmitter .emitObjectGuaranteedDiagnostic (
1182
+ moveChecker.diagnosticEmitter .emitAddressInstLoadedAndConsumed (
1169
1183
markedValue);
1170
1184
emittedEarlyDiagnostic = true ;
1171
1185
return true ;
@@ -1856,14 +1870,18 @@ void MoveOnlyChecker::rewriteUses(
1856
1870
// destroy_value and use then to create a new load_borrow scope.
1857
1871
SILBuilderWithScope builder (li);
1858
1872
auto *lbi = builder.createLoadBorrow (li->getLoc (), li->getOperand ());
1859
-
1873
+ // We use this auxillary list to avoid iterator invalidation of
1874
+ // li->getConsumingUse();
1875
+ StackList<DestroyValueInst *> toDelete (lbi->getFunction ());
1860
1876
for (auto *consumeUse : li->getConsumingUses ()) {
1861
1877
auto *dvi = cast<DestroyValueInst>(consumeUse->getUser ());
1862
1878
SILBuilderWithScope destroyBuilder (dvi);
1863
1879
destroyBuilder.createEndBorrow (dvi->getLoc (), lbi);
1864
- dvi-> eraseFromParent ( );
1880
+ toDelete. push_back (dvi );
1865
1881
changed = true ;
1866
1882
}
1883
+ while (!toDelete.empty ())
1884
+ toDelete.pop_back_val ()->eraseFromParent ();
1867
1885
1868
1886
li->replaceAllUsesWith (lbi);
1869
1887
li->eraseFromParent ();
@@ -1903,7 +1921,7 @@ bool MoveOnlyChecker::performSingleCheck(MarkMustCheckInst *markedAddress) {
1903
1921
diagnosticEmitter, gatherUsesLiveness);
1904
1922
SWIFT_DEFER { visitor.clear (); };
1905
1923
visitor.reset (markedAddress);
1906
- if (!visitAccessPathUses (visitor, accessPath , fn)) {
1924
+ if (!visitAccessPathBaseUses (visitor, accessPathWithBase , fn)) {
1907
1925
LLVM_DEBUG (llvm::dbgs () << " Failed access path visit: " << *markedAddress);
1908
1926
return false ;
1909
1927
}
0 commit comments