Skip to content

Commit d065a3e

Browse files
authored
Merge pull request #75562 from atrick/nfc-lifedep
[nfc] LifetimeDiagnostics cleanup
2 parents 1869174 + 1113c75 commit d065a3e

14 files changed

+165
-68
lines changed

SwiftCompilerSources/Sources/Basic/Utils.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,14 @@ public func precondition(_ condition: Bool, _ message: @autoclosure () -> String
5858
// Debugging Utilities
5959
//===----------------------------------------------------------------------===//
6060

61+
public func debugLog(prefix: Bool = true, _ message: @autoclosure () -> String) {
62+
let formatted = (prefix ? "### " : "") + message()
63+
formatted._withBridgedStringRef { ref in
64+
Bridged_dbgs().write(ref)
65+
}
66+
Bridged_dbgs().newLine()
67+
}
68+
6169
/// Let's lldb's `po` command not print any "internal" properties of the conforming type.
6270
///
6371
/// This is useful if the `description` already contains all the information of a type instance.

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/LifetimeDependenceDiagnostics.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ private let verbose = false
1616

1717
private func log(prefix: Bool = true, _ message: @autoclosure () -> String) {
1818
if verbose {
19-
print((prefix ? "### " : "") + message())
19+
debugLog(prefix: prefix, message())
2020
}
2121
}
2222

@@ -36,6 +36,7 @@ let lifetimeDependenceDiagnosticsPass = FunctionPass(
3636
#endif
3737
log(prefix: false, "\n--- Diagnosing lifetime dependence in \(function.name)")
3838
log("\(function)")
39+
log("\(function.convention)")
3940

4041
for argument in function.arguments
4142
where !argument.type.isEscapable(in: function)
@@ -54,8 +55,8 @@ let lifetimeDependenceDiagnosticsPass = FunctionPass(
5455
continue
5556
}
5657
if let apply = instruction as? FullApplySite {
57-
// Handle ~Escapable results that do not have a lifetime
58-
// dependence (@_unsafeNonescapableResult).
58+
// Handle ~Escapable results that do not have a lifetime dependence. This includes implicit initializers and
59+
// @_unsafeNonescapableResult.
5960
apply.resultOrYields.forEach {
6061
if let lifetimeDep = LifetimeDependence(unsafeApplyResult: $0,
6162
context) {

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/LifetimeDependenceInsertion.swift

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ private func insertDependencies(for apply: LifetimeDependentApply,
116116
insertMarkDependencies(value: dependentValue, initializer: nil,
117117
bases: bases, builder: builder, context)
118118
}
119-
let builder = Builder(after: apply.applySite, context)
120119
for resultOper in apply.applySite.indirectResultOperands {
121120
let accessBase = resultOper.value.accessBase
122121
guard let (initialAddress, initializingStore) =
@@ -132,11 +131,11 @@ private func insertDependencies(for apply: LifetimeDependentApply,
132131
context) else {
133132
continue
134133
}
135-
assert(initializingStore == resultOper.instruction,
136-
"an indirect result is a store")
137-
insertMarkDependencies(value: initialAddress,
138-
initializer: initializingStore, bases: bases,
139-
builder: builder, context)
134+
assert(initializingStore == resultOper.instruction, "an indirect result is a store")
135+
Builder.insert(after: apply.applySite, context) { builder in
136+
insertMarkDependencies(value: initialAddress, initializer: initializingStore, bases: bases, builder: builder,
137+
context)
138+
}
140139
}
141140
}
142141

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ObjCBridgingOptimization.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ private func optimizeNonOptionalBridging(_ apply: ApplyInst,
232232
private func removeBridgingCodeInPredecessors(of block: BasicBlock, _ context: FunctionPassContext) {
233233
for pred in block.predecessors {
234234
let branch = pred.terminator as! BranchInst
235-
let builder = Builder(after: branch, context)
235+
let builder = Builder(atEndOf: branch.parentBlock, location: branch.location, context)
236236
builder.createBranch(to: block)
237237

238238
let en = branch.operands[0].value as! EnumInst

SwiftCompilerSources/Sources/Optimizer/PassManager/Context.swift

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -487,19 +487,23 @@ extension Builder {
487487
}
488488

489489
/// Creates a builder which inserts _after_ `insPnt`, using a custom `location`.
490+
///
491+
/// TODO: this is usually incorrect for terminator instructions. Instead use
492+
/// `Builder.insert(after:location:_:insertFunc)` from OptUtils.swift. Rename this to afterNonTerminator.
490493
init(after insPnt: Instruction, location: Location, _ context: some MutatingContext) {
491494
context.verifyIsTransforming(function: insPnt.parentFunction)
492-
if let nextInst = insPnt.next {
493-
self.init(insertAt: .before(nextInst), location: location,
494-
context.notifyInstructionChanged, context._bridged.asNotificationHandler())
495-
} else {
496-
self.init(insertAt: .atEndOf(insPnt.parentBlock), location: location,
497-
context.notifyInstructionChanged, context._bridged.asNotificationHandler())
495+
guard let nextInst = insPnt.next else {
496+
fatalError("cannot insert an instruction after a block terminator.")
498497
}
498+
self.init(insertAt: .before(nextInst), location: location,
499+
context.notifyInstructionChanged, context._bridged.asNotificationHandler())
499500
}
500501

501502
/// Creates a builder which inserts _after_ `insPnt`, using `insPnt`'s next
502503
/// non-meta instruction's location.
504+
///
505+
/// TODO: this is incorrect for terminator instructions. Instead use `Builder.insert(after:location:_:insertFunc)`
506+
/// from OptUtils.swift. Rename this to afterNonTerminator.
503507
init(after insPnt: Instruction, _ context: some MutatingContext) {
504508
self.init(after: insPnt, location: insPnt.locationOfNextNonMetaInstruction, context)
505509
}

SwiftCompilerSources/Sources/Optimizer/Utilities/AddressUtils.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ private func log(_ message: @autoclosure () -> String) {
2525
///
2626
/// TODO: Integrate this with SIL verification to ensure completeness.
2727
///
28-
/// TODO: Convert AddressDefUseWalker to conform to AddressUtils after
28+
/// TODO: Convert AddressDefUseWalker to use AddressUseVisitor after
2929
/// checking that the additional instructions are handled correctly by
3030
/// escape analysis.
3131
///

SwiftCompilerSources/Sources/Optimizer/Utilities/FunctionSignatureTransforms.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,6 @@ private func createForwardingApply(
179179
isNonThrowing: ai.isNonThrowing,
180180
isNonAsync: ai.isNonAsync,
181181
specializationInfo: ai.specializationInfo)
182-
let builder = Builder(after: newApply, context)
183182
builder.createReturn(of: newApply)
184183
case let tai as TryApplyInst:
185184
let normalBlock = thunk.appendNewBlock(context)

SwiftCompilerSources/Sources/Optimizer/Utilities/LifetimeDependenceUtils.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ struct LifetimeDependence : CustomStringConvertible {
109109
case caller(Argument)
110110
/// An access scope.
111111
case access(BeginAccessInst)
112-
/// An coroutine.
112+
/// A coroutine.
113113
case yield(Value)
114114
/// An owned value whose OSSA lifetime encloses nonescapable values
115115
case owned(Value)

SwiftCompilerSources/Sources/Optimizer/Utilities/OptUtils.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,10 @@ extension FullApplySite {
163163
}
164164

165165
extension Builder {
166+
static func insert(after inst: Instruction, _ context: some MutatingContext, insertFunc: (Builder) -> ()) {
167+
Builder.insert(after: inst, location: inst.location, context, insertFunc: insertFunc)
168+
}
169+
166170
static func insert(after inst: Instruction, location: Location,
167171
_ context: some MutatingContext, insertFunc: (Builder) -> ()) {
168172
if inst is TermInst {

SwiftCompilerSources/Sources/SIL/ApplySite.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ public struct ApplyOperandConventions : Collection {
7171
calleeArgumentIndex(ofOperandIndex: operandIndex)!]
7272
}
7373

74+
public subscript(parameterDependencies operandIndex: Int)
75+
-> FunctionConvention.LifetimeDependencies? {
76+
return calleeArgumentConventions[parameterDependencies:
77+
calleeArgumentIndex(ofOperandIndex: operandIndex)!]
78+
}
79+
7480
public var firstParameterOperandIndex: Int {
7581
return ApplyOperandConventions.firstArgumentIndex +
7682
calleeArgumentConventions.firstParameterIndex
@@ -222,6 +228,16 @@ extension ApplySite {
222228
functionConvention.resultDependencies != nil
223229
}
224230

231+
public var hasLifetimeDependence: Bool {
232+
functionConvention.hasLifetimeDependencies()
233+
}
234+
235+
public func parameterDependencies(target operand: Operand) -> FunctionConvention.LifetimeDependencies? {
236+
let idx = operand.index
237+
return idx < operandConventions.startIndex ? nil
238+
: operandConventions[parameterDependencies: idx]
239+
}
240+
225241
public var yieldConventions: YieldConventions {
226242
YieldConventions(convention: functionConvention)
227243
}

SwiftCompilerSources/Sources/SIL/Argument.swift

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -248,13 +248,22 @@ public struct ArgumentConventions : Collection, CustomStringConvertible {
248248
return convention.parameters[paramIdx]
249249
}
250250

251-
/// Return a dependence of the function results on the indexed parameter.
252-
public subscript(resultDependsOn argumentIndex: Int)
253-
-> LifetimeDependenceConvention? {
254-
guard let paramIdx = parameterIndex(for: argumentIndex) else {
251+
public subscript(parameterDependencies targetArgumentIndex: Int) -> FunctionConvention.LifetimeDependencies? {
252+
guard let targetParamIdx = parameterIndex(for: targetArgumentIndex) else {
255253
return nil
256254
}
257-
return convention.resultDependencies?[paramIdx]
255+
return convention.parameterDependencies(for: targetParamIdx)
256+
}
257+
258+
/// Return a dependence of the function results on the indexed parameter.
259+
public subscript(resultDependsOn argumentIndex: Int) -> LifetimeDependenceConvention? {
260+
findDependence(source: argumentIndex, in: convention.resultDependencies)
261+
}
262+
263+
/// Return a dependence of the target argument on the source argument.
264+
public func getDependence(target targetArgumentIndex: Int, source sourceArgumentIndex: Int)
265+
-> LifetimeDependenceConvention? {
266+
findDependence(source: sourceArgumentIndex, in: self[parameterDependencies: targetArgumentIndex])
258267
}
259268

260269
/// Number of SIL arguments for the function type's results
@@ -282,8 +291,11 @@ public struct ArgumentConventions : Collection, CustomStringConvertible {
282291
}
283292
for idx in indirectSILResultCount..<endIndex {
284293
str += "\n[\(idx)] parameter: " + self[idx].description
294+
if let deps = self[parameterDependencies: idx] {
295+
str += "\n lifetime: \(deps)"
296+
}
285297
if let dep = self[resultDependsOn: idx] {
286-
str += "resultDependsOn: " + dep.description
298+
str += "\n result dependence: " + dep.description
287299
}
288300
}
289301
return str
@@ -295,6 +307,14 @@ extension ArgumentConventions {
295307
let firstParamIdx = firstParameterIndex // bridging call
296308
return argIdx < firstParamIdx ? nil : argIdx - firstParamIdx
297309
}
310+
311+
private func findDependence(source argumentIndex: Int, in dependencies: FunctionConvention.LifetimeDependencies?)
312+
-> LifetimeDependenceConvention? {
313+
guard let paramIdx = parameterIndex(for: argumentIndex) else {
314+
return nil
315+
}
316+
return dependencies?[paramIdx]
317+
}
298318
}
299319

300320
public struct YieldConventions : Collection, CustomStringConvertible {

SwiftCompilerSources/Sources/SIL/FunctionConvention.swift

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -73,31 +73,33 @@ public struct FunctionConvention : CustomStringConvertible {
7373
hasLoweredAddresses: hasLoweredAddresses)
7474
}
7575

76-
/// If the function result depends on any parameters, return a
77-
/// Collection of LifetimeDependenceConvention indexed on the
78-
/// function parameter.
79-
public var resultDependencies: ResultDependencies? {
80-
let bridgedDependencies = bridgedFunctionType.SILFunctionType_getLifetimeDependencies()
81-
let dependencies = LifetimeDependencies(bridged: bridgedDependencies)
82-
let targetIndex = parameters.count
83-
84-
for dependence in dependencies {
85-
if dependence.getTargetIndex() == targetIndex {
86-
return ResultDependencies(bridged: dependence,
87-
parameterCount: parameters.count,
88-
hasSelfParameter: hasSelfParameter)
89-
}
90-
}
91-
return nil
76+
/// If the function result depends on any parameters, return a Collection of LifetimeDependenceConventions for the
77+
/// dependence source parameters.
78+
public var resultDependencies: LifetimeDependencies? {
79+
lifetimeDependencies(for: parameters.count)
80+
}
81+
82+
/// If the parameter indexed by 'targetParameterIndex' is the target of any dependencies on other parameters, return a
83+
/// Collection of LifetimeDependenceConventions for the dependence source parameters.
84+
public func parameterDependencies(for targetParameterIndex: Int) -> LifetimeDependencies? {
85+
lifetimeDependencies(for: targetParameterIndex)
86+
}
87+
88+
public func hasLifetimeDependencies() -> Bool {
89+
return bridgedFunctionType.SILFunctionType_getLifetimeDependencies().count() != 0
9290
}
9391

9492
public var description: String {
9593
var str = String(taking: bridgedFunctionType.getDebugDescription())
96-
parameters.forEach { str += "\nparameter: " + $0.description }
94+
for paramIdx in 0..<parameters.count {
95+
str += "\nparameter: " + parameters[paramIdx].description
96+
if let deps = parameterDependencies(for: paramIdx) {
97+
str += "\n lifetime: \(deps)"
98+
}
99+
}
97100
results.forEach { str += "\n result: " + $0.description }
98-
str += (hasLoweredAddresses ? "\n[lowered_address]" : "\n[sil_opaque]")
99101
if let deps = resultDependencies {
100-
str += "\nresult dependences \(deps)"
102+
str += "\n lifetime: \(deps)"
101103
}
102104
return str
103105
}
@@ -248,28 +250,22 @@ public enum LifetimeDependenceConvention : CustomStringConvertible {
248250
}
249251

250252
extension FunctionConvention {
251-
struct LifetimeDependencies : Collection {
252-
let bridged: BridgedLifetimeDependenceInfoArray
253-
254-
var startIndex: Int { 0 }
255-
256-
var endIndex: Int { bridged.count() }
257-
258-
func index(after index: Int) -> Int {
259-
return index + 1
260-
}
261-
// Create a Swift LifetimeDependenceInfo for BridgedLifetimeDependenceInfo if this method needs
262-
// to be exposed outside FunctionConvention.
263-
// That will likely need bridging IndexSubset to Swift.
264-
subscript(_ index: Int) -> BridgedLifetimeDependenceInfo {
265-
return bridged.at(index)
253+
// 'targetIndex' is either the parameter index or parameters.count for the function result.
254+
private func lifetimeDependencies(for targetIndex: Int) -> LifetimeDependencies? {
255+
let bridgedDependenceInfoArray = bridgedFunctionType.SILFunctionType_getLifetimeDependencies()
256+
for infoIndex in 0..<bridgedDependenceInfoArray.count() {
257+
let bridgedDependenceInfo = bridgedDependenceInfoArray.at(infoIndex)
258+
if bridgedDependenceInfo.targetIndex == targetIndex {
259+
return LifetimeDependencies(bridged: bridgedDependenceInfo,
260+
parameterCount: parameters.count,
261+
hasSelfParameter: hasSelfParameter)
262+
}
266263
}
264+
return nil
267265
}
268-
}
269266

270-
extension FunctionConvention {
271267
/// Collection of LifetimeDependenceConvention? that parallels parameters.
272-
public struct ResultDependencies : Collection, CustomStringConvertible {
268+
public struct LifetimeDependencies : Collection, CustomStringConvertible {
273269
let bridged: BridgedLifetimeDependenceInfo
274270
let paramCount: Int
275271
let hasSelfParam: Bool

include/swift/Basic/BasicBridging.h

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -185,16 +185,12 @@ enum ENUM_EXTENSIBILITY_ATTR(open) BridgedFeature {
185185
#include "swift/Basic/Features.def"
186186
};
187187

188-
//===----------------------------------------------------------------------===//
189-
// MARK: OStream
190-
//===----------------------------------------------------------------------===//
191-
192-
BRIDGING_WRAPPER_NONNULL(llvm::raw_ostream, OStream)
193-
194188
//===----------------------------------------------------------------------===//
195189
// MARK: StringRef
196190
//===----------------------------------------------------------------------===//
197191

192+
class BridgedOStream;
193+
198194
class BridgedStringRef {
199195
const char *_Nullable Data;
200196
size_t Length;
@@ -250,6 +246,39 @@ BRIDGED_INLINE SwiftInt BridgedOwnedString_count(BridgedOwnedString str);
250246
SWIFT_NAME("getter:BridgedOwnedString.isEmpty(self:)")
251247
BRIDGED_INLINE bool BridgedOwnedString_empty(BridgedOwnedString str);
252248

249+
//===----------------------------------------------------------------------===//
250+
// MARK: OStream
251+
//===----------------------------------------------------------------------===//
252+
253+
class BridgedOStream {
254+
llvm::raw_ostream * _Nonnull os;
255+
256+
public:
257+
SWIFT_UNAVAILABLE("Use init(raw:) instead")
258+
BridgedOStream(llvm::raw_ostream * _Nonnull os) : os(os) {}
259+
260+
SWIFT_UNAVAILABLE("Use '.raw' instead")
261+
llvm::raw_ostream * _Nonnull unbridged() const { return os; }
262+
263+
void write(BridgedStringRef string) const;
264+
265+
void newLine() const;
266+
267+
void flush() const;
268+
};
269+
270+
SWIFT_NAME("getter:BridgedOStream.raw(self:)")
271+
inline void * _Nonnull BridgedOStream_getRaw(BridgedOStream bridged) {
272+
return bridged.unbridged();
273+
}
274+
275+
SWIFT_NAME("BridgedOStream.init(raw:)")
276+
inline BridgedOStream BridgedOStream_fromRaw(void * _Nonnull os) {
277+
return static_cast<llvm::raw_ostream *>(os);
278+
}
279+
280+
BridgedOStream Bridged_dbgs();
281+
253282
//===----------------------------------------------------------------------===//
254283
// MARK: SourceLoc
255284
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)