@@ -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 .( 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+
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
@@ -74,6 +139,10 @@ IntValue getPointerBitOffset(PointerOffsetInstruction instr) {
74139 * be a constant, then `bitOffset` is `unknown()`.
75140 */
76141private 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
77146 instr = operand .getUse ( ) and
78147 (
79148 // 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
118187 or
119188 // A copy propagates the source value.
120189 operand = instr .( CopyInstruction ) .getSourceValueOperand ( ) and bitOffset = 0
121- or
122- // Some functions are known to propagate an argument
123- isAlwaysReturnedArgument ( operand ) and bitOffset = 0
124190 )
125191}
126192
@@ -215,13 +281,6 @@ private predicate isArgumentForParameter(
215281 )
216282}
217283
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-
225284private predicate isOnlyEscapesViaReturnArgument ( Operand operand ) {
226285 exists ( AliasModels:: AliasFunction f |
227286 f = operand .getUse ( ) .( CallInstruction ) .getStaticCallTarget ( ) and
@@ -271,7 +330,9 @@ predicate allocationEscapes(Configuration::Allocation allocation) {
271330/**
272331 * Equivalent to `operandIsPropagated()`, but includes interprocedural propagation.
273332 */
274- private predicate operandIsPropagatedIncludingByCall ( Operand operand , IntValue bitOffset , Instruction instr ) {
333+ private predicate operandIsPropagatedIncludingByCall (
334+ Operand operand , IntValue bitOffset , Instruction instr
335+ ) {
275336 operandIsPropagated ( operand , bitOffset , instr )
276337 or
277338 exists ( CallInstruction call , Instruction init |
0 commit comments