C++: recompute IRBlock membership at each stage

This enables the addition of new instructions in later phases of IR
construction; in particular, aliasing write instructions and inference
instructions.
This commit is contained in:
Robert Marsh
2018-10-31 11:09:08 -07:00
committed by Dave Bartolomeo
parent 7aef8fa945
commit f9ed39915f
10 changed files with 240 additions and 170 deletions

View File

@@ -47,10 +47,6 @@
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SimpleSSA.qll"
],
"C++ SSA IRBlockConstruction": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/IRBlockConstruction.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/IRBlockConstruction.qll"
],
"C++ SSA SSAConstruction": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll"

View File

@@ -1,7 +1,7 @@
private import internal.IRInternal
import Instruction
import semmle.code.cpp.ir.implementation.EdgeKind
private import Construction::BlockConstruction
import Cached
class IRBlock extends TIRBlock {
final string toString() {
@@ -98,3 +98,82 @@ class IRBlock extends TIRBlock {
getAPredecessor().isReachableFromFunctionEntry()
}
}
private predicate startsBasicBlock(Instruction instr) {
not instr instanceof PhiInstruction and
(
count(Instruction predecessor |
instr = predecessor.getASuccessor()
) != 1 or // Multiple predecessors or no predecessor
exists(Instruction predecessor |
instr = predecessor.getASuccessor() and
strictcount(Instruction other |
other = predecessor.getASuccessor()
) > 1
) or // Predecessor has multiple successors
exists(Instruction predecessor, EdgeKind kind |
instr = predecessor.getSuccessor(kind) and
not kind instanceof GotoEdge
) // Incoming edge is not a GotoEdge
)
}
private predicate isEntryBlock(TIRBlock block) {
block = MkIRBlock(any(EnterFunctionInstruction enter))
}
private cached module Cached {
cached newtype TIRBlock =
MkIRBlock(Instruction firstInstr) {
startsBasicBlock(firstInstr)
}
/** Holds if `i2` follows `i1` in a `IRBlock`. */
private predicate adjacentInBlock(Instruction i1, Instruction i2) {
exists(GotoEdge edgeKind | i2 = i1.getSuccessor(edgeKind)) and
not startsBasicBlock(i2)
}
/** Gets the index of `i` in its `IRBlock`. */
private int getMemberIndex(Instruction i) {
startsBasicBlock(i) and
result = 0
or
exists(Instruction iPrev |
adjacentInBlock(iPrev, i) and
result = getMemberIndex(iPrev) + 1
)
}
/** Holds if `i` is the `index`th instruction in `block`. */
cached Instruction getInstruction(TIRBlock block, int index) {
exists(Instruction first |
block = MkIRBlock(first) and
index = getMemberIndex(result) and
adjacentInBlock*(first, result)
)
}
cached int getInstructionCount(TIRBlock block) {
result = strictcount(getInstruction(block, _))
}
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
exists(Instruction predLast, Instruction succFirst |
predLast = getInstruction(pred, getInstructionCount(pred) - 1) and
succFirst = predLast.getSuccessor(kind) and
succ = MkIRBlock(succFirst)
)
}
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ) {
blockSuccessor(pred, succ, _)
}
cached predicate blockImmediatelyDominates(TIRBlock dominator, TIRBlock block) =
idominance(isEntryBlock/1, blockSuccessor/2)(_, dominator, block)
}
Instruction getFirstInstruction(TIRBlock block) {
block = MkIRBlock(result)
}

View File

@@ -1,38 +0,0 @@
import SSAConstructionInternal
private import SSAConstruction as Construction
private import NewIR
import Cached
private cached module Cached {
cached newtype TIRBlock = MkIRBlock(OldIR::IRBlock oldBlock)
private OldIR::IRBlock getOldBlock(TIRBlock block) {
block = MkIRBlock(result)
}
cached Instruction getInstruction(TIRBlock block, int index) {
Construction::getOldInstruction(result) =
getOldBlock(block).getInstruction(index)
}
cached int getInstructionCount(TIRBlock block) {
result = getOldBlock(block).getInstructionCount()
}
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
succ = MkIRBlock(getOldBlock(pred).getSuccessor(kind))
}
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ) {
blockSuccessor(pred, succ, _)
}
cached predicate blockImmediatelyDominates(TIRBlock dominator, TIRBlock block) {
getOldBlock(dominator).immediatelyDominates(getOldBlock(block))
}
cached Instruction getFirstInstruction(TIRBlock block) {
Construction::getOldInstruction(result) =
getOldBlock(block).getFirstInstruction()
}
}

View File

@@ -3,7 +3,6 @@ import cpp
private import semmle.code.cpp.ir.implementation.Opcode
private import semmle.code.cpp.ir.internal.OperandTag
private import NewIR
import IRBlockConstruction as BlockConstruction
import Cached
cached private module Cached {

View File

@@ -1,7 +1,7 @@
private import internal.IRInternal
import Instruction
import semmle.code.cpp.ir.implementation.EdgeKind
private import Construction::BlockConstruction
import Cached
class IRBlock extends TIRBlock {
final string toString() {
@@ -98,3 +98,82 @@ class IRBlock extends TIRBlock {
getAPredecessor().isReachableFromFunctionEntry()
}
}
private predicate startsBasicBlock(Instruction instr) {
not instr instanceof PhiInstruction and
(
count(Instruction predecessor |
instr = predecessor.getASuccessor()
) != 1 or // Multiple predecessors or no predecessor
exists(Instruction predecessor |
instr = predecessor.getASuccessor() and
strictcount(Instruction other |
other = predecessor.getASuccessor()
) > 1
) or // Predecessor has multiple successors
exists(Instruction predecessor, EdgeKind kind |
instr = predecessor.getSuccessor(kind) and
not kind instanceof GotoEdge
) // Incoming edge is not a GotoEdge
)
}
private predicate isEntryBlock(TIRBlock block) {
block = MkIRBlock(any(EnterFunctionInstruction enter))
}
private cached module Cached {
cached newtype TIRBlock =
MkIRBlock(Instruction firstInstr) {
startsBasicBlock(firstInstr)
}
/** Holds if `i2` follows `i1` in a `IRBlock`. */
private predicate adjacentInBlock(Instruction i1, Instruction i2) {
exists(GotoEdge edgeKind | i2 = i1.getSuccessor(edgeKind)) and
not startsBasicBlock(i2)
}
/** Gets the index of `i` in its `IRBlock`. */
private int getMemberIndex(Instruction i) {
startsBasicBlock(i) and
result = 0
or
exists(Instruction iPrev |
adjacentInBlock(iPrev, i) and
result = getMemberIndex(iPrev) + 1
)
}
/** Holds if `i` is the `index`th instruction in `block`. */
cached Instruction getInstruction(TIRBlock block, int index) {
exists(Instruction first |
block = MkIRBlock(first) and
index = getMemberIndex(result) and
adjacentInBlock*(first, result)
)
}
cached int getInstructionCount(TIRBlock block) {
result = strictcount(getInstruction(block, _))
}
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
exists(Instruction predLast, Instruction succFirst |
predLast = getInstruction(pred, getInstructionCount(pred) - 1) and
succFirst = predLast.getSuccessor(kind) and
succ = MkIRBlock(succFirst)
)
}
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ) {
blockSuccessor(pred, succ, _)
}
cached predicate blockImmediatelyDominates(TIRBlock dominator, TIRBlock block) =
idominance(isEntryBlock/1, blockSuccessor/2)(_, dominator, block)
}
Instruction getFirstInstruction(TIRBlock block) {
block = MkIRBlock(result)
}

View File

@@ -1,83 +0,0 @@
import semmle.code.cpp.ir.implementation.raw.Instruction
import cpp
import semmle.code.cpp.ir.implementation.EdgeKind
private predicate startsBasicBlock(Instruction instr) {
not instr instanceof PhiInstruction and
(
count(Instruction predecessor |
instr = predecessor.getASuccessor()
) != 1 or // Multiple predecessors or no predecessor
exists(Instruction predecessor |
instr = predecessor.getASuccessor() and
strictcount(Instruction other |
other = predecessor.getASuccessor()
) > 1
) or // Predecessor has multiple successors
exists(Instruction predecessor, EdgeKind kind |
instr = predecessor.getSuccessor(kind) and
not kind instanceof GotoEdge
) // Incoming edge is not a GotoEdge
)
}
private predicate isEntryBlock(TIRBlock block) {
block = MkIRBlock(any(EnterFunctionInstruction enter))
}
import Cached
private cached module Cached {
cached newtype TIRBlock =
MkIRBlock(Instruction firstInstr) {
startsBasicBlock(firstInstr)
}
/** Holds if `i2` follows `i1` in a `IRBlock`. */
private predicate adjacentInBlock(Instruction i1, Instruction i2) {
exists(GotoEdge edgeKind | i2 = i1.getSuccessor(edgeKind)) and
not startsBasicBlock(i2)
}
/** Gets the index of `i` in its `IRBlock`. */
private int getMemberIndex(Instruction i) {
startsBasicBlock(i) and
result = 0
or
exists(Instruction iPrev |
adjacentInBlock(iPrev, i) and
result = getMemberIndex(iPrev) + 1
)
}
/** Holds if `i` is the `index`th instruction in `block`. */
cached Instruction getInstruction(TIRBlock block, int index) {
exists(Instruction first |
block = MkIRBlock(first) and
index = getMemberIndex(result) and
adjacentInBlock*(first, result)
)
}
cached int getInstructionCount(TIRBlock block) {
result = strictcount(getInstruction(block, _))
}
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
exists(Instruction predLast, Instruction succFirst |
predLast = getInstruction(pred, getInstructionCount(pred) - 1) and
succFirst = predLast.getSuccessor(kind) and
succ = MkIRBlock(succFirst)
)
}
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ) {
blockSuccessor(pred, succ, _)
}
cached predicate blockImmediatelyDominates(TIRBlock dominator, TIRBlock block) =
idominance(isEntryBlock/1, blockSuccessor/2)(_, dominator, block)
}
Instruction getFirstInstruction(TIRBlock block) {
block = MkIRBlock(result)
}

View File

@@ -1,6 +1,5 @@
import cpp
import semmle.code.cpp.ir.implementation.raw.IR
import IRBlockConstruction as BlockConstruction
private import semmle.code.cpp.ir.internal.OperandTag
private import semmle.code.cpp.ir.internal.TempVariableTag
private import InstructionTag

View File

@@ -1,7 +1,7 @@
private import internal.IRInternal
import Instruction
import semmle.code.cpp.ir.implementation.EdgeKind
private import Construction::BlockConstruction
import Cached
class IRBlock extends TIRBlock {
final string toString() {
@@ -98,3 +98,82 @@ class IRBlock extends TIRBlock {
getAPredecessor().isReachableFromFunctionEntry()
}
}
private predicate startsBasicBlock(Instruction instr) {
not instr instanceof PhiInstruction and
(
count(Instruction predecessor |
instr = predecessor.getASuccessor()
) != 1 or // Multiple predecessors or no predecessor
exists(Instruction predecessor |
instr = predecessor.getASuccessor() and
strictcount(Instruction other |
other = predecessor.getASuccessor()
) > 1
) or // Predecessor has multiple successors
exists(Instruction predecessor, EdgeKind kind |
instr = predecessor.getSuccessor(kind) and
not kind instanceof GotoEdge
) // Incoming edge is not a GotoEdge
)
}
private predicate isEntryBlock(TIRBlock block) {
block = MkIRBlock(any(EnterFunctionInstruction enter))
}
private cached module Cached {
cached newtype TIRBlock =
MkIRBlock(Instruction firstInstr) {
startsBasicBlock(firstInstr)
}
/** Holds if `i2` follows `i1` in a `IRBlock`. */
private predicate adjacentInBlock(Instruction i1, Instruction i2) {
exists(GotoEdge edgeKind | i2 = i1.getSuccessor(edgeKind)) and
not startsBasicBlock(i2)
}
/** Gets the index of `i` in its `IRBlock`. */
private int getMemberIndex(Instruction i) {
startsBasicBlock(i) and
result = 0
or
exists(Instruction iPrev |
adjacentInBlock(iPrev, i) and
result = getMemberIndex(iPrev) + 1
)
}
/** Holds if `i` is the `index`th instruction in `block`. */
cached Instruction getInstruction(TIRBlock block, int index) {
exists(Instruction first |
block = MkIRBlock(first) and
index = getMemberIndex(result) and
adjacentInBlock*(first, result)
)
}
cached int getInstructionCount(TIRBlock block) {
result = strictcount(getInstruction(block, _))
}
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
exists(Instruction predLast, Instruction succFirst |
predLast = getInstruction(pred, getInstructionCount(pred) - 1) and
succFirst = predLast.getSuccessor(kind) and
succ = MkIRBlock(succFirst)
)
}
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ) {
blockSuccessor(pred, succ, _)
}
cached predicate blockImmediatelyDominates(TIRBlock dominator, TIRBlock block) =
idominance(isEntryBlock/1, blockSuccessor/2)(_, dominator, block)
}
Instruction getFirstInstruction(TIRBlock block) {
block = MkIRBlock(result)
}

View File

@@ -1,38 +0,0 @@
import SSAConstructionInternal
private import SSAConstruction as Construction
private import NewIR
import Cached
private cached module Cached {
cached newtype TIRBlock = MkIRBlock(OldIR::IRBlock oldBlock)
private OldIR::IRBlock getOldBlock(TIRBlock block) {
block = MkIRBlock(result)
}
cached Instruction getInstruction(TIRBlock block, int index) {
Construction::getOldInstruction(result) =
getOldBlock(block).getInstruction(index)
}
cached int getInstructionCount(TIRBlock block) {
result = getOldBlock(block).getInstructionCount()
}
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ, EdgeKind kind) {
succ = MkIRBlock(getOldBlock(pred).getSuccessor(kind))
}
cached predicate blockSuccessor(TIRBlock pred, TIRBlock succ) {
blockSuccessor(pred, succ, _)
}
cached predicate blockImmediatelyDominates(TIRBlock dominator, TIRBlock block) {
getOldBlock(dominator).immediatelyDominates(getOldBlock(block))
}
cached Instruction getFirstInstruction(TIRBlock block) {
Construction::getOldInstruction(result) =
getOldBlock(block).getFirstInstruction()
}
}

View File

@@ -1,9 +1,7 @@
import SSAConstructionInternal
import cpp
private import semmle.code.cpp.ir.implementation.Opcode
private import semmle.code.cpp.ir.internal.OperandTag
private import NewIR
import IRBlockConstruction as BlockConstruction
import Cached
cached private module Cached {