Skip to content

Commit 7a3ae09

Browse files
committed
Effects: add some comments and add enum argument labels
For clarity
1 parent 9f92220 commit 7a3ae09

File tree

2 files changed

+37
-16
lines changed

2 files changed

+37
-16
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ComputeEscapeEffects.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,12 +155,12 @@ func addArgEffects(_ arg: FunctionArgument, argPath ap: SmallProjectionPath,
155155
case .toReturn(let toPath):
156156
let exclusive = isExclusiveEscapeToReturn(fromArgument: arg, fromPath: argPath,
157157
toPath: toPath, returnInst: returnInst, context)
158-
effect = EscapeEffects.ArgumentEffect(.escapingToReturn(toPath, exclusive),
158+
effect = EscapeEffects.ArgumentEffect(.escapingToReturn(toPath: toPath, isExclusive: exclusive),
159159
argumentIndex: arg.index, pathPattern: argPath)
160160
case .toArgument(let toArgIdx, let toPath):
161161
// Exclusive argument -> argument effects cannot appear because such an effect would
162162
// involve a store which is not permitted for exclusive escapes.
163-
effect = EscapeEffects.ArgumentEffect(.escapingToArgument(toArgIdx, toPath, /*exclusive*/ false),
163+
effect = EscapeEffects.ArgumentEffect(.escapingToArgument(toArgumentIndex: toArgIdx, toPath: toPath, isExclusive: false),
164164
argumentIndex: arg.index, pathPattern: argPath)
165165
}
166166
newEffects.append(effect)

SwiftCompilerSources/Sources/SIL/Effects.swift

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -240,9 +240,9 @@ public struct EscapeEffects : CustomStringConvertible, NoReflectionChildren {
240240
/// [%0: escape s1 => %r] // field 2 of argument 0 exclusively escapes via return.
241241
/// [%0: escape s1 -> %r] // field 2 of argument 0 - and other values - escape via return
242242
///
243-
/// The "exclusive" flag (= second payload) is true if only the argument escapes,
244-
/// but nothing else escapes to the return value.
245-
/// For example, "exclusive" is true for the following function:
243+
/// The `isExclusive` flag is true if only the argument escapes, but nothing else escapes to
244+
/// the return value.
245+
/// For example, `isExclusive` is true for the following function:
246246
///
247247
/// @_effect(escaping c => return)
248248
/// func exclusiveEscape(_ c: Class) -> Class { return c }
@@ -254,17 +254,38 @@ public struct EscapeEffects : CustomStringConvertible, NoReflectionChildren {
254254
/// @_effect(escaping c -> return)
255255
/// func notExclusiveEscape(_ c: Class) -> Class { return cond ? c : global }
256256
///
257-
case escapingToReturn(SmallProjectionPath, Bool) // toPath, exclusive
257+
/// Also, if `isExclusive` is true, there must not be a store in the chain from the argument to
258+
/// the return, e.g.
259+
///
260+
/// @_effect(escaping x -> return)
261+
/// func notExclusiveEscape(_ s: String) -> Class {
262+
/// c = new Class()
263+
/// c.s = s // Store, which prevents the effect to be `isExclusive`
264+
/// return s
265+
/// }
266+
case escapingToReturn(toPath: SmallProjectionPath, isExclusive: Bool)
258267

259268
/// Like `escapingToReturn`, but the argument escapes to another argument.
260269
///
261270
/// Example: The argument effects of
271+
///
262272
/// func argToArgEscape(_ r: inout Class, _ c: Class) { r = c }
263273
///
264274
/// would be
265275
/// [%1: escape => %0] // Argument 1 escapes to argument 0
266276
///
267-
case escapingToArgument(Int, SmallProjectionPath, Bool) // toArgumentIndex, toPath, exclusive
277+
/// It's not allowed that the argument (or a derived value) is _stored_ to an object which is loaded from somewhere.
278+
/// In the following example `c` is loaded from the indirect inout argument and `s` is stored to a field of `c`:
279+
///
280+
/// func noEscapeEffect(_ c: inout Class, s: String) {
281+
/// c.s = s
282+
/// }
283+
///
284+
/// In this case there is no escaping effect from `s` to `c`.
285+
/// Note that theoretically this rule also applies to the `escapingToReturn` effect, but it's impossible
286+
/// to construct such a situation for an argument which is only escaping to the function return.
287+
///
288+
case escapingToArgument(toArgumentIndex: Int, toPath: SmallProjectionPath, isExclusive: Bool)
268289
}
269290

270291
/// To which argument does this effect apply to?
@@ -309,19 +330,19 @@ public struct EscapeEffects : CustomStringConvertible, NoReflectionChildren {
309330
if resultArgDelta != 1 {
310331
return nil
311332
}
312-
self.kind = .escapingToArgument(0, toPath, exclusive)
333+
self.kind = .escapingToArgument(toArgumentIndex: 0, toPath: toPath, isExclusive: exclusive)
313334
} else {
314-
self.kind = .escapingToReturn(toPath, exclusive)
335+
self.kind = .escapingToReturn(toPath: toPath, isExclusive: exclusive)
315336
}
316337
case .escapingToArgument(let toArgIdx, let toPath, let exclusive):
317338
let resultingToArgIdx = toArgIdx + resultArgDelta
318339
if resultingToArgIdx < 0 {
319340
if resultingToArgIdx != -1 {
320341
return nil
321342
}
322-
self.kind = .escapingToReturn(toPath, exclusive)
343+
self.kind = .escapingToReturn(toPath: toPath, isExclusive: exclusive)
323344
} else {
324-
self.kind = .escapingToArgument(resultingToArgIdx, toPath, exclusive)
345+
self.kind = .escapingToArgument(toArgumentIndex: resultingToArgIdx, toPath: toPath, isExclusive: exclusive)
325346
}
326347
}
327348
}
@@ -642,16 +663,16 @@ extension StringParser {
642663
try throwError("multi-value returns not supported yet")
643664
}
644665
let toPath = try parsePathPatternFromSource(for: function, type: function.argumentTypes[0])
645-
return EscapeEffects.ArgumentEffect(.escapingToArgument(0, toPath, exclusive),
666+
return EscapeEffects.ArgumentEffect(.escapingToArgument(toArgumentIndex: 0, toPath: toPath, isExclusive: exclusive),
646667
argumentIndex: fromArgIdx, pathPattern: fromPath, isDerived: false)
647668
}
648669
let toPath = try parsePathPatternFromSource(for: function, type: function.resultType)
649-
return EscapeEffects.ArgumentEffect(.escapingToReturn(toPath, exclusive),
670+
return EscapeEffects.ArgumentEffect(.escapingToReturn(toPath: toPath, isExclusive: exclusive),
650671
argumentIndex: fromArgIdx, pathPattern: fromPath, isDerived: false)
651672
}
652673
let toArgIdx = try parseArgumentIndexFromSource(for: function, params: params)
653674
let toPath = try parsePathPatternFromSource(for: function, type: function.argumentTypes[toArgIdx])
654-
return EscapeEffects.ArgumentEffect(.escapingToArgument(toArgIdx, toPath, exclusive),
675+
return EscapeEffects.ArgumentEffect(.escapingToArgument(toArgumentIndex: toArgIdx, toPath: toPath, isExclusive: exclusive),
655676
argumentIndex: fromArgIdx, pathPattern: fromPath, isDerived: false)
656677
}
657678
try throwError("unknown effect")
@@ -715,12 +736,12 @@ extension StringParser {
715736
let effect: EscapeEffects.ArgumentEffect
716737
if consume("%r") {
717738
let toPath = consume(".") ? try parseProjectionPathFromSIL() : SmallProjectionPath()
718-
effect = EscapeEffects.ArgumentEffect(.escapingToReturn(toPath, exclusive),
739+
effect = EscapeEffects.ArgumentEffect(.escapingToReturn(toPath: toPath, isExclusive: exclusive),
719740
argumentIndex: argumentIndex, pathPattern: fromPath, isDerived: isDerived)
720741
} else {
721742
let toArgIdx = try parseArgumentIndexFromSIL()
722743
let toPath = consume(".") ? try parseProjectionPathFromSIL() : SmallProjectionPath()
723-
effect = EscapeEffects.ArgumentEffect(.escapingToArgument(toArgIdx, toPath, exclusive),
744+
effect = EscapeEffects.ArgumentEffect(.escapingToArgument(toArgumentIndex: toArgIdx, toPath: toPath, isExclusive: exclusive),
724745
argumentIndex: argumentIndex, pathPattern: fromPath, isDerived: isDerived)
725746
}
726747
effects.escapeEffects.arguments.append(effect)

0 commit comments

Comments
 (0)