@@ -45,6 +45,7 @@ private newtype TIRDataFlowNode =
45
45
or
46
46
Ssa:: isModifiableByCall ( operand , indirectionIndex )
47
47
} or
48
+ TSsaPhiInputNode ( Ssa:: PhiNode phi , IRBlock input ) { phi .hasInputFromBlock ( _, _, _, _, input ) } or
48
49
TSsaPhiNode ( Ssa:: PhiNode phi ) or
49
50
TSsaIteratorNode ( IteratorFlow:: IteratorFlowNode n ) or
50
51
TRawIndirectOperand0 ( Node0Impl node , int indirectionIndex ) {
@@ -170,6 +171,9 @@ class Node extends TIRDataFlowNode {
170
171
or
171
172
this .( SsaPhiNode ) .getPhiNode ( ) .getBasicBlock ( ) = block and i = - 1
172
173
or
174
+ this .( SsaPhiInputNode ) .getBlock ( ) = block and
175
+ i = block .getInstructionCount ( )
176
+ or
173
177
this .( RawIndirectOperand ) .getOperand ( ) .getUse ( ) = block .getInstruction ( i )
174
178
or
175
179
this .( RawIndirectInstruction ) .getInstruction ( ) = block .getInstruction ( i )
@@ -654,6 +658,58 @@ class SsaPhiNode extends Node, TSsaPhiNode {
654
658
predicate isPhiRead ( ) { phi .isPhiRead ( ) }
655
659
}
656
660
661
+ /**
662
+ * INTERNAL: Do not use.
663
+ *
664
+ * A note that is used as an input to a phi node.
665
+ *
666
+ * This class exists to allow more powerful barrier guards. Consider this
667
+ * example:
668
+ *
669
+ * ```cpp
670
+ * int x = source();
671
+ * if(!safe(x)) {
672
+ * x = clear();
673
+ * }
674
+ * // phi node for x here
675
+ * sink(x);
676
+ * ```
677
+ *
678
+ * At the phi node for `x` it is neither the case that `x` is dominated by
679
+ * `safe(x)`, or is the case that the phi is dominated by a clearing of `x`.
680
+ *
681
+ * However, by inserting an "phi input" nodes as the last entry in the basic
682
+ * block that defines the inputs to the phi we can conclude that each of those
683
+ * inputs are safe to pass to `sink`.
684
+ */
685
+ class SsaPhiInputNode extends Node , TSsaPhiInputNode {
686
+ Ssa:: PhiNode phi ;
687
+ IRBlock block ;
688
+
689
+ SsaPhiInputNode ( ) { this = TSsaPhiInputNode ( phi , block ) }
690
+
691
+ /** Gets the phi node associated with this node. */
692
+ Ssa:: PhiNode getPhiNode ( ) { result = phi }
693
+
694
+ /** Gets the basic block in which this input originates. */
695
+ IRBlock getBlock ( ) { result = block }
696
+
697
+ override Declaration getEnclosingCallable ( ) { result = this .getFunction ( ) }
698
+
699
+ override Declaration getFunction ( ) { result = phi .getBasicBlock ( ) .getEnclosingFunction ( ) }
700
+
701
+ override DataFlowType getType ( ) { result = this .getSourceVariable ( ) .getType ( ) }
702
+
703
+ override predicate isGLValue ( ) { phi .getSourceVariable ( ) .isGLValue ( ) }
704
+
705
+ final override Location getLocationImpl ( ) { result = block .getLastInstruction ( ) .getLocation ( ) }
706
+
707
+ override string toStringImpl ( ) { result = "Phi input" }
708
+
709
+ /** Gets the source variable underlying this phi node. */
710
+ Ssa:: SourceVariable getSourceVariable ( ) { result = phi .getSourceVariable ( ) }
711
+ }
712
+
657
713
/**
658
714
* INTERNAL: do not use.
659
715
*
0 commit comments