@@ -410,6 +410,11 @@ struct UseState {
410
410
llvm::SmallMapVector<SILInstruction *, TypeTreeLeafTypeRange, 4 > reinitInsts;
411
411
SmallSetVector<SILInstruction *, 2 > inoutTermUsers;
412
412
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
+
413
418
SILFunction *getFunction () const { return address->getFunction (); }
414
419
415
420
// / Returns true if this is a terminator instruction that although it doesn't
@@ -429,6 +434,7 @@ struct UseState {
429
434
initInsts.clear ();
430
435
reinitInsts.clear ();
431
436
inoutTermUsers.clear ();
437
+ debugValue = nullptr ;
432
438
}
433
439
434
440
void dump () {
@@ -465,6 +471,10 @@ struct UseState {
465
471
for (auto *inst : inoutTermUsers) {
466
472
llvm::dbgs () << *inst;
467
473
}
474
+ llvm::dbgs () << " Debug Value User:\n " ;
475
+ if (debugValue) {
476
+ llvm::dbgs () << *debugValue;
477
+ }
468
478
}
469
479
470
480
void
@@ -1198,10 +1208,6 @@ bool GatherUsesVisitor::visitUse(Operand *op, AccessUseType useTy) {
1198
1208
return true ;
1199
1209
}
1200
1210
1201
- // We don't care about debug instructions.
1202
- if (op->getUser ()->isDebugInstruction ())
1203
- return true ;
1204
-
1205
1211
// For convenience, grab the user of op.
1206
1212
auto *user = op->getUser ();
1207
1213
@@ -1261,6 +1267,19 @@ bool GatherUsesVisitor::visitUse(Operand *op, AccessUseType useTy) {
1261
1267
if (isa<EndAccessInst>(user))
1262
1268
return true ;
1263
1269
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
+
1264
1283
// At this point, we have handled all of the non-loadTakeOrCopy/consuming
1265
1284
// uses.
1266
1285
if (auto *copyAddr = dyn_cast<CopyAddrInst>(user)) {
@@ -1943,21 +1962,6 @@ void MoveOnlyAddressCheckerPImpl::insertDestroysOnBoundary(
1943
1962
liveness.getRootValue (), defPair.second ,
1944
1963
consumes);
1945
1964
} 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
-
1961
1965
auto *inst = cast<SILInstruction>(defPair.first );
1962
1966
auto *insertPt = inst->getNextInstruction ();
1963
1967
assert (insertPt && " def instruction was a terminator" );
@@ -2144,9 +2148,28 @@ bool MoveOnlyAddressCheckerPImpl::performSingleCheck(
2144
2148
return true ;
2145
2149
}
2146
2150
2151
+ // ===
2152
+ // Final Transformation
2153
+ //
2154
+
2147
2155
// Ok, we now know that we fit our model since we did not emit errors and thus
2148
2156
// can begin the transformation.
2149
2157
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
+
2150
2173
FieldSensitivePrunedLivenessBoundary boundary (liveness.getNumSubElements ());
2151
2174
liveness.computeBoundary (boundary);
2152
2175
insertDestroysOnBoundary (markedAddress, liveness, boundary);
0 commit comments