@@ -4,6 +4,71 @@ private import AliasAnalysisImports
4
4
5
5
private class IntValue = Ints:: IntValue ;
6
6
7
+ /**
8
+ * If `instr` is a `SideEffectInstruction`, gets the primary `CallInstruction` that caused the side
9
+ * effect. If `instr` is a `CallInstruction`, gets that same `CallInstruction`.
10
+ */
11
+ private CallInstruction getPrimaryCall ( Instruction instr ) {
12
+ result = instr .( CallInstruction )
13
+ or
14
+ result = instr .( SideEffectInstruction ) .getPrimaryInstruction ( )
15
+ }
16
+
17
+ /**
18
+ * Holds if `operand` serves as an input argument (or indirection) to `call`, in the position
19
+ * specified by `input`.
20
+ */
21
+ private predicate isCallInput (
22
+ CallInstruction call , Operand operand , AliasModels:: FunctionInput input
23
+ ) {
24
+ call = getPrimaryCall ( operand .getUse ( ) ) and
25
+ (
26
+ exists ( int index |
27
+ input .isParameterOrQualifierAddress ( index ) and
28
+ operand = call .getArgumentOperand ( index )
29
+ )
30
+ or
31
+ exists ( int index , ReadSideEffectInstruction read |
32
+ input .isParameterDerefOrQualifierObject ( index ) and
33
+ read = call .getAParameterSideEffect ( index ) and
34
+ operand = read .getSideEffectOperand ( )
35
+ )
36
+ )
37
+ }
38
+
39
+ /**
40
+ * Holds if `instr` serves as a return value or output argument indirection for `call`, in the
41
+ * position specified by `output`.
42
+ */
43
+ private predicate isCallOutput (
44
+ CallInstruction call , Instruction instr , AliasModels:: FunctionOutput output
45
+ ) {
46
+ call = getPrimaryCall ( instr ) and
47
+ (
48
+ output .isReturnValue ( ) and instr = call
49
+ or
50
+ exists ( int index , WriteSideEffectInstruction write |
51
+ output .isParameterDerefOrQualifierObject ( index ) and
52
+ write = call .getAParameterSideEffect ( index ) and
53
+ instr = write
54
+ )
55
+ )
56
+ }
57
+
58
+ /**
59
+ * Holds if the address in `operand` flows directly to the result of `resultInstr` due to modeled
60
+ * address flow through a function call.
61
+ */
62
+ private predicate hasAddressFlowThroughCall ( Operand operand , Instruction resultInstr ) {
63
+ exists (
64
+ CallInstruction call , AliasModels:: FunctionInput input , AliasModels:: FunctionOutput output
65
+ |
66
+ call .getStaticCallTarget ( ) .( AliasModels:: AliasFunction ) .hasAddressFlow ( input , output ) and
67
+ isCallInput ( call , operand , input ) and
68
+ isCallOutput ( call , resultInstr , output )
69
+ )
70
+ }
71
+
7
72
/**
8
73
* Holds if the operand `tag` of instruction `instr` is used in a way that does
9
74
* not result in any address held in that operand from escaping beyond the
@@ -74,6 +139,10 @@ IntValue getPointerBitOffset(PointerOffsetInstruction instr) {
74
139
* be a constant, then `bitOffset` is `unknown()`.
75
140
*/
76
141
private predicate operandIsPropagated ( Operand operand , IntValue bitOffset , Instruction instr ) {
142
+ // Some functions are known to propagate an argument
143
+ hasAddressFlowThroughCall ( operand , instr ) and
144
+ bitOffset = 0
145
+ or
77
146
instr = operand .getUse ( ) and
78
147
(
79
148
// Converting to a non-virtual base class adds the offset of the base class.
@@ -118,9 +187,6 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset, Instr
118
187
or
119
188
// A copy propagates the source value.
120
189
operand = instr .( CopyInstruction ) .getSourceValueOperand ( ) and bitOffset = 0
121
- or
122
- // Some functions are known to propagate an argument
123
- isAlwaysReturnedArgument ( operand ) and bitOffset = 0
124
190
)
125
191
}
126
192
@@ -215,13 +281,6 @@ private predicate isArgumentForParameter(
215
281
)
216
282
}
217
283
218
- private predicate isAlwaysReturnedArgument ( Operand operand ) {
219
- exists ( AliasModels:: AliasFunction f |
220
- f = operand .getUse ( ) .( CallInstruction ) .getStaticCallTarget ( ) and
221
- f .parameterIsAlwaysReturned ( operand .( PositionalArgumentOperand ) .getIndex ( ) )
222
- )
223
- }
224
-
225
284
private predicate isOnlyEscapesViaReturnArgument ( Operand operand ) {
226
285
exists ( AliasModels:: AliasFunction f |
227
286
f = operand .getUse ( ) .( CallInstruction ) .getStaticCallTarget ( ) and
@@ -271,7 +330,9 @@ predicate allocationEscapes(Configuration::Allocation allocation) {
271
330
/**
272
331
* Equivalent to `operandIsPropagated()`, but includes interprocedural propagation.
273
332
*/
274
- private predicate operandIsPropagatedIncludingByCall ( Operand operand , IntValue bitOffset , Instruction instr ) {
333
+ private predicate operandIsPropagatedIncludingByCall (
334
+ Operand operand , IntValue bitOffset , Instruction instr
335
+ ) {
275
336
operandIsPropagated ( operand , bitOffset , instr )
276
337
or
277
338
exists ( CallInstruction call , Instruction init |
0 commit comments