@@ -299,12 +299,6 @@ module Make<LocationSig Location, InputSig<Location> Input> {
299
299
v = TValue ( TValueConstant ( c .asConstantValue ( ) ) , true )
300
300
}
301
301
302
- private predicate exprHasValue ( Expr e , GuardValue v ) {
303
- constantHasValue ( e , v )
304
- or
305
- e instanceof NonNullExpr and v = TValue ( TValueNull ( ) , false )
306
- }
307
-
308
302
private predicate exceptionBranchPoint ( BasicBlock bb1 , BasicBlock normalSucc , BasicBlock excSucc ) {
309
303
exists ( SuccessorType norm , ExceptionSuccessor exc |
310
304
bb1 .getASuccessor ( norm ) = normalSucc and
@@ -426,30 +420,6 @@ module Make<LocationSig Location, InputSig<Location> Input> {
426
420
branch = false and result = cond .getElse ( )
427
421
}
428
422
429
- bindingset [ g1, v1]
430
- pragma [ inline_late]
431
- private predicate unboundBaseImpliesStep ( PreGuard g1 , GuardValue v1 , PreGuard g2 , GuardValue v2 ) {
432
- g1 .( IdExpr ) .getEqualChildExpr ( ) = g2 and v1 = v2 and not v1 instanceof TException
433
- or
434
- exists ( ConditionalExpr cond , boolean branch , Expr e , GuardValue ev |
435
- cond = g1 and
436
- e = getBranchExpr ( cond , branch ) and
437
- exprHasValue ( e , ev ) and
438
- disjointValues ( v1 , ev )
439
- |
440
- // g1 === g2 ? e : ...;
441
- // g1 === g2 ? ... : e;
442
- g2 = cond .getCondition ( ) and
443
- v2 = TValue ( TValueTrue ( ) , branch .booleanNot ( ) )
444
- or
445
- // g1 === ... ? g2 : e
446
- // g1 === ... ? e : g2
447
- g2 = getBranchExpr ( cond , branch .booleanNot ( ) ) and
448
- v2 = v1 and
449
- not exprHasValue ( g2 , v2 ) // disregard trivial guard
450
- )
451
- }
452
-
453
423
private predicate baseImpliesStep ( PreGuard g1 , GuardValue v1 , PreGuard g2 , GuardValue v2 ) {
454
424
g1 .( AndExpr ) .getAnOperand ( ) = g2 and v1 = TValue ( TValueTrue ( ) , true ) and v2 = v1
455
425
or
@@ -532,15 +502,17 @@ module Make<LocationSig Location, InputSig<Location> Input> {
532
502
private import LogicInput
533
503
534
504
private predicate guardControlsPhiBranch (
535
- Guard guard , GuardValue v , SsaPhiNode phi , Expr input , BasicBlock bbInput , BasicBlock bbPhi
505
+ Guard guard , GuardValue v , SsaPhiNode phi , SsaDefinition inp
536
506
) {
537
- exists ( SsaWriteDefinition inp |
538
- phi .hasInputFromBlock ( inp , bbInput ) and
507
+ exists ( BasicBlock bbPhi |
508
+ phi .hasInputFromBlock ( inp , _ ) and
539
509
phi .getBasicBlock ( ) = bbPhi and
540
- inp .getDefinition ( ) = input and
541
- guard .directlyValueControls ( bbInput , v ) and
542
510
guard .getBasicBlock ( ) .strictlyDominates ( bbPhi ) and
543
- not guard .directlyValueControls ( bbPhi , _)
511
+ not guard .directlyValueControls ( bbPhi , _) and
512
+ forex ( BasicBlock bbInput | phi .hasInputFromBlock ( inp , bbInput ) |
513
+ guard .directlyValueControls ( bbInput , v ) or
514
+ guard .hasValueBranchEdge ( bbInput , bbPhi , v )
515
+ )
544
516
)
545
517
}
546
518
@@ -552,13 +524,12 @@ module Make<LocationSig Location, InputSig<Location> Input> {
552
524
* This makes `phi` similar to the conditional `phi = guard==v ? input : ...`.
553
525
*/
554
526
private predicate guardDeterminesPhiInput ( Guard guard , GuardValue v , SsaPhiNode phi , Expr input ) {
555
- exists ( GuardValue dv , BasicBlock bbInput , BasicBlock bbPhi |
556
- guardControlsPhiBranch ( guard , v , phi , input , bbInput , bbPhi ) and
527
+ exists ( GuardValue dv , SsaWriteDefinition inp |
528
+ guardControlsPhiBranch ( guard , v , phi , inp ) and
529
+ inp .getDefinition ( ) = input and
557
530
dv = v .getDualValue ( ) and
558
- forall ( BasicBlock other | phi .hasInputFromBlock ( _, other ) and other != bbInput |
559
- guard .directlyValueControls ( other , dv )
560
- or
561
- guard .hasValueBranchEdge ( other , bbPhi , dv )
531
+ forall ( SsaDefinition other | phi .hasInputFromBlock ( other , _) and other != inp |
532
+ guardControlsPhiBranch ( guard , dv , phi , other )
562
533
)
563
534
)
564
535
}
@@ -702,14 +673,67 @@ module Make<LocationSig Location, InputSig<Location> Input> {
702
673
or
703
674
exists ( boolean isNull |
704
675
additionalNullCheck ( g1 , v1 , g2 , isNull ) and
705
- v2 = TValue ( TValueNull ( ) , isNull )
676
+ v2 = TValue ( TValueNull ( ) , isNull ) and
677
+ not ( g2 instanceof NonNullExpr and isNull = false ) // disregard trivial guard
678
+ )
679
+ }
680
+
681
+ /**
682
+ * Holds if `g` evaluating to `v` implies that `def` evaluates to `ssaVal`.
683
+ * The included set of implications is somewhat restricted to avoid a
684
+ * recursive dependency on `exprHasValue`.
685
+ */
686
+ private predicate baseSsaValueCheck ( SsaDefinition def , GuardValue ssaVal , Guard g , GuardValue v ) {
687
+ exists ( Guard g0 , GuardValue v0 |
688
+ guardReadsSsaVar ( g0 , def ) and v0 = ssaVal
689
+ or
690
+ baseSsaValueCheck ( def , ssaVal , g0 , v0 )
691
+ |
692
+ impliesStep ( g , v , g0 , v0 )
693
+ )
694
+ }
695
+
696
+ private predicate exprHasValue ( Expr e , GuardValue v ) {
697
+ constantHasValue ( e , v )
698
+ or
699
+ e instanceof NonNullExpr and v = TValue ( TValueNull ( ) , false )
700
+ or
701
+ exprHasValue ( e .( IdExpr ) .getEqualChildExpr ( ) , v )
702
+ or
703
+ exists ( SsaDefinition def , Guard g , GuardValue gv |
704
+ e = def .getARead ( ) and
705
+ g .directlyValueControls ( e .getBasicBlock ( ) , gv ) and
706
+ baseSsaValueCheck ( def , v , g , gv )
707
+ )
708
+ or
709
+ exists ( SsaWriteDefinition def |
710
+ exprHasValue ( def .getDefinition ( ) , v ) and
711
+ e = def .getARead ( )
706
712
)
707
713
}
708
714
709
715
bindingset [ g1, v1]
710
716
pragma [ inline_late]
711
717
private predicate unboundImpliesStep ( Guard g1 , GuardValue v1 , Guard g2 , GuardValue v2 ) {
712
- unboundBaseImpliesStep ( g1 , v1 , g2 , v2 )
718
+ g1 .( IdExpr ) .getEqualChildExpr ( ) = g2 and v1 = v2 and not v1 instanceof TException
719
+ or
720
+ exists ( ConditionalExpr cond , boolean branch , Expr e , GuardValue ev |
721
+ cond = g1 and
722
+ e = getBranchExpr ( cond , branch ) and
723
+ exprHasValue ( e , ev ) and
724
+ disjointValues ( v1 , ev )
725
+ |
726
+ // g1 === g2 ? e : ...;
727
+ // g1 === g2 ? ... : e;
728
+ g2 = cond .getCondition ( ) and
729
+ v2 = TValue ( TValueTrue ( ) , branch .booleanNot ( ) )
730
+ or
731
+ // g1 === ... ? g2 : e
732
+ // g1 === ... ? e : g2
733
+ g2 = getBranchExpr ( cond , branch .booleanNot ( ) ) and
734
+ v2 = v1 and
735
+ not exprHasValue ( g2 , v2 ) // disregard trivial guard
736
+ )
713
737
}
714
738
715
739
bindingset [ def1, v1]
@@ -742,7 +766,11 @@ module Make<LocationSig Location, InputSig<Location> Input> {
742
766
* Calculates the transitive closure of all the guard implication steps
743
767
* starting from a given set of base cases.
744
768
*/
745
- private module ImpliesTC< baseGuardValueSig / 2 baseGuardValue> {
769
+ module ImpliesTC< baseGuardValueSig / 2 baseGuardValue> {
770
+ /**
771
+ * Holds if `tgtGuard` evaluating to `tgtVal` implies that `guard`
772
+ * evaluates to `v`.
773
+ */
746
774
pragma [ nomagic]
747
775
predicate guardControls ( Guard guard , GuardValue v , Guard tgtGuard , GuardValue tgtVal ) {
748
776
baseGuardValue ( tgtGuard , tgtVal ) and
@@ -770,6 +798,10 @@ module Make<LocationSig Location, InputSig<Location> Input> {
770
798
)
771
799
}
772
800
801
+ /**
802
+ * Holds if `tgtGuard` evaluating to `tgtVal` implies that `def`
803
+ * evaluates to `v`.
804
+ */
773
805
pragma [ nomagic]
774
806
predicate ssaControls ( SsaDefinition def , GuardValue v , Guard tgtGuard , GuardValue tgtVal ) {
775
807
exists ( Guard g0 |
0 commit comments