11
11
* controls the basic block `A`, in this case because the true branch dominates
12
12
* `A`, but more elaborate controls-relationships may also hold.
13
13
* For example, in
14
- * ```
14
+ * ```java
15
15
* int sz = a != null ? a.length : 0;
16
16
* if (sz != 0) {
17
17
* // this block is controlled by:
@@ -104,6 +104,19 @@ signature module InputSig<LocationSig Location> {
104
104
predicate strictlyDominates ( BasicBlock bb ) ;
105
105
}
106
106
107
+ /**
108
+ * Holds if `bb1` has `bb2` as a direct successor and the edge between `bb1`
109
+ * and `bb2` is a dominating edge.
110
+ *
111
+ * An edge `(bb1, bb2)` is dominating if there exists a basic block that can
112
+ * only be reached from the entry block by going through `(bb1, bb2)`. This
113
+ * implies that `(bb1, bb2)` dominates its endpoint `bb2`. I.e., `bb2` can
114
+ * only be reached from the entry block by going via `(bb1, bb2)`.
115
+ *
116
+ * This is a necessary and sufficient condition for an edge to dominate some
117
+ * block, and therefore `dominatingEdge(bb1, bb2) and bb2.dominates(bb3)`
118
+ * means that the edge `(bb1, bb2)` dominates `bb3`.
119
+ */
107
120
predicate dominatingEdge ( BasicBlock bb1 , BasicBlock bb2 ) ;
108
121
109
122
class AstNode {
@@ -528,6 +541,17 @@ module Make<LocationSig Location, InputSig<Location> Input> {
528
541
module Logic< LogicInputSig LogicInput> {
529
542
private import LogicInput
530
543
544
+ /**
545
+ * Holds if `guard` evaluating to `v` directly controls `phi` taking the value
546
+ * `inp`. This means that `guard` evaluating to `v` must control all the input
547
+ * edges to `phi` that read `inp`.
548
+ *
549
+ * We also require that `guard` dominates `phi` in order to allow logical inferences
550
+ * from the value of `phi` to the value of `guard`.
551
+ *
552
+ * Trivial cases where `guard` controls `phi` itself are excluded, since that makes
553
+ * logical inferences from `phi` to `guard` trivial and irrelevant.
554
+ */
531
555
private predicate guardControlsPhiBranch (
532
556
Guard guard , GuardValue v , SsaPhiNode phi , SsaDefinition inp
533
557
) {
@@ -571,6 +595,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
571
595
private predicate guardReadsSsaVar ( Guard guard , SsaDefinition def ) {
572
596
def .getARead ( ) = guard
573
597
or
598
+ // A read of `y` can be considered as a read of `x` if guarded by `x == y`.
574
599
exists ( Guard eqtest , SsaDefinition other , boolean branch |
575
600
guardChecksEqualVars ( eqtest , def , other , branch ) and
576
601
other .getARead ( ) = guard and
@@ -602,21 +627,21 @@ module Make<LocationSig Location, InputSig<Location> Input> {
602
627
* boolean `fromBackEdge` indicates whether the flow from `result` to `v` goes
603
628
* through a back edge.
604
629
*/
605
- private SsaDefinition getADefinition ( SsaDefinition v , boolean fromBackEdge ) {
630
+ private SsaDefinition getAnUltimateDefinition ( SsaDefinition v , boolean fromBackEdge ) {
606
631
result = v and not v instanceof SsaPhiNode and fromBackEdge = false
607
632
or
608
633
exists ( SsaDefinition inp , BasicBlock bb , boolean fbe |
609
634
v .( SsaPhiNode ) .hasInputFromBlock ( inp , bb ) and
610
- result = getADefinition ( inp , fbe ) and
635
+ result = getAnUltimateDefinition ( inp , fbe ) and
611
636
( if v .getBasicBlock ( ) .dominates ( bb ) then fromBackEdge = true else fromBackEdge = fbe )
612
637
)
613
638
}
614
639
615
640
/**
616
- * Holds if `v` can have a value that is not representable as an `GuardValue`.
641
+ * Holds if `v` can have a value that is not representable as a `GuardValue`.
617
642
*/
618
643
private predicate hasPossibleUnknownValue ( SsaDefinition v ) {
619
- exists ( SsaDefinition def | def = getADefinition ( v , _) |
644
+ exists ( SsaDefinition def | def = getAnUltimateDefinition ( v , _) |
620
645
not exists ( def .( SsaWriteDefinition ) .getDefinition ( ) )
621
646
or
622
647
exists ( Expr e | e = possibleValue ( def .( SsaWriteDefinition ) .getDefinition ( ) ) |
@@ -633,7 +658,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
633
658
private predicate possibleValue ( SsaDefinition v , boolean fromBackEdge , Expr e , GuardValue k ) {
634
659
not hasPossibleUnknownValue ( v ) and
635
660
exists ( SsaWriteDefinition def |
636
- def = getADefinition ( v , fromBackEdge ) and
661
+ def = getAnUltimateDefinition ( v , fromBackEdge ) and
637
662
e = possibleValue ( def .getDefinition ( ) ) and
638
663
constantHasValue ( e , k )
639
664
)
@@ -676,7 +701,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
676
701
or
677
702
exists ( SsaDefinition def |
678
703
guardReadsSsaVar ( e , def ) and
679
- relevantInt ( getADefinition ( def , _) .( SsaWriteDefinition ) .getDefinition ( ) , k )
704
+ relevantInt ( getAnUltimateDefinition ( def , _) .( SsaWriteDefinition ) .getDefinition ( ) , k )
680
705
)
681
706
}
682
707
@@ -808,7 +833,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
808
833
* starting from a given set of base cases.
809
834
*/
810
835
cached
811
- module ImpliesTC< baseGuardValueSig / 2 baseGuardValue> {
836
+ private module ImpliesTC< baseGuardValueSig / 2 baseGuardValue> {
812
837
/**
813
838
* Holds if `tgtGuard` evaluating to `tgtVal` implies that `guard`
814
839
* evaluates to `v`.
0 commit comments