1
1
import python
2
2
import semmle.python.flow.NameNode
3
3
private import semmle.python.pointsto.PointsTo
4
- private import semmle.python.Pruning
5
4
6
5
/* Note about matching parent and child nodes and CFG splitting:
7
6
*
@@ -33,10 +32,6 @@ private AstNode toAst(ControlFlowNode n) {
33
32
*/
34
33
class ControlFlowNode extends @py_flow_node {
35
34
36
- cached ControlFlowNode ( ) {
37
- Pruner:: reachable ( this )
38
- }
39
-
40
35
/** Whether this control flow node is a load (including those in augmented assignments) */
41
36
predicate isLoad ( ) {
42
37
exists ( Expr e | e = toAst ( this ) | py_expr_contexts ( _, 3 , e ) and not augstore ( _, this ) )
@@ -180,8 +175,7 @@ class ControlFlowNode extends @py_flow_node {
180
175
181
176
/** Gets a successor of this flow node */
182
177
ControlFlowNode getASuccessor ( ) {
183
- py_successors ( this , result ) and
184
- not Pruner:: unreachableEdge ( this , result )
178
+ py_successors ( this , result )
185
179
}
186
180
187
181
/** Gets the immediate dominator of this flow node */
@@ -973,91 +967,21 @@ predicate defined_by(NameNode def, Variable v) {
973
967
exists ( NameNode p | defined_by ( p , v ) and p .getASuccessor ( ) = def and not p .defines ( v ) )
974
968
}
975
969
976
- /* Combine extractor-generated basic block after pruning */
977
-
978
- private class BasicBlockPart extends @py_flow_node {
979
-
980
- string toString ( ) { result = "Basic block part" }
981
-
982
- BasicBlockPart ( ) {
983
- py_flow_bb_node ( _, _, this , _) and
984
- Pruner:: reachable ( this )
985
- }
986
-
987
- predicate isHead ( ) {
988
- count ( this .( ControlFlowNode ) .getAPredecessor ( ) ) != 1
989
- or
990
- exists ( ControlFlowNode pred | pred = this .( ControlFlowNode ) .getAPredecessor ( ) | strictcount ( pred .getASuccessor ( ) ) > 1 )
991
- }
992
-
993
- private BasicBlockPart previous ( ) {
994
- not this .isHead ( ) and
995
- py_flow_bb_node ( this .( ControlFlowNode ) .getAPredecessor ( ) , _, result , _)
996
- }
997
-
998
- BasicBlockPart getHead ( ) {
999
- this .isHead ( ) and result = this
1000
- or
1001
- result = this .previous ( ) .getHead ( )
1002
- }
1003
-
1004
- predicate isLast ( ) {
1005
- not exists ( BasicBlockPart part | part .previous ( ) = this )
1006
- }
1007
-
1008
- int length ( ) {
1009
- result = max ( int j | py_flow_bb_node ( _, _, this , j ) ) + 1
1010
- }
1011
-
1012
- int startIndex ( ) {
1013
- this .isHead ( ) and result = 0
1014
- or
1015
- exists ( BasicBlockPart prev |
1016
- prev = this .previous ( ) and
1017
- result = prev .startIndex ( ) + prev .length ( )
1018
- )
1019
- }
1020
-
1021
- predicate contains ( ControlFlowNode node ) {
1022
- py_flow_bb_node ( node , _, this , _)
1023
- }
1024
-
1025
- int indexOf ( ControlFlowNode node ) {
1026
- py_flow_bb_node ( node , _, this , result )
1027
- }
1028
-
1029
- ControlFlowNode lastNode ( ) {
1030
- this .indexOf ( result ) = max ( this .indexOf ( _) )
1031
- }
1032
-
1033
- BasicBlockPart getImmediateDominator ( ) {
1034
- result .contains ( this .( ControlFlowNode ) .getImmediateDominator ( ) )
1035
- }
1036
-
1037
- }
1038
-
1039
970
/** A basic block (ignoring exceptional flow edges to scope exit) */
1040
971
class BasicBlock extends @py_flow_node {
1041
972
1042
973
BasicBlock ( ) {
1043
- this .( BasicBlockPart ) .isHead ( )
1044
- }
1045
-
1046
- private BasicBlockPart getAPart ( ) {
1047
- result .getHead ( ) = this
974
+ py_flow_bb_node ( _, _, this , _)
1048
975
}
1049
976
1050
977
/** Whether this basic block contains the specified node */
1051
978
predicate contains ( ControlFlowNode node ) {
1052
- this . getAPart ( ) . contains ( node )
979
+ py_flow_bb_node ( node , _ , this , _ )
1053
980
}
1054
981
1055
982
/** Gets the nth node in this basic block */
1056
983
ControlFlowNode getNode ( int n ) {
1057
- exists ( BasicBlockPart part |
1058
- part = this .getAPart ( ) and
1059
- n = part .startIndex ( ) + part .indexOf ( result )
1060
- )
984
+ py_flow_bb_node ( result , _, this , n )
1061
985
}
1062
986
1063
987
string toString ( ) {
@@ -1077,7 +1001,7 @@ class BasicBlock extends @py_flow_node {
1077
1001
}
1078
1002
1079
1003
cached BasicBlock getImmediateDominator ( ) {
1080
- this .getAPart ( ) .getImmediateDominator ( ) = result . getAPart ( )
1004
+ this .firstNode ( ) .getImmediateDominator ( ) . getBasicBlock ( ) = result
1081
1005
}
1082
1006
1083
1007
/** Dominance frontier of a node x is the set of all nodes `other` such that `this` dominates a predecessor
@@ -1093,10 +1017,9 @@ class BasicBlock extends @py_flow_node {
1093
1017
1094
1018
/** Gets the last node in this basic block */
1095
1019
ControlFlowNode getLastNode ( ) {
1096
- exists ( BasicBlockPart part |
1097
- part = this .getAPart ( ) and
1098
- part .isLast ( ) and
1099
- result = part .lastNode ( )
1020
+ exists ( int i |
1021
+ this .getNode ( i ) = result and
1022
+ i = max ( int j | py_flow_bb_node ( _, _, this , j ) )
1100
1023
)
1101
1024
}
1102
1025
0 commit comments