@@ -410,6 +410,11 @@ struct UseState {
410410 llvm::SmallMapVector<SILInstruction *, TypeTreeLeafTypeRange, 4 > reinitInsts;
411411 SmallSetVector<SILInstruction *, 2 > inoutTermUsers;
412412
413+ // / We add debug_values to liveness late after we diagnose, but before we
414+ // / hoist destroys to ensure that we do not hoist destroys out of access
415+ // / scopes.
416+ DebugValueInst *debugValue = nullptr ;
417+
413418 SILFunction *getFunction () const { return address->getFunction (); }
414419
415420 // / Returns true if this is a terminator instruction that although it doesn't
@@ -429,6 +434,7 @@ struct UseState {
429434 initInsts.clear ();
430435 reinitInsts.clear ();
431436 inoutTermUsers.clear ();
437+ debugValue = nullptr ;
432438 }
433439
434440 void dump () {
@@ -465,6 +471,10 @@ struct UseState {
465471 for (auto *inst : inoutTermUsers) {
466472 llvm::dbgs () << *inst;
467473 }
474+ llvm::dbgs () << " Debug Value User:\n " ;
475+ if (debugValue) {
476+ llvm::dbgs () << *debugValue;
477+ }
468478 }
469479
470480 void
@@ -1198,10 +1208,6 @@ bool GatherUsesVisitor::visitUse(Operand *op, AccessUseType useTy) {
11981208 return true ;
11991209 }
12001210
1201- // We don't care about debug instructions.
1202- if (op->getUser ()->isDebugInstruction ())
1203- return true ;
1204-
12051211 // For convenience, grab the user of op.
12061212 auto *user = op->getUser ();
12071213
@@ -1261,6 +1267,19 @@ bool GatherUsesVisitor::visitUse(Operand *op, AccessUseType useTy) {
12611267 if (isa<EndAccessInst>(user))
12621268 return true ;
12631269
1270+ if (auto *di = dyn_cast<DebugValueInst>(user)) {
1271+ // Make sure that our debug_value is always on our root value. If not, we
1272+ // have something we don't understand and should bail. This ensures we can
1273+ // always hoist the debug_value to our mark_must_check. This ensures that by
1274+ // marking debug_value later as requiring liveness, we do not change our
1275+ // liveness calculation since values are always live at the mark_must_check.
1276+ if (di->getOperand () != getRootAddress ())
1277+ return false ;
1278+
1279+ useState.debugValue = di;
1280+ return true ;
1281+ }
1282+
12641283 // At this point, we have handled all of the non-loadTakeOrCopy/consuming
12651284 // uses.
12661285 if (auto *copyAddr = dyn_cast<CopyAddrInst>(user)) {
@@ -1943,21 +1962,6 @@ void MoveOnlyAddressCheckerPImpl::insertDestroysOnBoundary(
19431962 liveness.getRootValue (), defPair.second ,
19441963 consumes);
19451964 } else {
1946- // If our dead def is a mark_must_check and we are processing an inout
1947- // argument, do not insert a destroy_addr. We are cheating a little bit by
1948- // modeling the initial value as a mark_must_check... so we need to
1949- // compensate for our cheating by not inserting the destroy_addr here
1950- // since we would be destroying the inout argument before we use it.
1951- if (auto *markMustCheckInst =
1952- dyn_cast<MarkMustCheckInst>(defPair.first )) {
1953- if (auto *arg = dyn_cast<SILFunctionArgument>(
1954- markMustCheckInst->getOperand ())) {
1955- if (arg->getArgumentConvention ().isInoutConvention ()) {
1956- continue ;
1957- }
1958- }
1959- }
1960-
19611965 auto *inst = cast<SILInstruction>(defPair.first );
19621966 auto *insertPt = inst->getNextInstruction ();
19631967 assert (insertPt && " def instruction was a terminator" );
@@ -2144,9 +2148,28 @@ bool MoveOnlyAddressCheckerPImpl::performSingleCheck(
21442148 return true ;
21452149 }
21462150
2151+ // ===
2152+ // Final Transformation
2153+ //
2154+
21472155 // Ok, we now know that we fit our model since we did not emit errors and thus
21482156 // can begin the transformation.
21492157 SWIFT_DEFER { consumes.clear (); };
2158+
2159+ // First add any debug_values that we saw as liveness uses. This is important
2160+ // since the debugger wants to see live values when we define a debug_value,
2161+ // but we do not want to use them earlier when emitting diagnostic errors.
2162+ if (auto *di = addressUseState.debugValue ) {
2163+ // Move the debug_value to right before the markedAddress to ensure that we
2164+ // do not actually change our liveness computation.
2165+ //
2166+ // NOTE: The author is not sure if this can ever happen with SILGen output,
2167+ // but this is being put just to be safe.
2168+ di->moveAfter (markedAddress);
2169+ liveness.updateForUse (di, TypeTreeLeafTypeRange (markedAddress),
2170+ false /* lifetime ending*/ );
2171+ }
2172+
21502173 FieldSensitivePrunedLivenessBoundary boundary (liveness.getNumSubElements ());
21512174 liveness.computeBoundary (boundary);
21522175 insertDestroysOnBoundary (markedAddress, liveness, boundary);
0 commit comments