C++: Factor out IRBlock.qll differences

All three `IRBlock.qll` files are now identical again, and they are just
a thin object-oriented layer on top of the three
`IRBlockConstruction.qll` files, two of which are identical.
This commit is contained in:
Jonas Jensen
2018-08-14 14:12:26 +02:00
parent d88c9c67f1
commit dc22833259
7 changed files with 190 additions and 146 deletions

View File

@@ -1,78 +1,11 @@
private import IRInternal
private import IRBlockConstruction
import Instruction import Instruction
import cpp
import semmle.code.cpp.ir.EdgeKind import semmle.code.cpp.ir.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))
}
private import Cached
private cached module Cached {
cached newtype TIRBlock =
MkIRBlock(Instruction firstInstr) {
startsBasicBlock(firstInstr)
}
cached Instruction getInstruction(TIRBlock block, int index) {
index = 0 and block = MkIRBlock(result) or
(
index > 0 and
not startsBasicBlock(result) and
exists(Instruction predecessor, GotoEdge edge |
predecessor = getInstruction(block, index - 1) and
result = predecessor.getSuccessor(edge)
)
)
}
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)
}
class IRBlock extends TIRBlock { class IRBlock extends TIRBlock {
Instruction firstInstr;
IRBlock() {
this = MkIRBlock(firstInstr)
}
final string toString() { final string toString() {
result = firstInstr.toString() result = getFirstInstruction(this).toString()
} }
final Location getLocation() { final Location getLocation() {
@@ -80,7 +13,7 @@ class IRBlock extends TIRBlock {
} }
final string getUniqueId() { final string getUniqueId() {
result = firstInstr.getUniqueId() result = getFirstInstruction(this).getUniqueId()
} }
final Instruction getInstruction(int index) { final Instruction getInstruction(int index) {
@@ -88,7 +21,7 @@ class IRBlock extends TIRBlock {
} }
final PhiInstruction getAPhiInstruction() { final PhiInstruction getAPhiInstruction() {
none() Construction::getPhiInstructionBlockStart(result) = getFirstInstruction()
} }
final Instruction getAnInstruction() { final Instruction getAnInstruction() {
@@ -97,7 +30,7 @@ class IRBlock extends TIRBlock {
} }
final Instruction getFirstInstruction() { final Instruction getFirstInstruction() {
result = firstInstr result = getFirstInstruction(this)
} }
final Instruction getLastInstruction() { final Instruction getLastInstruction() {
@@ -109,11 +42,11 @@ class IRBlock extends TIRBlock {
} }
final FunctionIR getFunctionIR() { final FunctionIR getFunctionIR() {
result = firstInstr.getFunctionIR() result = getFirstInstruction(this).getFunctionIR()
} }
final Function getFunction() { final Function getFunction() {
result = firstInstr.getFunction() result = getFirstInstruction(this).getFunction()
} }
final IRBlock getASuccessor() { final IRBlock getASuccessor() {

View File

@@ -0,0 +1,70 @@
private import IRInternal
import Instruction
import cpp
import semmle.code.cpp.ir.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)
}
cached Instruction getInstruction(TIRBlock block, int index) {
index = 0 and block = MkIRBlock(result) or
(
index > 0 and
not startsBasicBlock(result) and
exists(Instruction predecessor, GotoEdge edge |
predecessor = getInstruction(block, index - 1) and
result = predecessor.getSuccessor(edge)
)
)
}
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,7 +1,6 @@
import cpp import cpp
import semmle.code.cpp.ir.IR import semmle.code.cpp.ir.IR
private import InstructionTag private import InstructionTag
private import Opcode
private import TempVariableTag private import TempVariableTag
private import TranslatedElement private import TranslatedElement
private import TranslatedFunction private import TranslatedFunction

View File

@@ -1,36 +1,27 @@
private import IRInternal private import IRInternal
private import Construction::OldIR as OldIR private import IRBlockConstruction
import Instruction import Instruction
import semmle.code.cpp.ir.EdgeKind import semmle.code.cpp.ir.EdgeKind
cached newtype TIRBlock = MkIRBlock(OldIR::IRBlock oldBlock)
class IRBlock extends TIRBlock { class IRBlock extends TIRBlock {
OldIR::IRBlock oldBlock;
IRBlock() {
this = MkIRBlock(oldBlock)
}
final string toString() { final string toString() {
result = oldBlock.toString() result = getFirstInstruction(this).toString()
} }
final Location getLocation() { final Location getLocation() {
result = oldBlock.getLocation() result = getFirstInstruction().getLocation()
} }
final string getUniqueId() { final string getUniqueId() {
result = oldBlock.getUniqueId() result = getFirstInstruction(this).getUniqueId()
} }
final Instruction getInstruction(int index) { final Instruction getInstruction(int index) {
Construction::getOldInstruction(result) = oldBlock.getInstruction(index) result = getInstruction(this, index)
} }
final PhiInstruction getAPhiInstruction() { final PhiInstruction getAPhiInstruction() {
Construction::getPhiInstructionBlockStart(result) = Construction::getPhiInstructionBlockStart(result) = getFirstInstruction()
getFirstInstruction()
} }
final Instruction getAnInstruction() { final Instruction getAnInstruction() {
@@ -39,47 +30,43 @@ class IRBlock extends TIRBlock {
} }
final Instruction getFirstInstruction() { final Instruction getFirstInstruction() {
Construction::getOldInstruction(result) = oldBlock.getFirstInstruction() result = getFirstInstruction(this)
} }
final Instruction getLastInstruction() { final Instruction getLastInstruction() {
Construction::getOldInstruction(result) = oldBlock.getLastInstruction() result = getInstruction(getInstructionCount() - 1)
} }
final int getInstructionCount() { final int getInstructionCount() {
result = oldBlock.getInstructionCount() result = strictcount(getInstruction(_))
} }
final FunctionIR getFunctionIR() { final FunctionIR getFunctionIR() {
result = getFirstInstruction().getFunctionIR() result = getFirstInstruction(this).getFunctionIR()
} }
final Function getFunction() { final Function getFunction() {
result = getFirstInstruction().getFunction() result = getFirstInstruction(this).getFunction()
} }
final IRBlock getASuccessor() { final IRBlock getASuccessor() {
result = MkIRBlock(oldBlock.getASuccessor()) blockSuccessor(this, result)
} }
final IRBlock getAPredecessor() { final IRBlock getAPredecessor() {
result.getASuccessor() = this blockSuccessor(result, this)
} }
final IRBlock getSuccessor(EdgeKind kind) { final IRBlock getSuccessor(EdgeKind kind) {
result = MkIRBlock(oldBlock.getSuccessor(kind)) blockSuccessor(this, result, kind)
} }
final predicate immediatelyDominates(IRBlock block) { final predicate immediatelyDominates(IRBlock block) {
oldBlock.immediatelyDominates(block.getOldBlock()) blockImmediatelyDominates(this, block)
} }
final predicate strictlyDominates(IRBlock block) { final predicate strictlyDominates(IRBlock block) {
// This is recomputed from scratch rather than reusing the corresponding blockImmediatelyDominates+(this, block)
// predicate of `getOldBlock` because `getOldBlock.strictlyDominates/1` may
// at run time be a compactly stored transitive closure that we don't want
// to risk materializing in order to join with `MkIRBlock`.
immediatelyDominates+(block)
} }
final predicate dominates(IRBlock block) { final predicate dominates(IRBlock block) {
@@ -91,8 +78,4 @@ class IRBlock extends TIRBlock {
dominates(result.getAPredecessor()) and dominates(result.getAPredecessor()) and
not strictlyDominates(result) not strictlyDominates(result)
} }
private OldIR::IRBlock getOldBlock() {
result = oldBlock
}
} }

View File

@@ -0,0 +1,38 @@
private import IRInternal
private import Construction::OldIR as OldIR
import Instruction
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,36 +1,27 @@
private import IRInternal private import IRInternal
private import Construction::OldIR as OldIR private import IRBlockConstruction
import Instruction import Instruction
import semmle.code.cpp.ir.EdgeKind import semmle.code.cpp.ir.EdgeKind
cached newtype TIRBlock = MkIRBlock(OldIR::IRBlock oldBlock)
class IRBlock extends TIRBlock { class IRBlock extends TIRBlock {
OldIR::IRBlock oldBlock;
IRBlock() {
this = MkIRBlock(oldBlock)
}
final string toString() { final string toString() {
result = oldBlock.toString() result = getFirstInstruction(this).toString()
} }
final Location getLocation() { final Location getLocation() {
result = oldBlock.getLocation() result = getFirstInstruction().getLocation()
} }
final string getUniqueId() { final string getUniqueId() {
result = oldBlock.getUniqueId() result = getFirstInstruction(this).getUniqueId()
} }
final Instruction getInstruction(int index) { final Instruction getInstruction(int index) {
Construction::getOldInstruction(result) = oldBlock.getInstruction(index) result = getInstruction(this, index)
} }
final PhiInstruction getAPhiInstruction() { final PhiInstruction getAPhiInstruction() {
Construction::getPhiInstructionBlockStart(result) = Construction::getPhiInstructionBlockStart(result) = getFirstInstruction()
getFirstInstruction()
} }
final Instruction getAnInstruction() { final Instruction getAnInstruction() {
@@ -39,47 +30,43 @@ class IRBlock extends TIRBlock {
} }
final Instruction getFirstInstruction() { final Instruction getFirstInstruction() {
Construction::getOldInstruction(result) = oldBlock.getFirstInstruction() result = getFirstInstruction(this)
} }
final Instruction getLastInstruction() { final Instruction getLastInstruction() {
Construction::getOldInstruction(result) = oldBlock.getLastInstruction() result = getInstruction(getInstructionCount() - 1)
} }
final int getInstructionCount() { final int getInstructionCount() {
result = oldBlock.getInstructionCount() result = strictcount(getInstruction(_))
} }
final FunctionIR getFunctionIR() { final FunctionIR getFunctionIR() {
result = getFirstInstruction().getFunctionIR() result = getFirstInstruction(this).getFunctionIR()
} }
final Function getFunction() { final Function getFunction() {
result = getFirstInstruction().getFunction() result = getFirstInstruction(this).getFunction()
} }
final IRBlock getASuccessor() { final IRBlock getASuccessor() {
result = MkIRBlock(oldBlock.getASuccessor()) blockSuccessor(this, result)
} }
final IRBlock getAPredecessor() { final IRBlock getAPredecessor() {
result.getASuccessor() = this blockSuccessor(result, this)
} }
final IRBlock getSuccessor(EdgeKind kind) { final IRBlock getSuccessor(EdgeKind kind) {
result = MkIRBlock(oldBlock.getSuccessor(kind)) blockSuccessor(this, result, kind)
} }
final predicate immediatelyDominates(IRBlock block) { final predicate immediatelyDominates(IRBlock block) {
oldBlock.immediatelyDominates(block.getOldBlock()) blockImmediatelyDominates(this, block)
} }
final predicate strictlyDominates(IRBlock block) { final predicate strictlyDominates(IRBlock block) {
// This is recomputed from scratch rather than reusing the corresponding blockImmediatelyDominates+(this, block)
// predicate of `getOldBlock` because `getOldBlock.strictlyDominates/1` may
// at run time be a compactly stored transitive closure that we don't want
// to risk materializing in order to join with `MkIRBlock`.
immediatelyDominates+(block)
} }
final predicate dominates(IRBlock block) { final predicate dominates(IRBlock block) {
@@ -91,8 +78,4 @@ class IRBlock extends TIRBlock {
dominates(result.getAPredecessor()) and dominates(result.getAPredecessor()) and
not strictlyDominates(result) not strictlyDominates(result)
} }
private OldIR::IRBlock getOldBlock() {
result = oldBlock
}
} }

View File

@@ -0,0 +1,38 @@
private import IRInternal
private import Construction::OldIR as OldIR
import Instruction
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()
}
}