@@ -234,6 +234,9 @@ module Make<LocationSig Location, InputSig<Location> Input> {
234
234
/** Holds if this value represents `null`. */
235
235
predicate isNullValue ( ) { this = TValue ( TValueNull ( ) , true ) }
236
236
237
+ /** Holds if this value represents `null` or non-`null` as indicated by `isNull`. */
238
+ predicate isNullness ( boolean isNull ) { this = TValue ( TValueNull ( ) , isNull ) }
239
+
237
240
/** Gets the integer that this value represents, if any. */
238
241
int asIntValue ( ) { this = TValue ( TValueInt ( result ) , true ) }
239
242
@@ -320,17 +323,19 @@ module Make<LocationSig Location, InputSig<Location> Input> {
320
323
)
321
324
)
322
325
or
323
- exists ( Case c |
326
+ exceptionBranchPoint ( bb1 , bb2 , _) and v = TException ( false )
327
+ or
328
+ exceptionBranchPoint ( bb1 , _, bb2 ) and v = TException ( true )
329
+ }
330
+
331
+ private predicate caseBranchEdge ( BasicBlock bb1 , BasicBlock bb2 , GuardValue v , Expr switchExpr ) {
332
+ exists ( Case c | switchExpr = c .getSwitchExpr ( ) |
324
333
v = TCaseMatch ( c , true ) and
325
334
c .matchEdge ( bb1 , bb2 )
326
335
or
327
336
v = TCaseMatch ( c , false ) and
328
337
c .nonMatchEdge ( bb1 , bb2 )
329
338
)
330
- or
331
- exceptionBranchPoint ( bb1 , bb2 , _) and v = TException ( false )
332
- or
333
- exceptionBranchPoint ( bb1 , _, bb2 ) and v = TException ( true )
334
339
}
335
340
336
341
pragma [ nomagic]
@@ -362,12 +367,16 @@ module Make<LocationSig Location, InputSig<Location> Input> {
362
367
*/
363
368
final class PreGuard extends ExprFinal {
364
369
/**
365
- * Holds if this guard is the last node in `bb1` and that its successor is
366
- * `bb2` exactly when evaluating to `v`.
370
+ * Holds if this guard evaluating to `v` corresponds to taking the edge
371
+ * from `bb1` to `bb2`. For ordinary conditional branching this guard is
372
+ * the last node in `bb1`, but for switch case matching it is the switch
373
+ * expression, which may either be in `bb1` or an earlier basic block.
367
374
*/
368
375
predicate hasValueBranchEdge ( BasicBlock bb1 , BasicBlock bb2 , GuardValue v ) {
369
376
bb1 .getLastNode ( ) = this .getControlFlowNode ( ) and
370
377
branchEdge ( bb1 , bb2 , v )
378
+ or
379
+ caseBranchEdge ( bb1 , bb2 , v , this )
371
380
}
372
381
373
382
/**
@@ -457,6 +466,12 @@ module Make<LocationSig Location, InputSig<Location> Input> {
457
466
BasicBlock getBasicBlock ( ) ;
458
467
459
468
Expr getARead ( ) ;
469
+
470
+ /** Gets a textual representation of this SSA definition. */
471
+ string toString ( ) ;
472
+
473
+ /** Gets the location of this SSA definition. */
474
+ Location getLocation ( ) ;
460
475
}
461
476
462
477
class SsaWriteDefinition extends SsaDefinition {
@@ -549,6 +564,9 @@ module Make<LocationSig Location, InputSig<Location> Input> {
549
564
other .getARead ( ) = guard and
550
565
eqtest .directlyControls ( guard .getBasicBlock ( ) , branch )
551
566
)
567
+ or
568
+ // An expression `x = ...` can be considered as a read of `x`.
569
+ guard .( IdExpr ) .getEqualChildExpr ( ) = def .( SsaWriteDefinition ) .getDefinition ( )
552
570
}
553
571
554
572
private predicate valueStep ( Expr e1 , Expr e2 ) {
@@ -649,7 +667,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
649
667
)
650
668
}
651
669
652
- private predicate impliesStep ( Guard g1 , GuardValue v1 , Guard g2 , GuardValue v2 ) {
670
+ private predicate impliesStep1 ( Guard g1 , GuardValue v1 , Guard g2 , GuardValue v2 ) {
653
671
baseImpliesStep ( g1 , v1 , g2 , v2 )
654
672
or
655
673
exists ( SsaDefinition def , Expr e |
@@ -689,7 +707,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
689
707
or
690
708
baseSsaValueCheck ( def , ssaVal , g0 , v0 )
691
709
|
692
- impliesStep ( g , v , g0 , v0 )
710
+ impliesStep1 ( g , v , g0 , v0 )
693
711
)
694
712
}
695
713
@@ -712,6 +730,16 @@ module Make<LocationSig Location, InputSig<Location> Input> {
712
730
)
713
731
}
714
732
733
+ private predicate impliesStep2 ( Guard g1 , GuardValue v1 , Guard g2 , GuardValue v2 ) {
734
+ impliesStep1 ( g1 , v1 , g2 , v2 )
735
+ or
736
+ exists ( Expr nonnull |
737
+ exprHasValue ( nonnull , v2 ) and
738
+ eqtestHasOperands ( g1 , g2 , nonnull , v1 .asBooleanValue ( ) ) and
739
+ v2 = TValue ( TValueNull ( ) , false )
740
+ )
741
+ }
742
+
715
743
bindingset [ g1, v1]
716
744
pragma [ inline_late]
717
745
private predicate unboundImpliesStep ( Guard g1 , GuardValue v1 , Guard g2 , GuardValue v2 ) {
@@ -779,7 +807,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
779
807
or
780
808
exists ( Guard g0 , GuardValue v0 |
781
809
guardControls ( g0 , v0 , tgtGuard , tgtVal ) and
782
- impliesStep ( g0 , v0 , guard , v )
810
+ impliesStep2 ( g0 , v0 , guard , v )
783
811
)
784
812
or
785
813
exists ( Guard g0 , GuardValue v0 |
@@ -816,6 +844,27 @@ module Make<LocationSig Location, InputSig<Location> Input> {
816
844
}
817
845
}
818
846
847
+ private predicate booleanGuard ( Guard guard , GuardValue val ) {
848
+ exists ( guard ) and exists ( val .asBooleanValue ( ) )
849
+ }
850
+
851
+ private module BooleanImplies = ImpliesTC< booleanGuard / 2 > ;
852
+
853
+ /** INTERNAL: Don't use. */
854
+ predicate boolImplies ( Guard g1 , GuardValue v1 , Guard g2 , GuardValue v2 ) {
855
+ BooleanImplies:: guardControls ( g2 , v2 , g1 , v1 ) and
856
+ g2 != g1
857
+ }
858
+
859
+ /**
860
+ * Holds if `guard` evaluating to `v` implies that `e` is guaranteed to be
861
+ * null if `isNull` is true, and non-null if `isNull` is false.
862
+ */
863
+ predicate nullGuard ( Guard guard , GuardValue v , Expr e , boolean isNull ) {
864
+ impliesStep2 ( guard , v , e , TValue ( TValueNull ( ) , isNull ) ) or
865
+ additionalImpliesStep ( guard , v , e , TValue ( TValueNull ( ) , isNull ) )
866
+ }
867
+
819
868
private predicate hasAValueBranchEdge ( Guard guard , GuardValue v ) {
820
869
guard .hasValueBranchEdge ( _, _, v )
821
870
}
@@ -831,6 +880,30 @@ module Make<LocationSig Location, InputSig<Location> Input> {
831
880
)
832
881
}
833
882
883
+ /**
884
+ * Holds if `def` evaluating to `v` controls the control-flow branch
885
+ * edge from `bb1` to `bb2`. That is, following the edge from `bb1` to
886
+ * `bb2` implies that `def` evaluated to `v`.
887
+ */
888
+ predicate ssaControlsBranchEdge ( SsaDefinition def , BasicBlock bb1 , BasicBlock bb2 , GuardValue v ) {
889
+ exists ( Guard g0 , GuardValue v0 |
890
+ g0 .hasValueBranchEdge ( bb1 , bb2 , v0 ) and
891
+ BranchImplies:: ssaControls ( def , v , g0 , v0 )
892
+ )
893
+ }
894
+
895
+ /**
896
+ * Holds if `def` evaluating to `v` controls the basic block `bb`.
897
+ * That is, execution of `bb` implies that `def` evaluated to `v`.
898
+ */
899
+ predicate ssaControls ( SsaDefinition def , BasicBlock bb , GuardValue v ) {
900
+ exists ( BasicBlock guard , BasicBlock succ |
901
+ ssaControlsBranchEdge ( def , guard , succ , v ) and
902
+ dominatingEdge ( guard , succ ) and
903
+ succ .dominates ( bb )
904
+ )
905
+ }
906
+
834
907
signature module CustomGuardInputSig {
835
908
class ParameterPosition {
836
909
/** Gets a textual representation of this element. */
0 commit comments