@@ -5,33 +5,58 @@ private import DataFlowDispatch
5
5
private import DataFlowImplConsistency
6
6
private import semmle.code.cpp.ir.internal.IRCppLanguage
7
7
private import SsaInternals as Ssa
8
- private import DataFlowImplCommon
9
- private import semmle.code.cpp.ir.ValueNumbering
8
+ private import DataFlowImplCommon as DataFlowImplCommon
10
9
11
10
cached
12
11
private module Cached {
13
12
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
13
+ module Nodes0 {
14
+ cached
15
+ newtype TIRDataFlowNode0 =
16
+ TInstructionNode0 ( Instruction i ) {
17
+ not Ssa:: ignoreInstruction ( i ) and
18
+ not exists ( Operand op |
19
+ not Ssa:: ignoreOperand ( op ) and i = Ssa:: getIRRepresentationOfOperand ( op )
20
+ ) and
21
+ // We exclude `void`-typed instructions because they cannot contain data.
22
+ // However, if the instruction is a glvalue, and their type is `void`, then the result
23
+ // type of the instruction is really `void*`, and thus we still want to have a dataflow
24
+ // node for it.
25
+ ( not i .getResultType ( ) instanceof VoidType or i .isGLValue ( ) )
26
+ } or
27
+ TMultipleUseOperandNode0 ( Operand op ) {
28
+ not Ssa:: ignoreOperand ( op ) and not exists ( Ssa:: getIRRepresentationOfOperand ( op ) )
29
+ } or
30
+ TSingleUseOperandNode0 ( Operand op ) {
31
+ not Ssa:: ignoreOperand ( op ) and exists ( Ssa:: getIRRepresentationOfOperand ( op ) )
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Gets an additional term that is added to the `join` and `branch` computations to reflect
37
+ * an additional forward or backwards branching factor that is not taken into account
38
+ * when calculating the (virtual) dispatch cost.
39
+ *
40
+ * Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter.
41
+ */
42
+ pragma [ nomagic]
43
+ cached
44
+ int getAdditionalFlowIntoCallNodeTerm ( ArgumentNode arg , ParameterNode p ) {
45
+ DataFlowImplCommon:: forceCachingInSameStage ( ) and
46
+ exists (
47
+ ParameterNode switchee , SwitchInstruction switch , ConditionOperand op , DataFlowCall call
48
+ |
49
+ DataFlowImplCommon:: viableParamArg ( call , p , arg ) and
50
+ DataFlowImplCommon:: viableParamArg ( call , switchee , _) and
51
+ switch .getExpressionOperand ( ) = op and
52
+ getAdditionalFlowIntoCallNodeTermStep + ( switchee , operandNode ( op ) ) and
53
+ result = countNumberOfBranchesUsingParameter ( switch , p )
54
+ )
55
+ }
56
+ }
57
+
58
+ import Cached
59
+ private import Nodes0
35
60
36
61
class Node0Impl extends TIRDataFlowNode0 {
37
62
/**
@@ -898,23 +923,54 @@ IRBlock getBasicBlock(Node node) {
898
923
}
899
924
900
925
/**
901
- * Gets an additional term that is added to the `join` and `branch` computations to reflect
902
- * an additional forward or backwards branching factor that is not taken into account
903
- * when calculating the (virtual) dispatch cost.
904
- *
905
- * Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter.
926
+ * A local flow relation that includes both local steps, read steps and
927
+ * argument-to-return flow through summarized functions.
906
928
*/
907
- pragma [ nomagic]
908
- int getAdditionalFlowIntoCallNodeTerm ( ArgumentNode arg , ParameterNode p ) {
909
- exists ( ParameterNode switchee , SwitchInstruction switch , ConditionOperand op , DataFlowCall call |
910
- viableParamArg ( call , p , arg ) and
911
- viableParamArg ( call , switchee , _) and
912
- switch .getExpressionOperand ( ) = op and
913
- valueNumber ( switchee .asInstruction ( ) ) .getAUse ( ) = op and
914
- result = countNumberOfBranchesUsingParameter ( switch , p )
929
+ private predicate localFlowStepWithSummaries ( Node node1 , Node node2 ) {
930
+ localFlowStep ( node1 , node2 )
931
+ or
932
+ readStep ( node1 , _, node2 )
933
+ or
934
+ DataFlowImplCommon:: argumentValueFlowsThrough ( node1 , _, node2 )
935
+ }
936
+
937
+ /** Holds if `node` flows to a node that is used in a `SwitchInstruction`. */
938
+ private predicate localStepsToSwitch ( Node node ) {
939
+ node .asOperand ( ) = any ( SwitchInstruction switch ) .getExpressionOperand ( )
940
+ or
941
+ exists ( Node succ |
942
+ localStepsToSwitch ( succ ) and
943
+ localFlowStepWithSummaries ( node , succ )
915
944
)
916
945
}
917
946
947
+ /**
948
+ * Holds if `node` is part of a path from a `ParameterNode` to an operand
949
+ * of a `SwitchInstruction`.
950
+ */
951
+ private predicate localStepsFromParameterToSwitch ( Node node ) {
952
+ localStepsToSwitch ( node ) and
953
+ (
954
+ node instanceof ParameterNode
955
+ or
956
+ exists ( Node prev |
957
+ localStepsFromParameterToSwitch ( prev ) and
958
+ localFlowStepWithSummaries ( prev , node )
959
+ )
960
+ )
961
+ }
962
+
963
+ /**
964
+ * The local flow relation `localFlowStepWithSummaries` pruned to only
965
+ * include steps that are part of a path from a `ParameterNode` to an
966
+ * operand of a `SwitchInstruction`.
967
+ */
968
+ private predicate getAdditionalFlowIntoCallNodeTermStep ( Node node1 , Node node2 ) {
969
+ localStepsFromParameterToSwitch ( node1 ) and
970
+ localStepsFromParameterToSwitch ( node2 ) and
971
+ localFlowStepWithSummaries ( node1 , node2 )
972
+ }
973
+
918
974
/** Gets the `IRVariable` associated with the parameter node `p`. */
919
975
pragma [ nomagic]
920
976
private IRVariable getIRVariableForParameterNode ( ParameterNode p ) {
@@ -943,7 +999,7 @@ private EdgeKind caseOrDefaultEdge() {
943
999
/**
944
1000
* Gets the number of switch branches that that read from (or write to) the parameter `p`.
945
1001
*/
946
- int countNumberOfBranchesUsingParameter ( SwitchInstruction switch , ParameterNode p ) {
1002
+ private int countNumberOfBranchesUsingParameter ( SwitchInstruction switch , ParameterNode p ) {
947
1003
exists ( Ssa:: SourceVariable sv |
948
1004
parameterNodeHasSourceVariable ( p , sv ) and
949
1005
// Count the number of cases that use the parameter. We do this by finding the phi node
0 commit comments