@@ -27,7 +27,7 @@ import ExprNodes
27
27
* - `VariableNode`, which is used to model flow through global variables.
28
28
* - `PostUpdateNodeImpl`, which is used to model the state of an object after
29
29
* an update after a number of loads.
30
- * - `SsaPhiNode `, which represents phi nodes as computed by the shared SSA
30
+ * - `SsaSynthNode `, which represents synthesized nodes as computed by the shared SSA
31
31
* library.
32
32
* - `RawIndirectOperand`, which represents the value of `operand` after
33
33
* loading the address a number of times.
@@ -47,8 +47,7 @@ private newtype TIRDataFlowNode =
47
47
or
48
48
Ssa:: isModifiableByCall ( operand , indirectionIndex )
49
49
} or
50
- TSsaPhiInputNode ( Ssa:: PhiNode phi , IRBlock input ) { phi .hasInputFromBlock ( _, _, _, _, input ) } or
51
- TSsaPhiNode ( Ssa:: PhiNode phi ) or
50
+ TSsaSynthNode ( Ssa:: SynthNode n ) or
52
51
TSsaIteratorNode ( IteratorFlow:: IteratorFlowNode n ) or
53
52
TRawIndirectOperand0 ( Node0Impl node , int indirectionIndex ) {
54
53
Ssa:: hasRawIndirectOperand ( node .asOperand ( ) , indirectionIndex )
@@ -184,10 +183,11 @@ class Node extends TIRDataFlowNode {
184
183
or
185
184
this .asOperand ( ) .getUse ( ) = block .getInstruction ( i )
186
185
or
187
- this .( SsaPhiNode ) .getPhiNode ( ) .getBasicBlock ( ) = block and i = - 1
188
- or
189
- this .( SsaPhiInputNode ) .getBlock ( ) = block and
190
- i = block .getInstructionCount ( )
186
+ exists ( Ssa:: SynthNode ssaNode |
187
+ this .( SsaSynthNode ) .getSynthNode ( ) = ssaNode and
188
+ ssaNode .getBasicBlock ( ) = block and
189
+ ssaNode .getIndex ( ) = i
190
+ )
191
191
or
192
192
this .( RawIndirectOperand ) .getOperand ( ) .getUse ( ) = block .getInstruction ( i )
193
193
or
@@ -686,117 +686,45 @@ class PostFieldUpdateNode extends PostUpdateNodeImpl {
686
686
/**
687
687
* INTERNAL: do not use.
688
688
*
689
- * A phi node produced by the shared SSA library, viewed as a node in a data flow graph.
689
+ * A synthesized SSA node produced by the shared SSA library, viewed as a node
690
+ * in a data flow graph.
690
691
*/
691
- class SsaPhiNode extends Node , TSsaPhiNode {
692
- Ssa:: PhiNode phi ;
692
+ class SsaSynthNode extends Node , TSsaSynthNode {
693
+ Ssa:: SynthNode node ;
693
694
694
- SsaPhiNode ( ) { this = TSsaPhiNode ( phi ) }
695
+ SsaSynthNode ( ) { this = TSsaSynthNode ( node ) }
695
696
696
- /** Gets the phi node associated with this node. */
697
- Ssa:: PhiNode getPhiNode ( ) { result = phi }
697
+ /** Gets the synthesized SSA node associated with this node. */
698
+ Ssa:: SynthNode getSynthNode ( ) { result = node }
698
699
699
700
override DataFlowCallable getEnclosingCallable ( ) {
700
701
result .asSourceCallable ( ) = this .getFunction ( )
701
702
}
702
703
703
- override Declaration getFunction ( ) { result = phi .getBasicBlock ( ) .getEnclosingFunction ( ) }
704
+ override Declaration getFunction ( ) { result = node .getBasicBlock ( ) .getEnclosingFunction ( ) }
704
705
705
- override DataFlowType getType ( ) {
706
- exists ( Ssa:: SourceVariable sv |
707
- this .getPhiNode ( ) .definesAt ( sv , _, _, _) and
708
- result = sv .getType ( )
709
- )
710
- }
706
+ override DataFlowType getType ( ) { result = node .getSourceVariable ( ) .getType ( ) }
711
707
712
- override predicate isGLValue ( ) { phi .getSourceVariable ( ) .isGLValue ( ) }
708
+ override predicate isGLValue ( ) { node .getSourceVariable ( ) .isGLValue ( ) }
713
709
714
- final override Location getLocationImpl ( ) { result = phi .getBasicBlock ( ) .getLocation ( ) }
715
-
716
- override string toStringImpl ( ) { result = phi .toString ( ) }
717
-
718
- /**
719
- * Gets a node that is used as input to this phi node.
720
- * `fromBackEdge` is true if data flows along a back-edge,
721
- * and `false` otherwise.
722
- */
723
- cached
724
- final Node getAnInput ( boolean fromBackEdge ) {
725
- result .( SsaPhiInputNode ) .getPhiNode ( ) = phi and
726
- exists ( IRBlock bPhi , IRBlock bResult |
727
- bPhi = phi .getBasicBlock ( ) and bResult = result .getBasicBlock ( )
728
- |
729
- if bPhi .dominates ( bResult ) then fromBackEdge = true else fromBackEdge = false
730
- )
731
- }
732
-
733
- /** Gets a node that is used as input to this phi node. */
734
- final Node getAnInput ( ) { result = this .getAnInput ( _) }
735
-
736
- /** Gets the source variable underlying this phi node. */
737
- Ssa:: SourceVariable getSourceVariable ( ) { result = phi .getSourceVariable ( ) }
710
+ final override Location getLocationImpl ( ) { result = node .getLocation ( ) }
738
711
739
- /**
740
- * Holds if this phi node is a phi-read node.
741
- *
742
- * Phi-read nodes are like normal phi nodes, but they are inserted based
743
- * on reads instead of writes.
744
- */
745
- predicate isPhiRead ( ) { phi .isPhiRead ( ) }
712
+ override string toStringImpl ( ) { result = node .toString ( ) }
746
713
}
747
714
748
715
/**
749
- * INTERNAL: Do not use.
750
- *
751
- * A node that is used as an input to a phi node.
752
- *
753
- * This class exists to allow more powerful barrier guards. Consider this
754
- * example:
755
- *
756
- * ```cpp
757
- * int x = source();
758
- * if(!safe(x)) {
759
- * x = clear();
760
- * }
761
- * // phi node for x here
762
- * sink(x);
763
- * ```
764
- *
765
- * At the phi node for `x` it is neither the case that `x` is dominated by
766
- * `safe(x)`, or is the case that the phi is dominated by a clearing of `x`.
767
- *
768
- * By inserting a "phi input" node as the last entry in the basic block that
769
- * defines the inputs to the phi we can conclude that each of those inputs are
770
- * safe to pass to `sink`.
716
+ * Holds if `n` has a local flow step that goes through a back-edge.
771
717
*/
772
- class SsaPhiInputNode extends Node , TSsaPhiInputNode {
773
- Ssa:: PhiNode phi ;
774
- IRBlock block ;
775
-
776
- SsaPhiInputNode ( ) { this = TSsaPhiInputNode ( phi , block ) }
777
-
778
- /** Gets the phi node associated with this node. */
779
- Ssa:: PhiNode getPhiNode ( ) { result = phi }
780
-
781
- /** Gets the basic block in which this input originates. */
782
- IRBlock getBlock ( ) { result = block }
783
-
784
- override DataFlowCallable getEnclosingCallable ( ) {
785
- result .asSourceCallable ( ) = this .getFunction ( )
786
- }
787
-
788
- override Declaration getFunction ( ) { result = phi .getBasicBlock ( ) .getEnclosingFunction ( ) }
789
-
790
- override DataFlowType getType ( ) { result = this .getSourceVariable ( ) .getType ( ) }
791
-
792
- override predicate isGLValue ( ) { phi .getSourceVariable ( ) .isGLValue ( ) }
793
-
794
- final override Location getLocationImpl ( ) { result = block .getLastInstruction ( ) .getLocation ( ) }
795
-
796
- override string toStringImpl ( ) { result = "Phi input" }
797
-
798
- /** Gets the source variable underlying this phi node. */
799
- Ssa:: SourceVariable getSourceVariable ( ) { result = phi .getSourceVariable ( ) }
718
+ cached
719
+ predicate flowsToBackEdge ( Node n ) {
720
+ exists ( Node succ , IRBlock bb1 , IRBlock bb2 |
721
+ Ssa:: ssaFlow ( n , succ ) and
722
+ bb1 = n .getBasicBlock ( ) and
723
+ bb2 = succ .getBasicBlock ( ) and
724
+ bb1 != bb2 and
725
+ bb2 .dominates ( bb1 ) and
726
+ bb1 .getASuccessor + ( ) = bb2
727
+ )
800
728
}
801
729
802
730
/**
@@ -1374,7 +1302,7 @@ class UninitializedNode extends Node {
1374
1302
exists ( Ssa:: Definition def , Ssa:: SourceVariable sv |
1375
1303
def .getIndirectionIndex ( ) = 0 and
1376
1304
def .getValue ( ) .asInstruction ( ) instanceof UninitializedInstruction and
1377
- Ssa:: defToNode ( this , def , sv , _ , _ , _ ) and
1305
+ Ssa:: defToNode ( this , def , sv ) and
1378
1306
v = sv .getBaseVariable ( ) .( Ssa:: BaseIRVariable ) .getIRVariable ( ) .getAst ( )
1379
1307
)
1380
1308
}
@@ -1887,15 +1815,9 @@ private module Cached {
1887
1815
cached
1888
1816
predicate simpleLocalFlowStep ( Node nodeFrom , Node nodeTo , string model ) {
1889
1817
(
1890
- // Post update node -> Node flow
1891
- Ssa:: postUpdateFlow ( nodeFrom , nodeTo )
1892
- or
1893
1818
// Def-use/Use-use flow
1894
1819
Ssa:: ssaFlow ( nodeFrom , nodeTo )
1895
1820
or
1896
- // Phi input -> Phi
1897
- nodeFrom .( SsaPhiInputNode ) .getPhiNode ( ) = nodeTo .( SsaPhiNode ) .getPhiNode ( )
1898
- or
1899
1821
IteratorFlow:: localFlowStep ( nodeFrom , nodeTo )
1900
1822
or
1901
1823
// Operand -> Instruction flow
@@ -1910,9 +1832,6 @@ private module Cached {
1910
1832
not iFrom = Ssa:: getIRRepresentationOfOperand ( opTo )
1911
1833
)
1912
1834
or
1913
- // Phi node -> Node flow
1914
- Ssa:: fromPhiNode ( nodeFrom , nodeTo )
1915
- or
1916
1835
// Indirect operand -> (indirect) instruction flow
1917
1836
indirectionOperandFlow ( nodeFrom , nodeTo )
1918
1837
or
@@ -2356,22 +2275,6 @@ class ContentSet instanceof Content {
2356
2275
}
2357
2276
}
2358
2277
2359
- pragma [ nomagic]
2360
- private predicate guardControlsPhiInput (
2361
- IRGuardCondition g , boolean branch , Ssa:: DefinitionExt def , IRBlock input , Ssa:: PhiNode phi
2362
- ) {
2363
- phi .hasInputFromBlock ( def , _, _, _, input ) and
2364
- (
2365
- g .controls ( input , branch )
2366
- or
2367
- exists ( EdgeKind kind |
2368
- g .getBlock ( ) = input and
2369
- kind = getConditionalEdge ( branch ) and
2370
- input .getSuccessor ( kind ) = phi .getBasicBlock ( )
2371
- )
2372
- )
2373
- }
2374
-
2375
2278
/**
2376
2279
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
2377
2280
*
@@ -2403,6 +2306,10 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
2403
2306
)
2404
2307
}
2405
2308
2309
+ private predicate guardChecksNode ( IRGuardCondition g , Node n , boolean branch ) {
2310
+ guardChecks ( g , n .asOperand ( ) .getDef ( ) .getConvertedResultExpression ( ) , branch )
2311
+ }
2312
+
2406
2313
/**
2407
2314
* Gets an expression node that is safely guarded by the given guard check.
2408
2315
*
@@ -2443,14 +2350,7 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
2443
2350
controls ( g , result , edge )
2444
2351
)
2445
2352
or
2446
- exists (
2447
- IRGuardCondition g , boolean branch , Ssa:: DefinitionExt def , IRBlock input , Ssa:: PhiNode phi
2448
- |
2449
- guardChecks ( g , def .getARead ( ) .asOperand ( ) .getDef ( ) .getConvertedResultExpression ( ) , branch ) and
2450
- guardControlsPhiInput ( g , branch , def , pragma [ only_bind_into ] ( input ) ,
2451
- pragma [ only_bind_into ] ( phi ) ) and
2452
- result = TSsaPhiInputNode ( phi , input )
2453
- )
2353
+ result = Ssa:: BarrierGuard< guardChecksNode / 3 > :: getABarrierNode ( )
2454
2354
}
2455
2355
2456
2356
/**
@@ -2499,6 +2399,13 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
2499
2399
)
2500
2400
}
2501
2401
2402
+ private predicate guardChecksIndirectNode (
2403
+ IRGuardCondition g , Node n , boolean branch , int indirectionIndex
2404
+ ) {
2405
+ guardChecks ( g , n .asIndirectOperand ( indirectionIndex ) .getDef ( ) .getConvertedResultExpression ( ) ,
2406
+ branch )
2407
+ }
2408
+
2502
2409
/**
2503
2410
* Gets an indirect expression node with indirection index `indirectionIndex` that is
2504
2411
* safely guarded by the given guard check.
@@ -2541,16 +2448,8 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
2541
2448
controls ( g , result , edge )
2542
2449
)
2543
2450
or
2544
- exists (
2545
- IRGuardCondition g , boolean branch , Ssa:: DefinitionExt def , IRBlock input , Ssa:: PhiNode phi
2546
- |
2547
- guardChecks ( g ,
2548
- def .getARead ( ) .asIndirectOperand ( indirectionIndex ) .getDef ( ) .getConvertedResultExpression ( ) ,
2549
- branch ) and
2550
- guardControlsPhiInput ( g , branch , def , pragma [ only_bind_into ] ( input ) ,
2551
- pragma [ only_bind_into ] ( phi ) ) and
2552
- result = TSsaPhiInputNode ( phi , input )
2553
- )
2451
+ result =
2452
+ Ssa:: BarrierGuardWithIntParam< guardChecksIndirectNode / 4 > :: getABarrierNode ( indirectionIndex )
2554
2453
}
2555
2454
}
2556
2455
@@ -2559,14 +2458,6 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
2559
2458
*/
2560
2459
signature predicate instructionGuardChecksSig ( IRGuardCondition g , Instruction instr , boolean branch ) ;
2561
2460
2562
- private EdgeKind getConditionalEdge ( boolean branch ) {
2563
- branch = true and
2564
- result instanceof TrueEdge
2565
- or
2566
- branch = false and
2567
- result instanceof FalseEdge
2568
- }
2569
-
2570
2461
/**
2571
2462
* Provides a set of barrier nodes for a guard that validates an instruction.
2572
2463
*
@@ -2583,6 +2474,10 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
2583
2474
)
2584
2475
}
2585
2476
2477
+ private predicate guardChecksNode ( IRGuardCondition g , Node n , boolean branch ) {
2478
+ instructionGuardChecks ( g , n .asOperand ( ) .getDef ( ) , branch )
2479
+ }
2480
+
2586
2481
/** Gets a node that is safely guarded by the given guard check. */
2587
2482
Node getABarrierNode ( ) {
2588
2483
exists ( IRGuardCondition g , ValueNumber value , boolean edge |
@@ -2591,14 +2486,7 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
2591
2486
controls ( g , result , edge )
2592
2487
)
2593
2488
or
2594
- exists (
2595
- IRGuardCondition g , boolean branch , Ssa:: DefinitionExt def , IRBlock input , Ssa:: PhiNode phi
2596
- |
2597
- instructionGuardChecks ( g , def .getARead ( ) .asOperand ( ) .getDef ( ) , branch ) and
2598
- guardControlsPhiInput ( g , branch , def , pragma [ only_bind_into ] ( input ) ,
2599
- pragma [ only_bind_into ] ( phi ) ) and
2600
- result = TSsaPhiInputNode ( phi , input )
2601
- )
2489
+ result = Ssa:: BarrierGuard< guardChecksNode / 3 > :: getABarrierNode ( )
2602
2490
}
2603
2491
2604
2492
bindingset [ value, n]
@@ -2610,6 +2498,12 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
2610
2498
)
2611
2499
}
2612
2500
2501
+ private predicate guardChecksIndirectNode (
2502
+ IRGuardCondition g , Node n , boolean branch , int indirectionIndex
2503
+ ) {
2504
+ instructionGuardChecks ( g , n .asIndirectOperand ( indirectionIndex ) .getDef ( ) , branch )
2505
+ }
2506
+
2613
2507
/**
2614
2508
* Gets an indirect node with indirection index `indirectionIndex` that is
2615
2509
* safely guarded by the given guard check.
@@ -2621,14 +2515,8 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
2621
2515
controls ( g , result , edge )
2622
2516
)
2623
2517
or
2624
- exists (
2625
- IRGuardCondition g , boolean branch , Ssa:: DefinitionExt def , IRBlock input , Ssa:: PhiNode phi
2626
- |
2627
- instructionGuardChecks ( g , def .getARead ( ) .asIndirectOperand ( indirectionIndex ) .getDef ( ) , branch ) and
2628
- guardControlsPhiInput ( g , branch , def , pragma [ only_bind_into ] ( input ) ,
2629
- pragma [ only_bind_into ] ( phi ) ) and
2630
- result = TSsaPhiInputNode ( phi , input )
2631
- )
2518
+ result =
2519
+ Ssa:: BarrierGuardWithIntParam< guardChecksIndirectNode / 4 > :: getABarrierNode ( indirectionIndex )
2632
2520
}
2633
2521
}
2634
2522
0 commit comments