Skip to content

Commit cfc1df6

Browse files
authored
Merge pull request #72150 from atrick/fix-isescapable
Fix SILType::isEscapable for box types.
2 parents e96642c + df7326d commit cfc1df6

File tree

9 files changed

+59
-22
lines changed

9 files changed

+59
-22
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/AllocVectorLowering.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ private struct ComputeNonEscapingLiferange : EscapeVisitorWithResult {
414414
if dominates {
415415
liferange.insert(user)
416416
}
417-
if !apply.type.isEscapable {
417+
if !apply.isEscapable {
418418
return .abort
419419
}
420420
return .ignore

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/LifetimeDependenceDiagnostics.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ let lifetimeDependenceDiagnosticsPass = FunctionPass(
3535
log(" --- Diagnosing lifetime dependence in \(function.name)")
3636
log("\(function)")
3737

38-
for argument in function.arguments where !argument.type.isEscapable {
38+
for argument in function.arguments
39+
where !argument.type.isEscapable(in: function)
40+
{
3941
// Indirect results are not checked here. Type checking ensures
4042
// that they have a lifetime dependence.
4143
if let lifetimeDep = LifetimeDependence(argument, context) {

SwiftCompilerSources/Sources/Optimizer/Utilities/LifetimeDependenceUtils.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ extension LifetimeDependence {
219219
//
220220
// TODO: handle indirect results
221221
init?(unsafeApplyResult value: Value, _ context: some Context) {
222-
if value.type.isEscapable {
222+
if value.isEscapable {
223223
return nil
224224
}
225225
if (value.definingInstruction as! FullApplySite).hasResultDependence {
@@ -832,7 +832,7 @@ extension LifetimeDependenceDefUseWalker {
832832
mutating func walkDownUses(of value: Value, using operand: Operand?)
833833
-> WalkResult {
834834
// Only track ~Escapable and @noescape types.
835-
if value.type.mayEscape {
835+
if value.mayEscape {
836836
return .continueWalk
837837
}
838838
return walkDownUsesDefault(forwarding: value, using: operand)
@@ -857,10 +857,10 @@ extension LifetimeDependenceDefUseWalker {
857857
if let apply = operand.instruction as? FullApplySite {
858858
return visitAppliedUse(of: operand, by: apply)
859859
}
860-
if operand.instruction is ReturnInst, !operand.value.type.isEscapable {
860+
if operand.instruction is ReturnInst, !operand.value.isEscapable {
861861
return returnedDependence(result: operand)
862862
}
863-
if operand.instruction is YieldInst, !operand.value.type.isEscapable {
863+
if operand.instruction is YieldInst, !operand.value.isEscapable {
864864
return yieldedDependence(result: operand)
865865
}
866866
return escapingDependence(on: operand)
@@ -1025,10 +1025,10 @@ extension LifetimeDependenceDefUseWalker {
10251025
assert(!mdi.isUnresolved && !mdi.isNonEscaping,
10261026
"should be handled as a dependence by AddressUseVisitor")
10271027
}
1028-
if operand.instruction is ReturnInst, !operand.value.type.isEscapable {
1028+
if operand.instruction is ReturnInst, !operand.value.isEscapable {
10291029
return returnedDependence(result: operand)
10301030
}
1031-
if operand.instruction is YieldInst, !operand.value.type.isEscapable {
1031+
if operand.instruction is YieldInst, !operand.value.isEscapable {
10321032
return yieldedDependence(result: operand)
10331033
}
10341034
return escapingDependence(on: operand)
@@ -1088,19 +1088,19 @@ extension LifetimeDependenceDefUseWalker {
10881088
case let .argument(arg):
10891089
if arg.convention.isIndirectIn || arg.convention.isInout {
10901090
allocation = arg
1091-
} else if arg.convention.isIndirectOut, !arg.type.isEscapable {
1091+
} else if arg.convention.isIndirectOut, !arg.isEscapable {
10921092
return returnedDependence(address: arg, using: operand)
10931093
}
10941094
break
10951095
case .global, .class, .tail, .yield, .pointer, .unidentified:
10961096
break
10971097
}
10981098
if let allocation = allocation {
1099-
if !allocation.type.objectType.isEscapable {
1099+
if !allocation.isEscapable {
11001100
return visitLocalStore(allocation: allocation, storedOperand: operand, storeAddress: address)
11011101
}
11021102
}
1103-
if address.type.objectType.isEscapable {
1103+
if address.isEscapable {
11041104
return .continueWalk
11051105
}
11061106
return escapingDependence(on: operand)
@@ -1179,13 +1179,13 @@ extension LifetimeDependenceDefUseWalker {
11791179
// If the lifetime dependence is scoped, then we can ignore it
11801180
// because a mark_dependence [nonescaping] represents the
11811181
// dependence.
1182-
if let result = apply.singleDirectResult, !result.type.isEscapable {
1182+
if let result = apply.singleDirectResult, !result.isEscapable {
11831183
if dependentUse(of: operand, into: result) == .abortWalk {
11841184
return .abortWalk
11851185
}
11861186
}
11871187
for resultAddr in apply.indirectResultOperands
1188-
where !resultAddr.value.type.isEscapable {
1188+
where !resultAddr.value.isEscapable {
11891189
if visitStoredUses(of: operand, into: resultAddr.value) == .abortWalk {
11901190
return .abortWalk
11911191
}

SwiftCompilerSources/Sources/SIL/Type.swift

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,12 @@ public struct Type : CustomStringConvertible, NoReflectionChildren {
6363

6464
public var isMoveOnly: Bool { bridged.isMoveOnly() }
6565

66-
public var isEscapable: Bool { bridged.isEscapable() }
67-
public var mayEscape: Bool { !isNoEscapeFunction && isEscapable }
66+
public func isEscapable(in function: Function) -> Bool {
67+
bridged.isEscapable(function.bridged)
68+
}
69+
public func mayEscape(in function: Function) -> Bool {
70+
!isNoEscapeFunction && isEscapable(in: function)
71+
}
6872

6973
/// Can only be used if the type is in fact a nominal type (`isNominal` is true).
7074
public var nominal: NominalTypeDecl {
@@ -146,6 +150,16 @@ public struct Type : CustomStringConvertible, NoReflectionChildren {
146150
}
147151
}
148152

153+
extension Value {
154+
public var isEscapable: Bool {
155+
type.objectType.isEscapable(in: parentFunction)
156+
}
157+
158+
public var mayEscape: Bool {
159+
type.objectType.mayEscape(in: parentFunction)
160+
}
161+
}
162+
149163
extension Type: Equatable {
150164
public static func ==(lhs: Type, rhs: Type) -> Bool {
151165
lhs.bridged.opaqueValue == rhs.bridged.opaqueValue

include/swift/SIL/SILBridging.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ struct BridgedType {
350350
BRIDGED_INLINE bool isEmpty(BridgedFunction f) const;
351351
BRIDGED_INLINE TraitResult canBeClass() const;
352352
BRIDGED_INLINE bool isMoveOnly() const;
353-
BRIDGED_INLINE bool isEscapable() const;
353+
BRIDGED_INLINE bool isEscapable(BridgedFunction f) const;
354354
BRIDGED_INLINE bool isOrContainsObjectiveCClass() const;
355355
BRIDGED_INLINE bool isBuiltinInteger() const;
356356
BRIDGED_INLINE bool isBuiltinFloat() const;

include/swift/SIL/SILBridgingImpl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,8 @@ bool BridgedType::isMoveOnly() const {
274274
return unbridged().isMoveOnly();
275275
}
276276

277-
bool BridgedType::isEscapable() const {
278-
return unbridged().isEscapable();
277+
bool BridgedType::isEscapable(BridgedFunction f) const {
278+
return unbridged().isEscapable(*f.getFunction());
279279
}
280280

281281
bool BridgedType::isOrContainsObjectiveCClass() const {

include/swift/SIL/SILType.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -897,13 +897,15 @@ class SILType {
897897

898898
/// False if SILValues of this type cannot be used outside the scope of their
899899
/// lifetime dependence.
900-
bool isEscapable() const;
900+
bool isEscapable(const SILFunction &function) const;
901901

902902
/// True for (isEscapable && !isNoEscapeFunction)
903903
///
904904
/// Equivalent to getASTType()->mayEscape(), but handles SIL-specific types,
905905
/// namely SILFunctionType.
906-
bool mayEscape() const { return !isNoEscapeFunction() && isEscapable(); }
906+
bool mayEscape(const SILFunction &function) const {
907+
return !isNoEscapeFunction() && isEscapable(function);
908+
}
907909

908910
//
909911
// Accessors for types used in SIL instructions:

lib/SIL/IR/SILType.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,7 +1051,7 @@ SILType::getSingletonAggregateFieldType(SILModule &M,
10511051
return SILType();
10521052
}
10531053

1054-
bool SILType::isEscapable() const {
1054+
bool SILType::isEscapable(const SILFunction &function) const {
10551055
CanType ty = getASTType();
10561056

10571057
// For storage with reference ownership, check the referent.
@@ -1065,7 +1065,8 @@ bool SILType::isEscapable() const {
10651065
if (auto boxTy = getAs<SILBoxType>()) {
10661066
auto fields = boxTy->getLayout()->getFields();
10671067
assert(fields.size() == 1);
1068-
ty = fields[0].getLoweredType();
1068+
ty = ::getSILBoxFieldLoweredType(function.getTypeExpansionContext(), boxTy,
1069+
function.getModule().Types, 0);
10691070
}
10701071

10711072
// TODO: Support ~Escapable in parameter packs.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %target-sil-opt %s \
2+
// RUN: -o /dev/null \
3+
// RUN: -sil-verify-all \
4+
// RUN: -enable-experimental-feature NonescapableTypes \
5+
// RUN: -enable-experimental-feature NoncopyableGenerics \
6+
// RUN: -lifetime-dependence-diagnostics
7+
8+
// REQUIRES: asserts
9+
// REQUIRES: swift_in_compiler
10+
11+
sil_stage raw
12+
13+
// Test that SILType.isEscpable does not crash on a generic box when NoncopyableGenerics is enabled.
14+
sil shared [serialized] [ossa] @testLocalFunc : $@convention(thin) <T, U> (@guaranteed <τ_0_0> { var τ_0_0 } <U>) -> () {
15+
bb0(%1 : @closureCapture @guaranteed $<τ_0_0> { var τ_0_0 } <U>):
16+
%33 = tuple ()
17+
return %33 : $()
18+
}

0 commit comments

Comments
 (0)