From 34554fd000176461e7c995896eb5ed10a933ff1f Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Mon, 31 Mar 2025 13:25:42 +0200 Subject: [PATCH 1/3] SSA: Deprecate the public DefinitionExt. --- shared/ssa/codeql/ssa/Ssa.qll | 185 ++++++++++++++++++++-------------- 1 file changed, 107 insertions(+), 78 deletions(-) diff --git a/shared/ssa/codeql/ssa/Ssa.qll b/shared/ssa/codeql/ssa/Ssa.qll index 36895a28a8b6..dab99df65b4d 100644 --- a/shared/ssa/codeql/ssa/Ssa.qll +++ b/shared/ssa/codeql/ssa/Ssa.qll @@ -608,21 +608,21 @@ module Make Input> { } private module SsaDefReaches { - newtype TSsaRefKind = + deprecated newtype TSsaRefKind = SsaActualRead() or SsaPhiRead() or SsaDef() - class SsaRead = SsaActualRead or SsaPhiRead; + deprecated class SsaRead = SsaActualRead or SsaPhiRead; - class SsaDefExt = SsaDef or SsaPhiRead; + deprecated class SsaDefExt = SsaDef or SsaPhiRead; - SsaDefExt ssaDefExt() { any() } + deprecated SsaDefExt ssaDefExt() { any() } /** * A classification of SSA variable references into reads and definitions. */ - class SsaRefKind extends TSsaRefKind { + deprecated class SsaRefKind extends TSsaRefKind { string toString() { this = SsaActualRead() and result = "SsaActualRead" @@ -651,7 +651,7 @@ module Make Input> { * Unlike `Liveness::varRef`, this includes `phi` (read) nodes. */ pragma[nomagic] - predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) { + deprecated predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) { variableRead(bb, i, v, _) and k = SsaActualRead() or @@ -665,14 +665,14 @@ module Make Input> { * Holds if the `i`th node of basic block `bb` is a reference to `v`, and * this reference is not a phi-read. */ - predicate ssaRefNonPhiRead(BasicBlock bb, int i, SourceVariable v) { + deprecated predicate ssaRefNonPhiRead(BasicBlock bb, int i, SourceVariable v) { ssaRef(bb, i, v, [SsaActualRead().(TSsaRefKind), SsaDef()]) } - private newtype OrderedSsaRefIndex = - MkOrderedSsaRefIndex(int i, SsaRefKind k) { ssaRef(_, i, _, k) } + deprecated private newtype OrderedSsaRefIndex = + deprecated MkOrderedSsaRefIndex(int i, SsaRefKind k) { ssaRef(_, i, _, k) } - private OrderedSsaRefIndex ssaRefOrd( + deprecated private OrderedSsaRefIndex ssaRefOrd( BasicBlock bb, int i, SourceVariable v, SsaRefKind k, int ord ) { ssaRef(bb, i, v, k) and @@ -695,7 +695,7 @@ module Make Input> { * * Reads are considered before writes when they happen at the same index. */ - int ssaRefRank(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) { + deprecated int ssaRefRank(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) { ssaRefOrd(bb, i, v, k, _) = rank[result](int j, int ord, OrderedSsaRefIndex res | res = ssaRefOrd(bb, j, v, _, ord) @@ -704,7 +704,7 @@ module Make Input> { ) } - int maxSsaRefRank(BasicBlock bb, SourceVariable v) { + deprecated int maxSsaRefRank(BasicBlock bb, SourceVariable v) { result = ssaRefRank(bb, _, v, _) and not result + 1 = ssaRefRank(bb, _, v, _) } @@ -713,7 +713,9 @@ module Make Input> { * Holds if the SSA definition `def` reaches rank index `rnk` in its own * basic block `bb`. */ - predicate ssaDefReachesRank(BasicBlock bb, DefinitionExt def, int rnk, SourceVariable v) { + deprecated predicate ssaDefReachesRank( + BasicBlock bb, DefinitionExt def, int rnk, SourceVariable v + ) { exists(int i | rnk = ssaRefRank(bb, i, v, ssaDefExt()) and def.definesAt(v, bb, i, _) @@ -727,7 +729,9 @@ module Make Input> { * Holds if the SSA definition of `v` at `def` reaches index `i` in the same * basic block `bb`, without crossing another SSA definition of `v`. */ - predicate ssaDefReachesReadWithinBlock(SourceVariable v, DefinitionExt def, BasicBlock bb, int i) { + deprecated predicate ssaDefReachesReadWithinBlock( + SourceVariable v, DefinitionExt def, BasicBlock bb, int i + ) { exists(int rnk | ssaDefReachesRank(bb, def, rnk, v) and rnk = ssaRefRank(bb, i, v, SsaActualRead()) @@ -737,7 +741,9 @@ module Make Input> { /** * Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`. */ - int ssaDefRank(DefinitionExt def, SourceVariable v, BasicBlock bb, int i, SsaRefKind k) { + deprecated int ssaDefRank( + DefinitionExt def, SourceVariable v, BasicBlock bb, int i, SsaRefKind k + ) { result = ssaRefRank(bb, i, v, k) and ( ssaDefReachesReadExt(v, def, bb, i) @@ -751,34 +757,38 @@ module Make Input> { * last reference to `v` inside `bb`. */ pragma[noinline] - predicate lastSsaRefExt(DefinitionExt def, SourceVariable v, BasicBlock bb, int i) { + deprecated predicate lastSsaRefExt(DefinitionExt def, SourceVariable v, BasicBlock bb, int i) { ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v) } /** Gets a phi-read node into which `inp` is an input, if any. */ pragma[nomagic] - private DefinitionExt getAPhiReadOutput(DefinitionExt inp) { + deprecated private DefinitionExt getAPhiReadOutput(DefinitionExt inp) { phiHasInputFromBlockExt(result.(PhiReadNode), inp, _) } pragma[nomagic] - DefinitionExt getAnUltimateOutput(Definition def) { result = getAPhiReadOutput*(def) } + deprecated DefinitionExt getAnUltimateOutput(Definition def) { + result = getAPhiReadOutput*(def) + } /** * Same as `lastSsaRefExt`, but ignores phi-reads. */ pragma[noinline] - predicate lastSsaRef(Definition def, SourceVariable v, BasicBlock bb, int i) { + deprecated predicate lastSsaRef(Definition def, SourceVariable v, BasicBlock bb, int i) { lastSsaRefExt(getAnUltimateOutput(def), v, bb, i) and ssaRefNonPhiRead(bb, i, v) } - predicate defOccursInBlock(DefinitionExt def, BasicBlock bb, SourceVariable v, SsaRefKind k) { + deprecated predicate defOccursInBlock( + DefinitionExt def, BasicBlock bb, SourceVariable v, SsaRefKind k + ) { exists(ssaDefRank(def, v, bb, _, k)) } pragma[noinline] - predicate ssaDefReachesThroughBlock(DefinitionExt def, BasicBlock bb) { + deprecated predicate ssaDefReachesThroughBlock(DefinitionExt def, BasicBlock bb) { exists(SourceVariable v | ssaDefReachesEndOfBlockExt0(bb, def, v) and not defOccursInBlock(_, bb, v, _) @@ -792,7 +802,9 @@ module Make Input> { * nor written in any block on the path between `bb1` and `bb2`. */ pragma[nomagic] - predicate varBlockReachesExt(DefinitionExt def, SourceVariable v, BasicBlock bb1, BasicBlock bb2) { + deprecated predicate varBlockReachesExt( + DefinitionExt def, SourceVariable v, BasicBlock bb1, BasicBlock bb2 + ) { defOccursInBlock(def, bb1, v, _) and bb2 = getABasicBlockSuccessor(bb1) or @@ -804,7 +816,9 @@ module Make Input> { } pragma[nomagic] - private predicate phiReadStep(DefinitionExt def, PhiReadNode phi, BasicBlock bb1, BasicBlock bb2) { + deprecated private predicate phiReadStep( + DefinitionExt def, PhiReadNode phi, BasicBlock bb1, BasicBlock bb2 + ) { exists(SourceVariable v | varBlockReachesExt(pragma[only_bind_into](def), v, bb1, pragma[only_bind_into](bb2)) and phi.definesAt(v, bb2, _, _) and @@ -813,7 +827,7 @@ module Make Input> { } pragma[nomagic] - private predicate varBlockReachesExclPhiRead( + deprecated private predicate varBlockReachesExclPhiRead( DefinitionExt def, SourceVariable v, BasicBlock bb1, BasicBlock bb2 ) { varBlockReachesExt(def, v, bb1, bb2) and @@ -831,13 +845,17 @@ module Make Input> { * `def` is referenced (either a read or a write). */ pragma[nomagic] - predicate varBlockReachesRef(Definition def, SourceVariable v, BasicBlock bb1, BasicBlock bb2) { + deprecated predicate varBlockReachesRef( + Definition def, SourceVariable v, BasicBlock bb1, BasicBlock bb2 + ) { varBlockReachesExclPhiRead(getAnUltimateOutput(def), v, bb1, bb2) and ssaRefNonPhiRead(bb1, _, v) } pragma[nomagic] - predicate defAdjacentReadExt(DefinitionExt def, BasicBlock bb1, BasicBlock bb2, int i2) { + deprecated predicate defAdjacentReadExt( + DefinitionExt def, BasicBlock bb1, BasicBlock bb2, int i2 + ) { exists(SourceVariable v | varBlockReachesExt(def, v, bb1, bb2) and ssaRefRank(bb2, i2, v, SsaActualRead()) = 1 @@ -845,7 +863,7 @@ module Make Input> { } pragma[nomagic] - predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) { + deprecated predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) { exists(SourceVariable v | varBlockReachesRef(def, v, bb1, bb2) | ssaRefRank(bb2, i2, v, SsaActualRead()) = 1 or @@ -861,7 +879,7 @@ module Make Input> { * and `bb2`. */ pragma[nomagic] - predicate varBlockReachesExitExt(DefinitionExt def, BasicBlock bb) { + deprecated predicate varBlockReachesExitExt(DefinitionExt def, BasicBlock bb) { exists(BasicBlock bb2 | varBlockReachesExt(def, _, bb, bb2) | not defOccursInBlock(def, bb2, _, _) and not ssaDefReachesEndOfBlockExt0(bb2, def, _) @@ -869,7 +887,7 @@ module Make Input> { } pragma[nomagic] - private predicate varBlockReachesExitExclPhiRead(DefinitionExt def, BasicBlock bb) { + deprecated private predicate varBlockReachesExitExclPhiRead(DefinitionExt def, BasicBlock bb) { exists(BasicBlock bb2, SourceVariable v | varBlockReachesExt(def, v, bb, bb2) and not defOccursInBlock(def, bb2, _, _) and @@ -887,7 +905,7 @@ module Make Input> { * Same as `varBlockReachesExitExt`, but ignores phi-reads. */ pragma[nomagic] - predicate varBlockReachesExit(Definition def, BasicBlock bb) { + deprecated predicate varBlockReachesExit(Definition def, BasicBlock bb) { varBlockReachesExitExclPhiRead(getAnUltimateOutput(def), bb) } } @@ -895,7 +913,7 @@ module Make Input> { private import SsaDefReaches pragma[nomagic] - private predicate liveThroughExt(BasicBlock bb, SourceVariable v) { + deprecated private predicate liveThroughExt(BasicBlock bb, SourceVariable v) { liveAtExit(bb, v) and not ssaRef(bb, _, v, ssaDefExt()) } @@ -908,7 +926,9 @@ module Make Input> { * SSA definition of `v`. */ pragma[nomagic] - private predicate ssaDefReachesEndOfBlockExt0(BasicBlock bb, DefinitionExt def, SourceVariable v) { + deprecated private predicate ssaDefReachesEndOfBlockExt0( + BasicBlock bb, DefinitionExt def, SourceVariable v + ) { exists(int last | last = maxSsaRefRank(pragma[only_bind_into](bb), pragma[only_bind_into](v)) and ssaDefReachesRank(bb, def, last, v) and @@ -954,7 +974,7 @@ module Make Input> { * Holds if `inp` is an input to the phi (read) node `phi` along the edge originating in `bb`. */ pragma[nomagic] - predicate phiHasInputFromBlockExt(DefinitionExt phi, DefinitionExt inp, BasicBlock bb) { + deprecated predicate phiHasInputFromBlockExt(DefinitionExt phi, DefinitionExt inp, BasicBlock bb) { exists(SourceVariable v, BasicBlock bbDef | phi.definesAt(v, bbDef, _, _) and getABasicBlockPredecessor(bbDef) = bb and @@ -972,7 +992,9 @@ module Make Input> { * basic block `bb`, without crossing another SSA definition of `v`. */ pragma[nomagic] - predicate ssaDefReachesReadExt(SourceVariable v, DefinitionExt def, BasicBlock bb, int i) { + deprecated predicate ssaDefReachesReadExt( + SourceVariable v, DefinitionExt def, BasicBlock bb, int i + ) { ssaDefReachesReadWithinBlock(v, def, bb, i) or ssaRef(bb, i, v, SsaActualRead()) and @@ -998,7 +1020,7 @@ module Make Input> { * path between them without any read of `def`. */ pragma[nomagic] - predicate adjacentDefReadExt( + deprecated predicate adjacentDefReadExt( DefinitionExt def, SourceVariable v, BasicBlock bb1, int i1, BasicBlock bb2, int i2 ) { exists(int rnk | @@ -1018,7 +1040,9 @@ module Make Input> { * Same as `adjacentDefReadExt`, but ignores phi-reads. */ pragma[nomagic] - predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) { + deprecated predicate adjacentDefRead( + Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2 + ) { exists(SourceVariable v | adjacentDefReadExt(getAnUltimateOutput(def), v, bb1, i1, bb2, i2) and ssaRefNonPhiRead(bb1, i1, v) @@ -1028,7 +1052,7 @@ module Make Input> { defAdjacentRead(def, bb1, bb2, i2) } - private predicate lastRefRedefExtSameBlock( + deprecated private predicate lastRefRedefExtSameBlock( DefinitionExt def, SourceVariable v, BasicBlock bb, int i, DefinitionExt next ) { exists(int rnk, int j | @@ -1046,7 +1070,7 @@ module Make Input> { * without passing through another read or write. */ pragma[nomagic] - predicate lastRefRedefExt( + deprecated predicate lastRefRedefExt( DefinitionExt def, SourceVariable v, BasicBlock bb, int i, DefinitionExt next ) { // Next reference to `v` inside `bb` is a write @@ -1072,7 +1096,7 @@ module Make Input> { * occurs in basic block `bb`. */ pragma[nomagic] - predicate lastRefRedefExt( + deprecated predicate lastRefRedefExt( DefinitionExt def, SourceVariable v, BasicBlock bb, int i, BasicBlock input, DefinitionExt next ) { // Next reference to `v` inside `bb` is a write @@ -1098,7 +1122,7 @@ module Make Input> { * Same as `lastRefRedefExt`, but ignores phi-reads. */ pragma[nomagic] - predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) { + deprecated predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) { exists(SourceVariable v | lastRefRedefExt(getAnUltimateOutput(def), v, bb, i, next) and ssaRefNonPhiRead(bb, i, v) @@ -1228,30 +1252,43 @@ module Make Input> { } } + deprecated class DefinitionExt = DefinitionExt_; + /** * An extended static single assignment (SSA) definition. * * This is either a normal SSA definition (`Definition`) or a * phi-read node (`PhiReadNode`). */ - class DefinitionExt extends TDefinitionExt { + private class DefinitionExt_ extends TDefinitionExt { /** Gets the source variable underlying this SSA definition. */ - SourceVariable getSourceVariable() { this.definesAt(result, _, _, _) } + SourceVariable getSourceVariable() { this.definesAt(result, _, _) } /** * Holds if this SSA definition defines `v` at index `i` in basic block `bb`. * Phi nodes are considered to be at index `-1`, while normal variable writes * are at the index of the control flow node they wrap. */ - final predicate definesAt(SourceVariable v, BasicBlock bb, int i, SsaRefKind kind) { + deprecated final predicate definesAt(SourceVariable v, BasicBlock bb, int i, SsaRefKind kind) { this.(Definition).definesAt(v, bb, i) and kind = SsaDef() or this = TPhiReadNode(v, bb) and i = -1 and kind = SsaPhiRead() } + /** + * Holds if this SSA definition defines `v` at index `i` in basic block `bb`. + * Phi nodes are considered to be at index `-1`, while normal variable writes + * are at the index of the control flow node they wrap. + */ + final predicate definesAt(SourceVariable v, BasicBlock bb, int i) { + this.(Definition).definesAt(v, bb, i) + or + this = TPhiReadNode(v, bb) and i = -1 + } + /** Gets the basic block to which this SSA definition belongs. */ - final BasicBlock getBasicBlock() { this.definesAt(_, result, _, _) } + final BasicBlock getBasicBlock() { this.definesAt(_, result, _) } /** Gets a textual representation of this SSA definition. */ string toString() { result = this.(Definition).toString() } @@ -1260,6 +1297,8 @@ module Make Input> { Location getLocation() { result = this.(Definition).getLocation() } } + deprecated class PhiReadNode = PhiReadNode_; + /** * A phi-read node. * @@ -1341,7 +1380,7 @@ module Make Input> { * to `phi-read` goes through a dominance-frontier block, and hence a phi node, * which contradicts reachability. */ - class PhiReadNode extends DefinitionExt, TPhiReadNode { + private class PhiReadNode_ extends DefinitionExt_, TPhiReadNode { override string toString() { result = "SSA phi read(" + this.getSourceVariable() + ")" } override Location getLocation() { result = this.getBasicBlock().getLocation() } @@ -1369,18 +1408,6 @@ module Make Input> { not uncertainWriteDefinitionInput(_, def) } - /** Holds if a read is not dominated by a definition. */ - query predicate notDominatedByDef(Definition def, SourceVariable v, BasicBlock bb, int i) { - exists(BasicBlock bbDef, int iDef | def.definesAt(v, bbDef, iDef) | - ssaDefReachesReadWithinBlock(v, def, bb, i) and - (bb != bbDef or i < iDef) - or - ssaDefReachesRead(v, def, bb, i) and - not ssaDefReachesReadWithinBlock(v, def, bb, i) and - not def.definesAt(v, getImmediateBasicBlockDominator*(bb), _) - ) - } - /** Holds if the end of a basic block can be reached by multiple definitions. */ query predicate nonUniqueDefReachesEndOfBlock(Definition def, SourceVariable v, BasicBlock bb) { ssaDefReachesEndOfBlock(bb, def, v) and @@ -1525,21 +1552,21 @@ module Make Input> { module DataFlowIntegration { private import codeql.util.Boolean - final private class DefinitionExtFinal = DefinitionExt; + final private class DefinitionExtFinal = DefinitionExt_; /** An SSA definition which is either a phi node or a phi read node. */ private class SsaPhiExt extends DefinitionExtFinal { SsaPhiExt() { this instanceof PhiNode or - this instanceof PhiReadNode + this instanceof PhiReadNode_ } } cached private Definition getAPhiInputDef(SsaPhiExt phi, BasicBlock bb) { exists(SourceVariable v, BasicBlock bbDef | - phi.definesAt(v, bbDef, _, _) and + phi.definesAt(v, bbDef, _) and getABasicBlockPredecessor(bbDef) = bb and ssaDefReachesEndOfBlock(bb, result, v) ) @@ -1612,9 +1639,9 @@ module Make Input> { SsaPhiExt phi, SsaPhiExt phi2, BasicBlock input, boolean relevant ) { exists(BasicBlock bb1, int i, SourceVariable v, BasicBlock bb2 | - phi.definesAt(pragma[only_bind_into](v), bb1, i, _) and + phi.definesAt(pragma[only_bind_into](v), bb1, i) and AdjacentSsaRefs::adjacentRefPhi(bb1, i, input, bb2, v) and - phi2.definesAt(pragma[only_bind_into](v), bb2, _, _) and + phi2.definesAt(pragma[only_bind_into](v), bb2, _) and if relevantPhiInputNode(phi2, input) then relevant = true else relevant = false ) } @@ -1626,7 +1653,7 @@ module Make Input> { */ private predicate phiStepsToRef(SsaPhiExt phi, BasicBlock bb, int i, boolean isUse) { exists(SourceVariable v, BasicBlock bb1, int i1 | - phi.definesAt(v, bb1, i1, _) and + phi.definesAt(v, bb1, i1) and AdjacentSsaRefs::adjacentRefRead(bb1, i1, bb, i, v) | isUse = true and @@ -1660,13 +1687,13 @@ module Make Input> { private newtype TNode = TWriteDefSource(WriteDefinition def) { DfInput::ssaDefHasSource(def) } or TExprNode(DfInput::Expr e, Boolean isPost) { e = DfInput::getARead(_) } or - TSsaDefinitionNode(DefinitionExt def) { + TSsaDefinitionNode(DefinitionExt_ def) { not phiHasUniqNextNode(def) and if DfInput::includeWriteDefsInFlowStep() then any() else ( def instanceof PhiNode or - def instanceof PhiReadNode or + def instanceof PhiReadNode_ or DfInput::allowFlowIntoUncertainDef(def) ) } or @@ -1792,18 +1819,18 @@ module Make Input> { /** An SSA definition, viewed as a node in a data flow graph. */ private class SsaDefinitionExtNodeImpl extends SsaNodeImpl, TSsaDefinitionNode { - private DefinitionExt def; + private DefinitionExt_ def; SsaDefinitionExtNodeImpl() { this = TSsaDefinitionNode(def) } /** Gets the corresponding `DefinitionExt`. */ - DefinitionExt getDefExt() { result = def } + DefinitionExt_ getDefExt() { result = def } deprecated override DefinitionExt getDefinitionExt() { result = def } override BasicBlock getBasicBlock() { result = def.getBasicBlock() } - override int getIndex() { def.definesAt(_, _, result, _) } + override int getIndex() { def.definesAt(_, _, result) } override SourceVariable getSourceVariable() { result = def.getSourceVariable() } @@ -1829,7 +1856,7 @@ module Make Input> { /** A node that represents a synthetic read of a source variable. */ final class SsaSynthReadNode extends SsaNode { SsaSynthReadNode() { - this.(SsaDefinitionExtNodeImpl).getDefExt() instanceof PhiReadNode or + this.(SsaDefinitionExtNodeImpl).getDefExt() instanceof PhiReadNode_ or this instanceof SsaInputNodeImpl } } @@ -1876,7 +1903,7 @@ module Make Input> { SsaInputNodeImpl() { this = TSsaInputNode(def_, input_) } /** Holds if this node represents input into SSA definition `def` via basic block `input`. */ - predicate isInputInto(DefinitionExt def, BasicBlock input) { + predicate isInputInto(DefinitionExt_ def, BasicBlock input) { def = def_ and input = input_ } @@ -1907,9 +1934,9 @@ module Make Input> { private predicate flowOutOf( Node nodeFrom, SourceVariable v, BasicBlock bb, int i, boolean isUseStep ) { - exists(DefinitionExt def | + exists(DefinitionExt_ def | nodeFrom.(SsaDefinitionExtNodeImpl).getDefExt() = def and - def.definesAt(v, bb, i, _) and + def.definesAt(v, bb, i) and isUseStep = false ) or @@ -1935,9 +1962,9 @@ module Make Input> { ) or // Flow from definition/read to phi input - exists(BasicBlock input, BasicBlock bbPhi, DefinitionExt phi | + exists(BasicBlock input, BasicBlock bbPhi, DefinitionExt_ phi | AdjacentSsaRefs::adjacentRefPhi(bb1, i1, input, bbPhi, v) and - phi.definesAt(v, bbPhi, -1, _) + phi.definesAt(v, bbPhi, -1) | if relevantPhiInputNode(phi, input) then nodeTo = TSsaInputNode(phi, input) @@ -1945,8 +1972,10 @@ module Make Input> { ) } - private predicate flowIntoPhi(DefinitionExt phi, SourceVariable v, BasicBlock bbPhi, Node nodeTo) { - phi.definesAt(v, bbPhi, -1, _) and + private predicate flowIntoPhi( + DefinitionExt_ phi, SourceVariable v, BasicBlock bbPhi, Node nodeTo + ) { + phi.definesAt(v, bbPhi, -1) and if phiHasUniqNextNode(phi) then flowFromRefToNode(v, bbPhi, -1, nodeTo) else nodeTo.(SsaDefinitionExtNodeImpl).getDefExt() = phi @@ -1981,7 +2010,7 @@ module Make Input> { ) or // Flow from input node to def - exists(DefinitionExt phi | + exists(DefinitionExt_ phi | phi = nodeFrom.(SsaInputNodeImpl).getPhi() and isUseStep = false and nodeFrom != nodeTo and @@ -2001,7 +2030,7 @@ module Make Input> { ) or // Flow from SSA definition to read - exists(DefinitionExt def | + exists(DefinitionExt_ def | nodeFrom.(SsaDefinitionExtNodeImpl).getDefExt() = def and nodeTo.(ExprNode).getExpr() = DfInput::getARead(def) and v = def.getSourceVariable() From 6ac4cb71cba9fc2da0063f49f07d790de9e932f4 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Thu, 3 Apr 2025 09:57:48 +0200 Subject: [PATCH 2/3] SSA: Add change note. --- .../ssa/change-notes/2025-04-03-definitionext-deprecation.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 shared/ssa/change-notes/2025-04-03-definitionext-deprecation.md diff --git a/shared/ssa/change-notes/2025-04-03-definitionext-deprecation.md b/shared/ssa/change-notes/2025-04-03-definitionext-deprecation.md new file mode 100644 index 000000000000..0f0db7c81a17 --- /dev/null +++ b/shared/ssa/change-notes/2025-04-03-definitionext-deprecation.md @@ -0,0 +1,4 @@ +--- +category: deprecated +--- +* All references to the `DefinitionExt` and `PhiReadNode` classes in the SSA library have been deprecated. The concept of phi-read nodes is now strictly an internal implementation detail. Their sole use-case is to improve the structure of the use-use flow relation for data flow, and this use-case remains supported by the `DataFlowIntegration` module. From ce19972aeff42c93b9594897831e1d7b99b4dc8c Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Thu, 3 Apr 2025 16:16:20 +0200 Subject: [PATCH 3/3] SSA: Reinstate consistency check. --- shared/ssa/codeql/ssa/Ssa.qll | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/shared/ssa/codeql/ssa/Ssa.qll b/shared/ssa/codeql/ssa/Ssa.qll index dab99df65b4d..5a18d128ab62 100644 --- a/shared/ssa/codeql/ssa/Ssa.qll +++ b/shared/ssa/codeql/ssa/Ssa.qll @@ -1408,6 +1408,18 @@ module Make Input> { not uncertainWriteDefinitionInput(_, def) } + /** Holds if a read is not dominated by a definition. */ + query predicate notDominatedByDef(Definition def, SourceVariable v, BasicBlock bb, int i) { + exists(BasicBlock bbDef, int iDef | def.definesAt(v, bbDef, iDef) | + SsaDefReachesNew::ssaDefReachesReadWithinBlock(v, def, bb, i) and + (bb != bbDef or i < iDef) + or + ssaDefReachesRead(v, def, bb, i) and + not SsaDefReachesNew::ssaDefReachesReadWithinBlock(v, def, bb, i) and + not def.definesAt(v, getImmediateBasicBlockDominator*(bb), _) + ) + } + /** Holds if the end of a basic block can be reached by multiple definitions. */ query predicate nonUniqueDefReachesEndOfBlock(Definition def, SourceVariable v, BasicBlock bb) { ssaDefReachesEndOfBlock(bb, def, v) and