Merge pull request #10203 from hvitved/ssa/param-module

SSA: Make shared library a parameterized module
This commit is contained in:
Tom Hvitved
2022-09-01 09:27:05 +02:00
committed by GitHub
29 changed files with 3803 additions and 5804 deletions

View File

@@ -2,55 +2,131 @@ cached
module Ssa {
private import swift
private import internal.SsaImplCommon as SsaImplCommon
private import internal.SsaImplSpecific as SsaImplSpecific
private import codeql.swift.controlflow.CfgNodes
private import codeql.swift.controlflow.ControlFlowGraph
private import codeql.swift.controlflow.BasicBlocks
private import codeql.swift.controlflow.BasicBlocks as BasicBlocks
private module SsaInput implements SsaImplCommon::InputSig {
private import internal.DataFlowPrivate
private import codeql.swift.controlflow.ControlFlowGraph
private import codeql.swift.controlflow.CfgNodes
class BasicBlock = BasicBlocks::BasicBlock;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) {
result = bb.getImmediateDominator()
}
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock = BasicBlocks::ExitBasicBlock;
class SourceVariable = VarDecl;
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(AssignExpr assign |
bb.getNode(i).getNode().asAstNode() = assign and
assign.getDest() = v.getAnAccess() and
certain = true
)
or
exists(PatternBindingDecl decl, Pattern pattern |
bb.getNode(i).getNode().asAstNode() = pattern and
decl.getAPattern() = pattern and
v.getParentPattern() = pattern and
certain = true
)
or
v instanceof ParamDecl and
bb.getNode(i).getNode().asAstNode() = v and
certain = true
or
// Mark the subexpression as a write of the local variable declared in the `TapExpr`.
exists(TapExpr tap |
v = tap.getVar() and
bb.getNode(i).getNode().asAstNode() = tap.getSubExpr() and
certain = true
)
}
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(DeclRefExpr ref |
not isLValue(ref) and
bb.getNode(i).getNode().asAstNode() = ref and
v = ref.getDecl() and
certain = true
)
or
exists(InOutExpr expr |
bb.getNode(i).getNode().asAstNode() = expr and
expr.getSubExpr() = v.getAnAccess() and
certain = true
)
or
exists(ExitNode exit, AbstractFunctionDecl func |
func.getAParam() = v or func.getSelfParam() = v
|
bb.getNode(i) = exit and
modifiableParam(v) and
bb.getScope() = func and
certain = true
)
or
// Mark the `TapExpr` as a read of the of the local variable.
exists(TapExpr tap |
v = tap.getVar() and
bb.getNode(i).getNode().asAstNode() = tap and
certain = true
)
}
}
private module SsaImpl = SsaImplCommon::Make<SsaInput>;
cached
class Definition extends SsaImplCommon::Definition {
class Definition extends SsaImpl::Definition {
cached
Location getLocation() { none() }
cached
ControlFlowNode getARead() {
exists(VarDecl v, BasicBlock bb, int i |
SsaImplCommon::ssaDefReachesRead(v, this, bb, i) and
SsaImplSpecific::variableRead(bb, i, v, true) and
exists(VarDecl v, SsaInput::BasicBlock bb, int i |
SsaImpl::ssaDefReachesRead(v, this, bb, i) and
SsaInput::variableRead(bb, i, v, true) and
result = bb.getNode(i)
)
}
cached
ControlFlowNode getAFirstRead() {
exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2 |
exists(SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2 |
this.definesAt(_, bb1, i1) and
SsaImplCommon::adjacentDefNoUncertainReads(this, bb1, i1, bb2, i2) and
SsaImpl::adjacentDefNoUncertainReads(this, bb1, i1, bb2, i2) and
result = bb2.getNode(i2)
)
}
cached
predicate adjacentReadPair(ControlFlowNode read1, ControlFlowNode read2) {
exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2 |
exists(SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2 |
read1 = bb1.getNode(i1) and
SsaImplSpecific::variableRead(bb1, i1, _, true) and
SsaImplCommon::adjacentDefNoUncertainReads(this, bb1, i1, bb2, i2) and
SsaInput::variableRead(bb1, i1, _, true) and
SsaImpl::adjacentDefNoUncertainReads(this, bb1, i1, bb2, i2) and
read2 = bb2.getNode(i2)
)
}
cached
predicate lastRefRedef(BasicBlock bb, int i, Definition next) {
SsaImplCommon::lastRefRedef(this, bb, i, next)
predicate lastRefRedef(SsaInput::BasicBlock bb, int i, Definition next) {
SsaImpl::lastRefRedef(this, bb, i, next)
}
}
cached
class WriteDefinition extends Definition, SsaImplCommon::WriteDefinition {
class WriteDefinition extends Definition, SsaImpl::WriteDefinition {
cached
override Location getLocation() {
exists(BasicBlock bb, int i |
exists(SsaInput::BasicBlock bb, int i |
this.definesAt(_, bb, i) and
result = bb.getNode(i).getLocation()
)
@@ -63,14 +139,16 @@ module Ssa {
cached
predicate assigns(CfgNode value) {
exists(
AssignExpr a, BasicBlock bb, int i // TODO: use CFG node for assignment expr
AssignExpr a, SsaInput::BasicBlock bb, int i // TODO: use CFG node for assignment expr
|
this.definesAt(_, bb, i) and
a = bb.getNode(i).getNode().asAstNode() and
value.getNode().asAstNode() = a.getSource()
)
or
exists(VarDecl var, BasicBlock bb, int blockIndex, PatternBindingDecl pbd, Expr init |
exists(
VarDecl var, SsaInput::BasicBlock bb, int blockIndex, PatternBindingDecl pbd, Expr init
|
this.definesAt(var, bb, blockIndex) and
pbd.getAPattern() = bb.getNode(blockIndex).getNode().asAstNode() and
init = var.getParentInitializer()
@@ -84,17 +162,19 @@ module Ssa {
}
cached
class PhiDefinition extends Definition, SsaImplCommon::PhiNode {
class PhiDefinition extends Definition, SsaImpl::PhiNode {
cached
override Location getLocation() {
exists(BasicBlock bb, int i |
exists(SsaInput::BasicBlock bb, int i |
this.definesAt(_, bb, i) and
result = bb.getLocation()
)
}
cached
Definition getPhiInput(BasicBlock bb) { SsaImplCommon::phiHasInputFromBlock(this, result, bb) }
Definition getPhiInput(SsaInput::BasicBlock bb) {
SsaImpl::phiHasInputFromBlock(this, result, bb)
}
cached
Definition getAPhiInput() { result = this.getPhiInput(_) }

File diff suppressed because it is too large Load Diff

View File

@@ -1,74 +0,0 @@
/** Provides the Swift specific parameters for `SsaImplCommon.qll`. */
private import swift
private import codeql.swift.controlflow.BasicBlocks as BasicBlocks
private import codeql.swift.controlflow.ControlFlowGraph
private import codeql.swift.controlflow.CfgNodes
private import DataFlowPrivate
class BasicBlock = BasicBlocks::BasicBlock;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result = bb.getImmediateDominator() }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock = BasicBlocks::ExitBasicBlock;
class SourceVariable = VarDecl;
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(AssignExpr assign |
bb.getNode(i).getNode().asAstNode() = assign and
assign.getDest() = v.getAnAccess() and
certain = true
)
or
exists(PatternBindingDecl decl, Pattern pattern |
bb.getNode(i).getNode().asAstNode() = pattern and
decl.getAPattern() = pattern and
v.getParentPattern() = pattern and
certain = true
)
or
v instanceof ParamDecl and
bb.getNode(i).getNode().asAstNode() = v and
certain = true
or
// Mark the subexpression as a write of the local variable declared in the `TapExpr`.
exists(TapExpr tap |
v = tap.getVar() and
bb.getNode(i).getNode().asAstNode() = tap.getSubExpr() and
certain = true
)
}
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(DeclRefExpr ref |
not isLValue(ref) and
bb.getNode(i).getNode().asAstNode() = ref and
v = ref.getDecl() and
certain = true
)
or
exists(InOutExpr expr |
bb.getNode(i).getNode().asAstNode() = expr and
expr.getSubExpr() = v.getAnAccess() and
certain = true
)
or
exists(ExitNode exit, AbstractFunctionDecl func |
func.getAParam() = v or func.getSelfParam() = v
|
bb.getNode(i) = exit and
modifiableParam(v) and
bb.getScope() = func and
certain = true
)
or
// Mark the `TapExpr` as a read of the of the local variable.
exists(TapExpr tap |
v = tap.getVar() and
bb.getNode(i).getNode().asAstNode() = tap and
certain = true
)
}