@@ -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 ) {
@@ -165,6 +166,12 @@ class Node extends TIRDataFlowNode {
165166 /** Gets the operands corresponding to this node, if any. */
166167 Operand asOperand ( ) { result = this .( OperandNode ) .getOperand ( ) }
167168
169+ /**
170+ * Gets the operand that is indirectly tracked by this node behind `index`
171+ * number of indirections.
172+ */
173+ Operand asIndirectOperand ( int index ) { hasOperandAndIndex ( this , result , index ) }
174+
168175 /**
169176 * Holds if this node is at index `i` in basic block `block`.
170177 *
@@ -177,6 +184,9 @@ class Node extends TIRDataFlowNode {
177184 or
178185 this .( SsaPhiNode ) .getPhiNode ( ) .getBasicBlock ( ) = block and i = - 1
179186 or
187+ this .( SsaPhiInputNode ) .getBlock ( ) = block and
188+ i = block .getInstructionCount ( )
189+ or
180190 this .( RawIndirectOperand ) .getOperand ( ) .getUse ( ) = block .getInstruction ( i )
181191 or
182192 this .( RawIndirectInstruction ) .getInstruction ( ) = block .getInstruction ( i )
@@ -629,7 +639,7 @@ class SsaPhiNode extends Node, TSsaPhiNode {
629639
630640 final override Location getLocationImpl ( ) { result = phi .getBasicBlock ( ) .getLocation ( ) }
631641
632- override string toStringImpl ( ) { result = "Phi" }
642+ override string toStringImpl ( ) { result = phi . toString ( ) }
633643
634644 /**
635645 * Gets a node that is used as input to this phi node.
@@ -638,7 +648,7 @@ class SsaPhiNode extends Node, TSsaPhiNode {
638648 */
639649 cached
640650 final Node getAnInput ( boolean fromBackEdge ) {
641- localFlowStep ( result , this ) and
651+ result . ( SsaPhiInputNode ) . getPhiNode ( ) = phi and
642652 exists ( IRBlock bPhi , IRBlock bResult |
643653 bPhi = phi .getBasicBlock ( ) and bResult = result .getBasicBlock ( )
644654 |
@@ -661,6 +671,58 @@ class SsaPhiNode extends Node, TSsaPhiNode {
661671 predicate isPhiRead ( ) { phi .isPhiRead ( ) }
662672}
663673
674+ /**
675+ * INTERNAL: Do not use.
676+ *
677+ * A node that is used as an input to a phi node.
678+ *
679+ * This class exists to allow more powerful barrier guards. Consider this
680+ * example:
681+ *
682+ * ```cpp
683+ * int x = source();
684+ * if(!safe(x)) {
685+ * x = clear();
686+ * }
687+ * // phi node for x here
688+ * sink(x);
689+ * ```
690+ *
691+ * At the phi node for `x` it is neither the case that `x` is dominated by
692+ * `safe(x)`, or is the case that the phi is dominated by a clearing of `x`.
693+ *
694+ * By inserting a "phi input" node as the last entry in the basic block that
695+ * defines the inputs to the phi we can conclude that each of those inputs are
696+ * safe to pass to `sink`.
697+ */
698+ class SsaPhiInputNode extends Node , TSsaPhiInputNode {
699+ Ssa:: PhiNode phi ;
700+ IRBlock block ;
701+
702+ SsaPhiInputNode ( ) { this = TSsaPhiInputNode ( phi , block ) }
703+
704+ /** Gets the phi node associated with this node. */
705+ Ssa:: PhiNode getPhiNode ( ) { result = phi }
706+
707+ /** Gets the basic block in which this input originates. */
708+ IRBlock getBlock ( ) { result = block }
709+
710+ override Declaration getEnclosingCallable ( ) { result = this .getFunction ( ) }
711+
712+ override Declaration getFunction ( ) { result = phi .getBasicBlock ( ) .getEnclosingFunction ( ) }
713+
714+ override DataFlowType getType ( ) { result = this .getSourceVariable ( ) .getType ( ) }
715+
716+ override predicate isGLValue ( ) { phi .getSourceVariable ( ) .isGLValue ( ) }
717+
718+ final override Location getLocationImpl ( ) { result = block .getLastInstruction ( ) .getLocation ( ) }
719+
720+ override string toStringImpl ( ) { result = "Phi input" }
721+
722+ /** Gets the source variable underlying this phi node. */
723+ Ssa:: SourceVariable getSourceVariable ( ) { result = phi .getSourceVariable ( ) }
724+ }
725+
664726/**
665727 * INTERNAL: do not use.
666728 *
@@ -2183,6 +2245,9 @@ private module Cached {
21832245 // Def-use/Use-use flow
21842246 Ssa:: ssaFlow ( nodeFrom , nodeTo )
21852247 or
2248+ // Phi input -> Phi
2249+ nodeFrom .( SsaPhiInputNode ) .getPhiNode ( ) = nodeTo .( SsaPhiNode ) .getPhiNode ( )
2250+ or
21862251 IteratorFlow:: localFlowStep ( nodeFrom , nodeTo )
21872252 or
21882253 // Operand -> Instruction flow
@@ -2621,6 +2686,22 @@ class ContentSet instanceof Content {
26212686 }
26222687}
26232688
2689+ pragma [ nomagic]
2690+ private predicate guardControlsPhiInput (
2691+ IRGuardCondition g , boolean branch , Ssa:: Definition def , IRBlock input , Ssa:: PhiNode phi
2692+ ) {
2693+ phi .hasInputFromBlock ( def , _, _, _, input ) and
2694+ (
2695+ g .controls ( input , branch )
2696+ or
2697+ exists ( EdgeKind kind |
2698+ g .getBlock ( ) = input and
2699+ kind = getConditionalEdge ( branch ) and
2700+ input .getSuccessor ( kind ) = phi .getBasicBlock ( )
2701+ )
2702+ )
2703+ }
2704+
26242705/**
26252706 * Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
26262707 *
@@ -2669,13 +2750,21 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
26692750 *
26702751 * NOTE: If an indirect expression is tracked, use `getAnIndirectBarrierNode` instead.
26712752 */
2672- ExprNode getABarrierNode ( ) {
2753+ Node getABarrierNode ( ) {
26732754 exists ( IRGuardCondition g , Expr e , ValueNumber value , boolean edge |
26742755 e = value .getAnInstruction ( ) .getConvertedResultExpression ( ) and
2675- result .getConvertedExpr ( ) = e and
2756+ result .asConvertedExpr ( ) = e and
26762757 guardChecks ( g , value .getAnInstruction ( ) .getConvertedResultExpression ( ) , edge ) and
26772758 g .controls ( result .getBasicBlock ( ) , edge )
26782759 )
2760+ or
2761+ exists (
2762+ IRGuardCondition g , boolean branch , Ssa:: DefinitionExt def , IRBlock input , Ssa:: PhiNode phi
2763+ |
2764+ guardChecks ( g , def .getARead ( ) .asOperand ( ) .getDef ( ) .getConvertedResultExpression ( ) , branch ) and
2765+ guardControlsPhiInput ( g , branch , def , input , phi ) and
2766+ result = TSsaPhiInputNode ( phi , input )
2767+ )
26792768 }
26802769
26812770 /**
@@ -2711,7 +2800,7 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
27112800 *
27122801 * NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
27132802 */
2714- IndirectExprNode getAnIndirectBarrierNode ( ) { result = getAnIndirectBarrierNode ( _) }
2803+ Node getAnIndirectBarrierNode ( ) { result = getAnIndirectBarrierNode ( _) }
27152804
27162805 /**
27172806 * Gets an indirect expression node with indirection index `indirectionIndex` that is
@@ -2747,13 +2836,23 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
27472836 *
27482837 * NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
27492838 */
2750- IndirectExprNode getAnIndirectBarrierNode ( int indirectionIndex ) {
2839+ Node getAnIndirectBarrierNode ( int indirectionIndex ) {
27512840 exists ( IRGuardCondition g , Expr e , ValueNumber value , boolean edge |
27522841 e = value .getAnInstruction ( ) .getConvertedResultExpression ( ) and
2753- result .getConvertedExpr ( indirectionIndex ) = e and
2842+ result .asIndirectConvertedExpr ( indirectionIndex ) = e and
27542843 guardChecks ( g , value .getAnInstruction ( ) .getConvertedResultExpression ( ) , edge ) and
27552844 g .controls ( result .getBasicBlock ( ) , edge )
27562845 )
2846+ or
2847+ exists (
2848+ IRGuardCondition g , boolean branch , Ssa:: DefinitionExt def , IRBlock input , Ssa:: PhiNode phi
2849+ |
2850+ guardChecks ( g ,
2851+ def .getARead ( ) .asIndirectOperand ( indirectionIndex ) .getDef ( ) .getConvertedResultExpression ( ) ,
2852+ branch ) and
2853+ guardControlsPhiInput ( g , branch , def , input , phi ) and
2854+ result = TSsaPhiInputNode ( phi , input )
2855+ )
27572856 }
27582857}
27592858
@@ -2762,6 +2861,14 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
27622861 */
27632862signature predicate instructionGuardChecksSig ( IRGuardCondition g , Instruction instr , boolean branch ) ;
27642863
2864+ private EdgeKind getConditionalEdge ( boolean branch ) {
2865+ branch = true and
2866+ result instanceof TrueEdge
2867+ or
2868+ branch = false and
2869+ result instanceof FalseEdge
2870+ }
2871+
27652872/**
27662873 * Provides a set of barrier nodes for a guard that validates an instruction.
27672874 *
@@ -2770,12 +2877,20 @@ signature predicate instructionGuardChecksSig(IRGuardCondition g, Instruction in
27702877 */
27712878module InstructionBarrierGuard< instructionGuardChecksSig / 3 instructionGuardChecks> {
27722879 /** Gets a node that is safely guarded by the given guard check. */
2773- ExprNode getABarrierNode ( ) {
2880+ Node getABarrierNode ( ) {
27742881 exists ( IRGuardCondition g , ValueNumber value , boolean edge , Operand use |
27752882 instructionGuardChecks ( g , value .getAnInstruction ( ) , edge ) and
27762883 use = value .getAnInstruction ( ) .getAUse ( ) and
27772884 result .asOperand ( ) = use and
2778- g .controls ( use .getDef ( ) .getBlock ( ) , edge )
2885+ g .controls ( result .getBasicBlock ( ) , edge )
2886+ )
2887+ or
2888+ exists (
2889+ IRGuardCondition g , boolean branch , Ssa:: DefinitionExt def , IRBlock input , Ssa:: PhiNode phi
2890+ |
2891+ instructionGuardChecks ( g , def .getARead ( ) .asOperand ( ) .getDef ( ) , branch ) and
2892+ guardControlsPhiInput ( g , branch , def , input , phi ) and
2893+ result = TSsaPhiInputNode ( phi , input )
27792894 )
27802895 }
27812896}
0 commit comments