mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Java/C++: Move SsaReadPosition to shared qlpack.
This commit is contained in:
@@ -21,7 +21,7 @@ module ModulusAnalysis<
|
||||
|
||||
bindingset[pos, v]
|
||||
pragma[inline_late]
|
||||
private predicate hasReadOfVarInlineLate(Sem::SsaReadPosition pos, Sem::SsaVariable v) {
|
||||
private predicate hasReadOfVarInlineLate(SsaReadPosition pos, Sem::SsaVariable v) {
|
||||
pos.hasReadOfVar(v)
|
||||
}
|
||||
|
||||
@@ -29,9 +29,7 @@ module ModulusAnalysis<
|
||||
* Holds if `e + delta` equals `v` at `pos`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate valueFlowStepSsa(
|
||||
Sem::SsaVariable v, Sem::SsaReadPosition pos, Sem::Expr e, int delta
|
||||
) {
|
||||
private predicate valueFlowStepSsa(Sem::SsaVariable v, SsaReadPosition pos, Sem::Expr e, int delta) {
|
||||
U::semSsaUpdateStep(v, e, D::fromInt(delta)) and pos.hasReadOfVar(v)
|
||||
or
|
||||
exists(Sem::Guard guard, boolean testIsTrue |
|
||||
@@ -105,7 +103,7 @@ module ModulusAnalysis<
|
||||
/**
|
||||
* Holds if a guard ensures that `v` at `pos` is congruent with `val` modulo `mod`.
|
||||
*/
|
||||
private predicate moduloGuardedRead(Sem::SsaVariable v, Sem::SsaReadPosition pos, int val, int mod) {
|
||||
private predicate moduloGuardedRead(Sem::SsaVariable v, SsaReadPosition pos, int val, int mod) {
|
||||
exists(Sem::Guard guard, boolean testIsTrue |
|
||||
pos.hasReadOfVar(v) and
|
||||
guard = moduloCheck(v, val, mod, testIsTrue) and
|
||||
@@ -148,7 +146,7 @@ module ModulusAnalysis<
|
||||
* Holds if `inp` is an input to `phi` and equals `phi` modulo `mod` along `edge`.
|
||||
*/
|
||||
private predicate phiSelfModulus(
|
||||
Sem::SsaPhiNode phi, Sem::SsaVariable inp, Sem::SsaReadPositionPhiInputEdge edge, int mod
|
||||
Sem::SsaPhiNode phi, Sem::SsaVariable inp, SsaReadPositionPhiInputEdge edge, int mod
|
||||
) {
|
||||
exists(Bounds::SemSsaBound phibound, int v, int m |
|
||||
edge.phiInput(phi, inp) and
|
||||
@@ -163,7 +161,7 @@ module ModulusAnalysis<
|
||||
* Holds if `b + val` modulo `mod` is a candidate congruence class for `phi`.
|
||||
*/
|
||||
private predicate phiModulusInit(Sem::SsaPhiNode phi, Bounds::SemBound b, int val, int mod) {
|
||||
exists(Sem::SsaVariable inp, Sem::SsaReadPositionPhiInputEdge edge |
|
||||
exists(Sem::SsaVariable inp, SsaReadPositionPhiInputEdge edge |
|
||||
edge.phiInput(phi, inp) and
|
||||
ssaModulus(inp, edge, b, val, mod)
|
||||
)
|
||||
@@ -181,7 +179,7 @@ module ModulusAnalysis<
|
||||
rix = 0 and
|
||||
phiModulusInit(phi, b, val, mod)
|
||||
or
|
||||
exists(Sem::SsaVariable inp, Sem::SsaReadPositionPhiInputEdge edge, int v1, int m1 |
|
||||
exists(Sem::SsaVariable inp, SsaReadPositionPhiInputEdge edge, int v1, int m1 |
|
||||
mod != 1 and
|
||||
val = remainder(v1, mod)
|
||||
|
|
||||
@@ -192,7 +190,7 @@ module ModulusAnalysis<
|
||||
// equals `v2` modulo `mod`. The largest value of `mod` that satisfies
|
||||
// this is the greatest common divisor of `m1`, `m2`, and `v1 - v2`.
|
||||
exists(int v2, int m2 |
|
||||
U::rankedPhiInput(phi, inp, edge, rix) and
|
||||
rankedPhiInput(phi, inp, edge, rix) and
|
||||
phiModulusRankStep(phi, b, v1, m1, rix - 1) and
|
||||
ssaModulus(inp, edge, b, v2, m2) and
|
||||
mod = m1.gcd(m2).gcd(v1 - v2)
|
||||
@@ -202,7 +200,7 @@ module ModulusAnalysis<
|
||||
// preceding potential congruence class `b + v1` mod `m1`. The result will be
|
||||
// the congruence class modulo the greatest common divisor of `m1` and `m2`.
|
||||
exists(int m2 |
|
||||
U::rankedPhiInput(phi, inp, edge, rix) and
|
||||
rankedPhiInput(phi, inp, edge, rix) and
|
||||
phiModulusRankStep(phi, b, v1, m1, rix - 1) and
|
||||
phiSelfModulus(phi, inp, edge, m2) and
|
||||
mod = m1.gcd(m2)
|
||||
@@ -215,7 +213,7 @@ module ModulusAnalysis<
|
||||
*/
|
||||
private predicate phiModulus(Sem::SsaPhiNode phi, Bounds::SemBound b, int val, int mod) {
|
||||
exists(int r |
|
||||
U::maxPhiInputRank(phi, r) and
|
||||
maxPhiInputRank(phi, r) and
|
||||
phiModulusRankStep(phi, b, val, mod, r)
|
||||
)
|
||||
}
|
||||
@@ -224,7 +222,7 @@ module ModulusAnalysis<
|
||||
* Holds if `v` at `pos` is equal to `b + val` modulo `mod`.
|
||||
*/
|
||||
private predicate ssaModulus(
|
||||
Sem::SsaVariable v, Sem::SsaReadPosition pos, Bounds::SemBound b, int val, int mod
|
||||
Sem::SsaVariable v, SsaReadPosition pos, Bounds::SemBound b, int val, int mod
|
||||
) {
|
||||
phiModulus(v, b, val, mod) and pos.hasReadOfVar(v)
|
||||
or
|
||||
@@ -254,7 +252,7 @@ module ModulusAnalysis<
|
||||
val = 0 and
|
||||
b instanceof Bounds::SemZeroBound
|
||||
or
|
||||
exists(Sem::SsaVariable v, Sem::SsaReadPositionBlock bb |
|
||||
exists(Sem::SsaVariable v, SsaReadPositionBlock bb |
|
||||
ssaModulus(v, bb, b, val, mod) and
|
||||
e = v.getAUse() and
|
||||
bb.getBlock() = e.getBasicBlock()
|
||||
|
||||
@@ -150,6 +150,16 @@ signature module Semantic {
|
||||
/** Gets an immediate successor of basic block `bb`, if any. */
|
||||
BasicBlock getABasicBlockSuccessor(BasicBlock bb);
|
||||
|
||||
/**
|
||||
* Gets an ideally unique integer for `bb`. If it is undesirable to make this
|
||||
* unique, then `getBlock2` must provide a tiebreaker, such that the pair
|
||||
* `(getBlockId1(bb),getBlockId2(bb))` becomes unique.
|
||||
*/
|
||||
int getBlockId1(BasicBlock bb);
|
||||
|
||||
/** Gets a tiebreaker id in case `getBlockId1` is not unique. */
|
||||
default string getBlockId2(BasicBlock bb) { result = "" }
|
||||
|
||||
class Guard {
|
||||
string toString();
|
||||
|
||||
@@ -184,28 +194,15 @@ signature module Semantic {
|
||||
BasicBlock getBasicBlock();
|
||||
}
|
||||
|
||||
class SsaPhiNode extends SsaVariable;
|
||||
class SsaPhiNode extends SsaVariable {
|
||||
/** Holds if `inp` is an input to the phi node along the edge originating in `bb`. */
|
||||
predicate hasInputFromBlock(SsaVariable inp, BasicBlock bb);
|
||||
}
|
||||
|
||||
class SsaExplicitUpdate extends SsaVariable {
|
||||
Expr getDefiningExpr();
|
||||
}
|
||||
|
||||
class SsaReadPosition {
|
||||
predicate hasReadOfVar(SsaVariable v);
|
||||
}
|
||||
|
||||
class SsaReadPositionPhiInputEdge extends SsaReadPosition {
|
||||
BasicBlock getOrigBlock();
|
||||
|
||||
BasicBlock getPhiBlock();
|
||||
|
||||
predicate phiInput(SsaPhiNode phi, SsaVariable inp);
|
||||
}
|
||||
|
||||
class SsaReadPositionBlock extends SsaReadPosition {
|
||||
BasicBlock getBlock();
|
||||
}
|
||||
|
||||
predicate conversionCannotOverflow(Type fromType, Type toType);
|
||||
}
|
||||
|
||||
@@ -330,19 +327,6 @@ signature module UtilSig<Semantic Sem, DeltaSig DeltaParam> {
|
||||
* primitive types as the underlying primitive type.
|
||||
*/
|
||||
Sem::Type getTrackedType(Sem::Expr e);
|
||||
|
||||
/**
|
||||
* Holds if `inp` is an input to `phi` along `edge` and this input has index `r`
|
||||
* in an arbitrary 1-based numbering of the input edges to `phi`.
|
||||
*/
|
||||
predicate rankedPhiInput(
|
||||
Sem::SsaPhiNode phi, Sem::SsaVariable inp, Sem::SsaReadPositionPhiInputEdge edge, int r
|
||||
);
|
||||
|
||||
/**
|
||||
* Holds if `rix` is the number of input edges to `phi`.
|
||||
*/
|
||||
predicate maxPhiInputRank(Sem::SsaPhiNode phi, int rix);
|
||||
}
|
||||
|
||||
signature module BoundSig<LocationSig Location, Semantic Sem, DeltaSig D> {
|
||||
@@ -688,7 +672,7 @@ module RangeStage<
|
||||
* - `upper = false` : `v >= e + delta`
|
||||
*/
|
||||
private predicate boundFlowStepSsa(
|
||||
Sem::SsaVariable v, Sem::SsaReadPosition pos, Sem::Expr e, D::Delta delta, boolean upper,
|
||||
Sem::SsaVariable v, SsaReadPosition pos, Sem::Expr e, D::Delta delta, boolean upper,
|
||||
SemReason reason
|
||||
) {
|
||||
semSsaUpdateStep(v, e, delta) and
|
||||
@@ -706,7 +690,7 @@ module RangeStage<
|
||||
|
||||
/** Holds if `v != e + delta` at `pos` and `v` is of integral type. */
|
||||
private predicate unequalFlowStepIntegralSsa(
|
||||
Sem::SsaVariable v, Sem::SsaReadPosition pos, Sem::Expr e, D::Delta delta, SemReason reason
|
||||
Sem::SsaVariable v, SsaReadPosition pos, Sem::Expr e, D::Delta delta, SemReason reason
|
||||
) {
|
||||
getTrackedTypeForSsaVariable(v) instanceof Sem::IntegerType and
|
||||
exists(Sem::Guard guard, boolean testIsTrue |
|
||||
@@ -836,7 +820,7 @@ module RangeStage<
|
||||
* - `upper = false` : `v >= b + delta`
|
||||
*/
|
||||
private predicate boundedSsa(
|
||||
Sem::SsaVariable v, SemBound b, D::Delta delta, Sem::SsaReadPosition pos, boolean upper,
|
||||
Sem::SsaVariable v, SemBound b, D::Delta delta, SsaReadPosition pos, boolean upper,
|
||||
boolean fromBackEdge, D::Delta origdelta, SemReason reason
|
||||
) {
|
||||
exists(Sem::Expr mid, D::Delta d1, D::Delta d2, SemReason r1, SemReason r2 |
|
||||
@@ -873,7 +857,7 @@ module RangeStage<
|
||||
* Holds if `v != b + delta` at `pos` and `v` is of integral type.
|
||||
*/
|
||||
private predicate unequalIntegralSsa(
|
||||
Sem::SsaVariable v, SemBound b, D::Delta delta, Sem::SsaReadPosition pos, SemReason reason
|
||||
Sem::SsaVariable v, SemBound b, D::Delta delta, SsaReadPosition pos, SemReason reason
|
||||
) {
|
||||
exists(Sem::Expr e, D::Delta d1, D::Delta d2 |
|
||||
unequalFlowStepIntegralSsa(v, pos, e, d1, reason) and
|
||||
@@ -920,7 +904,7 @@ module RangeStage<
|
||||
* - `upper = false` : `inp >= b + delta`
|
||||
*/
|
||||
private predicate boundedPhiInp(
|
||||
Sem::SsaPhiNode phi, Sem::SsaVariable inp, Sem::SsaReadPositionPhiInputEdge edge, SemBound b,
|
||||
Sem::SsaPhiNode phi, Sem::SsaVariable inp, SsaReadPositionPhiInputEdge edge, SemBound b,
|
||||
D::Delta delta, boolean upper, boolean fromBackEdge, D::Delta origdelta, SemReason reason
|
||||
) {
|
||||
edge.phiInput(phi, inp) and
|
||||
@@ -964,7 +948,7 @@ module RangeStage<
|
||||
pragma[noinline]
|
||||
private predicate boundedPhiInp1(
|
||||
Sem::SsaPhiNode phi, SemBound b, boolean upper, Sem::SsaVariable inp,
|
||||
Sem::SsaReadPositionPhiInputEdge edge, D::Delta delta
|
||||
SsaReadPositionPhiInputEdge edge, D::Delta delta
|
||||
) {
|
||||
boundedPhiInp(phi, inp, edge, b, delta, upper, _, _, _)
|
||||
}
|
||||
@@ -976,7 +960,7 @@ module RangeStage<
|
||||
* - `upper = false` : `inp >= phi`
|
||||
*/
|
||||
private predicate selfBoundedPhiInp(
|
||||
Sem::SsaPhiNode phi, Sem::SsaVariable inp, Sem::SsaReadPositionPhiInputEdge edge, boolean upper
|
||||
Sem::SsaPhiNode phi, Sem::SsaVariable inp, SsaReadPositionPhiInputEdge edge, boolean upper
|
||||
) {
|
||||
exists(D::Delta d, SemSsaBound phibound |
|
||||
phibound.getVariable() = phi and
|
||||
@@ -1009,8 +993,7 @@ module RangeStage<
|
||||
*/
|
||||
private predicate boundedPhiCandValidForEdge(
|
||||
Sem::SsaPhiNode phi, SemBound b, D::Delta delta, boolean upper, boolean fromBackEdge,
|
||||
D::Delta origdelta, SemReason reason, Sem::SsaVariable inp,
|
||||
Sem::SsaReadPositionPhiInputEdge edge
|
||||
D::Delta origdelta, SemReason reason, Sem::SsaVariable inp, SsaReadPositionPhiInputEdge edge
|
||||
) {
|
||||
boundedPhiCand(phi, upper, b, delta, fromBackEdge, origdelta, reason) and
|
||||
(
|
||||
@@ -1036,7 +1019,7 @@ module RangeStage<
|
||||
Sem::SsaPhiNode phi, SemBound b, D::Delta delta, boolean upper, boolean fromBackEdge,
|
||||
D::Delta origdelta, SemReason reason, int rix
|
||||
) {
|
||||
exists(Sem::SsaVariable inp, Sem::SsaReadPositionPhiInputEdge edge |
|
||||
exists(Sem::SsaVariable inp, SsaReadPositionPhiInputEdge edge |
|
||||
rankedPhiInput(phi, inp, edge, rix) and
|
||||
boundedPhiCandValidForEdge(phi, b, delta, upper, fromBackEdge, origdelta, reason, inp, edge)
|
||||
|
|
||||
@@ -1208,7 +1191,7 @@ module RangeStage<
|
||||
origdelta = delta and
|
||||
reason = TSemNoReason()
|
||||
or
|
||||
exists(Sem::SsaVariable v, Sem::SsaReadPositionBlock bb |
|
||||
exists(Sem::SsaVariable v, SsaReadPositionBlock bb |
|
||||
boundedSsa(v, b, delta, bb, upper, fromBackEdge, origdelta, reason) and
|
||||
e = v.getAUse() and
|
||||
bb.getBlock() = e.getBasicBlock()
|
||||
|
||||
@@ -1,38 +1,99 @@
|
||||
private import codeql.rangeanalysis.RangeAnalysis
|
||||
|
||||
module MakeUtils<Semantic Lang, DeltaSig D> {
|
||||
private import Lang
|
||||
|
||||
/**
|
||||
* Gets an expression that equals `v - d`.
|
||||
*/
|
||||
Lang::Expr ssaRead(Lang::SsaVariable v, D::Delta delta) {
|
||||
Expr ssaRead(SsaVariable v, D::Delta delta) {
|
||||
result = v.getAUse() and delta = D::fromInt(0)
|
||||
or
|
||||
exists(D::Delta d1, Lang::ConstantIntegerExpr c |
|
||||
result.(Lang::AddExpr).hasOperands(ssaRead(v, d1), c) and
|
||||
exists(D::Delta d1, ConstantIntegerExpr c |
|
||||
result.(AddExpr).hasOperands(ssaRead(v, d1), c) and
|
||||
delta = D::fromFloat(D::toFloat(d1) - c.getIntValue()) and
|
||||
// In the scope of `x += ..`, which is SSA translated as `x2 = x1 + ..`,
|
||||
// the variable `x1` is shadowed by `x2`, so there's no need to view this
|
||||
// as a read of `x1`.
|
||||
not Lang::isAssignOp(result)
|
||||
not isAssignOp(result)
|
||||
)
|
||||
or
|
||||
exists(Lang::SubExpr sub, D::Delta d1, Lang::ConstantIntegerExpr c |
|
||||
exists(SubExpr sub, D::Delta d1, ConstantIntegerExpr c |
|
||||
result = sub and
|
||||
sub.getLeftOperand() = ssaRead(v, d1) and
|
||||
sub.getRightOperand() = c and
|
||||
delta = D::fromFloat(D::toFloat(d1) + c.getIntValue()) and
|
||||
not Lang::isAssignOp(result)
|
||||
not isAssignOp(result)
|
||||
)
|
||||
or
|
||||
result = v.(Lang::SsaExplicitUpdate).getDefiningExpr() and
|
||||
if result instanceof Lang::PostIncExpr
|
||||
result = v.(SsaExplicitUpdate).getDefiningExpr() and
|
||||
if result instanceof PostIncExpr
|
||||
then delta = D::fromFloat(1) // x++ === ++x - 1
|
||||
else
|
||||
if result instanceof Lang::PostDecExpr
|
||||
if result instanceof PostDecExpr
|
||||
then delta = D::fromFloat(-1) // x-- === --x + 1
|
||||
else delta = D::fromFloat(0)
|
||||
or
|
||||
result.(Lang::CopyValueExpr).getOperand() = ssaRead(v, delta)
|
||||
result.(CopyValueExpr).getOperand() = ssaRead(v, delta)
|
||||
}
|
||||
|
||||
private newtype TSsaReadPosition =
|
||||
TSsaReadPositionBlock(BasicBlock bb) {
|
||||
exists(SsaVariable v | v.getAUse().getBasicBlock() = bb)
|
||||
} or
|
||||
TSsaReadPositionPhiInputEdge(BasicBlock bbOrig, BasicBlock bbPhi) {
|
||||
exists(SsaPhiNode phi | phi.hasInputFromBlock(_, bbOrig) and bbPhi = phi.getBasicBlock())
|
||||
}
|
||||
|
||||
/**
|
||||
* A position at which an SSA variable is read. This includes both ordinary
|
||||
* reads occurring in basic blocks and input to phi nodes occurring along an
|
||||
* edge between two basic blocks.
|
||||
*/
|
||||
class SsaReadPosition extends TSsaReadPosition {
|
||||
/** Holds if `v` is read at this position. */
|
||||
abstract predicate hasReadOfVar(SsaVariable v);
|
||||
|
||||
/** Gets a textual representation of this SSA read position. */
|
||||
abstract string toString();
|
||||
}
|
||||
|
||||
/** A basic block in which an SSA variable is read. */
|
||||
class SsaReadPositionBlock extends SsaReadPosition, TSsaReadPositionBlock {
|
||||
/** Gets the basic block corresponding to this position. */
|
||||
BasicBlock getBlock() { this = TSsaReadPositionBlock(result) }
|
||||
|
||||
override predicate hasReadOfVar(SsaVariable v) { exists(this.getAnSsaRead(v)) }
|
||||
|
||||
pragma[nomagic]
|
||||
Expr getAnSsaRead(SsaVariable v) {
|
||||
v.getAUse() = result and result.getBasicBlock() = this.getBlock()
|
||||
}
|
||||
|
||||
override string toString() { result = "block" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An edge between two basic blocks where the latter block has an SSA phi
|
||||
* definition. The edge therefore has a read of an SSA variable serving as the
|
||||
* input to the phi node.
|
||||
*/
|
||||
class SsaReadPositionPhiInputEdge extends SsaReadPosition, TSsaReadPositionPhiInputEdge {
|
||||
/** Gets the source of the edge. */
|
||||
BasicBlock getOrigBlock() { this = TSsaReadPositionPhiInputEdge(result, _) }
|
||||
|
||||
/** Gets the target of the edge. */
|
||||
BasicBlock getPhiBlock() { this = TSsaReadPositionPhiInputEdge(_, result) }
|
||||
|
||||
override predicate hasReadOfVar(SsaVariable v) { this.phiInput(_, v) }
|
||||
|
||||
/** Holds if `inp` is an input to `phi` along this edge. */
|
||||
predicate phiInput(SsaPhiNode phi, SsaVariable inp) {
|
||||
phi.hasInputFromBlock(inp, this.getOrigBlock()) and
|
||||
this.getPhiBlock() = phi.getBasicBlock()
|
||||
}
|
||||
|
||||
override string toString() { result = "edge" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -40,10 +101,10 @@ module MakeUtils<Semantic Lang, DeltaSig D> {
|
||||
* value `testIsTrue`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate guardDirectlyControlsSsaRead(Lang::Guard guard, Lang::SsaReadPosition controlled, boolean testIsTrue) {
|
||||
guard.directlyControls(controlled.(Lang::SsaReadPositionBlock).getBlock(), testIsTrue)
|
||||
predicate guardDirectlyControlsSsaRead(Guard guard, SsaReadPosition controlled, boolean testIsTrue) {
|
||||
guard.directlyControls(controlled.(SsaReadPositionBlock).getBlock(), testIsTrue)
|
||||
or
|
||||
exists(Lang::SsaReadPositionPhiInputEdge controlledEdge | controlledEdge = controlled |
|
||||
exists(SsaReadPositionPhiInputEdge controlledEdge | controlledEdge = controlled |
|
||||
guard.directlyControls(controlledEdge.getOrigBlock(), testIsTrue) or
|
||||
guard.hasBranchEdge(controlledEdge.getOrigBlock(), controlledEdge.getPhiBlock(), testIsTrue)
|
||||
)
|
||||
@@ -52,11 +113,11 @@ module MakeUtils<Semantic Lang, DeltaSig D> {
|
||||
/**
|
||||
* Holds if `guard` controls the position `controlled` with the value `testIsTrue`.
|
||||
*/
|
||||
predicate guardControlsSsaRead(Lang::Guard guard, Lang::SsaReadPosition controlled, boolean testIsTrue) {
|
||||
predicate guardControlsSsaRead(Guard guard, SsaReadPosition controlled, boolean testIsTrue) {
|
||||
guardDirectlyControlsSsaRead(guard, controlled, testIsTrue)
|
||||
or
|
||||
exists(Lang::Guard guard0, boolean testIsTrue0 |
|
||||
Lang::implies_v2(guard0, testIsTrue0, guard, testIsTrue) and
|
||||
exists(Guard guard0, boolean testIsTrue0 |
|
||||
implies_v2(guard0, testIsTrue0, guard, testIsTrue) and
|
||||
guardControlsSsaRead(guard0, controlled, testIsTrue0)
|
||||
)
|
||||
}
|
||||
@@ -64,9 +125,7 @@ module MakeUtils<Semantic Lang, DeltaSig D> {
|
||||
/**
|
||||
* Holds if `inp` is an input to `phi` along a back edge.
|
||||
*/
|
||||
predicate backEdge(
|
||||
Lang::SsaPhiNode phi, Lang::SsaVariable inp, Lang::SsaReadPositionPhiInputEdge edge
|
||||
) {
|
||||
predicate backEdge(SsaPhiNode phi, SsaVariable inp, SsaReadPositionPhiInputEdge edge) {
|
||||
edge.phiInput(phi, inp) and
|
||||
(
|
||||
phi.getBasicBlock().bbDominates(edge.getOrigBlock()) or
|
||||
@@ -85,12 +144,33 @@ module MakeUtils<Semantic Lang, DeltaSig D> {
|
||||
* dominated by the successor block, then mark all edges in a cycle in the resulting graph as back
|
||||
* edges.
|
||||
*/
|
||||
private predicate irreducibleSccEdge(Lang::BasicBlock b1, Lang::BasicBlock b2) {
|
||||
private predicate irreducibleSccEdge(BasicBlock b1, BasicBlock b2) {
|
||||
trimmedEdge(b1, b2) and trimmedEdge+(b2, b1)
|
||||
}
|
||||
|
||||
private predicate trimmedEdge(Lang::BasicBlock pred, Lang::BasicBlock succ) {
|
||||
Lang::getABasicBlockSuccessor(pred) = succ and
|
||||
private predicate trimmedEdge(BasicBlock pred, BasicBlock succ) {
|
||||
getABasicBlockSuccessor(pred) = succ and
|
||||
not succ.bbDominates(pred)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `inp` is an input to `phi` along `edge` and this input has index `r`
|
||||
* in an arbitrary 1-based numbering of the input edges to `phi`.
|
||||
*/
|
||||
predicate rankedPhiInput(SsaPhiNode phi, SsaVariable inp, SsaReadPositionPhiInputEdge edge, int r) {
|
||||
edge.phiInput(phi, inp) and
|
||||
edge =
|
||||
rank[r](SsaReadPositionPhiInputEdge e |
|
||||
e.phiInput(phi, _)
|
||||
|
|
||||
e order by getBlockId1(e.getOrigBlock()), getBlockId2(e.getOrigBlock())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `rix` is the number of input edges to `phi`.
|
||||
*/
|
||||
predicate maxPhiInputRank(SsaPhiNode phi, int rix) {
|
||||
rix = max(int r | rankedPhiInput(phi, _, _, r))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user