@@ -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
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
@@ -34,7 +99,7 @@ private predicate operandIsConsumedWithoutEscaping(Operand operand) {
34
99
35
100
private predicate operandEscapesDomain ( Operand operand ) {
36
101
not operandIsConsumedWithoutEscaping ( operand ) and
37
- not operandIsPropagated ( operand , _) and
102
+ not operandIsPropagated ( operand , _, _ ) and
38
103
not isArgumentForParameter ( _, operand , _) and
39
104
not isOnlyEscapesViaReturnArgument ( operand ) and
40
105
not operand .getUse ( ) instanceof ReturnValueInstruction and
@@ -69,67 +134,67 @@ IntValue getPointerBitOffset(PointerOffsetInstruction instr) {
69
134
}
70
135
71
136
/**
72
- * Holds if any address held in operand `tag` of instruction `instr` is
73
- * propagated to the result of `instr`, offset by the number of bits in
74
- * `bitOffset`. If the address is propagated, but the offset is not known to be
75
- * a constant, then `bitOffset` is unknown.
137
+ * Holds if any address held in operand `operand` is propagated to the result of `instr`, offset by
138
+ * the number of bits in `bitOffset`. If the address is propagated, but the offset is not known to
139
+ * be a constant, then `bitOffset` is `unknown()`.
76
140
*/
77
- private predicate operandIsPropagated ( Operand operand , IntValue bitOffset ) {
78
- exists ( Instruction instr |
79
- instr = operand .getUse ( ) and
80
- (
81
- // Converting to a non-virtual base class adds the offset of the base class.
82
- exists ( ConvertToNonVirtualBaseInstruction convert |
83
- convert = instr and
84
- bitOffset = Ints:: mul ( convert .getDerivation ( ) .getByteOffset ( ) , 8 )
85
- )
86
- or
87
- // Conversion using dynamic_cast results in an unknown offset
88
- instr instanceof CheckedConvertOrNullInstruction and
89
- bitOffset = Ints:: unknown ( )
90
- or
91
- // Converting to a derived class subtracts the offset of the base class.
92
- exists ( ConvertToDerivedInstruction convert |
93
- convert = instr and
94
- bitOffset = Ints:: neg ( Ints:: mul ( convert .getDerivation ( ) .getByteOffset ( ) , 8 ) )
95
- )
96
- or
97
- // Converting to a virtual base class adds an unknown offset.
98
- instr instanceof ConvertToVirtualBaseInstruction and
99
- bitOffset = Ints:: unknown ( )
100
- or
101
- // Conversion to another pointer type propagates the source address.
102
- exists ( ConvertInstruction convert , IRType resultType |
103
- convert = instr and
104
- resultType = convert .getResultIRType ( ) and
105
- resultType instanceof IRAddressType and
106
- bitOffset = 0
107
- )
108
- or
109
- // Adding an integer to or subtracting an integer from a pointer propagates
110
- // the address with an offset.
111
- exists ( PointerOffsetInstruction ptrOffset |
112
- ptrOffset = instr and
113
- operand = ptrOffset .getLeftOperand ( ) and
114
- bitOffset = getPointerBitOffset ( ptrOffset )
115
- )
116
- or
117
- // Computing a field address from a pointer propagates the address plus the
118
- // offset of the field.
119
- bitOffset = Language:: getFieldBitOffset ( instr .( FieldAddressInstruction ) .getField ( ) )
120
- or
121
- // A copy propagates the source value.
122
- operand = instr .( CopyInstruction ) .getSourceValueOperand ( ) and bitOffset = 0
123
- or
124
- // Some functions are known to propagate an argument
125
- isAlwaysReturnedArgument ( operand ) and bitOffset = 0
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
146
+ instr = operand .getUse ( ) and
147
+ (
148
+ // Converting to a non-virtual base class adds the offset of the base class.
149
+ exists ( ConvertToNonVirtualBaseInstruction convert |
150
+ convert = instr and
151
+ bitOffset = Ints:: mul ( convert .getDerivation ( ) .getByteOffset ( ) , 8 )
152
+ )
153
+ or
154
+ // Conversion using dynamic_cast results in an unknown offset
155
+ instr instanceof CheckedConvertOrNullInstruction and
156
+ bitOffset = Ints:: unknown ( )
157
+ or
158
+ // Converting to a derived class subtracts the offset of the base class.
159
+ exists ( ConvertToDerivedInstruction convert |
160
+ convert = instr and
161
+ bitOffset = Ints:: neg ( Ints:: mul ( convert .getDerivation ( ) .getByteOffset ( ) , 8 ) )
162
+ )
163
+ or
164
+ // Converting to a virtual base class adds an unknown offset.
165
+ instr instanceof ConvertToVirtualBaseInstruction and
166
+ bitOffset = Ints:: unknown ( )
167
+ or
168
+ // Conversion to another pointer type propagates the source address.
169
+ exists ( ConvertInstruction convert , IRType resultType |
170
+ convert = instr and
171
+ resultType = convert .getResultIRType ( ) and
172
+ resultType instanceof IRAddressType and
173
+ bitOffset = 0
126
174
)
175
+ or
176
+ // Adding an integer to or subtracting an integer from a pointer propagates
177
+ // the address with an offset.
178
+ exists ( PointerOffsetInstruction ptrOffset |
179
+ ptrOffset = instr and
180
+ operand = ptrOffset .getLeftOperand ( ) and
181
+ bitOffset = getPointerBitOffset ( ptrOffset )
182
+ )
183
+ or
184
+ // Computing a field address from a pointer propagates the address plus the
185
+ // offset of the field.
186
+ bitOffset = Language:: getFieldBitOffset ( instr .( FieldAddressInstruction ) .getField ( ) )
187
+ or
188
+ // A copy propagates the source value.
189
+ operand = instr .( CopyInstruction ) .getSourceValueOperand ( ) and bitOffset = 0
127
190
)
128
191
}
129
192
130
193
private predicate operandEscapesNonReturn ( Operand operand ) {
131
- // The address is propagated to the result of the instruction, and that result itself is returned
132
- operandIsPropagated ( operand , _) and resultEscapesNonReturn ( operand .getUse ( ) )
194
+ exists ( Instruction instr |
195
+ // The address is propagated to the result of the instruction, and that result itself is returned
196
+ operandIsPropagated ( operand , _, instr ) and resultEscapesNonReturn ( instr )
197
+ )
133
198
or
134
199
// The operand is used in a function call which returns it, and the return value is then returned
135
200
exists ( CallInstruction ci , Instruction init |
@@ -151,9 +216,11 @@ private predicate operandEscapesNonReturn(Operand operand) {
151
216
}
152
217
153
218
private predicate operandMayReachReturn ( Operand operand ) {
154
- // The address is propagated to the result of the instruction, and that result itself is returned
155
- operandIsPropagated ( operand , _) and
156
- resultMayReachReturn ( operand .getUse ( ) )
219
+ exists ( Instruction instr |
220
+ // The address is propagated to the result of the instruction, and that result itself is returned
221
+ operandIsPropagated ( operand , _, instr ) and
222
+ resultMayReachReturn ( instr )
223
+ )
157
224
or
158
225
// The operand is used in a function call which returns it, and the return value is then returned
159
226
exists ( CallInstruction ci , Instruction init |
@@ -173,9 +240,9 @@ private predicate operandMayReachReturn(Operand operand) {
173
240
174
241
private predicate operandReturned ( Operand operand , IntValue bitOffset ) {
175
242
// The address is propagated to the result of the instruction, and that result itself is returned
176
- exists ( IntValue bitOffset1 , IntValue bitOffset2 |
177
- operandIsPropagated ( operand , bitOffset1 ) and
178
- resultReturned ( operand . getUse ( ) , bitOffset2 ) and
243
+ exists ( Instruction instr , IntValue bitOffset1 , IntValue bitOffset2 |
244
+ operandIsPropagated ( operand , bitOffset1 , instr ) and
245
+ resultReturned ( instr , bitOffset2 ) and
179
246
bitOffset = Ints:: add ( bitOffset1 , bitOffset2 )
180
247
)
181
248
or
@@ -214,13 +281,6 @@ private predicate isArgumentForParameter(
214
281
)
215
282
}
216
283
217
- private predicate isAlwaysReturnedArgument ( Operand operand ) {
218
- exists ( AliasModels:: AliasFunction f |
219
- f = operand .getUse ( ) .( CallInstruction ) .getStaticCallTarget ( ) and
220
- f .parameterIsAlwaysReturned ( operand .( PositionalArgumentOperand ) .getIndex ( ) )
221
- )
222
- }
223
-
224
284
private predicate isOnlyEscapesViaReturnArgument ( Operand operand ) {
225
285
exists ( AliasModels:: AliasFunction f |
226
286
f = operand .getUse ( ) .( CallInstruction ) .getStaticCallTarget ( ) and
@@ -270,12 +330,15 @@ predicate allocationEscapes(Configuration::Allocation allocation) {
270
330
/**
271
331
* Equivalent to `operandIsPropagated()`, but includes interprocedural propagation.
272
332
*/
273
- private predicate operandIsPropagatedIncludingByCall ( Operand operand , IntValue bitOffset ) {
274
- operandIsPropagated ( operand , bitOffset )
333
+ private predicate operandIsPropagatedIncludingByCall (
334
+ Operand operand , IntValue bitOffset , Instruction instr
335
+ ) {
336
+ operandIsPropagated ( operand , bitOffset , instr )
275
337
or
276
338
exists ( CallInstruction call , Instruction init |
277
339
isArgumentForParameter ( call , operand , init ) and
278
- resultReturned ( init , bitOffset )
340
+ resultReturned ( init , bitOffset ) and
341
+ instr = call
279
342
)
280
343
}
281
344
@@ -292,8 +355,7 @@ private predicate hasBaseAndOffset(AddressOperand addrOperand, Instruction base,
292
355
// We already have an offset from `middle`.
293
356
hasBaseAndOffset ( addrOperand , middle , previousBitOffset ) and
294
357
// `middle` is propagated from `base`.
295
- middleOperand = middle .getAnOperand ( ) and
296
- operandIsPropagatedIncludingByCall ( middleOperand , additionalBitOffset ) and
358
+ operandIsPropagatedIncludingByCall ( middleOperand , additionalBitOffset , middle ) and
297
359
base = middleOperand .getDef ( ) and
298
360
bitOffset = Ints:: add ( previousBitOffset , additionalBitOffset )
299
361
)
0 commit comments