@@ -45,6 +45,7 @@ private newtype TIRDataFlowNode =
4545 or
4646 Ssa:: isModifiableByCall ( operand , indirectionIndex )
4747 } or
48+ TSsaPhiInputNode ( Ssa:: PhiNode phi , IRBlock input ) { phi .hasInputFromBlock ( _, _, _, _, input ) } or
4849 TSsaPhiNode ( Ssa:: PhiNode phi ) or
4950 TSsaIteratorNode ( IteratorFlow:: IteratorFlowNode n ) or
5051 TRawIndirectOperand0 ( Node0Impl node , int indirectionIndex ) {
@@ -170,6 +171,9 @@ class Node extends TIRDataFlowNode {
170171 or
171172 this .( SsaPhiNode ) .getPhiNode ( ) .getBasicBlock ( ) = block and i = - 1
172173 or
174+ this .( SsaPhiInputNode ) .getBlock ( ) = block and
175+ i = block .getInstructionCount ( )
176+ or
173177 this .( RawIndirectOperand ) .getOperand ( ) .getUse ( ) = block .getInstruction ( i )
174178 or
175179 this .( RawIndirectInstruction ) .getInstruction ( ) = block .getInstruction ( i )
@@ -654,6 +658,58 @@ class SsaPhiNode extends Node, TSsaPhiNode {
654658 predicate isPhiRead ( ) { phi .isPhiRead ( ) }
655659}
656660
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+
657713/**
658714 * INTERNAL: do not use.
659715 *
0 commit comments