Skip to content

Commit e4e0760

Browse files
authored
Merge pull request #77695 from atrick/handle_markdep
[NFC] mark_dependence handling for coroutines and accessors.
2 parents 4a9d20d + 0a70bdd commit e4e0760

File tree

7 files changed

+44
-13
lines changed

7 files changed

+44
-13
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/LifetimeDependenceDiagnostics.swift

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,23 @@ let lifetimeDependenceDiagnosticsPass = FunctionPass(
4545
// Indirect results are not checked here. Type checking ensures
4646
// that they have a lifetime dependence.
4747
if let lifetimeDep = LifetimeDependence(argument, context) {
48-
analyze(dependence: lifetimeDep, context)
48+
_ = analyze(dependence: lifetimeDep, context)
4949
}
5050
}
5151
for instruction in function.instructions {
5252
if let markDep = instruction as? MarkDependenceInst, markDep.isUnresolved {
5353
if let lifetimeDep = LifetimeDependence(markDep, context) {
54-
analyze(dependence: lifetimeDep, context)
54+
if analyze(dependence: lifetimeDep, context) {
55+
// Note: This promotes the mark_dependence flag but does not invalidate SIL; preserving analyses is good,
56+
// but the change won't appear in -sil-print-function. Ideally, we could notify context of a flag change
57+
// without invalidating analyses.
58+
lifetimeDep.resolve(context)
59+
}
60+
} else {
61+
// For now, if the mark_dependence wasn't recognized as a lifetime dependence, conservatively settle it as
62+
// escaping. In the future, we should not need this because, for escapable types, mark_dependence [unresolved]
63+
// will all be settled during an early LifetimeNormalization pass.
64+
markDep.settleToEscaping()
5565
}
5666
continue
5767
}
@@ -61,7 +71,7 @@ let lifetimeDependenceDiagnosticsPass = FunctionPass(
6171
apply.resultOrYields.forEach {
6272
if let lifetimeDep = LifetimeDependence(unsafeApplyResult: $0,
6373
context) {
64-
analyze(dependence: lifetimeDep, context)
74+
_ = analyze(dependence: lifetimeDep, context)
6575
}
6676
}
6777
continue
@@ -74,8 +84,9 @@ let lifetimeDependenceDiagnosticsPass = FunctionPass(
7484
/// 1. Compute the LifetimeDependence scope.
7585
///
7686
/// 2. Walk down all dependent values checking that they are within range.
77-
private func analyze(dependence: LifetimeDependence,
78-
_ context: FunctionPassContext) {
87+
///
88+
/// Return true on success.
89+
private func analyze(dependence: LifetimeDependence, _ context: FunctionPassContext) -> Bool {
7990
log("Dependence scope:\n\(dependence)")
8091

8192
// Compute this dependence scope.
@@ -91,10 +102,7 @@ private func analyze(dependence: LifetimeDependence,
91102
var walker = DiagnoseDependenceWalker(diagnostics, context)
92103
defer { walker.deinitialize() }
93104
_ = walker.walkDown(root: dependence.dependentValue)
94-
95-
if !error {
96-
dependence.resolve(context)
97-
}
105+
return !error
98106
}
99107

100108
/// Analyze and diagnose a single LifetimeDependence.

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,10 @@ class MarkDependenceInst : SingleValueInstruction {
976976
public func resolveToNonEscaping() {
977977
bridged.MarkDependenceInst_resolveToNonEscaping()
978978
}
979+
980+
public func settleToEscaping() {
981+
bridged.MarkDependenceInst_settleToEscaping()
982+
}
979983
}
980984

981985
final public class RefToBridgeObjectInst : SingleValueInstruction {
@@ -1344,7 +1348,7 @@ final public class AbortApplyInst : Instruction, UnaryInstruction {
13441348

13451349
extension BeginApplyInst : ScopedInstruction {
13461350
public var endOperands: LazyFilterSequence<UseList> {
1347-
return token.uses.lazy.filter { $0.endsLifetime }
1351+
return token.uses.lazy.filter { $0.isScopeEndingUse }
13481352
}
13491353
}
13501354

SwiftCompilerSources/Sources/SIL/Operand.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,19 @@ extension Operand {
192192
}
193193
}
194194

195+
extension Operand {
196+
/// A scope ending use is a consuming use for normal borrow scopes, but it also applies to intructions that end the
197+
/// scope of an address (end_access) or a token (end_apply, abort_apply),
198+
public var isScopeEndingUse: Bool {
199+
switch instruction {
200+
case is EndBorrowInst, is EndAccessInst, is EndApplyInst, is AbortApplyInst:
201+
return true
202+
default:
203+
return false
204+
}
205+
}
206+
}
207+
195208
extension OptionalBridgedOperand {
196209
init(bridged: BridgedOperand?) {
197210
self = OptionalBridgedOperand(op: bridged?.op)

docs/SIL.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5699,6 +5699,8 @@ mark_dependence
56995699

57005700
%2 = mark_dependence %value : $*T on %base : $Builtin.NativeObject
57015701

5702+
``%base`` must not be identical to ``%value``.
5703+
57025704
Indicates that the validity of ``%value`` depends on the value of
57035705
``%base``. Operations that would destroy ``%base`` must not be moved
57045706
before any instructions which depend on the result of this
@@ -5715,7 +5717,7 @@ the dependency is on the current value stored in the address.
57155717
The optional ``nonescaping`` attribute indicates that no value derived
57165718
from ``%value`` escapes the lifetime of ``%base``. As with escaping
57175719
``mark_dependence``, all values transitively forwarded from ``%value``
5718-
must be destroyed within the lifetime of ` `%base``. Unlike escaping
5720+
must be destroyed within the lifetime of ``%base``. Unlike escaping
57195721
``mark_dependence``, this must be statically verifiable. Additionally,
57205722
unlike escaping ``mark_dependence``, derived values include copies of
57215723
``%value`` and values transitively forwarded from those copies. If

include/swift/SIL/SILBridging.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,7 @@ struct BridgedInstruction {
788788
BRIDGED_INLINE SwiftInt AssignInst_getAssignOwnership() const;
789789
BRIDGED_INLINE MarkDependenceKind MarkDependenceInst_dependenceKind() const;
790790
BRIDGED_INLINE void MarkDependenceInst_resolveToNonEscaping() const;
791+
BRIDGED_INLINE void MarkDependenceInst_settleToEscaping() const;
791792
BRIDGED_INLINE SwiftInt BeginAccessInst_getAccessKind() const;
792793
BRIDGED_INLINE bool BeginAccessInst_isStatic() const;
793794
BRIDGED_INLINE bool BeginAccessInst_isUnsafe() const;

include/swift/SIL/SILBridgingImpl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,6 +1387,10 @@ void BridgedInstruction::MarkDependenceInst_resolveToNonEscaping() const {
13871387
getAs<swift::MarkDependenceInst>()->resolveToNonEscaping();
13881388
}
13891389

1390+
void BridgedInstruction::MarkDependenceInst_settleToEscaping() const {
1391+
getAs<swift::MarkDependenceInst>()->settleToEscaping();
1392+
}
1393+
13901394
SwiftInt BridgedInstruction::BeginAccessInst_getAccessKind() const {
13911395
return (SwiftInt)getAs<swift::BeginAccessInst>()->getAccessKind();
13921396
}

lib/AST/LifetimeDependence.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,8 +441,7 @@ std::optional<LifetimeDependenceInfo> LifetimeDependenceInfo::fromDependsOn(
441441
auto kind = descriptor.getParsedLifetimeDependenceKind();
442442

443443
if (kind == ParsedLifetimeDependenceKind::Scope &&
444-
(!isGuaranteedParameterInCallee(paramConvention) &&
445-
!isMutatingParameter(paramConvention))) {
444+
isConsumedParameterInCallee(paramConvention)) {
446445
diags.diagnose(loc, diag::lifetime_dependence_cannot_use_kind, "_scope",
447446
getStringForParameterConvention(paramConvention));
448447
return true;

0 commit comments

Comments
 (0)