@@ -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 , ConditionOperand op , DataFlowCall call |
922
+ viableParamArg ( call , p , arg ) and
923
+ viableParamArg ( call , switchee , _) and
924
+ valueNumber ( switchee .asInstruction ( ) ) .getAUse ( ) = op and
925
+ result = countNumberOfBranchesUsingParameter ( op , p )
926
+ )
927
+ }
928
+
929
+ /** Gets the `IRVariable` associated with the parameter node `p`. */
930
+ pragma [ nomagic]
931
+ private IRVariable getIRVariableForParameterNode ( ParameterNode p ) {
932
+ result = p .( DirectParameterNode ) .getIRVariable ( )
933
+ or
934
+ result .getAst ( ) = p .( IndirectParameterNode ) .getParameter ( )
935
+ }
936
+
937
+ /** Holds if `v` is the source variable corresponding to the parameter represented by `p`. */
938
+ pragma [ nomagic]
939
+ private predicate parameterNodeHasSourceVariable ( ParameterNode p , Ssa:: SourceIRVariable v ) {
940
+ v .getIRVariable ( ) = getIRVariableForParameterNode ( p ) and
941
+ exists ( Position pos | p .isParameterOf ( _, pos ) |
942
+ pos instanceof DirectPosition and
943
+ v .getIndirection ( ) = 1
944
+ or
945
+ pos .( IndirectionPosition ) .getIndirectionIndex ( ) + 1 = v .getIndirection ( )
946
+ )
947
+ }
948
+
949
+ private EdgeKind caseOrDefaultEdge ( ) {
950
+ result instanceof CaseEdge or
951
+ result instanceof DefaultEdge
952
+ }
953
+
954
+ /**
955
+ * Gets the number of switch branches that that read from (or write to) the parameter `p`.
956
+ */
957
+ int countNumberOfBranchesUsingParameter ( ConditionOperand op , ParameterNode p ) {
958
+ exists ( SwitchInstruction switch , Ssa:: SourceVariable sv |
959
+ switch .getExpressionOperand ( ) = op and
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