12
12
13
13
import SIL
14
14
15
- /// Computes effects for function arguments.
15
+ /// Computes escape effects for function arguments.
16
16
///
17
17
/// For example, if an argument does not escape, adds a non-escaping effect,
18
- /// e.g. "[escapes !%0.**]":
19
- ///
20
- /// sil [escapes !%0.**] @foo : $@convention(thin) (@guaranteed X) -> () {
18
+ /// ```
19
+ /// sil @foo : $@convention(thin) (@guaranteed X) -> () {
20
+ /// [%0: noecape **]
21
21
/// bb0(%0 : $X):
22
22
/// %1 = tuple ()
23
23
/// return %1 : $()
24
24
/// }
25
- ///
25
+ /// ```
26
26
/// The pass does not try to change or re-compute _defined_ effects.
27
- /// Currently, only escaping effects are handled.
28
- /// In future, this pass may also add other effects, like memory side effects.
27
+ ///
29
28
let computeEffects = FunctionPass ( name: " compute-effects " , {
30
29
( function: Function , context: PassContext ) in
31
- var argsWithDefinedEffects = getArgIndicesWithDefinedEffects ( of: function)
32
30
33
- struct IgnoreRecursiveCallVisitor : EscapeVisitor {
34
- func visitUse( operand: Operand , path: EscapePath ) -> UseResult {
35
- return isOperandOfRecursiveCall ( operand) ? . ignore : . continueWalk
36
- }
37
- }
38
- var newEffects = Stack < ArgumentEffect > ( context)
31
+ var newEffects = Stack < EscapeEffects . ArgumentEffect > ( context)
32
+ defer { newEffects. deinitialize ( ) }
33
+
39
34
let returnInst = function. returnInstruction
35
+ let argsWithDefinedEffects = getArgIndicesWithDefinedEscapingEffects ( of: function)
40
36
41
37
for arg in function. arguments {
42
38
// We are not interested in arguments with trivial types.
43
39
if !arg. type. isNonTrivialOrContainsRawPointer ( in: function) { continue }
44
40
45
41
// Also, we don't want to override defined effects.
46
42
if argsWithDefinedEffects. contains ( arg. index) { continue }
47
-
43
+
44
+ struct IgnoreRecursiveCallVisitor : EscapeVisitor {
45
+ func visitUse( operand: Operand , path: EscapePath ) -> UseResult {
46
+ return isOperandOfRecursiveCall ( operand) ? . ignore : . continueWalk
47
+ }
48
+ }
49
+
48
50
// First check: is the argument (or a projected value of it) escaping at all?
49
51
if !arg. at ( . anything) . isEscapingWhenWalkingDown ( using: IgnoreRecursiveCallVisitor ( ) ,
50
52
context) {
51
- newEffects. push ( ArgumentEffect ( . notEscaping, argumentIndex: arg. index, pathPattern: SmallProjectionPath ( . anything) ) )
53
+ let effect = EscapeEffects . ArgumentEffect ( . notEscaping, argumentIndex: arg. index,
54
+ pathPattern: SmallProjectionPath ( . anything) )
55
+ newEffects. push ( effect)
52
56
continue
53
57
}
54
58
@@ -62,17 +66,16 @@ let computeEffects = FunctionPass(name: "compute-effects", {
62
66
}
63
67
64
68
context. modifyEffects ( in: function) { ( effects: inout FunctionEffects ) in
65
- effects. removeDerivedEffects ( )
66
- effects. argumentEffects . append ( contentsOf: newEffects)
69
+ effects. escapeEffects . arguments = effects . escapeEffects . arguments . filter { !$0 . isDerived }
70
+ effects. escapeEffects . arguments . append ( contentsOf: newEffects)
67
71
}
68
- newEffects. removeAll ( )
69
72
} )
70
73
71
74
72
75
/// Returns true if an argument effect was added.
73
76
private
74
77
func addArgEffects( _ arg: FunctionArgument , argPath ap: SmallProjectionPath ,
75
- to newEffects: inout Stack < ArgumentEffect > ,
78
+ to newEffects: inout Stack < EscapeEffects . ArgumentEffect > ,
76
79
_ returnInst: ReturnInst ? , _ context: PassContext ) -> Bool {
77
80
// Correct the path if the argument is not a class reference itself, but a value type
78
81
// containing one or more references.
@@ -141,39 +144,36 @@ func addArgEffects(_ arg: FunctionArgument, argPath ap: SmallProjectionPath,
141
144
return false
142
145
}
143
146
144
- let effect : ArgumentEffect
147
+ let effect : EscapeEffects . ArgumentEffect
145
148
switch result {
146
149
case . notSet:
147
- effect = ArgumentEffect ( . notEscaping, argumentIndex: arg. index, pathPattern: argPath)
150
+ effect = EscapeEffects . ArgumentEffect ( . notEscaping, argumentIndex: arg. index, pathPattern: argPath)
148
151
case . toReturn( let toPath) :
149
152
let exclusive = isExclusiveEscapeToReturn ( fromArgument: arg, fromPath: argPath,
150
153
toPath: toPath, returnInst: returnInst, context)
151
- effect = ArgumentEffect ( . escapingToReturn( toPath, exclusive) ,
152
- argumentIndex: arg. index, pathPattern: argPath)
154
+ effect = EscapeEffects . ArgumentEffect ( . escapingToReturn( toPath, exclusive) ,
155
+ argumentIndex: arg. index, pathPattern: argPath)
153
156
case . toArgument( let toArgIdx, let toPath) :
154
157
let exclusive = isExclusiveEscapeToArgument ( fromArgument: arg, fromPath: argPath,
155
158
toArgumentIndex: toArgIdx, toPath: toPath, context)
156
- effect = ArgumentEffect ( . escapingToArgument( toArgIdx, toPath, exclusive) ,
157
- argumentIndex: arg. index, pathPattern: argPath)
159
+ effect = EscapeEffects . ArgumentEffect ( . escapingToArgument( toArgIdx, toPath, exclusive) ,
160
+ argumentIndex: arg. index, pathPattern: argPath)
158
161
}
159
162
newEffects. push ( effect)
160
163
return true
161
164
}
162
165
163
166
/// Returns a set of argument indices for which there are "defined" effects (as opposed to derived effects).
164
- private func getArgIndicesWithDefinedEffects ( of function: Function ) -> Set < Int > {
167
+ private func getArgIndicesWithDefinedEscapingEffects ( of function: Function ) -> Set < Int > {
165
168
var argsWithDefinedEffects = Set < Int > ( )
166
169
167
- for effect in function. effects. argumentEffects {
170
+ for effect in function. effects. escapeEffects . arguments {
168
171
if effect. isDerived { continue }
169
172
170
173
argsWithDefinedEffects. insert ( effect. argumentIndex)
171
-
172
174
switch effect. kind {
173
- case . notEscaping, . escapingToReturn:
174
- break
175
- case . escapingToArgument( let toArgIdx, _, _) :
176
- argsWithDefinedEffects. insert ( toArgIdx)
175
+ case . notEscaping, . escapingToReturn: break
176
+ case . escapingToArgument( let toArgIdx, _, _) : argsWithDefinedEffects. insert ( toArgIdx)
177
177
}
178
178
}
179
179
return argsWithDefinedEffects
0 commit comments