@@ -5,6 +5,8 @@ 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
10
9
11
cached
10
12
private module Cached {
@@ -890,11 +892,81 @@ private class MyConsistencyConfiguration extends Consistency::ConsistencyConfigu
890
892
}
891
893
}
892
894
895
+ /**
896
+ * Gets the basic block of `node`.
897
+ */
898
+ IRBlock getBasicBlock ( Node node ) {
899
+ node .asInstruction ( ) .getBlock ( ) = result
900
+ or
901
+ node .asOperand ( ) .getUse ( ) .getBlock ( ) = result
902
+ or
903
+ node .( SsaPhiNode ) .getPhiNode ( ) .getBasicBlock ( ) = result
904
+ or
905
+ node .( RawIndirectOperand ) .getOperand ( ) .getUse ( ) .getBlock ( ) = result
906
+ or
907
+ node .( RawIndirectInstruction ) .getInstruction ( ) .getBlock ( ) = result
908
+ or
909
+ result = getBasicBlock ( node .( PostUpdateNode ) .getPreUpdateNode ( ) )
910
+ }
911
+
893
912
/**
894
913
* Gets an additional term that is added to the `join` and `branch` computations to reflect
895
914
* an additional forward or backwards branching factor that is not taken into account
896
915
* when calculating the (virtual) dispatch cost.
897
916
*
898
917
* Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter.
899
918
*/
900
- int getAdditionalFlowIntoCallNodeTerm ( ArgumentNode arg , ParameterNode p ) { none ( ) }
919
+ pragma [ nomagic]
920
+ int getAdditionalFlowIntoCallNodeTerm ( ArgumentNode arg , ParameterNode p ) {
921
+ exists ( ParameterNode switchee , SwitchInstruction switch , ConditionOperand op , DataFlowCall call |
922
+ viableParamArg ( call , p , arg ) and
923
+ viableParamArg ( call , switchee , _) and
924
+ switch .getExpressionOperand ( ) = op and
925
+ valueNumber ( switchee .asInstruction ( ) ) .getAUse ( ) = op and
926
+ result = countNumberOfBranchesUsingParameter ( switch , p )
927
+ )
928
+ }
929
+
930
+ /** Gets the `IRVariable` associated with the parameter node `p`. */
931
+ pragma [ nomagic]
932
+ private IRVariable getIRVariableForParameterNode ( ParameterNode p ) {
933
+ result = p .( DirectParameterNode ) .getIRVariable ( )
934
+ or
935
+ result .getAst ( ) = p .( IndirectParameterNode ) .getParameter ( )
936
+ }
937
+
938
+ /** Holds if `v` is the source variable corresponding to the parameter represented by `p`. */
939
+ pragma [ nomagic]
940
+ private predicate parameterNodeHasSourceVariable ( ParameterNode p , Ssa:: SourceIRVariable v ) {
941
+ v .getIRVariable ( ) = getIRVariableForParameterNode ( p ) and
942
+ exists ( Position pos | p .isParameterOf ( _, pos ) |
943
+ pos instanceof DirectPosition and
944
+ v .getIndirection ( ) = 1
945
+ or
946
+ pos .( IndirectionPosition ) .getIndirectionIndex ( ) + 1 = v .getIndirection ( )
947
+ )
948
+ }
949
+
950
+ private EdgeKind caseOrDefaultEdge ( ) {
951
+ result instanceof CaseEdge or
952
+ result instanceof DefaultEdge
953
+ }
954
+
955
+ /**
956
+ * Gets the number of switch branches that that read from (or write to) the parameter `p`.
957
+ */
958
+ int countNumberOfBranchesUsingParameter ( SwitchInstruction switch , ParameterNode p ) {
959
+ exists ( Ssa:: SourceVariable sv |
960
+ parameterNodeHasSourceVariable ( p , sv ) and
961
+ // Count the number of cases that use the parameter. We do this by finding the phi node
962
+ // that merges the uses/defs of the parameter. There might be multiple such phi nodes, so
963
+ // we pick the one with the highest edge count.
964
+ result =
965
+ max ( SsaPhiNode phi |
966
+ switch .getSuccessor ( caseOrDefaultEdge ( ) ) .getBlock ( ) .dominanceFrontier ( ) = getBasicBlock ( phi ) and
967
+ phi .getSourceVariable ( ) = sv
968
+ |
969
+ strictcount ( phi .getAnInput ( ) )
970
+ )
971
+ )
972
+ }
0 commit comments