@@ -4,6 +4,71 @@ private import AliasAnalysisImports
44
55private class IntValue = Ints:: IntValue ;
66
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+
772/**
873 * Holds if the operand `tag` of instruction `instr` is used in a way that does
974 * not result in any address held in that operand from escaping beyond the
@@ -34,7 +99,7 @@ private predicate operandIsConsumedWithoutEscaping(Operand operand) {
3499
35100private predicate operandEscapesDomain ( Operand operand ) {
36101 not operandIsConsumedWithoutEscaping ( operand ) and
37- not operandIsPropagated ( operand , _) and
102+ not operandIsPropagated ( operand , _, _ ) and
38103 not isArgumentForParameter ( _, operand , _) and
39104 not isOnlyEscapesViaReturnArgument ( operand ) and
40105 not operand .getUse ( ) instanceof ReturnValueInstruction and
@@ -69,67 +134,67 @@ IntValue getPointerBitOffset(PointerOffsetInstruction instr) {
69134}
70135
71136/**
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()`.
76140 */
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
126174 )
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
127190 )
128191}
129192
130193private 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+ )
133198 or
134199 // The operand is used in a function call which returns it, and the return value is then returned
135200 exists ( CallInstruction ci , Instruction init |
@@ -151,9 +216,11 @@ private predicate operandEscapesNonReturn(Operand operand) {
151216}
152217
153218private 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+ )
157224 or
158225 // The operand is used in a function call which returns it, and the return value is then returned
159226 exists ( CallInstruction ci , Instruction init |
@@ -173,9 +240,9 @@ private predicate operandMayReachReturn(Operand operand) {
173240
174241private predicate operandReturned ( Operand operand , IntValue bitOffset ) {
175242 // 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
179246 bitOffset = Ints:: add ( bitOffset1 , bitOffset2 )
180247 )
181248 or
@@ -214,13 +281,6 @@ private predicate isArgumentForParameter(
214281 )
215282}
216283
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-
224284private predicate isOnlyEscapesViaReturnArgument ( Operand operand ) {
225285 exists ( AliasModels:: AliasFunction f |
226286 f = operand .getUse ( ) .( CallInstruction ) .getStaticCallTarget ( ) and
@@ -270,12 +330,15 @@ predicate allocationEscapes(Configuration::Allocation allocation) {
270330/**
271331 * Equivalent to `operandIsPropagated()`, but includes interprocedural propagation.
272332 */
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 )
275337 or
276338 exists ( CallInstruction call , Instruction init |
277339 isArgumentForParameter ( call , operand , init ) and
278- resultReturned ( init , bitOffset )
340+ resultReturned ( init , bitOffset ) and
341+ instr = call
279342 )
280343}
281344
@@ -292,8 +355,7 @@ private predicate hasBaseAndOffset(AddressOperand addrOperand, Instruction base,
292355 // We already have an offset from `middle`.
293356 hasBaseAndOffset ( addrOperand , middle , previousBitOffset ) and
294357 // `middle` is propagated from `base`.
295- middleOperand = middle .getAnOperand ( ) and
296- operandIsPropagatedIncludingByCall ( middleOperand , additionalBitOffset ) and
358+ operandIsPropagatedIncludingByCall ( middleOperand , additionalBitOffset , middle ) and
297359 base = middleOperand .getDef ( ) and
298360 bitOffset = Ints:: add ( previousBitOffset , additionalBitOffset )
299361 )
0 commit comments