@@ -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
@@ -686,117 +686,45 @@ class PostFieldUpdateNode extends PostUpdateNodeImpl {
686686/**
687687 * INTERNAL: do not use.
688688 *
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.
690691 */
691- class SsaPhiNode extends Node , TSsaPhiNode {
692- Ssa:: PhiNode phi ;
692+ class SsaSynthNode extends Node , TSsaSynthNode {
693+ Ssa:: SynthNode node ;
693694
694- SsaPhiNode ( ) { this = TSsaPhiNode ( phi ) }
695+ SsaSynthNode ( ) { this = TSsaSynthNode ( node ) }
695696
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 }
698699
699700 override DataFlowCallable getEnclosingCallable ( ) {
700701 result .asSourceCallable ( ) = this .getFunction ( )
701702 }
702703
703- override Declaration getFunction ( ) { result = phi .getBasicBlock ( ) .getEnclosingFunction ( ) }
704+ override Declaration getFunction ( ) { result = node .getBasicBlock ( ) .getEnclosingFunction ( ) }
704705
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 ( ) }
711707
712- override predicate isGLValue ( ) { phi .getSourceVariable ( ) .isGLValue ( ) }
708+ override predicate isGLValue ( ) { node .getSourceVariable ( ) .isGLValue ( ) }
713709
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 ( ) }
738711
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 ( ) }
746713}
747714
748715/**
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.
771717 */
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+ )
800728}
801729
802730/**
@@ -1374,7 +1302,7 @@ class UninitializedNode extends Node {
13741302 exists ( Ssa:: Definition def , Ssa:: SourceVariable sv |
13751303 def .getIndirectionIndex ( ) = 0 and
13761304 def .getValue ( ) .asInstruction ( ) instanceof UninitializedInstruction and
1377- Ssa:: defToNode ( this , def , sv , _ , _ , _ ) and
1305+ Ssa:: defToNode ( this , def , sv ) and
13781306 v = sv .getBaseVariable ( ) .( Ssa:: BaseIRVariable ) .getIRVariable ( ) .getAst ( )
13791307 )
13801308 }
@@ -1887,15 +1815,9 @@ private module Cached {
18871815 cached
18881816 predicate simpleLocalFlowStep ( Node nodeFrom , Node nodeTo , string model ) {
18891817 (
1890- // Post update node -> Node flow
1891- Ssa:: postUpdateFlow ( nodeFrom , nodeTo )
1892- or
18931818 // Def-use/Use-use flow
18941819 Ssa:: ssaFlow ( nodeFrom , nodeTo )
18951820 or
1896- // Phi input -> Phi
1897- nodeFrom .( SsaPhiInputNode ) .getPhiNode ( ) = nodeTo .( SsaPhiNode ) .getPhiNode ( )
1898- or
18991821 IteratorFlow:: localFlowStep ( nodeFrom , nodeTo )
19001822 or
19011823 // Operand -> Instruction flow
@@ -1910,9 +1832,6 @@ private module Cached {
19101832 not iFrom = Ssa:: getIRRepresentationOfOperand ( opTo )
19111833 )
19121834 or
1913- // Phi node -> Node flow
1914- Ssa:: fromPhiNode ( nodeFrom , nodeTo )
1915- or
19161835 // Indirect operand -> (indirect) instruction flow
19171836 indirectionOperandFlow ( nodeFrom , nodeTo )
19181837 or
@@ -2356,22 +2275,6 @@ class ContentSet instanceof Content {
23562275 }
23572276}
23582277
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-
23752278/**
23762279 * Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
23772280 *
@@ -2403,6 +2306,10 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
24032306 )
24042307 }
24052308
2309+ private predicate guardChecksNode ( IRGuardCondition g , Node n , boolean branch ) {
2310+ guardChecks ( g , n .asOperand ( ) .getDef ( ) .getConvertedResultExpression ( ) , branch )
2311+ }
2312+
24062313 /**
24072314 * Gets an expression node that is safely guarded by the given guard check.
24082315 *
@@ -2443,14 +2350,7 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
24432350 controls ( g , result , edge )
24442351 )
24452352 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 ( )
24542354 }
24552355
24562356 /**
@@ -2499,6 +2399,13 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
24992399 )
25002400 }
25012401
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+
25022409 /**
25032410 * Gets an indirect expression node with indirection index `indirectionIndex` that is
25042411 * safely guarded by the given guard check.
@@ -2541,16 +2448,8 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
25412448 controls ( g , result , edge )
25422449 )
25432450 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 )
25542453 }
25552454}
25562455
@@ -2559,14 +2458,6 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
25592458 */
25602459signature predicate instructionGuardChecksSig ( IRGuardCondition g , Instruction instr , boolean branch ) ;
25612460
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-
25702461/**
25712462 * Provides a set of barrier nodes for a guard that validates an instruction.
25722463 *
@@ -2583,6 +2474,10 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
25832474 )
25842475 }
25852476
2477+ private predicate guardChecksNode ( IRGuardCondition g , Node n , boolean branch ) {
2478+ instructionGuardChecks ( g , n .asOperand ( ) .getDef ( ) , branch )
2479+ }
2480+
25862481 /** Gets a node that is safely guarded by the given guard check. */
25872482 Node getABarrierNode ( ) {
25882483 exists ( IRGuardCondition g , ValueNumber value , boolean edge |
@@ -2591,14 +2486,7 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
25912486 controls ( g , result , edge )
25922487 )
25932488 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 ( )
26022490 }
26032491
26042492 bindingset [ value, n]
@@ -2610,6 +2498,12 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
26102498 )
26112499 }
26122500
2501+ private predicate guardChecksIndirectNode (
2502+ IRGuardCondition g , Node n , boolean branch , int indirectionIndex
2503+ ) {
2504+ instructionGuardChecks ( g , n .asIndirectOperand ( indirectionIndex ) .getDef ( ) , branch )
2505+ }
2506+
26132507 /**
26142508 * Gets an indirect node with indirection index `indirectionIndex` that is
26152509 * safely guarded by the given guard check.
@@ -2621,14 +2515,8 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
26212515 controls ( g , result , edge )
26222516 )
26232517 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 )
26322520 }
26332521}
26342522
0 commit comments