Skip to content

Commit a0b2ae9

Browse files
committed
Add AccessBase.storeBorrow.
Don't treat StoreBorrow addresses as unknown bases. While they are never the base of a formal access, they are returned as the AccessBase when querying the enclosing scope of an address.
1 parent f037b63 commit a0b2ae9

File tree

7 files changed

+72
-9
lines changed

7 files changed

+72
-9
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/LifetimeDependenceDiagnostics.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,8 @@ private struct LifetimeVariable {
297297
// TODO: bridge VarDecl for FunctionConvention.Yields
298298
self.varDecl = nil
299299
self.sourceLoc = result.parentInstruction.location.sourceLoc
300+
case .storeBorrow(let sb):
301+
self = .init(dependent: sb.source, context)
300302
case .pointer(let ptrToAddr):
301303
self.varDecl = nil
302304
self.sourceLoc = ptrToAddr.location.sourceLoc

SwiftCompilerSources/Sources/Optimizer/ModulePasses/StackProtection.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ private extension AccessBase {
455455

456456
var isStackAllocated: IsStackAllocatedResult {
457457
switch self {
458-
case .stack:
458+
case .stack, .storeBorrow:
459459
return .yes
460460
case .box, .global:
461461
return .no

SwiftCompilerSources/Sources/Optimizer/Utilities/AddressUtils.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,8 @@ enum AddressOwnershipLiveRange : CustomStringConvertible {
458458
default:
459459
return nil
460460
}
461+
case .storeBorrow(let sb):
462+
return computeValueLiveRange(of: sb.source, context)
461463
case .pointer, .unidentified:
462464
return nil
463465
}

SwiftCompilerSources/Sources/Optimizer/Utilities/LifetimeDependenceUtils.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,11 @@ extension LifetimeDependence.Scope {
369369
}
370370
case let .yield(result):
371371
self = Self(yield: result)
372+
case .storeBorrow(let sb):
373+
guard let scope = Self(base: sb.source, context) else {
374+
return nil
375+
}
376+
self = scope
372377
case .pointer, .unidentified:
373378
self = .unknown(address)
374379
}
@@ -1084,7 +1089,8 @@ extension LifetimeDependenceDefUseWalker {
10841089
return returnedDependence(address: arg, using: operand)
10851090
}
10861091
break
1087-
case .global, .class, .tail, .yield, .pointer, .unidentified:
1092+
case .global, .class, .tail, .yield, .storeBorrow, .pointer, .unidentified:
1093+
// An address produced by .storeBorrow should never be stored into.
10881094
break
10891095
}
10901096
if let allocation = allocation {

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1230,7 +1230,15 @@ final public class BeginBorrowInst : SingleValueInstruction, UnaryInstruction, B
12301230

12311231
final public class LoadBorrowInst : SingleValueInstruction, LoadInstruction, BorrowIntroducingInstruction {}
12321232

1233-
final public class StoreBorrowInst : SingleValueInstruction, StoringInstruction, BorrowIntroducingInstruction { }
1233+
final public class StoreBorrowInst : SingleValueInstruction, StoringInstruction, BorrowIntroducingInstruction {
1234+
var allocStack: AllocStackInst {
1235+
var dest = destination
1236+
if let mark = dest as? MarkUnresolvedNonCopyableValueInst {
1237+
dest = mark.operand.value
1238+
}
1239+
return dest as! AllocStackInst
1240+
}
1241+
}
12341242

12351243
final public class BeginAccessInst : SingleValueInstruction, UnaryInstruction {
12361244
// The raw values must match SILAccessKind.

SwiftCompilerSources/Sources/SIL/Utilities/AccessUtils.swift

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ public enum AccessBase : CustomStringConvertible, Hashable {
6969
/// An indirect result of a `begin_apply`.
7070
case yield(MultipleValueInstructionResult)
7171

72+
/// store_borrow is never the base of a formal access, but calling Value.enclosingScope on an arbitrary address will
73+
/// return it as the accessBase. A store_borrow always stores into an alloc_stack, but it is handled separately
74+
/// because it may be useful for clients to know which value was stored in the temporary stack location for the
75+
/// duration of this borrow scope.
76+
case storeBorrow(StoreBorrowInst)
77+
7278
/// An address which is derived from a `Builtin.RawPointer`.
7379
case pointer(PointerToAddressInst)
7480

@@ -90,6 +96,8 @@ public enum AccessBase : CustomStringConvertible, Hashable {
9096
} else {
9197
self = .unidentified
9298
}
99+
case let sb as StoreBorrowInst:
100+
self = .storeBorrow(sb)
93101
default:
94102
self = .unidentified
95103
}
@@ -105,6 +113,7 @@ public enum AccessBase : CustomStringConvertible, Hashable {
105113
case .tail(let rta): return "tail - \(rta.instance)"
106114
case .argument(let arg): return "argument - \(arg)"
107115
case .yield(let result): return "yield - \(result)"
116+
case .storeBorrow(let sb): return "storeBorrow - \(sb)"
108117
case .pointer(let p): return "pointer - \(p)"
109118
}
110119
}
@@ -114,7 +123,7 @@ public enum AccessBase : CustomStringConvertible, Hashable {
114123
switch self {
115124
case .class, .tail:
116125
return true
117-
case .box, .stack, .global, .argument, .yield, .pointer, .unidentified:
126+
case .box, .stack, .global, .argument, .yield, .storeBorrow, .pointer, .unidentified:
118127
return false
119128
}
120129
}
@@ -125,7 +134,7 @@ public enum AccessBase : CustomStringConvertible, Hashable {
125134
case .box(let pbi): return pbi.box
126135
case .class(let rea): return rea.instance
127136
case .tail(let rta): return rta.instance
128-
case .stack, .global, .argument, .yield, .pointer, .unidentified:
137+
case .stack, .global, .argument, .yield, .storeBorrow, .pointer, .unidentified:
129138
return nil
130139
}
131140
}
@@ -153,7 +162,7 @@ public enum AccessBase : CustomStringConvertible, Hashable {
153162
switch self {
154163
case .class(let rea): return rea.fieldIsLet
155164
case .global(let g): return g.isLet
156-
case .box, .stack, .tail, .argument, .yield, .pointer, .unidentified:
165+
case .box, .stack, .tail, .argument, .yield, .storeBorrow, .pointer, .unidentified:
157166
return false
158167
}
159168
}
@@ -164,7 +173,7 @@ public enum AccessBase : CustomStringConvertible, Hashable {
164173
case .box(let pbi): return pbi.box.referenceRoot is AllocBoxInst
165174
case .class(let rea): return rea.instance.referenceRoot is AllocRefInstBase
166175
case .tail(let rta): return rta.instance.referenceRoot is AllocRefInstBase
167-
case .stack: return true
176+
case .stack, .storeBorrow: return true
168177
case .global, .argument, .yield, .pointer, .unidentified:
169178
return false
170179
}
@@ -173,7 +182,7 @@ public enum AccessBase : CustomStringConvertible, Hashable {
173182
/// True, if the kind of storage of the access is known (e.g. a class property, or global variable).
174183
public var hasKnownStorageKind: Bool {
175184
switch self {
176-
case .box, .class, .tail, .stack, .global:
185+
case .box, .class, .tail, .stack, .storeBorrow, .global:
177186
return true
178187
case .argument, .yield, .pointer, .unidentified:
179188
return false
@@ -203,6 +212,8 @@ public enum AccessBase : CustomStringConvertible, Hashable {
203212
return arg1 == arg2
204213
case (.yield(let baResult1), .yield(let baResult2)):
205214
return baResult1 == baResult2
215+
case (.storeBorrow(let sb1), .storeBorrow(let sb2)):
216+
return sb1 == sb2
206217
case (.pointer(let p1), .pointer(let p2)):
207218
return p1 == p2
208219
default:
@@ -260,6 +271,15 @@ public enum AccessBase : CustomStringConvertible, Hashable {
260271
case (_, .argument(let otherArg)):
261272
return argIsDistinct(otherArg, from: self)
262273

274+
case (.storeBorrow(let arg), .storeBorrow(let otherArg)):
275+
return arg.allocStack != otherArg.allocStack
276+
277+
// A StoreBorrow location can only be used by other StoreBorrows.
278+
case (.storeBorrow, _):
279+
return true
280+
case (_, .storeBorrow):
281+
return true
282+
263283
default:
264284
// As we already handled pairs of the same kind, here we handle pairs with different kinds.
265285
// Different storage kinds cannot alias, regardless where the storage comes from.
@@ -591,7 +611,7 @@ extension ValueUseDefWalker where Path == SmallProjectionPath {
591611
return walkUp(value: rea.instance, path: path.push(.classField, index: rea.fieldIndex)) != .abortWalk
592612
case .tail(let rta):
593613
return walkUp(value: rta.instance, path: path.push(.tailElements, index: 0)) != .abortWalk
594-
case .stack, .global, .argument, .yield, .pointer, .unidentified:
614+
case .stack, .global, .argument, .yield, .storeBorrow, .pointer, .unidentified:
595615
return false
596616
}
597617
}

test/SILOptimizer/accessutils.sil

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ struct Ptr {
2727
var p: Int64
2828
}
2929

30+
class C {}
31+
32+
sil @_getC : $@convention(thin) () -> @owned C
33+
3034
// CHECK-LABEL: Accesses for readIdentifiedArg
3135
// CHECK-NEXT: Value: %0 = argument of bb0 : $*Int64
3236
// CHECK-NEXT: Scope: base
@@ -522,3 +526,24 @@ bb0(%twoInts: $*TwoInts):
522526
%200 = tuple ()
523527
return %200 : $()
524528
}
529+
530+
// CHECK-LABEL: Accesses for storeBorrow
531+
// CHECK: Value: [[SB:%.*]] = store_borrow %0 to [[DEST:%.*]] : $*C
532+
// CHECK: Scope: base
533+
// CHECK: Base: storeBorrow - [[SB]] = store_borrow %0 to [[DEST]] : $*C
534+
// CHECK: Path: ""
535+
// CHECK: no Storage paths
536+
// CHECK-LABEL: End accesses for storeBorrow
537+
sil [ossa] @storeBorrow : $@convention(thin) (@guaranteed C) -> @owned C {
538+
bb0(%0 : @guaranteed $C):
539+
%1 = alloc_stack $C
540+
%2 = store_borrow %0 to %1 : $*C
541+
%3 = function_ref @_getC : $@convention(thin) () -> @owned C
542+
%4 = apply %3() : $@convention(thin) () -> @owned C
543+
%5 = mark_dependence [unresolved] %4 : $C on %2 : $*C
544+
%6 = load [copy] %2 : $*C
545+
destroy_value %5 : $C
546+
end_borrow %2 : $*C
547+
dealloc_stack %1 : $*C
548+
return %6 : $C
549+
}

0 commit comments

Comments
 (0)