@@ -5,33 +5,59 @@ private import DataFlowDispatch
55private import DataFlowImplConsistency
66private import semmle.code.cpp.ir.internal.IRCppLanguage
77private import SsaInternals as Ssa
8- private import DataFlowImplCommon
8+ private import DataFlowImplCommon as DataFlowImplCommon
99private import semmle.code.cpp.ir.ValueNumbering
1010
1111cached
1212private module Cached {
1313 cached
14- newtype TIRDataFlowNode0 =
15- TInstructionNode0 ( Instruction i ) {
16- not Ssa:: ignoreInstruction ( i ) and
17- not exists ( Operand op |
18- not Ssa:: ignoreOperand ( op ) and i = Ssa:: getIRRepresentationOfOperand ( op )
19- ) and
20- // We exclude `void`-typed instructions because they cannot contain data.
21- // However, if the instruction is a glvalue, and their type is `void`, then the result
22- // type of the instruction is really `void*`, and thus we still want to have a dataflow
23- // node for it.
24- ( not i .getResultType ( ) instanceof VoidType or i .isGLValue ( ) )
25- } or
26- TMultipleUseOperandNode0 ( Operand op ) {
27- not Ssa:: ignoreOperand ( op ) and not exists ( Ssa:: getIRRepresentationOfOperand ( op ) )
28- } or
29- TSingleUseOperandNode0 ( Operand op ) {
30- not Ssa:: ignoreOperand ( op ) and exists ( Ssa:: getIRRepresentationOfOperand ( op ) )
31- }
32- }
33-
34- private import Cached
14+ module Nodes0 {
15+ cached
16+ newtype TIRDataFlowNode0 =
17+ TInstructionNode0 ( Instruction i ) {
18+ not Ssa:: ignoreInstruction ( i ) and
19+ not exists ( Operand op |
20+ not Ssa:: ignoreOperand ( op ) and i = Ssa:: getIRRepresentationOfOperand ( op )
21+ ) and
22+ // We exclude `void`-typed instructions because they cannot contain data.
23+ // However, if the instruction is a glvalue, and their type is `void`, then the result
24+ // type of the instruction is really `void*`, and thus we still want to have a dataflow
25+ // node for it.
26+ ( not i .getResultType ( ) instanceof VoidType or i .isGLValue ( ) )
27+ } or
28+ TMultipleUseOperandNode0 ( Operand op ) {
29+ not Ssa:: ignoreOperand ( op ) and not exists ( Ssa:: getIRRepresentationOfOperand ( op ) )
30+ } or
31+ TSingleUseOperandNode0 ( Operand op ) {
32+ not Ssa:: ignoreOperand ( op ) and exists ( Ssa:: getIRRepresentationOfOperand ( op ) )
33+ }
34+ }
35+
36+ /**
37+ * Gets an additional term that is added to the `join` and `branch` computations to reflect
38+ * an additional forward or backwards branching factor that is not taken into account
39+ * when calculating the (virtual) dispatch cost.
40+ *
41+ * Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter.
42+ */
43+ pragma [ nomagic]
44+ cached
45+ int getAdditionalFlowIntoCallNodeTerm ( ArgumentNode arg , ParameterNode p ) {
46+ DataFlowImplCommon:: forceCachingInSameStage ( ) and
47+ exists (
48+ ParameterNode switchee , SwitchInstruction switch , ConditionOperand op , DataFlowCall call
49+ |
50+ DataFlowImplCommon:: viableParamArg ( call , p , arg ) and
51+ DataFlowImplCommon:: viableParamArg ( call , switchee , _) and
52+ switch .getExpressionOperand ( ) = op and
53+ getAdditionalFlowIntoCallNodeTermStep + ( switchee , operandNode ( op ) ) and
54+ result = countNumberOfBranchesUsingParameter ( switch , p )
55+ )
56+ }
57+ }
58+
59+ import Cached
60+ private import Nodes0
3561
3662class Node0Impl extends TIRDataFlowNode0 {
3763 /**
@@ -906,7 +932,7 @@ private predicate localFlowStepWithSummaries(Node node1, Node node2) {
906932 or
907933 readStep ( node1 , _, node2 )
908934 or
909- argumentValueFlowsThrough ( node1 , _, node2 )
935+ DataFlowImplCommon :: argumentValueFlowsThrough ( node1 , _, node2 )
910936}
911937
912938/** Holds if `node` flows to a node that is used in a `SwitchInstruction`. */
@@ -946,24 +972,6 @@ private predicate getAdditionalFlowIntoCallNodeTermStep(Node node1, Node node2)
946972 localFlowStepWithSummaries ( node1 , node2 )
947973}
948974
949- /**
950- * Gets an additional term that is added to the `join` and `branch` computations to reflect
951- * an additional forward or backwards branching factor that is not taken into account
952- * when calculating the (virtual) dispatch cost.
953- *
954- * Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter.
955- */
956- pragma [ nomagic]
957- int getAdditionalFlowIntoCallNodeTerm ( ArgumentNode arg , ParameterNode p ) {
958- exists ( ParameterNode switchee , SwitchInstruction switch , ConditionOperand op , DataFlowCall call |
959- viableParamArg ( call , p , arg ) and
960- viableParamArg ( call , switchee , _) and
961- switch .getExpressionOperand ( ) = op and
962- getAdditionalFlowIntoCallNodeTermStep + ( switchee , operandNode ( op ) ) and
963- result = countNumberOfBranchesUsingParameter ( switch , p )
964- )
965- }
966-
967975/** Gets the `IRVariable` associated with the parameter node `p`. */
968976pragma [ nomagic]
969977private IRVariable getIRVariableForParameterNode ( ParameterNode p ) {
@@ -992,7 +1000,7 @@ private EdgeKind caseOrDefaultEdge() {
9921000/**
9931001 * Gets the number of switch branches that that read from (or write to) the parameter `p`.
9941002 */
995- int countNumberOfBranchesUsingParameter ( SwitchInstruction switch , ParameterNode p ) {
1003+ private int countNumberOfBranchesUsingParameter ( SwitchInstruction switch , ParameterNode p ) {
9961004 exists ( Ssa:: SourceVariable sv |
9971005 parameterNodeHasSourceVariable ( p , sv ) and
9981006 // Count the number of cases that use the parameter. We do this by finding the phi node
0 commit comments