Merge pull request #8405 from smowton/smowton/fix/range-analysis-use-ranked-phi-nodes

C#/Java: Range analysis: use ranked phi nodes
This commit is contained in:
Chris Smowton
2022-03-14 11:55:55 +00:00
committed by GitHub
9 changed files with 105 additions and 69 deletions

View File

@@ -111,13 +111,6 @@ private predicate evenlyDivisibleExpr(Expr e, int factor) {
)
}
/**
* Holds if `rix` is the number of input edges to `phi`.
*/
private predicate maxPhiInputRank(SsaPhiNode phi, int rix) {
rix = max(int r | rankedPhiInput(phi, _, _, r))
}
/**
* Gets the remainder of `val` modulo `mod`.
*

View File

@@ -43,37 +43,4 @@ module Private {
predicate ssaUpdateStep = RU::ssaUpdateStep/3;
Expr getABasicBlockExpr(BasicBlock bb) { result = bb.getANode() }
private class PhiInputEdgeBlock extends BasicBlock {
PhiInputEdgeBlock() { this = any(SsaReadPositionPhiInputEdge edge).getOrigBlock() }
}
int getId(PhiInputEdgeBlock bb) {
exists(CfgImpl::ControlFlowTree::Range_ t | CfgImpl::ControlFlowTree::idOf(t, result) |
t = bb.getFirstNode().getElement()
or
t = bb.(CS::ControlFlow::BasicBlocks::EntryBlock).getCallable()
)
}
private string getSplitString(PhiInputEdgeBlock bb) {
result = bb.getFirstNode().(CS::ControlFlow::Nodes::ElementNode).getSplitsString()
or
not exists(bb.getFirstNode().(CS::ControlFlow::Nodes::ElementNode).getSplitsString()) and
result = ""
}
/**
* 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 getId(e.getOrigBlock()), getSplitString(e.getOrigBlock())
)
}
}

View File

@@ -3,6 +3,7 @@
*/
private import SsaReadPositionSpecific
import SsaReadPositionSpecific::Public
private newtype TSsaReadPosition =
TSsaReadPositionBlock(BasicBlock bb) { bb = getAReadBasicBlock(_) } or
@@ -55,3 +56,10 @@ class SsaReadPositionPhiInputEdge extends SsaReadPosition, TSsaReadPositionPhiIn
override string toString() { result = "edge" }
}
/**
* Holds if `rix` is the number of input edges to `phi`.
*/
predicate maxPhiInputRank(SsaPhiNode phi, int rix) {
rix = max(int r | rankedPhiInput(phi, _, _, r))
}

View File

@@ -3,6 +3,8 @@
*/
private import csharp
private import SsaReadPositionCommon
private import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl as CfgImpl
class SsaVariable = Ssa::Definition;
@@ -14,3 +16,41 @@ class BasicBlock = ControlFlow::BasicBlock;
BasicBlock getAReadBasicBlock(SsaVariable v) {
result = v.getARead().getAControlFlowNode().getBasicBlock()
}
private class PhiInputEdgeBlock extends BasicBlock {
PhiInputEdgeBlock() { this = any(SsaReadPositionPhiInputEdge edge).getOrigBlock() }
}
private int getId(PhiInputEdgeBlock bb) {
exists(CfgImpl::ControlFlowTree::Range_ t | CfgImpl::ControlFlowTree::idOf(t, result) |
t = bb.getFirstNode().getElement()
or
t = bb.(ControlFlow::BasicBlocks::EntryBlock).getCallable()
)
}
private string getSplitString(PhiInputEdgeBlock bb) {
result = bb.getFirstNode().(ControlFlow::Nodes::ElementNode).getSplitsString()
or
not exists(bb.getFirstNode().(ControlFlow::Nodes::ElementNode).getSplitsString()) and
result = ""
}
/**
* Declarations to be exposed to users of SsaReadPositionCommon.
*/
module Public {
/**
* 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 getId(e.getOrigBlock()), getSplitString(e.getOrigBlock())
)
}
}