@@ -27,7 +27,7 @@ import ExprNodes
2727 * - `VariableNode`, which is used to model flow through global variables.
2828 * - `PostUpdateNodeImpl`, which is used to model the state of an object after
2929 * 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
3131 * library.
3232 * - `RawIndirectOperand`, which represents the value of `operand` after
3333 * loading the address a number of times.
@@ -47,8 +47,7 @@ private newtype TIRDataFlowNode =
4747 or
4848 Ssa:: isModifiableByCall ( operand , indirectionIndex )
4949 } or
50- TSsaPhiInputNode ( Ssa:: PhiNode phi , IRBlock input ) { phi .hasInputFromBlock ( _, _, _, _, input ) } or
51- TSsaPhiNode ( Ssa:: PhiNode phi ) or
50+ TSsaSynthNode ( Ssa:: SynthNode n ) or
5251 TSsaIteratorNode ( IteratorFlow:: IteratorFlowNode n ) or
5352 TRawIndirectOperand0 ( Node0Impl node , int indirectionIndex ) {
5453 Ssa:: hasRawIndirectOperand ( node .asOperand ( ) , indirectionIndex )
@@ -184,10 +183,11 @@ class Node extends TIRDataFlowNode {
184183 or
185184 this .asOperand ( ) .getUse ( ) = block .getInstruction ( i )
186185 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+ )
191191 or
192192 this .( RawIndirectOperand ) .getOperand ( ) .getUse ( ) = block .getInstruction ( i )
193193 or
@@ -620,117 +620,45 @@ class PostFieldUpdateNode extends PostUpdateNodeImpl {
620620/**
621621 * INTERNAL: do not use.
622622 *
623- * A phi node produced by the shared SSA library, viewed as a node in a data flow graph.
623+ * A synthesized SSA node produced by the shared SSA library, viewed as a node
624+ * in a data flow graph.
624625 */
625- class SsaPhiNode extends Node , TSsaPhiNode {
626- Ssa:: PhiNode phi ;
626+ class SsaSynthNode extends Node , TSsaSynthNode {
627+ Ssa:: SynthNode node ;
627628
628- SsaPhiNode ( ) { this = TSsaPhiNode ( phi ) }
629+ SsaSynthNode ( ) { this = TSsaSynthNode ( node ) }
629630
630- /** Gets the phi node associated with this node. */
631- Ssa:: PhiNode getPhiNode ( ) { result = phi }
631+ /** Gets the synthesized SSA node associated with this node. */
632+ Ssa:: SynthNode getSynthNode ( ) { result = node }
632633
633634 override DataFlowCallable getEnclosingCallable ( ) {
634635 result .asSourceCallable ( ) = this .getFunction ( )
635636 }
636637
637- override Declaration getFunction ( ) { result = phi .getBasicBlock ( ) .getEnclosingFunction ( ) }
638+ override Declaration getFunction ( ) { result = node .getBasicBlock ( ) .getEnclosingFunction ( ) }
638639
639- override DataFlowType getType ( ) {
640- exists ( Ssa:: SourceVariable sv |
641- this .getPhiNode ( ) .definesAt ( sv , _, _, _) and
642- result = sv .getType ( )
643- )
644- }
640+ override DataFlowType getType ( ) { result = node .getSourceVariable ( ) .getType ( ) }
645641
646- override predicate isGLValue ( ) { phi .getSourceVariable ( ) .isGLValue ( ) }
642+ override predicate isGLValue ( ) { node .getSourceVariable ( ) .isGLValue ( ) }
647643
648- final override Location getLocationImpl ( ) { result = phi .getBasicBlock ( ) .getLocation ( ) }
649-
650- override string toStringImpl ( ) { result = phi .toString ( ) }
651-
652- /**
653- * Gets a node that is used as input to this phi node.
654- * `fromBackEdge` is true if data flows along a back-edge,
655- * and `false` otherwise.
656- */
657- cached
658- final Node getAnInput ( boolean fromBackEdge ) {
659- result .( SsaPhiInputNode ) .getPhiNode ( ) = phi and
660- exists ( IRBlock bPhi , IRBlock bResult |
661- bPhi = phi .getBasicBlock ( ) and bResult = result .getBasicBlock ( )
662- |
663- if bPhi .dominates ( bResult ) then fromBackEdge = true else fromBackEdge = false
664- )
665- }
666-
667- /** Gets a node that is used as input to this phi node. */
668- final Node getAnInput ( ) { result = this .getAnInput ( _) }
669-
670- /** Gets the source variable underlying this phi node. */
671- Ssa:: SourceVariable getSourceVariable ( ) { result = phi .getSourceVariable ( ) }
644+ final override Location getLocationImpl ( ) { result = node .getLocation ( ) }
672645
673- /**
674- * Holds if this phi node is a phi-read node.
675- *
676- * Phi-read nodes are like normal phi nodes, but they are inserted based
677- * on reads instead of writes.
678- */
679- predicate isPhiRead ( ) { phi .isPhiRead ( ) }
646+ override string toStringImpl ( ) { result = node .toString ( ) }
680647}
681648
682649/**
683- * INTERNAL: Do not use.
684- *
685- * A node that is used as an input to a phi node.
686- *
687- * This class exists to allow more powerful barrier guards. Consider this
688- * example:
689- *
690- * ```cpp
691- * int x = source();
692- * if(!safe(x)) {
693- * x = clear();
694- * }
695- * // phi node for x here
696- * sink(x);
697- * ```
698- *
699- * At the phi node for `x` it is neither the case that `x` is dominated by
700- * `safe(x)`, or is the case that the phi is dominated by a clearing of `x`.
701- *
702- * By inserting a "phi input" node as the last entry in the basic block that
703- * defines the inputs to the phi we can conclude that each of those inputs are
704- * safe to pass to `sink`.
650+ * Holds if `n` has a local flow step that goes through a back-edge.
705651 */
706- class SsaPhiInputNode extends Node , TSsaPhiInputNode {
707- Ssa:: PhiNode phi ;
708- IRBlock block ;
709-
710- SsaPhiInputNode ( ) { this = TSsaPhiInputNode ( phi , block ) }
711-
712- /** Gets the phi node associated with this node. */
713- Ssa:: PhiNode getPhiNode ( ) { result = phi }
714-
715- /** Gets the basic block in which this input originates. */
716- IRBlock getBlock ( ) { result = block }
717-
718- override DataFlowCallable getEnclosingCallable ( ) {
719- result .asSourceCallable ( ) = this .getFunction ( )
720- }
721-
722- override Declaration getFunction ( ) { result = phi .getBasicBlock ( ) .getEnclosingFunction ( ) }
723-
724- override DataFlowType getType ( ) { result = this .getSourceVariable ( ) .getType ( ) }
725-
726- override predicate isGLValue ( ) { phi .getSourceVariable ( ) .isGLValue ( ) }
727-
728- final override Location getLocationImpl ( ) { result = block .getLastInstruction ( ) .getLocation ( ) }
729-
730- override string toStringImpl ( ) { result = "Phi input" }
731-
732- /** Gets the source variable underlying this phi node. */
733- Ssa:: SourceVariable getSourceVariable ( ) { result = phi .getSourceVariable ( ) }
652+ cached
653+ predicate flowsToBackEdge ( Node n ) {
654+ exists ( Node succ , IRBlock bb1 , IRBlock bb2 |
655+ Ssa:: ssaFlow ( n , succ ) and
656+ bb1 = n .getBasicBlock ( ) and
657+ bb2 = succ .getBasicBlock ( ) and
658+ bb1 != bb2 and
659+ bb2 .dominates ( bb1 ) and
660+ bb1 .getASuccessor + ( ) = bb2
661+ )
734662}
735663
736664/**
@@ -1308,7 +1236,7 @@ class UninitializedNode extends Node {
13081236 exists ( Ssa:: Definition def , Ssa:: SourceVariable sv |
13091237 def .getIndirectionIndex ( ) = 0 and
13101238 def .getValue ( ) .asInstruction ( ) instanceof UninitializedInstruction and
1311- Ssa:: defToNode ( this , def , sv , _ , _ , _ ) and
1239+ Ssa:: defToNode ( this , def , sv ) and
13121240 v = sv .getBaseVariable ( ) .( Ssa:: BaseIRVariable ) .getIRVariable ( ) .getAst ( )
13131241 )
13141242 }
@@ -1821,15 +1749,9 @@ private module Cached {
18211749 cached
18221750 predicate simpleLocalFlowStep ( Node nodeFrom , Node nodeTo , string model ) {
18231751 (
1824- // Post update node -> Node flow
1825- Ssa:: postUpdateFlow ( nodeFrom , nodeTo )
1826- or
18271752 // Def-use/Use-use flow
18281753 Ssa:: ssaFlow ( nodeFrom , nodeTo )
18291754 or
1830- // Phi input -> Phi
1831- nodeFrom .( SsaPhiInputNode ) .getPhiNode ( ) = nodeTo .( SsaPhiNode ) .getPhiNode ( )
1832- or
18331755 IteratorFlow:: localFlowStep ( nodeFrom , nodeTo )
18341756 or
18351757 // Operand -> Instruction flow
@@ -1844,9 +1766,6 @@ private module Cached {
18441766 not iFrom = Ssa:: getIRRepresentationOfOperand ( opTo )
18451767 )
18461768 or
1847- // Phi node -> Node flow
1848- Ssa:: fromPhiNode ( nodeFrom , nodeTo )
1849- or
18501769 // Indirect operand -> (indirect) instruction flow
18511770 indirectionOperandFlow ( nodeFrom , nodeTo )
18521771 or
@@ -2290,22 +2209,6 @@ class ContentSet instanceof Content {
22902209 }
22912210}
22922211
2293- pragma [ nomagic]
2294- private predicate guardControlsPhiInput (
2295- IRGuardCondition g , boolean branch , Ssa:: DefinitionExt def , IRBlock input , Ssa:: PhiNode phi
2296- ) {
2297- phi .hasInputFromBlock ( def , _, _, _, input ) and
2298- (
2299- g .controls ( input , branch )
2300- or
2301- exists ( EdgeKind kind |
2302- g .getBlock ( ) = input and
2303- kind = getConditionalEdge ( branch ) and
2304- input .getSuccessor ( kind ) = phi .getBasicBlock ( )
2305- )
2306- )
2307- }
2308-
23092212/**
23102213 * Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
23112214 *
@@ -2337,6 +2240,10 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
23372240 )
23382241 }
23392242
2243+ private predicate guardChecksNode ( IRGuardCondition g , Node n , boolean branch ) {
2244+ guardChecks ( g , n .asOperand ( ) .getDef ( ) .getConvertedResultExpression ( ) , branch )
2245+ }
2246+
23402247 /**
23412248 * Gets an expression node that is safely guarded by the given guard check.
23422249 *
@@ -2377,14 +2284,7 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
23772284 controls ( g , result , edge )
23782285 )
23792286 or
2380- exists (
2381- IRGuardCondition g , boolean branch , Ssa:: DefinitionExt def , IRBlock input , Ssa:: PhiNode phi
2382- |
2383- guardChecks ( g , def .getARead ( ) .asOperand ( ) .getDef ( ) .getConvertedResultExpression ( ) , branch ) and
2384- guardControlsPhiInput ( g , branch , def , pragma [ only_bind_into ] ( input ) ,
2385- pragma [ only_bind_into ] ( phi ) ) and
2386- result = TSsaPhiInputNode ( phi , input )
2387- )
2287+ result = Ssa:: BarrierGuard< guardChecksNode / 3 > :: getABarrierNode ( )
23882288 }
23892289
23902290 /**
@@ -2433,6 +2333,13 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
24332333 )
24342334 }
24352335
2336+ private predicate guardChecksIndirectNode (
2337+ IRGuardCondition g , Node n , boolean branch , int indirectionIndex
2338+ ) {
2339+ guardChecks ( g , n .asIndirectOperand ( indirectionIndex ) .getDef ( ) .getConvertedResultExpression ( ) ,
2340+ branch )
2341+ }
2342+
24362343 /**
24372344 * Gets an indirect expression node with indirection index `indirectionIndex` that is
24382345 * safely guarded by the given guard check.
@@ -2475,16 +2382,8 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
24752382 controls ( g , result , edge )
24762383 )
24772384 or
2478- exists (
2479- IRGuardCondition g , boolean branch , Ssa:: DefinitionExt def , IRBlock input , Ssa:: PhiNode phi
2480- |
2481- guardChecks ( g ,
2482- def .getARead ( ) .asIndirectOperand ( indirectionIndex ) .getDef ( ) .getConvertedResultExpression ( ) ,
2483- branch ) and
2484- guardControlsPhiInput ( g , branch , def , pragma [ only_bind_into ] ( input ) ,
2485- pragma [ only_bind_into ] ( phi ) ) and
2486- result = TSsaPhiInputNode ( phi , input )
2487- )
2385+ result =
2386+ Ssa:: BarrierGuardWithIntParam< guardChecksIndirectNode / 4 > :: getABarrierNode ( indirectionIndex )
24882387 }
24892388}
24902389
@@ -2493,14 +2392,6 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
24932392 */
24942393signature predicate instructionGuardChecksSig ( IRGuardCondition g , Instruction instr , boolean branch ) ;
24952394
2496- private EdgeKind getConditionalEdge ( boolean branch ) {
2497- branch = true and
2498- result instanceof TrueEdge
2499- or
2500- branch = false and
2501- result instanceof FalseEdge
2502- }
2503-
25042395/**
25052396 * Provides a set of barrier nodes for a guard that validates an instruction.
25062397 *
@@ -2517,6 +2408,10 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
25172408 )
25182409 }
25192410
2411+ private predicate guardChecksNode ( IRGuardCondition g , Node n , boolean branch ) {
2412+ instructionGuardChecks ( g , n .asOperand ( ) .getDef ( ) , branch )
2413+ }
2414+
25202415 /** Gets a node that is safely guarded by the given guard check. */
25212416 Node getABarrierNode ( ) {
25222417 exists ( IRGuardCondition g , ValueNumber value , boolean edge |
@@ -2525,14 +2420,7 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
25252420 controls ( g , result , edge )
25262421 )
25272422 or
2528- exists (
2529- IRGuardCondition g , boolean branch , Ssa:: DefinitionExt def , IRBlock input , Ssa:: PhiNode phi
2530- |
2531- instructionGuardChecks ( g , def .getARead ( ) .asOperand ( ) .getDef ( ) , branch ) and
2532- guardControlsPhiInput ( g , branch , def , pragma [ only_bind_into ] ( input ) ,
2533- pragma [ only_bind_into ] ( phi ) ) and
2534- result = TSsaPhiInputNode ( phi , input )
2535- )
2423+ result = Ssa:: BarrierGuard< guardChecksNode / 3 > :: getABarrierNode ( )
25362424 }
25372425
25382426 bindingset [ value, n]
@@ -2544,6 +2432,12 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
25442432 )
25452433 }
25462434
2435+ private predicate guardChecksIndirectNode (
2436+ IRGuardCondition g , Node n , boolean branch , int indirectionIndex
2437+ ) {
2438+ instructionGuardChecks ( g , n .asIndirectOperand ( indirectionIndex ) .getDef ( ) , branch )
2439+ }
2440+
25472441 /**
25482442 * Gets an indirect node with indirection index `indirectionIndex` that is
25492443 * safely guarded by the given guard check.
@@ -2555,14 +2449,8 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
25552449 controls ( g , result , edge )
25562450 )
25572451 or
2558- exists (
2559- IRGuardCondition g , boolean branch , Ssa:: DefinitionExt def , IRBlock input , Ssa:: PhiNode phi
2560- |
2561- instructionGuardChecks ( g , def .getARead ( ) .asIndirectOperand ( indirectionIndex ) .getDef ( ) , branch ) and
2562- guardControlsPhiInput ( g , branch , def , pragma [ only_bind_into ] ( input ) ,
2563- pragma [ only_bind_into ] ( phi ) ) and
2564- result = TSsaPhiInputNode ( phi , input )
2565- )
2452+ result =
2453+ Ssa:: BarrierGuardWithIntParam< guardChecksIndirectNode / 4 > :: getABarrierNode ( indirectionIndex )
25662454 }
25672455}
25682456
0 commit comments