mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #648 from dave-bartolomeo/dave/UnreachableIR
C++: Remove unreachable IR
This commit is contained in:
@@ -68,7 +68,8 @@ private newtype TOpcode =
|
||||
TBufferReadSideEffect() or
|
||||
TBufferWriteSideEffect() or
|
||||
TBufferMayWriteSideEffect() or
|
||||
TChi()
|
||||
TChi() or
|
||||
TUnreached()
|
||||
|
||||
class Opcode extends TOpcode {
|
||||
string toString() {
|
||||
@@ -195,5 +196,6 @@ module Opcode {
|
||||
class BufferReadSideEffect extends ReadSideEffectOpcode, BufferAccessOpcode, TBufferReadSideEffect { override final string toString() { result = "BufferReadSideEffect" } }
|
||||
class BufferWriteSideEffect extends WriteSideEffectOpcode, BufferAccessOpcode, TBufferWriteSideEffect { override final string toString() { result = "BufferWriteSideEffect" } }
|
||||
class BufferMayWriteSideEffect extends MayWriteSideEffectOpcode, BufferAccessOpcode, TBufferMayWriteSideEffect { override final string toString() { result = "BufferMayWriteSideEffect" } }
|
||||
class Chi extends Opcode, TChi {override final string toString() { result = "Chi" } }
|
||||
class Chi extends Opcode, TChi { override final string toString() { result = "Chi" } }
|
||||
class Unreached extends Opcode, TUnreached { override final string toString() { result = "Unreached" } }
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
private import internal.IRInternal
|
||||
import Instruction
|
||||
import semmle.code.cpp.ir.implementation.EdgeKind
|
||||
import Cached
|
||||
private import Cached
|
||||
|
||||
class IRBlock extends TIRBlock {
|
||||
final string toString() {
|
||||
|
||||
@@ -102,7 +102,8 @@ module InstructionSanity {
|
||||
not exists(instr.getASuccessor()) and
|
||||
not instr instanceof ExitFunctionInstruction and
|
||||
// Phi instructions aren't linked into the instruction-level flow graph.
|
||||
not instr instanceof PhiInstruction
|
||||
not instr instanceof PhiInstruction and
|
||||
not instr instanceof UnreachedInstruction
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -451,8 +452,7 @@ class Instruction extends Construction::TInstruction {
|
||||
final predicate isResultModeled() {
|
||||
// Register results are always in SSA form.
|
||||
not hasMemoryResult() or
|
||||
// An unmodeled result will have a use on the `UnmodeledUse` instruction.
|
||||
not (getAUse() instanceof UnmodeledUseOperand)
|
||||
Construction::hasModeledMemoryResult(this)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1469,6 +1469,17 @@ class ChiInstruction extends Instruction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing unreachable code. Inserted in place of the original target
|
||||
* instruction of a `ConditionalBranch` or `Switch` instruction where that particular edge is
|
||||
* infeasible.
|
||||
*/
|
||||
class UnreachedInstruction extends Instruction {
|
||||
UnreachedInstruction() {
|
||||
opcode instanceof Opcode::Unreached
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing a built-in operation. This is used to represent
|
||||
* operations such as access to variable argument lists.
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
private import internal.ConstantAnalysisInternal
|
||||
import semmle.code.cpp.ir.internal.IntegerConstant
|
||||
private import IR
|
||||
|
||||
language[monotonicAggregates]
|
||||
IntValue getConstantValue(Instruction instr) {
|
||||
result = instr.(IntegerConstantInstruction).getValue().toInt() or
|
||||
exists(BinaryInstruction binInstr, IntValue left, IntValue right |
|
||||
binInstr = instr and
|
||||
left = getConstantValue(binInstr.getLeftOperand()) and
|
||||
right = getConstantValue(binInstr.getRightOperand()) and
|
||||
(
|
||||
binInstr instanceof AddInstruction and result = add(left, right) or
|
||||
binInstr instanceof SubInstruction and result = sub(left, right) or
|
||||
binInstr instanceof MulInstruction and result = mul(left, right) or
|
||||
binInstr instanceof DivInstruction and result = div(left, right) or
|
||||
binInstr instanceof CompareEQInstruction and result = compareEQ(left, right) or
|
||||
binInstr instanceof CompareNEInstruction and result = compareNE(left, right) or
|
||||
binInstr instanceof CompareLTInstruction and result = compareLT(left, right) or
|
||||
binInstr instanceof CompareGTInstruction and result = compareGT(left, right) or
|
||||
binInstr instanceof CompareLEInstruction and result = compareLE(left, right) or
|
||||
binInstr instanceof CompareGEInstruction and result = compareGE(left, right)
|
||||
)
|
||||
) or
|
||||
exists(UnaryInstruction unaryInstr, IntValue src |
|
||||
unaryInstr = instr and
|
||||
src = getConstantValue(unaryInstr.getOperand()) and
|
||||
(
|
||||
unaryInstr instanceof NegateInstruction and result = neg(src)
|
||||
)
|
||||
) or
|
||||
result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or
|
||||
exists(PhiInstruction phi |
|
||||
phi = instr and
|
||||
result = max(PhiOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction())) and
|
||||
result = min(PhiOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction()))
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
private import internal.ConstantAnalysisInternal
|
||||
private import semmle.code.cpp.ir.internal.IntegerConstant
|
||||
private import ConstantAnalysis
|
||||
import IR
|
||||
|
||||
private class ConstantAnalysisPropertyProvider extends IRPropertyProvider {
|
||||
override string getInstructionProperty(Instruction instr, string key) {
|
||||
key = "ConstantValue" and
|
||||
result = getValue(getConstantValue(instr)).toString()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
import semmle.code.cpp.ir.implementation.aliased_ssa.IR as IR
|
||||
@@ -268,9 +268,10 @@ MemoryAccess getOperandMemoryAccess(Operand operand) {
|
||||
if exists(IRVariable var, IntValue i |
|
||||
resultPointsTo(operand.getAddressOperand().getDefinitionInstruction(), var, i)
|
||||
)
|
||||
then exists(IRVariable var, IntValue i |
|
||||
then exists(IRVariable var, IntValue i, int size |
|
||||
resultPointsTo(operand.getAddressOperand().getDefinitionInstruction(), var, i) and
|
||||
result = getVariableMemoryAccess(var, i, operand.getDefinitionInstruction().getResultSize())
|
||||
result = getVariableMemoryAccess(var, i, size) and
|
||||
size = operand.getDefinitionInstruction().getResultSize()
|
||||
)
|
||||
else (
|
||||
result = TUnknownMemoryAccess(TUnknownVirtualVariable(operand.getInstruction().getFunctionIR())) and
|
||||
|
||||
@@ -4,23 +4,35 @@ private import semmle.code.cpp.ir.implementation.Opcode
|
||||
private import semmle.code.cpp.ir.internal.OperandTag
|
||||
private import NewIR
|
||||
|
||||
private class OldBlock = Reachability::ReachableBlock;
|
||||
private class OldInstruction = Reachability::ReachableInstruction;
|
||||
|
||||
import Cached
|
||||
cached private module Cached {
|
||||
|
||||
private IRBlock getNewBlock(OldIR::IRBlock oldBlock) {
|
||||
private IRBlock getNewBlock(OldBlock oldBlock) {
|
||||
result.getFirstInstruction() = getNewInstruction(oldBlock.getFirstInstruction())
|
||||
}
|
||||
|
||||
cached newtype TInstructionTag =
|
||||
WrappedInstructionTag(OldIR::Instruction oldInstruction) {
|
||||
WrappedInstructionTag(OldInstruction oldInstruction) {
|
||||
not oldInstruction instanceof OldIR::PhiInstruction
|
||||
} or
|
||||
PhiTag(Alias::VirtualVariable vvar, OldIR::IRBlock block) {
|
||||
PhiTag(Alias::VirtualVariable vvar, OldBlock block) {
|
||||
hasPhiNode(vvar, block)
|
||||
} or
|
||||
ChiTag(OldIR::Instruction oldInstruction) {
|
||||
ChiTag(OldInstruction oldInstruction) {
|
||||
not oldInstruction instanceof OldIR::PhiInstruction and
|
||||
hasChiNode(_, oldInstruction)
|
||||
} or
|
||||
UnreachedTag(OldInstruction oldInstruction, EdgeKind kind) {
|
||||
// We need an `Unreached` instruction for the destination of any edge whose predecessor
|
||||
// instruction is reachable, but whose successor block is not. This should occur only for
|
||||
// infeasible edges.
|
||||
exists(OldIR::Instruction succInstruction |
|
||||
succInstruction = oldInstruction.getSuccessor(kind) and
|
||||
not succInstruction instanceof OldInstruction
|
||||
)
|
||||
}
|
||||
|
||||
cached class InstructionTagType extends TInstructionTag {
|
||||
@@ -35,11 +47,11 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached OldIR::Instruction getOldInstruction(Instruction instr) {
|
||||
cached OldInstruction getOldInstruction(Instruction instr) {
|
||||
instr.getTag() = WrappedInstructionTag(result)
|
||||
}
|
||||
|
||||
private Instruction getNewInstruction(OldIR::Instruction instr) {
|
||||
private Instruction getNewInstruction(OldInstruction instr) {
|
||||
getOldInstruction(result) = instr
|
||||
}
|
||||
|
||||
@@ -47,21 +59,21 @@ cached private module Cached {
|
||||
* Gets the chi node corresponding to `instr` if one is present, or the new `Instruction`
|
||||
* corresponding to `instr` if there is no `Chi` node.
|
||||
*/
|
||||
private Instruction getNewFinalInstruction(OldIR::Instruction instr) {
|
||||
private Instruction getNewFinalInstruction(OldInstruction instr) {
|
||||
result = getChiInstruction(instr)
|
||||
or
|
||||
not exists(getChiInstruction(instr)) and
|
||||
result = getNewInstruction(instr)
|
||||
}
|
||||
|
||||
private PhiInstruction getPhiInstruction(Function func, OldIR::IRBlock oldBlock,
|
||||
private PhiInstruction getPhiInstruction(Function func, OldBlock oldBlock,
|
||||
Alias::VirtualVariable vvar) {
|
||||
result.getFunction() = func and
|
||||
result.getAST() = oldBlock.getFirstInstruction().getAST() and
|
||||
result.getTag() = PhiTag(vvar, oldBlock)
|
||||
}
|
||||
|
||||
private ChiInstruction getChiInstruction (OldIR::Instruction instr) {
|
||||
private ChiInstruction getChiInstruction (OldInstruction instr) {
|
||||
hasChiNode(_, instr) and
|
||||
result.getTag() = ChiTag(instr)
|
||||
}
|
||||
@@ -91,8 +103,8 @@ cached private module Cached {
|
||||
}
|
||||
|
||||
private predicate hasInstruction(Function func, Opcode opcode, Locatable ast,
|
||||
InstructionTag tag, Type resultType, boolean isGLValue) {
|
||||
exists(OldIR::Instruction instr |
|
||||
InstructionTag tag, Type resultType, boolean isGLValue) {
|
||||
exists(OldInstruction instr |
|
||||
instr.getFunction() = func and
|
||||
instr.getOpcode() = opcode and
|
||||
instr.getAST() = ast and
|
||||
@@ -103,7 +115,7 @@ cached private module Cached {
|
||||
else
|
||||
isGLValue = false
|
||||
) or
|
||||
exists(OldIR::IRBlock block, Alias::VirtualVariable vvar |
|
||||
exists(OldBlock block, Alias::VirtualVariable vvar |
|
||||
hasPhiNode(vvar, block) and
|
||||
block.getFunction() = func and
|
||||
opcode instanceof Opcode::Phi and
|
||||
@@ -112,7 +124,7 @@ cached private module Cached {
|
||||
resultType = vvar.getType() and
|
||||
isGLValue = false
|
||||
) or
|
||||
exists(OldIR::Instruction instr, Alias::VirtualVariable vvar |
|
||||
exists(OldInstruction instr, Alias::VirtualVariable vvar |
|
||||
hasChiNode(vvar, instr) and
|
||||
instr.getFunction() = func and
|
||||
opcode instanceof Opcode::Chi and
|
||||
@@ -120,11 +132,19 @@ cached private module Cached {
|
||||
tag = ChiTag(instr) and
|
||||
resultType = vvar.getType() and
|
||||
isGLValue = false
|
||||
) or
|
||||
exists(OldInstruction oldInstruction, EdgeKind kind |
|
||||
oldInstruction.getFunction() = func and
|
||||
tag = UnreachedTag(oldInstruction, kind) and
|
||||
opcode instanceof Opcode::Unreached and
|
||||
ast = oldInstruction.getSuccessor(kind).getAST() and
|
||||
resultType instanceof VoidType and
|
||||
isGLValue = false
|
||||
)
|
||||
}
|
||||
|
||||
cached predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag,
|
||||
Type type) {
|
||||
Type type) {
|
||||
exists(OldIR::IRTempVariable var |
|
||||
var.getFunction() = func and
|
||||
var.getAST() = ast and
|
||||
@@ -135,19 +155,20 @@ cached private module Cached {
|
||||
|
||||
cached predicate hasModeledMemoryResult(Instruction instruction) {
|
||||
exists(Alias::getResultMemoryAccess(getOldInstruction(instruction))) or
|
||||
instruction instanceof PhiInstruction // Phis always have modeled results
|
||||
instruction instanceof PhiInstruction or // Phis always have modeled results
|
||||
instruction instanceof ChiInstruction // Chis always have modeled results
|
||||
}
|
||||
|
||||
cached Instruction getInstructionOperandDefinition(Instruction instruction, OperandTag tag) {
|
||||
exists(OldIR::Instruction oldInstruction, OldIR::NonPhiOperand oldOperand |
|
||||
exists(OldInstruction oldInstruction, OldIR::NonPhiOperand oldOperand |
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
oldOperand = oldInstruction.getAnOperand() and
|
||||
tag = oldOperand.getOperandTag() and
|
||||
if oldOperand instanceof OldIR::MemoryOperand then (
|
||||
(
|
||||
if exists(Alias::getOperandMemoryAccess(oldOperand)) then (
|
||||
exists(OldIR::IRBlock useBlock, int useRank, Alias::VirtualVariable vvar,
|
||||
OldIR::IRBlock defBlock, int defRank, int defIndex |
|
||||
exists(OldBlock useBlock, int useRank, Alias::VirtualVariable vvar,
|
||||
OldBlock defBlock, int defRank, int defIndex |
|
||||
vvar = Alias::getOperandMemoryAccess(oldOperand).getVirtualVariable() and
|
||||
hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and
|
||||
hasUseAtRank(vvar, useBlock, useRank, oldInstruction) and
|
||||
@@ -164,7 +185,7 @@ cached private module Cached {
|
||||
) or
|
||||
// Connect any definitions that are not being modeled in SSA to the
|
||||
// `UnmodeledUse` instruction.
|
||||
exists(OldIR::Instruction oldDefinition |
|
||||
exists(OldInstruction oldDefinition |
|
||||
instruction instanceof UnmodeledUseInstruction and
|
||||
tag instanceof UnmodeledUseOperandTag and
|
||||
oldDefinition = oldOperand.getDefinitionInstruction() and
|
||||
@@ -189,8 +210,8 @@ cached private module Cached {
|
||||
|
||||
cached Instruction getPhiInstructionOperandDefinition(PhiInstruction instr,
|
||||
IRBlock newPredecessorBlock) {
|
||||
exists(Alias::VirtualVariable vvar, OldIR::IRBlock phiBlock,
|
||||
OldIR::IRBlock defBlock, int defRank, int defIndex, OldIR::IRBlock predBlock |
|
||||
exists(Alias::VirtualVariable vvar, OldBlock phiBlock,
|
||||
OldBlock defBlock, int defRank, int defIndex, OldBlock predBlock |
|
||||
hasPhiNode(vvar, phiBlock) and
|
||||
predBlock = phiBlock.getAPredecessor() and
|
||||
instr.getTag() = PhiTag(vvar, phiBlock) and
|
||||
@@ -205,8 +226,8 @@ cached private module Cached {
|
||||
}
|
||||
|
||||
cached Instruction getChiInstructionTotalOperand(ChiInstruction chiInstr) {
|
||||
exists(Alias::VirtualVariable vvar, OldIR::Instruction oldInstr, OldIR::IRBlock defBlock,
|
||||
int defRank, int defIndex, OldIR::IRBlock useBlock, int useRank |
|
||||
exists(Alias::VirtualVariable vvar, OldInstruction oldInstr, OldBlock defBlock,
|
||||
int defRank, int defIndex, OldBlock useBlock, int useRank |
|
||||
ChiTag(oldInstr) = chiInstr.getTag() and
|
||||
vvar = Alias::getResultMemoryAccess(oldInstr).getVirtualVariable() and
|
||||
hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and
|
||||
@@ -220,7 +241,7 @@ cached private module Cached {
|
||||
}
|
||||
|
||||
cached Instruction getPhiInstructionBlockStart(PhiInstruction instr) {
|
||||
exists(OldIR::IRBlock oldBlock |
|
||||
exists(OldBlock oldBlock |
|
||||
instr.getTag() = PhiTag(_, oldBlock) and
|
||||
result = getNewInstruction(oldBlock.getFirstInstruction())
|
||||
)
|
||||
@@ -247,10 +268,11 @@ cached private module Cached {
|
||||
else (
|
||||
result = getNewInstruction(getOldInstruction(instruction).getSuccessor(kind))
|
||||
or
|
||||
exists(OldIR::Instruction oldInstruction |
|
||||
exists(OldInstruction oldInstruction |
|
||||
instruction = getChiInstruction(oldInstruction) and
|
||||
result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
)
|
||||
) or
|
||||
result.getTag() = UnreachedTag(getOldInstruction(instruction), kind)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -310,29 +332,29 @@ cached private module Cached {
|
||||
}
|
||||
|
||||
private predicate ssa_variableUpdate(Alias::VirtualVariable vvar,
|
||||
OldIR::Instruction instr, OldIR::IRBlock block, int index) {
|
||||
OldInstruction instr, OldBlock block, int index) {
|
||||
block.getInstruction(index) = instr and
|
||||
Alias::getResultMemoryAccess(instr).getVirtualVariable() = vvar
|
||||
}
|
||||
|
||||
private predicate hasDefinition(Alias::VirtualVariable vvar, OldIR::IRBlock block, int index) {
|
||||
private predicate hasDefinition(Alias::VirtualVariable vvar, OldBlock block, int index) {
|
||||
(
|
||||
hasPhiNode(vvar, block) and
|
||||
index = -1
|
||||
) or
|
||||
exists(Alias::MemoryAccess access, OldIR::Instruction def |
|
||||
exists(Alias::MemoryAccess access, OldInstruction def |
|
||||
access = Alias::getResultMemoryAccess(def) and
|
||||
block.getInstruction(index) = def and
|
||||
vvar = access.getVirtualVariable()
|
||||
)
|
||||
}
|
||||
|
||||
private predicate defUseRank(Alias::VirtualVariable vvar, OldIR::IRBlock block, int rankIndex, int index) {
|
||||
private predicate defUseRank(Alias::VirtualVariable vvar, OldBlock block, int rankIndex, int index) {
|
||||
index = rank[rankIndex](int j | hasDefinition(vvar, block, j) or hasUse(vvar, _, block, j))
|
||||
}
|
||||
|
||||
private predicate hasUse(Alias::VirtualVariable vvar,
|
||||
OldIR::Instruction use, OldIR::IRBlock block, int index) {
|
||||
private predicate hasUse(Alias::VirtualVariable vvar, OldInstruction use, OldBlock block,
|
||||
int index) {
|
||||
exists(Alias::MemoryAccess access |
|
||||
(
|
||||
access = Alias::getOperandMemoryAccess(use.getAnOperand())
|
||||
@@ -349,7 +371,7 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate variableLiveOnEntryToBlock(Alias::VirtualVariable vvar, OldIR::IRBlock block) {
|
||||
private predicate variableLiveOnEntryToBlock(Alias::VirtualVariable vvar, OldBlock block) {
|
||||
exists (int index | hasUse(vvar, _, block, index) |
|
||||
not exists (int j | ssa_variableUpdate(vvar, _, block, j) | j < index)
|
||||
) or
|
||||
@@ -357,7 +379,7 @@ cached private module Cached {
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate variableLiveOnExitFromBlock(Alias::VirtualVariable vvar, OldIR::IRBlock block) {
|
||||
private predicate variableLiveOnExitFromBlock(Alias::VirtualVariable vvar, OldBlock block) {
|
||||
variableLiveOnEntryToBlock(vvar, block.getASuccessor())
|
||||
}
|
||||
|
||||
@@ -367,18 +389,18 @@ cached private module Cached {
|
||||
* end of the block, even if the definition is the last instruction in the
|
||||
* block.
|
||||
*/
|
||||
private int exitRank(Alias::VirtualVariable vvar, OldIR::IRBlock block) {
|
||||
private int exitRank(Alias::VirtualVariable vvar, OldBlock block) {
|
||||
result = max(int rankIndex | defUseRank(vvar, block, rankIndex, _)) + 1
|
||||
}
|
||||
|
||||
private predicate hasDefinitionAtRank(Alias::VirtualVariable vvar,
|
||||
OldIR::IRBlock block, int rankIndex, int instructionIndex) {
|
||||
private predicate hasDefinitionAtRank(Alias::VirtualVariable vvar, OldBlock block, int rankIndex,
|
||||
int instructionIndex) {
|
||||
hasDefinition(vvar, block, instructionIndex) and
|
||||
defUseRank(vvar, block, rankIndex, instructionIndex)
|
||||
}
|
||||
|
||||
private predicate hasUseAtRank(Alias::VirtualVariable vvar, OldIR::IRBlock block,
|
||||
int rankIndex, OldIR::Instruction use) {
|
||||
private predicate hasUseAtRank(Alias::VirtualVariable vvar, OldBlock block, int rankIndex,
|
||||
OldInstruction use) {
|
||||
exists(int index |
|
||||
hasUse(vvar, use, block, index) and
|
||||
defUseRank(vvar, block, rankIndex, index)
|
||||
@@ -389,8 +411,8 @@ cached private module Cached {
|
||||
* Holds if the definition of `vvar` at `(block, defRank)` reaches the rank
|
||||
* index `reachesRank` in block `block`.
|
||||
*/
|
||||
private predicate definitionReachesRank(Alias::VirtualVariable vvar,
|
||||
OldIR::IRBlock block, int defRank, int reachesRank) {
|
||||
private predicate definitionReachesRank(Alias::VirtualVariable vvar, OldBlock block, int defRank,
|
||||
int reachesRank) {
|
||||
hasDefinitionAtRank(vvar, block, defRank, _) and
|
||||
reachesRank <= exitRank(vvar, block) and // Without this, the predicate would be infinite.
|
||||
(
|
||||
@@ -410,8 +432,8 @@ cached private module Cached {
|
||||
* Holds if the definition of `vvar` at `(defBlock, defRank)` reaches the end of
|
||||
* block `block`.
|
||||
*/
|
||||
private predicate definitionReachesEndOfBlock(Alias::VirtualVariable vvar,
|
||||
OldIR::IRBlock defBlock, int defRank, OldIR::IRBlock block) {
|
||||
private predicate definitionReachesEndOfBlock(Alias::VirtualVariable vvar, OldBlock defBlock,
|
||||
int defRank, OldBlock block) {
|
||||
hasDefinitionAtRank(vvar, defBlock, defRank, _) and
|
||||
(
|
||||
(
|
||||
@@ -421,7 +443,7 @@ cached private module Cached {
|
||||
variableLiveOnExitFromBlock(vvar, defBlock) and
|
||||
definitionReachesRank(vvar, defBlock, defRank, exitRank(vvar, defBlock))
|
||||
) or
|
||||
exists(OldIR::IRBlock idom |
|
||||
exists(OldBlock idom |
|
||||
definitionReachesEndOfBlock(vvar, defBlock, defRank, idom) and
|
||||
noDefinitionsSinceIDominator(vvar, idom, block)
|
||||
)
|
||||
@@ -429,24 +451,23 @@ cached private module Cached {
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate noDefinitionsSinceIDominator(Alias::VirtualVariable vvar,
|
||||
OldIR::IRBlock idom, OldIR::IRBlock block) {
|
||||
idom.immediatelyDominates(block) and // It is sufficient to traverse the dominator graph, cf. discussion above.
|
||||
private predicate noDefinitionsSinceIDominator(Alias::VirtualVariable vvar, OldBlock idom,
|
||||
OldBlock block) {
|
||||
Dominance::blockImmediatelyDominates(idom, block) and // It is sufficient to traverse the dominator graph, cf. discussion above.
|
||||
variableLiveOnExitFromBlock(vvar, block) and
|
||||
not hasDefinition(vvar, block, _)
|
||||
}
|
||||
|
||||
private predicate definitionReachesUseWithinBlock(
|
||||
Alias::VirtualVariable vvar, OldIR::IRBlock defBlock, int defRank,
|
||||
OldIR::IRBlock useBlock, int useRank) {
|
||||
private predicate definitionReachesUseWithinBlock(Alias::VirtualVariable vvar, OldBlock defBlock,
|
||||
int defRank, OldBlock useBlock, int useRank) {
|
||||
defBlock = useBlock and
|
||||
hasDefinitionAtRank(vvar, defBlock, defRank, _) and
|
||||
hasUseAtRank(vvar, useBlock, useRank, _) and
|
||||
definitionReachesRank(vvar, defBlock, defRank, useRank)
|
||||
}
|
||||
|
||||
private predicate definitionReachesUse(Alias::VirtualVariable vvar,
|
||||
OldIR::IRBlock defBlock, int defRank, OldIR::IRBlock useBlock, int useRank) {
|
||||
private predicate definitionReachesUse(Alias::VirtualVariable vvar, OldBlock defBlock,
|
||||
int defRank, OldBlock useBlock, int useRank) {
|
||||
hasUseAtRank(vvar, useBlock, useRank, _) and
|
||||
(
|
||||
definitionReachesUseWithinBlock(vvar, defBlock, defRank, useBlock,
|
||||
@@ -459,24 +480,21 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate hasFrontierPhiNode(Alias::VirtualVariable vvar,
|
||||
OldIR::IRBlock phiBlock) {
|
||||
exists(OldIR::IRBlock defBlock |
|
||||
phiBlock = defBlock.dominanceFrontier() and
|
||||
private predicate hasFrontierPhiNode(Alias::VirtualVariable vvar, OldBlock phiBlock) {
|
||||
exists(OldBlock defBlock |
|
||||
phiBlock = Dominance::getDominanceFrontier(defBlock) and
|
||||
hasDefinition(vvar, defBlock, _) and
|
||||
/* We can also eliminate those nodes where the variable is not live on any incoming edge */
|
||||
variableLiveOnEntryToBlock(vvar, phiBlock)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate hasPhiNode(Alias::VirtualVariable vvar,
|
||||
OldIR::IRBlock phiBlock) {
|
||||
private predicate hasPhiNode(Alias::VirtualVariable vvar, OldBlock phiBlock) {
|
||||
hasFrontierPhiNode(vvar, phiBlock)
|
||||
//or ssa_sanitized_custom_phi_node(vvar, block)
|
||||
}
|
||||
|
||||
private predicate hasChiNode(Alias::VirtualVariable vvar,
|
||||
OldIR::Instruction def) {
|
||||
private predicate hasChiNode(Alias::VirtualVariable vvar, OldInstruction def) {
|
||||
exists(Alias::MemoryAccess ma |
|
||||
ma = Alias::getResultMemoryAccess(def) and
|
||||
ma.isPartialMemoryAccess() and
|
||||
@@ -492,13 +510,17 @@ cached private module CachedForDebugging {
|
||||
}
|
||||
|
||||
cached string getInstructionUniqueId(Instruction instr) {
|
||||
exists(OldIR::Instruction oldInstr |
|
||||
exists(OldInstruction oldInstr |
|
||||
oldInstr = getOldInstruction(instr) and
|
||||
result = "NonSSA: " + oldInstr.getUniqueId()
|
||||
) or
|
||||
exists(Alias::VirtualVariable vvar, OldIR::IRBlock phiBlock |
|
||||
exists(Alias::VirtualVariable vvar, OldBlock phiBlock |
|
||||
instr.getTag() = PhiTag(vvar, phiBlock) and
|
||||
result = "Phi Block(" + phiBlock.getUniqueId() + "): " + vvar.getUniqueId()
|
||||
) or
|
||||
exists(OldInstruction oldInstr, EdgeKind kind |
|
||||
instr.getTag() = UnreachedTag(oldInstr, kind) and
|
||||
result = "Unreached(" + oldInstr.getUniqueId() + ":" + kind.toString() + ")"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as OldIR
|
||||
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.reachability.ReachableBlock as Reachability
|
||||
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.reachability.Dominance as Dominance
|
||||
import semmle.code.cpp.ir.implementation.aliased_ssa.IR as NewIR
|
||||
import AliasedSSA as Alias
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
private import internal.IRInternal
|
||||
import Instruction
|
||||
import semmle.code.cpp.ir.implementation.EdgeKind
|
||||
import Cached
|
||||
private import Cached
|
||||
|
||||
class IRBlock extends TIRBlock {
|
||||
final string toString() {
|
||||
|
||||
@@ -102,7 +102,8 @@ module InstructionSanity {
|
||||
not exists(instr.getASuccessor()) and
|
||||
not instr instanceof ExitFunctionInstruction and
|
||||
// Phi instructions aren't linked into the instruction-level flow graph.
|
||||
not instr instanceof PhiInstruction
|
||||
not instr instanceof PhiInstruction and
|
||||
not instr instanceof UnreachedInstruction
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -451,8 +452,7 @@ class Instruction extends Construction::TInstruction {
|
||||
final predicate isResultModeled() {
|
||||
// Register results are always in SSA form.
|
||||
not hasMemoryResult() or
|
||||
// An unmodeled result will have a use on the `UnmodeledUse` instruction.
|
||||
not (getAUse() instanceof UnmodeledUseOperand)
|
||||
Construction::hasModeledMemoryResult(this)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1469,6 +1469,17 @@ class ChiInstruction extends Instruction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing unreachable code. Inserted in place of the original target
|
||||
* instruction of a `ConditionalBranch` or `Switch` instruction where that particular edge is
|
||||
* infeasible.
|
||||
*/
|
||||
class UnreachedInstruction extends Instruction {
|
||||
UnreachedInstruction() {
|
||||
opcode instanceof Opcode::Unreached
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing a built-in operation. This is used to represent
|
||||
* operations such as access to variable argument lists.
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
private import internal.ConstantAnalysisInternal
|
||||
import semmle.code.cpp.ir.internal.IntegerConstant
|
||||
private import IR
|
||||
|
||||
language[monotonicAggregates]
|
||||
IntValue getConstantValue(Instruction instr) {
|
||||
result = instr.(IntegerConstantInstruction).getValue().toInt() or
|
||||
exists(BinaryInstruction binInstr, IntValue left, IntValue right |
|
||||
binInstr = instr and
|
||||
left = getConstantValue(binInstr.getLeftOperand()) and
|
||||
right = getConstantValue(binInstr.getRightOperand()) and
|
||||
(
|
||||
binInstr instanceof AddInstruction and result = add(left, right) or
|
||||
binInstr instanceof SubInstruction and result = sub(left, right) or
|
||||
binInstr instanceof MulInstruction and result = mul(left, right) or
|
||||
binInstr instanceof DivInstruction and result = div(left, right) or
|
||||
binInstr instanceof CompareEQInstruction and result = compareEQ(left, right) or
|
||||
binInstr instanceof CompareNEInstruction and result = compareNE(left, right) or
|
||||
binInstr instanceof CompareLTInstruction and result = compareLT(left, right) or
|
||||
binInstr instanceof CompareGTInstruction and result = compareGT(left, right) or
|
||||
binInstr instanceof CompareLEInstruction and result = compareLE(left, right) or
|
||||
binInstr instanceof CompareGEInstruction and result = compareGE(left, right)
|
||||
)
|
||||
) or
|
||||
exists(UnaryInstruction unaryInstr, IntValue src |
|
||||
unaryInstr = instr and
|
||||
src = getConstantValue(unaryInstr.getOperand()) and
|
||||
(
|
||||
unaryInstr instanceof NegateInstruction and result = neg(src)
|
||||
)
|
||||
) or
|
||||
result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or
|
||||
exists(PhiInstruction phi |
|
||||
phi = instr and
|
||||
result = max(PhiOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction())) and
|
||||
result = min(PhiOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction()))
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
private import internal.ConstantAnalysisInternal
|
||||
private import semmle.code.cpp.ir.internal.IntegerConstant
|
||||
private import ConstantAnalysis
|
||||
import IR
|
||||
|
||||
private class ConstantAnalysisPropertyProvider extends IRPropertyProvider {
|
||||
override string getInstructionProperty(Instruction instr, string key) {
|
||||
key = "ConstantValue" and
|
||||
result = getValue(getConstantValue(instr)).toString()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
import semmle.code.cpp.ir.implementation.raw.IR as IR
|
||||
@@ -0,0 +1,21 @@
|
||||
private import DominanceInternal
|
||||
|
||||
predicate blockImmediatelyDominates(Graph::Block dominator, Graph::Block block) =
|
||||
idominance(Graph::isEntryBlock/1, Graph::blockSuccessor/2)(_, dominator, block)
|
||||
|
||||
predicate blockStrictlyDominates(Graph::Block dominator, Graph::Block block) {
|
||||
blockImmediatelyDominates+(dominator, block)
|
||||
}
|
||||
|
||||
predicate blockDominates(Graph::Block dominator, Graph::Block block) {
|
||||
blockStrictlyDominates(dominator, block) or dominator = block
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
Graph::Block getDominanceFrontier(Graph::Block dominator) {
|
||||
exists(Graph::Block pred |
|
||||
Graph::blockSuccessor(pred, result) and
|
||||
blockDominates(dominator, pred) and
|
||||
not blockStrictlyDominates(dominator, result)
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
private import ReachableBlock as Reachability
|
||||
private module ReachabilityGraph = Reachability::Graph;
|
||||
|
||||
module Graph {
|
||||
import Reachability::Graph
|
||||
class Block = Reachability::ReachableBlock;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
private import ReachableBlockInternal
|
||||
private import ReachableBlock
|
||||
import IR
|
||||
|
||||
private class ReachableBlockPropertyProvider extends IRPropertyProvider {
|
||||
override string getBlockProperty(IRBlock block, string key) {
|
||||
(
|
||||
not block instanceof ReachableBlock and
|
||||
key = "Unreachable" and
|
||||
result = "true"
|
||||
) or
|
||||
(
|
||||
exists(EdgeKind kind |
|
||||
isInfeasibleEdge(block, kind) and
|
||||
key = "Infeasible(" + kind.toString() + ")" and
|
||||
result = "true"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
private import ReachableBlockInternal
|
||||
private import semmle.code.cpp.ir.internal.IntegerConstant
|
||||
private import IR
|
||||
private import ConstantAnalysis
|
||||
|
||||
predicate isInfeasibleEdge(IRBlock block, EdgeKind kind) {
|
||||
exists(ConditionalBranchInstruction instr, int conditionValue |
|
||||
instr = block.getLastInstruction() and
|
||||
conditionValue = getValue(getConstantValue(instr.getCondition())) and
|
||||
if conditionValue = 0 then
|
||||
kind instanceof TrueEdge
|
||||
else
|
||||
kind instanceof FalseEdge
|
||||
)
|
||||
}
|
||||
|
||||
IRBlock getAFeasiblePredecessor(IRBlock successor) {
|
||||
exists(EdgeKind kind |
|
||||
result.getSuccessor(kind) = successor and
|
||||
not isInfeasibleEdge(result, kind)
|
||||
)
|
||||
}
|
||||
|
||||
predicate isBlockReachable(IRBlock block) {
|
||||
exists(FunctionIR f |
|
||||
getAFeasiblePredecessor*(block) = f.getEntryBlock()
|
||||
)
|
||||
}
|
||||
|
||||
predicate isInstructionReachable(Instruction instr) {
|
||||
isBlockReachable(instr.getBlock())
|
||||
}
|
||||
|
||||
class ReachableBlock extends IRBlock {
|
||||
ReachableBlock() {
|
||||
isBlockReachable(this)
|
||||
}
|
||||
}
|
||||
|
||||
class ReachableInstruction extends Instruction {
|
||||
ReachableInstruction() {
|
||||
this.getBlock() instanceof ReachableBlock
|
||||
}
|
||||
}
|
||||
|
||||
module Graph {
|
||||
predicate isEntryBlock(ReachableBlock block) {
|
||||
exists(FunctionIR f |
|
||||
block = f.getEntryBlock()
|
||||
)
|
||||
}
|
||||
|
||||
predicate blockSuccessor(ReachableBlock pred, ReachableBlock succ) {
|
||||
succ = pred.getASuccessor()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
import semmle.code.cpp.ir.implementation.raw.IR as IR
|
||||
import semmle.code.cpp.ir.implementation.raw.constant.ConstantAnalysis as ConstantAnalysis
|
||||
@@ -1,7 +1,7 @@
|
||||
private import internal.IRInternal
|
||||
import Instruction
|
||||
import semmle.code.cpp.ir.implementation.EdgeKind
|
||||
import Cached
|
||||
private import Cached
|
||||
|
||||
class IRBlock extends TIRBlock {
|
||||
final string toString() {
|
||||
|
||||
@@ -102,7 +102,8 @@ module InstructionSanity {
|
||||
not exists(instr.getASuccessor()) and
|
||||
not instr instanceof ExitFunctionInstruction and
|
||||
// Phi instructions aren't linked into the instruction-level flow graph.
|
||||
not instr instanceof PhiInstruction
|
||||
not instr instanceof PhiInstruction and
|
||||
not instr instanceof UnreachedInstruction
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -451,8 +452,7 @@ class Instruction extends Construction::TInstruction {
|
||||
final predicate isResultModeled() {
|
||||
// Register results are always in SSA form.
|
||||
not hasMemoryResult() or
|
||||
// An unmodeled result will have a use on the `UnmodeledUse` instruction.
|
||||
not (getAUse() instanceof UnmodeledUseOperand)
|
||||
Construction::hasModeledMemoryResult(this)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1469,6 +1469,17 @@ class ChiInstruction extends Instruction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing unreachable code. Inserted in place of the original target
|
||||
* instruction of a `ConditionalBranch` or `Switch` instruction where that particular edge is
|
||||
* infeasible.
|
||||
*/
|
||||
class UnreachedInstruction extends Instruction {
|
||||
UnreachedInstruction() {
|
||||
opcode instanceof Opcode::Unreached
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing a built-in operation. This is used to represent
|
||||
* operations such as access to variable argument lists.
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
private import internal.ConstantAnalysisInternal
|
||||
import semmle.code.cpp.ir.internal.IntegerConstant
|
||||
private import IR
|
||||
|
||||
language[monotonicAggregates]
|
||||
IntValue getConstantValue(Instruction instr) {
|
||||
result = instr.(IntegerConstantInstruction).getValue().toInt() or
|
||||
exists(BinaryInstruction binInstr, IntValue left, IntValue right |
|
||||
binInstr = instr and
|
||||
left = getConstantValue(binInstr.getLeftOperand()) and
|
||||
right = getConstantValue(binInstr.getRightOperand()) and
|
||||
(
|
||||
binInstr instanceof AddInstruction and result = add(left, right) or
|
||||
binInstr instanceof SubInstruction and result = sub(left, right) or
|
||||
binInstr instanceof MulInstruction and result = mul(left, right) or
|
||||
binInstr instanceof DivInstruction and result = div(left, right) or
|
||||
binInstr instanceof CompareEQInstruction and result = compareEQ(left, right) or
|
||||
binInstr instanceof CompareNEInstruction and result = compareNE(left, right) or
|
||||
binInstr instanceof CompareLTInstruction and result = compareLT(left, right) or
|
||||
binInstr instanceof CompareGTInstruction and result = compareGT(left, right) or
|
||||
binInstr instanceof CompareLEInstruction and result = compareLE(left, right) or
|
||||
binInstr instanceof CompareGEInstruction and result = compareGE(left, right)
|
||||
)
|
||||
) or
|
||||
exists(UnaryInstruction unaryInstr, IntValue src |
|
||||
unaryInstr = instr and
|
||||
src = getConstantValue(unaryInstr.getOperand()) and
|
||||
(
|
||||
unaryInstr instanceof NegateInstruction and result = neg(src)
|
||||
)
|
||||
) or
|
||||
result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or
|
||||
exists(PhiInstruction phi |
|
||||
phi = instr and
|
||||
result = max(PhiOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction())) and
|
||||
result = min(PhiOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction()))
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
private import internal.ConstantAnalysisInternal
|
||||
private import semmle.code.cpp.ir.internal.IntegerConstant
|
||||
private import ConstantAnalysis
|
||||
import IR
|
||||
|
||||
private class ConstantAnalysisPropertyProvider extends IRPropertyProvider {
|
||||
override string getInstructionProperty(Instruction instr, string key) {
|
||||
key = "ConstantValue" and
|
||||
result = getValue(getConstantValue(instr)).toString()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as IR
|
||||
@@ -4,23 +4,35 @@ private import semmle.code.cpp.ir.implementation.Opcode
|
||||
private import semmle.code.cpp.ir.internal.OperandTag
|
||||
private import NewIR
|
||||
|
||||
private class OldBlock = Reachability::ReachableBlock;
|
||||
private class OldInstruction = Reachability::ReachableInstruction;
|
||||
|
||||
import Cached
|
||||
cached private module Cached {
|
||||
|
||||
private IRBlock getNewBlock(OldIR::IRBlock oldBlock) {
|
||||
private IRBlock getNewBlock(OldBlock oldBlock) {
|
||||
result.getFirstInstruction() = getNewInstruction(oldBlock.getFirstInstruction())
|
||||
}
|
||||
|
||||
cached newtype TInstructionTag =
|
||||
WrappedInstructionTag(OldIR::Instruction oldInstruction) {
|
||||
WrappedInstructionTag(OldInstruction oldInstruction) {
|
||||
not oldInstruction instanceof OldIR::PhiInstruction
|
||||
} or
|
||||
PhiTag(Alias::VirtualVariable vvar, OldIR::IRBlock block) {
|
||||
PhiTag(Alias::VirtualVariable vvar, OldBlock block) {
|
||||
hasPhiNode(vvar, block)
|
||||
} or
|
||||
ChiTag(OldIR::Instruction oldInstruction) {
|
||||
ChiTag(OldInstruction oldInstruction) {
|
||||
not oldInstruction instanceof OldIR::PhiInstruction and
|
||||
hasChiNode(_, oldInstruction)
|
||||
} or
|
||||
UnreachedTag(OldInstruction oldInstruction, EdgeKind kind) {
|
||||
// We need an `Unreached` instruction for the destination of any edge whose predecessor
|
||||
// instruction is reachable, but whose successor block is not. This should occur only for
|
||||
// infeasible edges.
|
||||
exists(OldIR::Instruction succInstruction |
|
||||
succInstruction = oldInstruction.getSuccessor(kind) and
|
||||
not succInstruction instanceof OldInstruction
|
||||
)
|
||||
}
|
||||
|
||||
cached class InstructionTagType extends TInstructionTag {
|
||||
@@ -35,11 +47,11 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached OldIR::Instruction getOldInstruction(Instruction instr) {
|
||||
cached OldInstruction getOldInstruction(Instruction instr) {
|
||||
instr.getTag() = WrappedInstructionTag(result)
|
||||
}
|
||||
|
||||
private Instruction getNewInstruction(OldIR::Instruction instr) {
|
||||
private Instruction getNewInstruction(OldInstruction instr) {
|
||||
getOldInstruction(result) = instr
|
||||
}
|
||||
|
||||
@@ -47,21 +59,21 @@ cached private module Cached {
|
||||
* Gets the chi node corresponding to `instr` if one is present, or the new `Instruction`
|
||||
* corresponding to `instr` if there is no `Chi` node.
|
||||
*/
|
||||
private Instruction getNewFinalInstruction(OldIR::Instruction instr) {
|
||||
private Instruction getNewFinalInstruction(OldInstruction instr) {
|
||||
result = getChiInstruction(instr)
|
||||
or
|
||||
not exists(getChiInstruction(instr)) and
|
||||
result = getNewInstruction(instr)
|
||||
}
|
||||
|
||||
private PhiInstruction getPhiInstruction(Function func, OldIR::IRBlock oldBlock,
|
||||
private PhiInstruction getPhiInstruction(Function func, OldBlock oldBlock,
|
||||
Alias::VirtualVariable vvar) {
|
||||
result.getFunction() = func and
|
||||
result.getAST() = oldBlock.getFirstInstruction().getAST() and
|
||||
result.getTag() = PhiTag(vvar, oldBlock)
|
||||
}
|
||||
|
||||
private ChiInstruction getChiInstruction (OldIR::Instruction instr) {
|
||||
private ChiInstruction getChiInstruction (OldInstruction instr) {
|
||||
hasChiNode(_, instr) and
|
||||
result.getTag() = ChiTag(instr)
|
||||
}
|
||||
@@ -91,8 +103,8 @@ cached private module Cached {
|
||||
}
|
||||
|
||||
private predicate hasInstruction(Function func, Opcode opcode, Locatable ast,
|
||||
InstructionTag tag, Type resultType, boolean isGLValue) {
|
||||
exists(OldIR::Instruction instr |
|
||||
InstructionTag tag, Type resultType, boolean isGLValue) {
|
||||
exists(OldInstruction instr |
|
||||
instr.getFunction() = func and
|
||||
instr.getOpcode() = opcode and
|
||||
instr.getAST() = ast and
|
||||
@@ -103,7 +115,7 @@ cached private module Cached {
|
||||
else
|
||||
isGLValue = false
|
||||
) or
|
||||
exists(OldIR::IRBlock block, Alias::VirtualVariable vvar |
|
||||
exists(OldBlock block, Alias::VirtualVariable vvar |
|
||||
hasPhiNode(vvar, block) and
|
||||
block.getFunction() = func and
|
||||
opcode instanceof Opcode::Phi and
|
||||
@@ -112,7 +124,7 @@ cached private module Cached {
|
||||
resultType = vvar.getType() and
|
||||
isGLValue = false
|
||||
) or
|
||||
exists(OldIR::Instruction instr, Alias::VirtualVariable vvar |
|
||||
exists(OldInstruction instr, Alias::VirtualVariable vvar |
|
||||
hasChiNode(vvar, instr) and
|
||||
instr.getFunction() = func and
|
||||
opcode instanceof Opcode::Chi and
|
||||
@@ -120,11 +132,19 @@ cached private module Cached {
|
||||
tag = ChiTag(instr) and
|
||||
resultType = vvar.getType() and
|
||||
isGLValue = false
|
||||
) or
|
||||
exists(OldInstruction oldInstruction, EdgeKind kind |
|
||||
oldInstruction.getFunction() = func and
|
||||
tag = UnreachedTag(oldInstruction, kind) and
|
||||
opcode instanceof Opcode::Unreached and
|
||||
ast = oldInstruction.getSuccessor(kind).getAST() and
|
||||
resultType instanceof VoidType and
|
||||
isGLValue = false
|
||||
)
|
||||
}
|
||||
|
||||
cached predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag,
|
||||
Type type) {
|
||||
Type type) {
|
||||
exists(OldIR::IRTempVariable var |
|
||||
var.getFunction() = func and
|
||||
var.getAST() = ast and
|
||||
@@ -135,19 +155,20 @@ cached private module Cached {
|
||||
|
||||
cached predicate hasModeledMemoryResult(Instruction instruction) {
|
||||
exists(Alias::getResultMemoryAccess(getOldInstruction(instruction))) or
|
||||
instruction instanceof PhiInstruction // Phis always have modeled results
|
||||
instruction instanceof PhiInstruction or // Phis always have modeled results
|
||||
instruction instanceof ChiInstruction // Chis always have modeled results
|
||||
}
|
||||
|
||||
cached Instruction getInstructionOperandDefinition(Instruction instruction, OperandTag tag) {
|
||||
exists(OldIR::Instruction oldInstruction, OldIR::NonPhiOperand oldOperand |
|
||||
exists(OldInstruction oldInstruction, OldIR::NonPhiOperand oldOperand |
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
oldOperand = oldInstruction.getAnOperand() and
|
||||
tag = oldOperand.getOperandTag() and
|
||||
if oldOperand instanceof OldIR::MemoryOperand then (
|
||||
(
|
||||
if exists(Alias::getOperandMemoryAccess(oldOperand)) then (
|
||||
exists(OldIR::IRBlock useBlock, int useRank, Alias::VirtualVariable vvar,
|
||||
OldIR::IRBlock defBlock, int defRank, int defIndex |
|
||||
exists(OldBlock useBlock, int useRank, Alias::VirtualVariable vvar,
|
||||
OldBlock defBlock, int defRank, int defIndex |
|
||||
vvar = Alias::getOperandMemoryAccess(oldOperand).getVirtualVariable() and
|
||||
hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and
|
||||
hasUseAtRank(vvar, useBlock, useRank, oldInstruction) and
|
||||
@@ -164,7 +185,7 @@ cached private module Cached {
|
||||
) or
|
||||
// Connect any definitions that are not being modeled in SSA to the
|
||||
// `UnmodeledUse` instruction.
|
||||
exists(OldIR::Instruction oldDefinition |
|
||||
exists(OldInstruction oldDefinition |
|
||||
instruction instanceof UnmodeledUseInstruction and
|
||||
tag instanceof UnmodeledUseOperandTag and
|
||||
oldDefinition = oldOperand.getDefinitionInstruction() and
|
||||
@@ -189,8 +210,8 @@ cached private module Cached {
|
||||
|
||||
cached Instruction getPhiInstructionOperandDefinition(PhiInstruction instr,
|
||||
IRBlock newPredecessorBlock) {
|
||||
exists(Alias::VirtualVariable vvar, OldIR::IRBlock phiBlock,
|
||||
OldIR::IRBlock defBlock, int defRank, int defIndex, OldIR::IRBlock predBlock |
|
||||
exists(Alias::VirtualVariable vvar, OldBlock phiBlock,
|
||||
OldBlock defBlock, int defRank, int defIndex, OldBlock predBlock |
|
||||
hasPhiNode(vvar, phiBlock) and
|
||||
predBlock = phiBlock.getAPredecessor() and
|
||||
instr.getTag() = PhiTag(vvar, phiBlock) and
|
||||
@@ -205,8 +226,8 @@ cached private module Cached {
|
||||
}
|
||||
|
||||
cached Instruction getChiInstructionTotalOperand(ChiInstruction chiInstr) {
|
||||
exists(Alias::VirtualVariable vvar, OldIR::Instruction oldInstr, OldIR::IRBlock defBlock,
|
||||
int defRank, int defIndex, OldIR::IRBlock useBlock, int useRank |
|
||||
exists(Alias::VirtualVariable vvar, OldInstruction oldInstr, OldBlock defBlock,
|
||||
int defRank, int defIndex, OldBlock useBlock, int useRank |
|
||||
ChiTag(oldInstr) = chiInstr.getTag() and
|
||||
vvar = Alias::getResultMemoryAccess(oldInstr).getVirtualVariable() and
|
||||
hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and
|
||||
@@ -220,7 +241,7 @@ cached private module Cached {
|
||||
}
|
||||
|
||||
cached Instruction getPhiInstructionBlockStart(PhiInstruction instr) {
|
||||
exists(OldIR::IRBlock oldBlock |
|
||||
exists(OldBlock oldBlock |
|
||||
instr.getTag() = PhiTag(_, oldBlock) and
|
||||
result = getNewInstruction(oldBlock.getFirstInstruction())
|
||||
)
|
||||
@@ -247,10 +268,11 @@ cached private module Cached {
|
||||
else (
|
||||
result = getNewInstruction(getOldInstruction(instruction).getSuccessor(kind))
|
||||
or
|
||||
exists(OldIR::Instruction oldInstruction |
|
||||
exists(OldInstruction oldInstruction |
|
||||
instruction = getChiInstruction(oldInstruction) and
|
||||
result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
)
|
||||
) or
|
||||
result.getTag() = UnreachedTag(getOldInstruction(instruction), kind)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -310,29 +332,29 @@ cached private module Cached {
|
||||
}
|
||||
|
||||
private predicate ssa_variableUpdate(Alias::VirtualVariable vvar,
|
||||
OldIR::Instruction instr, OldIR::IRBlock block, int index) {
|
||||
OldInstruction instr, OldBlock block, int index) {
|
||||
block.getInstruction(index) = instr and
|
||||
Alias::getResultMemoryAccess(instr).getVirtualVariable() = vvar
|
||||
}
|
||||
|
||||
private predicate hasDefinition(Alias::VirtualVariable vvar, OldIR::IRBlock block, int index) {
|
||||
private predicate hasDefinition(Alias::VirtualVariable vvar, OldBlock block, int index) {
|
||||
(
|
||||
hasPhiNode(vvar, block) and
|
||||
index = -1
|
||||
) or
|
||||
exists(Alias::MemoryAccess access, OldIR::Instruction def |
|
||||
exists(Alias::MemoryAccess access, OldInstruction def |
|
||||
access = Alias::getResultMemoryAccess(def) and
|
||||
block.getInstruction(index) = def and
|
||||
vvar = access.getVirtualVariable()
|
||||
)
|
||||
}
|
||||
|
||||
private predicate defUseRank(Alias::VirtualVariable vvar, OldIR::IRBlock block, int rankIndex, int index) {
|
||||
private predicate defUseRank(Alias::VirtualVariable vvar, OldBlock block, int rankIndex, int index) {
|
||||
index = rank[rankIndex](int j | hasDefinition(vvar, block, j) or hasUse(vvar, _, block, j))
|
||||
}
|
||||
|
||||
private predicate hasUse(Alias::VirtualVariable vvar,
|
||||
OldIR::Instruction use, OldIR::IRBlock block, int index) {
|
||||
private predicate hasUse(Alias::VirtualVariable vvar, OldInstruction use, OldBlock block,
|
||||
int index) {
|
||||
exists(Alias::MemoryAccess access |
|
||||
(
|
||||
access = Alias::getOperandMemoryAccess(use.getAnOperand())
|
||||
@@ -349,7 +371,7 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate variableLiveOnEntryToBlock(Alias::VirtualVariable vvar, OldIR::IRBlock block) {
|
||||
private predicate variableLiveOnEntryToBlock(Alias::VirtualVariable vvar, OldBlock block) {
|
||||
exists (int index | hasUse(vvar, _, block, index) |
|
||||
not exists (int j | ssa_variableUpdate(vvar, _, block, j) | j < index)
|
||||
) or
|
||||
@@ -357,7 +379,7 @@ cached private module Cached {
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate variableLiveOnExitFromBlock(Alias::VirtualVariable vvar, OldIR::IRBlock block) {
|
||||
private predicate variableLiveOnExitFromBlock(Alias::VirtualVariable vvar, OldBlock block) {
|
||||
variableLiveOnEntryToBlock(vvar, block.getASuccessor())
|
||||
}
|
||||
|
||||
@@ -367,18 +389,18 @@ cached private module Cached {
|
||||
* end of the block, even if the definition is the last instruction in the
|
||||
* block.
|
||||
*/
|
||||
private int exitRank(Alias::VirtualVariable vvar, OldIR::IRBlock block) {
|
||||
private int exitRank(Alias::VirtualVariable vvar, OldBlock block) {
|
||||
result = max(int rankIndex | defUseRank(vvar, block, rankIndex, _)) + 1
|
||||
}
|
||||
|
||||
private predicate hasDefinitionAtRank(Alias::VirtualVariable vvar,
|
||||
OldIR::IRBlock block, int rankIndex, int instructionIndex) {
|
||||
private predicate hasDefinitionAtRank(Alias::VirtualVariable vvar, OldBlock block, int rankIndex,
|
||||
int instructionIndex) {
|
||||
hasDefinition(vvar, block, instructionIndex) and
|
||||
defUseRank(vvar, block, rankIndex, instructionIndex)
|
||||
}
|
||||
|
||||
private predicate hasUseAtRank(Alias::VirtualVariable vvar, OldIR::IRBlock block,
|
||||
int rankIndex, OldIR::Instruction use) {
|
||||
private predicate hasUseAtRank(Alias::VirtualVariable vvar, OldBlock block, int rankIndex,
|
||||
OldInstruction use) {
|
||||
exists(int index |
|
||||
hasUse(vvar, use, block, index) and
|
||||
defUseRank(vvar, block, rankIndex, index)
|
||||
@@ -389,8 +411,8 @@ cached private module Cached {
|
||||
* Holds if the definition of `vvar` at `(block, defRank)` reaches the rank
|
||||
* index `reachesRank` in block `block`.
|
||||
*/
|
||||
private predicate definitionReachesRank(Alias::VirtualVariable vvar,
|
||||
OldIR::IRBlock block, int defRank, int reachesRank) {
|
||||
private predicate definitionReachesRank(Alias::VirtualVariable vvar, OldBlock block, int defRank,
|
||||
int reachesRank) {
|
||||
hasDefinitionAtRank(vvar, block, defRank, _) and
|
||||
reachesRank <= exitRank(vvar, block) and // Without this, the predicate would be infinite.
|
||||
(
|
||||
@@ -410,8 +432,8 @@ cached private module Cached {
|
||||
* Holds if the definition of `vvar` at `(defBlock, defRank)` reaches the end of
|
||||
* block `block`.
|
||||
*/
|
||||
private predicate definitionReachesEndOfBlock(Alias::VirtualVariable vvar,
|
||||
OldIR::IRBlock defBlock, int defRank, OldIR::IRBlock block) {
|
||||
private predicate definitionReachesEndOfBlock(Alias::VirtualVariable vvar, OldBlock defBlock,
|
||||
int defRank, OldBlock block) {
|
||||
hasDefinitionAtRank(vvar, defBlock, defRank, _) and
|
||||
(
|
||||
(
|
||||
@@ -421,7 +443,7 @@ cached private module Cached {
|
||||
variableLiveOnExitFromBlock(vvar, defBlock) and
|
||||
definitionReachesRank(vvar, defBlock, defRank, exitRank(vvar, defBlock))
|
||||
) or
|
||||
exists(OldIR::IRBlock idom |
|
||||
exists(OldBlock idom |
|
||||
definitionReachesEndOfBlock(vvar, defBlock, defRank, idom) and
|
||||
noDefinitionsSinceIDominator(vvar, idom, block)
|
||||
)
|
||||
@@ -429,24 +451,23 @@ cached private module Cached {
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate noDefinitionsSinceIDominator(Alias::VirtualVariable vvar,
|
||||
OldIR::IRBlock idom, OldIR::IRBlock block) {
|
||||
idom.immediatelyDominates(block) and // It is sufficient to traverse the dominator graph, cf. discussion above.
|
||||
private predicate noDefinitionsSinceIDominator(Alias::VirtualVariable vvar, OldBlock idom,
|
||||
OldBlock block) {
|
||||
Dominance::blockImmediatelyDominates(idom, block) and // It is sufficient to traverse the dominator graph, cf. discussion above.
|
||||
variableLiveOnExitFromBlock(vvar, block) and
|
||||
not hasDefinition(vvar, block, _)
|
||||
}
|
||||
|
||||
private predicate definitionReachesUseWithinBlock(
|
||||
Alias::VirtualVariable vvar, OldIR::IRBlock defBlock, int defRank,
|
||||
OldIR::IRBlock useBlock, int useRank) {
|
||||
private predicate definitionReachesUseWithinBlock(Alias::VirtualVariable vvar, OldBlock defBlock,
|
||||
int defRank, OldBlock useBlock, int useRank) {
|
||||
defBlock = useBlock and
|
||||
hasDefinitionAtRank(vvar, defBlock, defRank, _) and
|
||||
hasUseAtRank(vvar, useBlock, useRank, _) and
|
||||
definitionReachesRank(vvar, defBlock, defRank, useRank)
|
||||
}
|
||||
|
||||
private predicate definitionReachesUse(Alias::VirtualVariable vvar,
|
||||
OldIR::IRBlock defBlock, int defRank, OldIR::IRBlock useBlock, int useRank) {
|
||||
private predicate definitionReachesUse(Alias::VirtualVariable vvar, OldBlock defBlock,
|
||||
int defRank, OldBlock useBlock, int useRank) {
|
||||
hasUseAtRank(vvar, useBlock, useRank, _) and
|
||||
(
|
||||
definitionReachesUseWithinBlock(vvar, defBlock, defRank, useBlock,
|
||||
@@ -459,24 +480,21 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate hasFrontierPhiNode(Alias::VirtualVariable vvar,
|
||||
OldIR::IRBlock phiBlock) {
|
||||
exists(OldIR::IRBlock defBlock |
|
||||
phiBlock = defBlock.dominanceFrontier() and
|
||||
private predicate hasFrontierPhiNode(Alias::VirtualVariable vvar, OldBlock phiBlock) {
|
||||
exists(OldBlock defBlock |
|
||||
phiBlock = Dominance::getDominanceFrontier(defBlock) and
|
||||
hasDefinition(vvar, defBlock, _) and
|
||||
/* We can also eliminate those nodes where the variable is not live on any incoming edge */
|
||||
variableLiveOnEntryToBlock(vvar, phiBlock)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate hasPhiNode(Alias::VirtualVariable vvar,
|
||||
OldIR::IRBlock phiBlock) {
|
||||
private predicate hasPhiNode(Alias::VirtualVariable vvar, OldBlock phiBlock) {
|
||||
hasFrontierPhiNode(vvar, phiBlock)
|
||||
//or ssa_sanitized_custom_phi_node(vvar, block)
|
||||
}
|
||||
|
||||
private predicate hasChiNode(Alias::VirtualVariable vvar,
|
||||
OldIR::Instruction def) {
|
||||
private predicate hasChiNode(Alias::VirtualVariable vvar, OldInstruction def) {
|
||||
exists(Alias::MemoryAccess ma |
|
||||
ma = Alias::getResultMemoryAccess(def) and
|
||||
ma.isPartialMemoryAccess() and
|
||||
@@ -492,13 +510,17 @@ cached private module CachedForDebugging {
|
||||
}
|
||||
|
||||
cached string getInstructionUniqueId(Instruction instr) {
|
||||
exists(OldIR::Instruction oldInstr |
|
||||
exists(OldInstruction oldInstr |
|
||||
oldInstr = getOldInstruction(instr) and
|
||||
result = "NonSSA: " + oldInstr.getUniqueId()
|
||||
) or
|
||||
exists(Alias::VirtualVariable vvar, OldIR::IRBlock phiBlock |
|
||||
exists(Alias::VirtualVariable vvar, OldBlock phiBlock |
|
||||
instr.getTag() = PhiTag(vvar, phiBlock) and
|
||||
result = "Phi Block(" + phiBlock.getUniqueId() + "): " + vvar.getUniqueId()
|
||||
) or
|
||||
exists(OldInstruction oldInstr, EdgeKind kind |
|
||||
instr.getTag() = UnreachedTag(oldInstr, kind) and
|
||||
result = "Unreached(" + oldInstr.getUniqueId() + ":" + kind.toString() + ")"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import semmle.code.cpp.ir.implementation.raw.IR as OldIR
|
||||
import semmle.code.cpp.ir.implementation.raw.internal.reachability.ReachableBlock as Reachability
|
||||
import semmle.code.cpp.ir.implementation.raw.internal.reachability.Dominance as Dominance
|
||||
import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as NewIR
|
||||
import SimpleSSA as Alias
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
private import DominanceInternal
|
||||
|
||||
predicate blockImmediatelyDominates(Graph::Block dominator, Graph::Block block) =
|
||||
idominance(Graph::isEntryBlock/1, Graph::blockSuccessor/2)(_, dominator, block)
|
||||
|
||||
predicate blockStrictlyDominates(Graph::Block dominator, Graph::Block block) {
|
||||
blockImmediatelyDominates+(dominator, block)
|
||||
}
|
||||
|
||||
predicate blockDominates(Graph::Block dominator, Graph::Block block) {
|
||||
blockStrictlyDominates(dominator, block) or dominator = block
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
Graph::Block getDominanceFrontier(Graph::Block dominator) {
|
||||
exists(Graph::Block pred |
|
||||
Graph::blockSuccessor(pred, result) and
|
||||
blockDominates(dominator, pred) and
|
||||
not blockStrictlyDominates(dominator, result)
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
private import ReachableBlock as Reachability
|
||||
private module ReachabilityGraph = Reachability::Graph;
|
||||
|
||||
module Graph {
|
||||
import Reachability::Graph
|
||||
class Block = Reachability::ReachableBlock;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
private import ReachableBlockInternal
|
||||
private import ReachableBlock
|
||||
import IR
|
||||
|
||||
private class ReachableBlockPropertyProvider extends IRPropertyProvider {
|
||||
override string getBlockProperty(IRBlock block, string key) {
|
||||
(
|
||||
not block instanceof ReachableBlock and
|
||||
key = "Unreachable" and
|
||||
result = "true"
|
||||
) or
|
||||
(
|
||||
exists(EdgeKind kind |
|
||||
isInfeasibleEdge(block, kind) and
|
||||
key = "Infeasible(" + kind.toString() + ")" and
|
||||
result = "true"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
private import ReachableBlockInternal
|
||||
private import semmle.code.cpp.ir.internal.IntegerConstant
|
||||
private import IR
|
||||
private import ConstantAnalysis
|
||||
|
||||
predicate isInfeasibleEdge(IRBlock block, EdgeKind kind) {
|
||||
exists(ConditionalBranchInstruction instr, int conditionValue |
|
||||
instr = block.getLastInstruction() and
|
||||
conditionValue = getValue(getConstantValue(instr.getCondition())) and
|
||||
if conditionValue = 0 then
|
||||
kind instanceof TrueEdge
|
||||
else
|
||||
kind instanceof FalseEdge
|
||||
)
|
||||
}
|
||||
|
||||
IRBlock getAFeasiblePredecessor(IRBlock successor) {
|
||||
exists(EdgeKind kind |
|
||||
result.getSuccessor(kind) = successor and
|
||||
not isInfeasibleEdge(result, kind)
|
||||
)
|
||||
}
|
||||
|
||||
predicate isBlockReachable(IRBlock block) {
|
||||
exists(FunctionIR f |
|
||||
getAFeasiblePredecessor*(block) = f.getEntryBlock()
|
||||
)
|
||||
}
|
||||
|
||||
predicate isInstructionReachable(Instruction instr) {
|
||||
isBlockReachable(instr.getBlock())
|
||||
}
|
||||
|
||||
class ReachableBlock extends IRBlock {
|
||||
ReachableBlock() {
|
||||
isBlockReachable(this)
|
||||
}
|
||||
}
|
||||
|
||||
class ReachableInstruction extends Instruction {
|
||||
ReachableInstruction() {
|
||||
this.getBlock() instanceof ReachableBlock
|
||||
}
|
||||
}
|
||||
|
||||
module Graph {
|
||||
predicate isEntryBlock(ReachableBlock block) {
|
||||
exists(FunctionIR f |
|
||||
block = f.getEntryBlock()
|
||||
)
|
||||
}
|
||||
|
||||
predicate blockSuccessor(ReachableBlock pred, ReachableBlock succ) {
|
||||
succ = pred.getASuccessor()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as IR
|
||||
import semmle.code.cpp.ir.implementation.unaliased_ssa.constant.ConstantAnalysis as ConstantAnalysis
|
||||
@@ -102,6 +102,96 @@ IntValue div(IntValue a, IntValue b) {
|
||||
result = unknown()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `a == b`. If either input is unknown, the result is unknown.
|
||||
*/
|
||||
bindingset[a, b]
|
||||
IntValue compareEQ(IntValue a, IntValue b) {
|
||||
if hasValue(a) and hasValue(b) then (
|
||||
if a = b then
|
||||
result = 1
|
||||
else
|
||||
result = 0
|
||||
)
|
||||
else
|
||||
result = unknown()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `a != b`. If either input is unknown, the result is unknown.
|
||||
*/
|
||||
bindingset[a, b]
|
||||
IntValue compareNE(IntValue a, IntValue b) {
|
||||
if hasValue(a) and hasValue(b) then (
|
||||
if a != b then
|
||||
result = 1
|
||||
else
|
||||
result = 0
|
||||
)
|
||||
else
|
||||
result = unknown()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `a < b`. If either input is unknown, the result is unknown.
|
||||
*/
|
||||
bindingset[a, b]
|
||||
IntValue compareLT(IntValue a, IntValue b) {
|
||||
if hasValue(a) and hasValue(b) then (
|
||||
if a < b then
|
||||
result = 1
|
||||
else
|
||||
result = 0
|
||||
)
|
||||
else
|
||||
result = unknown()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `a > b`. If either input is unknown, the result is unknown.
|
||||
*/
|
||||
bindingset[a, b]
|
||||
IntValue compareGT(IntValue a, IntValue b) {
|
||||
if hasValue(a) and hasValue(b) then (
|
||||
if a > b then
|
||||
result = 1
|
||||
else
|
||||
result = 0
|
||||
)
|
||||
else
|
||||
result = unknown()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `a <= b`. If either input is unknown, the result is unknown.
|
||||
*/
|
||||
bindingset[a, b]
|
||||
IntValue compareLE(IntValue a, IntValue b) {
|
||||
if hasValue(a) and hasValue(b) then (
|
||||
if a <= b then
|
||||
result = 1
|
||||
else
|
||||
result = 0
|
||||
)
|
||||
else
|
||||
result = unknown()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `a >= b`. If either input is unknown, the result is unknown.
|
||||
*/
|
||||
bindingset[a, b]
|
||||
IntValue compareGE(IntValue a, IntValue b) {
|
||||
if hasValue(a) and hasValue(b) then (
|
||||
if a >= b then
|
||||
result = 1
|
||||
else
|
||||
result = 0
|
||||
)
|
||||
else
|
||||
result = unknown()
|
||||
}
|
||||
|
||||
/**
|
||||
* Return `-a`. If `a` is unknown, the result is unknown.
|
||||
*/
|
||||
|
||||
@@ -25,7 +25,6 @@ astGuards
|
||||
| test.c:126:12:126:26 | call to test3_condition |
|
||||
| test.c:131:7:131:7 | b |
|
||||
| test.c:137:7:137:7 | 0 |
|
||||
| test.c:138:9:138:9 | i |
|
||||
| test.c:146:7:146:8 | ! ... |
|
||||
| test.c:146:8:146:8 | x |
|
||||
| test.c:152:10:152:10 | x |
|
||||
@@ -164,6 +163,7 @@ astGuardsControl
|
||||
| test.c:42:16:42:21 | ... < ... | true | 45 | 47 |
|
||||
| test.c:42:16:42:21 | ... < ... | true | 48 | 55 |
|
||||
| test.c:42:16:42:21 | ... < ... | true | 51 | 53 |
|
||||
| test.c:44:12:44:16 | ... > ... | false | 42 | 42 |
|
||||
| test.c:44:12:44:16 | ... > ... | false | 51 | 53 |
|
||||
| test.c:44:12:44:16 | ... > ... | true | 45 | 45 |
|
||||
| test.c:44:12:44:16 | ... > ... | true | 45 | 47 |
|
||||
@@ -203,9 +203,8 @@ astGuardsControl
|
||||
| test.c:126:7:126:28 | ... && ... | true | 126 | 128 |
|
||||
| test.c:126:12:126:26 | call to test3_condition | true | 126 | 128 |
|
||||
| test.c:131:7:131:7 | b | true | 131 | 132 |
|
||||
| test.c:137:7:137:7 | 0 | false | 142 | 136 |
|
||||
| test.c:137:7:137:7 | 0 | true | 137 | 138 |
|
||||
| test.c:137:7:137:7 | 0 | true | 138 | 139 |
|
||||
| test.c:138:9:138:9 | i | true | 138 | 139 |
|
||||
| test.c:146:7:146:8 | ! ... | true | 146 | 147 |
|
||||
| test.c:146:8:146:8 | x | false | 146 | 147 |
|
||||
| test.c:152:10:152:10 | x | true | 151 | 152 |
|
||||
@@ -302,6 +301,7 @@ astGuardsEnsure
|
||||
| test.c:42:16:42:21 | ... < ... | test.c:42:20:42:21 | 10 | >= | test.c:42:16:42:16 | j | 1 | 45 | 47 |
|
||||
| test.c:42:16:42:21 | ... < ... | test.c:42:20:42:21 | 10 | >= | test.c:42:16:42:16 | j | 1 | 48 | 55 |
|
||||
| test.c:42:16:42:21 | ... < ... | test.c:42:20:42:21 | 10 | >= | test.c:42:16:42:16 | j | 1 | 51 | 53 |
|
||||
| test.c:44:12:44:16 | ... > ... | test.c:44:12:44:12 | z | < | test.c:44:16:44:16 | 0 | 1 | 42 | 42 |
|
||||
| test.c:44:12:44:16 | ... > ... | test.c:44:12:44:12 | z | < | test.c:44:16:44:16 | 0 | 1 | 51 | 53 |
|
||||
| test.c:44:12:44:16 | ... > ... | test.c:44:12:44:12 | z | >= | test.c:44:16:44:16 | 0 | 1 | 45 | 45 |
|
||||
| test.c:44:12:44:16 | ... > ... | test.c:44:12:44:12 | z | >= | test.c:44:16:44:16 | 0 | 1 | 45 | 47 |
|
||||
@@ -309,6 +309,7 @@ astGuardsEnsure
|
||||
| test.c:44:12:44:16 | ... > ... | test.c:44:16:44:16 | 0 | < | test.c:44:12:44:12 | z | 0 | 45 | 45 |
|
||||
| test.c:44:12:44:16 | ... > ... | test.c:44:16:44:16 | 0 | < | test.c:44:12:44:12 | z | 0 | 45 | 47 |
|
||||
| test.c:44:12:44:16 | ... > ... | test.c:44:16:44:16 | 0 | < | test.c:44:12:44:12 | z | 0 | 48 | 55 |
|
||||
| test.c:44:12:44:16 | ... > ... | test.c:44:16:44:16 | 0 | >= | test.c:44:12:44:12 | z | 0 | 42 | 42 |
|
||||
| test.c:44:12:44:16 | ... > ... | test.c:44:16:44:16 | 0 | >= | test.c:44:12:44:12 | z | 0 | 51 | 53 |
|
||||
| test.c:45:16:45:20 | ... > ... | test.c:45:16:45:16 | y | < | test.c:45:20:45:20 | 0 | 1 | 48 | 55 |
|
||||
| test.c:45:16:45:20 | ... > ... | test.c:45:16:45:16 | y | >= | test.c:45:20:45:20 | 0 | 1 | 45 | 47 |
|
||||
@@ -406,7 +407,6 @@ irGuards
|
||||
| test.c:126:12:126:26 | Call: call to test3_condition |
|
||||
| test.c:131:7:131:7 | Load: b |
|
||||
| test.c:137:7:137:7 | Constant: 0 |
|
||||
| test.c:138:9:138:9 | Load: i |
|
||||
| test.c:146:8:146:8 | Load: x |
|
||||
| test.c:152:10:152:10 | Load: x |
|
||||
| test.c:152:15:152:15 | Load: y |
|
||||
@@ -521,7 +521,6 @@ irGuardsControl
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | false | 59 | 59 |
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | false | 62 | 62 |
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | true | 35 | 35 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | true | 42 | 42 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | true | 43 | 43 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | true | 45 | 45 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | true | 46 | 46 |
|
||||
@@ -563,9 +562,8 @@ irGuardsControl
|
||||
| test.c:126:7:126:7 | Constant: 1 | true | 127 | 127 |
|
||||
| test.c:126:12:126:26 | Call: call to test3_condition | true | 127 | 127 |
|
||||
| test.c:131:7:131:7 | Load: b | true | 132 | 132 |
|
||||
| test.c:137:7:137:7 | Constant: 0 | false | 142 | 142 |
|
||||
| test.c:137:7:137:7 | Constant: 0 | true | 138 | 138 |
|
||||
| test.c:137:7:137:7 | Constant: 0 | true | 139 | 139 |
|
||||
| test.c:138:9:138:9 | Load: i | true | 139 | 139 |
|
||||
| test.c:146:8:146:8 | Load: x | false | 147 | 147 |
|
||||
| test.c:152:10:152:10 | Load: x | true | 152 | 152 |
|
||||
| test.c:152:15:152:15 | Load: y | true | 152 | 152 |
|
||||
@@ -644,13 +642,11 @@ irGuardsEnsure
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:20:34:21 | Constant: 10 | < | test.c:34:16:34:16 | Load: j | 1 | 59 | 59 |
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:20:34:21 | Constant: 10 | < | test.c:34:16:34:16 | Load: j | 1 | 62 | 62 |
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:20:34:21 | Constant: 10 | >= | test.c:34:16:34:16 | Load: j | 1 | 35 | 35 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:16:42:16 | Load: j | < | test.c:42:20:42:21 | Constant: 10 | 0 | 42 | 42 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:16:42:16 | Load: j | < | test.c:42:20:42:21 | Constant: 10 | 0 | 43 | 43 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:16:42:16 | Load: j | < | test.c:42:20:42:21 | Constant: 10 | 0 | 45 | 45 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:16:42:16 | Load: j | < | test.c:42:20:42:21 | Constant: 10 | 0 | 46 | 46 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:16:42:16 | Load: j | < | test.c:42:20:42:21 | Constant: 10 | 0 | 49 | 49 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:16:42:16 | Load: j | < | test.c:42:20:42:21 | Constant: 10 | 0 | 52 | 52 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:20:42:21 | Constant: 10 | >= | test.c:42:16:42:16 | Load: j | 1 | 42 | 42 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:20:42:21 | Constant: 10 | >= | test.c:42:16:42:16 | Load: j | 1 | 43 | 43 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:20:42:21 | Constant: 10 | >= | test.c:42:16:42:16 | Load: j | 1 | 45 | 45 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:20:42:21 | Constant: 10 | >= | test.c:42:16:42:16 | Load: j | 1 | 46 | 46 |
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
| test.cpp:6:12:6:17 | test.cpp:21:8:21:9 | IR only |
|
||||
| test.cpp:66:30:66:36 | test.cpp:71:8:71:9 | AST only |
|
||||
| test.cpp:89:28:89:34 | test.cpp:90:8:90:14 | AST only |
|
||||
| test.cpp:100:13:100:18 | test.cpp:103:10:103:12 | AST only |
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
| test.cpp:9:8:9:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source |
|
||||
| test.cpp:10:8:10:9 | Load: t2 | test.cpp:6:12:6:17 | Call: call to source |
|
||||
| test.cpp:15:8:15:9 | Load: t2 | test.cpp:6:12:6:17 | Call: call to source |
|
||||
| test.cpp:21:8:21:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source |
|
||||
| test.cpp:26:8:26:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source |
|
||||
| test.cpp:30:8:30:8 | Load: t | test.cpp:35:10:35:15 | Call: call to source |
|
||||
| test.cpp:31:8:31:8 | Load: c | test.cpp:36:13:36:18 | Call: call to source |
|
||||
|
||||
@@ -30,3 +30,31 @@ int ReturnConstantPhiLoop(int x) {
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
int UnreachableViaGoto() {
|
||||
goto skip;
|
||||
return 1;
|
||||
skip:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int UnreachableIf(bool b) {
|
||||
int x = 5;
|
||||
int y = 10;
|
||||
if (b) {
|
||||
if (x == y) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (x < y) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
| constant_func.cpp:1:5:1:18 | IR: ReturnConstant | 7 |
|
||||
| constant_func.cpp:5:5:5:21 | IR: ReturnConstantPhi | 7 |
|
||||
| constant_func.cpp:25:5:25:25 | IR: ReturnConstantPhiLoop | 7 |
|
||||
| constant_func.cpp:34:5:34:22 | IR: UnreachableViaGoto | 0 |
|
||||
| constant_func.cpp:41:5:41:17 | IR: UnreachableIf | 0 |
|
||||
|
||||
@@ -1,29 +1,8 @@
|
||||
import default
|
||||
import semmle.code.cpp.ir.IR
|
||||
import semmle.code.cpp.ir.implementation.aliased_ssa.constant.ConstantAnalysis
|
||||
import semmle.code.cpp.ir.internal.IntegerConstant
|
||||
|
||||
language[monotonicAggregates]
|
||||
IntValue getConstantValue(Instruction instr) {
|
||||
result = instr.(IntegerConstantInstruction).getValue().toInt() or
|
||||
exists(BinaryInstruction binInstr, IntValue left, IntValue right |
|
||||
binInstr = instr and
|
||||
left = getConstantValue(binInstr.getLeftOperand()) and
|
||||
right = getConstantValue(binInstr.getRightOperand()) and
|
||||
(
|
||||
binInstr instanceof AddInstruction and result = add(left, right) or
|
||||
binInstr instanceof SubInstruction and result = sub(left, right) or
|
||||
binInstr instanceof MulInstruction and result = mul(left, right) or
|
||||
binInstr instanceof DivInstruction and result = div(left, right)
|
||||
)
|
||||
) or
|
||||
result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or
|
||||
exists(PhiInstruction phi |
|
||||
phi = instr and
|
||||
result = max(PhiOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction())) and
|
||||
result = min(PhiOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction()))
|
||||
)
|
||||
}
|
||||
|
||||
from FunctionIR funcIR, int value
|
||||
where
|
||||
value = getValue(getConstantValue(funcIR.getReturnInstruction().(ReturnValueInstruction).getReturnValue()))
|
||||
|
||||
@@ -21,15 +21,49 @@
|
||||
| -1 * -INT_MAX | 2147483647 |
|
||||
| -1 - -INT_MAX | 2147483646 |
|
||||
| -1 - INT_MAX | unknown |
|
||||
| -3 != 6 | 1 |
|
||||
| -3 != -3 | 0 |
|
||||
| -3 != unknown | unknown |
|
||||
| -3 < 6 | 1 |
|
||||
| -3 < -3 | 0 |
|
||||
| -3 < -7 | 0 |
|
||||
| -3 < unknown | unknown |
|
||||
| -3 <= 6 | 1 |
|
||||
| -3 <= -3 | 1 |
|
||||
| -3 <= -7 | 0 |
|
||||
| -3 <= unknown | unknown |
|
||||
| -3 == 6 | 0 |
|
||||
| -3 == -3 | 1 |
|
||||
| -3 == unknown | unknown |
|
||||
| -3 > 6 | 0 |
|
||||
| -3 > -3 | 0 |
|
||||
| -3 > -7 | 1 |
|
||||
| -3 > unknown | unknown |
|
||||
| -3 >= 6 | 0 |
|
||||
| -3 >= -3 | 1 |
|
||||
| -3 >= -7 | 1 |
|
||||
| -3 >= unknown | unknown |
|
||||
| -35 / 7 | -5 |
|
||||
| -35 / 8 | -4 |
|
||||
| -35 / -7 | 5 |
|
||||
| -35 / -8 | 4 |
|
||||
| INT_MAX * INT_MAX | unknown |
|
||||
| INT_MAX / 0 | unknown |
|
||||
| unknown != 6 | unknown |
|
||||
| unknown != unknown | unknown |
|
||||
| unknown + 5 | unknown |
|
||||
| unknown + unknown | unknown |
|
||||
| unknown - 5 | unknown |
|
||||
| unknown - unknown | unknown |
|
||||
| unknown / 3 | unknown |
|
||||
| unknown / unknown | unknown |
|
||||
| unknown < 6 | unknown |
|
||||
| unknown < unknown | unknown |
|
||||
| unknown <= 6 | unknown |
|
||||
| unknown <= unknown | unknown |
|
||||
| unknown == 6 | unknown |
|
||||
| unknown == unknown | unknown |
|
||||
| unknown > 6 | unknown |
|
||||
| unknown > unknown | unknown |
|
||||
| unknown >= 6 | unknown |
|
||||
| unknown >= unknown | unknown |
|
||||
|
||||
@@ -45,5 +45,39 @@ where
|
||||
expr = "INT_MAX / 0" and res = Ints::div(Ints::maxValue(), 0) or
|
||||
expr = "0 / unknown" and res = Ints::div(0, Ints::unknown()) or
|
||||
expr = "unknown / 3" and res = Ints::div(Ints::unknown(), 3) or
|
||||
expr = "unknown / unknown" and res = Ints::div(Ints::unknown(), Ints::unknown())
|
||||
expr = "unknown / unknown" and res = Ints::div(Ints::unknown(), Ints::unknown()) or
|
||||
expr = "-3 == -3" and res = Ints::compareEQ(-3, -3) or
|
||||
expr = "-3 == 6" and res = Ints::compareEQ(-3, 6) or
|
||||
expr = "-3 == unknown" and res = Ints::compareEQ(-3, Ints::unknown()) or
|
||||
expr = "unknown == 6" and res = Ints::compareEQ(Ints::unknown(), 6) or
|
||||
expr = "unknown == unknown" and res = Ints::compareEQ(Ints::unknown(), Ints::unknown()) or
|
||||
expr = "-3 != -3" and res = Ints::compareNE(-3, -3) or
|
||||
expr = "-3 != 6" and res = Ints::compareNE(-3, 6) or
|
||||
expr = "-3 != unknown" and res = Ints::compareNE(-3, Ints::unknown()) or
|
||||
expr = "unknown != 6" and res = Ints::compareNE(Ints::unknown(), 6) or
|
||||
expr = "unknown != unknown" and res = Ints::compareNE(Ints::unknown(), Ints::unknown()) or
|
||||
expr = "-3 < -3" and res = Ints::compareLT(-3, -3) or
|
||||
expr = "-3 < 6" and res = Ints::compareLT(-3, 6) or
|
||||
expr = "-3 < -7" and res = Ints::compareLT(-3, -7) or
|
||||
expr = "-3 < unknown" and res = Ints::compareLT(-3, Ints::unknown()) or
|
||||
expr = "unknown < 6" and res = Ints::compareLT(Ints::unknown(), 6) or
|
||||
expr = "unknown < unknown" and res = Ints::compareLT(Ints::unknown(), Ints::unknown()) or
|
||||
expr = "-3 > -3" and res = Ints::compareGT(-3, -3) or
|
||||
expr = "-3 > 6" and res = Ints::compareGT(-3, 6) or
|
||||
expr = "-3 > -7" and res = Ints::compareGT(-3, -7) or
|
||||
expr = "-3 > unknown" and res = Ints::compareGT(-3, Ints::unknown()) or
|
||||
expr = "unknown > 6" and res = Ints::compareGT(Ints::unknown(), 6) or
|
||||
expr = "unknown > unknown" and res = Ints::compareGT(Ints::unknown(), Ints::unknown()) or
|
||||
expr = "-3 <= -3" and res = Ints::compareLE(-3, -3) or
|
||||
expr = "-3 <= 6" and res = Ints::compareLE(-3, 6) or
|
||||
expr = "-3 <= -7" and res = Ints::compareLE(-3, -7) or
|
||||
expr = "-3 <= unknown" and res = Ints::compareLE(-3, Ints::unknown()) or
|
||||
expr = "unknown <= 6" and res = Ints::compareLE(Ints::unknown(), 6) or
|
||||
expr = "unknown <= unknown" and res = Ints::compareLE(Ints::unknown(), Ints::unknown()) or
|
||||
expr = "-3 >= -3" and res = Ints::compareGE(-3, -3) or
|
||||
expr = "-3 >= 6" and res = Ints::compareGE(-3, 6) or
|
||||
expr = "-3 >= -7" and res = Ints::compareGE(-3, -7) or
|
||||
expr = "-3 >= unknown" and res = Ints::compareGE(-3, Ints::unknown()) or
|
||||
expr = "unknown >= 6" and res = Ints::compareGE(Ints::unknown(), 6) or
|
||||
expr = "unknown >= unknown" and res = Ints::compareGE(Ints::unknown(), Ints::unknown())
|
||||
select expr, resultString(res)
|
||||
|
||||
@@ -6668,3 +6668,89 @@ ir.cpp:
|
||||
# 1018| -1: p
|
||||
# 1018| Type = Point *
|
||||
# 1018| ValueCategory = prvalue(load)
|
||||
# 1021| UnreachableViaGoto() -> int
|
||||
# 1021| params:
|
||||
# 1021| body: { ... }
|
||||
# 1022| 0: goto ...
|
||||
# 1023| 1: return ...
|
||||
# 1023| 0: 1
|
||||
# 1023| Type = int
|
||||
# 1023| Value = 1
|
||||
# 1023| ValueCategory = prvalue
|
||||
# 1024| 2: label ...:
|
||||
# 1025| 3: return ...
|
||||
# 1025| 0: 0
|
||||
# 1025| Type = int
|
||||
# 1025| Value = 0
|
||||
# 1025| ValueCategory = prvalue
|
||||
# 1028| UnreachableIf(bool) -> int
|
||||
# 1028| params:
|
||||
# 1028| 0: b
|
||||
# 1028| Type = bool
|
||||
# 1028| body: { ... }
|
||||
# 1029| 0: declaration
|
||||
# 1029| 0: definition of x
|
||||
# 1029| Type = int
|
||||
# 1029| init: initializer for x
|
||||
# 1029| expr: 5
|
||||
# 1029| Type = int
|
||||
# 1029| Value = 5
|
||||
# 1029| ValueCategory = prvalue
|
||||
# 1030| 1: declaration
|
||||
# 1030| 0: definition of y
|
||||
# 1030| Type = int
|
||||
# 1030| init: initializer for y
|
||||
# 1030| expr: 10
|
||||
# 1030| Type = int
|
||||
# 1030| Value = 10
|
||||
# 1030| ValueCategory = prvalue
|
||||
# 1031| 2: if (...) ...
|
||||
# 1031| 0: b
|
||||
# 1031| Type = bool
|
||||
# 1031| ValueCategory = prvalue(load)
|
||||
# 1031| 1: { ... }
|
||||
# 1032| 0: if (...) ...
|
||||
# 1032| 0: ... == ...
|
||||
# 1032| Type = bool
|
||||
# 1032| ValueCategory = prvalue
|
||||
# 1032| 0: x
|
||||
# 1032| Type = int
|
||||
# 1032| ValueCategory = prvalue(load)
|
||||
# 1032| 1: y
|
||||
# 1032| Type = int
|
||||
# 1032| ValueCategory = prvalue(load)
|
||||
# 1032| 1: { ... }
|
||||
# 1033| 0: return ...
|
||||
# 1033| 0: 1
|
||||
# 1033| Type = int
|
||||
# 1033| Value = 1
|
||||
# 1033| ValueCategory = prvalue
|
||||
# 1035| 2: { ... }
|
||||
# 1036| 0: return ...
|
||||
# 1036| 0: 0
|
||||
# 1036| Type = int
|
||||
# 1036| Value = 0
|
||||
# 1036| ValueCategory = prvalue
|
||||
# 1039| 2: { ... }
|
||||
# 1040| 0: if (...) ...
|
||||
# 1040| 0: ... < ...
|
||||
# 1040| Type = bool
|
||||
# 1040| ValueCategory = prvalue
|
||||
# 1040| 0: x
|
||||
# 1040| Type = int
|
||||
# 1040| ValueCategory = prvalue(load)
|
||||
# 1040| 1: y
|
||||
# 1040| Type = int
|
||||
# 1040| ValueCategory = prvalue(load)
|
||||
# 1040| 1: { ... }
|
||||
# 1041| 0: return ...
|
||||
# 1041| 0: 0
|
||||
# 1041| Type = int
|
||||
# 1041| Value = 0
|
||||
# 1041| ValueCategory = prvalue
|
||||
# 1043| 2: { ... }
|
||||
# 1044| 0: return ...
|
||||
# 1044| 0: 1
|
||||
# 1044| Type = int
|
||||
# 1044| Value = 1
|
||||
# 1044| ValueCategory = prvalue
|
||||
|
||||
@@ -1171,16 +1171,11 @@ ir.cpp:
|
||||
# 265| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 266| r0_3(glval<int>) = VariableAddress[j] :
|
||||
# 266| m0_4(int) = Uninitialized[j] : r0_3
|
||||
#-----| Goto -> Block 2
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 265| Block 1
|
||||
# 265| v1_0(void) = ReturnVoid :
|
||||
# 265| v1_1(void) = UnmodeledUse : mu*
|
||||
# 265| v1_2(void) = ExitFunction :
|
||||
|
||||
# 268| Block 2
|
||||
# 268| v2_0(void) = NoOp :
|
||||
#-----| Goto -> Block 2
|
||||
# 268| Block 1
|
||||
# 268| v1_0(void) = NoOp :
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 272| For_Init() -> void
|
||||
# 272| Block 0
|
||||
@@ -1190,16 +1185,11 @@ ir.cpp:
|
||||
# 273| r0_3(glval<int>) = VariableAddress[i] :
|
||||
# 273| r0_4(int) = Constant[0] :
|
||||
# 273| m0_5(int) = Store : r0_3, r0_4
|
||||
#-----| Goto -> Block 2
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 272| Block 1
|
||||
# 272| v1_0(void) = ReturnVoid :
|
||||
# 272| v1_1(void) = UnmodeledUse : mu*
|
||||
# 272| v1_2(void) = ExitFunction :
|
||||
|
||||
# 274| Block 2
|
||||
# 274| v2_0(void) = NoOp :
|
||||
#-----| Goto -> Block 2
|
||||
# 274| Block 1
|
||||
# 274| v1_0(void) = NoOp :
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 278| For_Condition() -> void
|
||||
# 278| Block 0
|
||||
@@ -1225,10 +1215,7 @@ ir.cpp:
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 283| Block 3
|
||||
# 283| v3_0(void) = NoOp :
|
||||
# 278| v3_1(void) = ReturnVoid :
|
||||
# 278| v3_2(void) = UnmodeledUse : mu*
|
||||
# 278| v3_3(void) = ExitFunction :
|
||||
# 283| v3_0(void) = Unreached :
|
||||
|
||||
# 285| For_Update() -> void
|
||||
# 285| Block 0
|
||||
@@ -1238,22 +1225,17 @@ ir.cpp:
|
||||
# 286| r0_3(glval<int>) = VariableAddress[i] :
|
||||
# 286| r0_4(int) = Constant[0] :
|
||||
# 286| m0_5(int) = Store : r0_3, r0_4
|
||||
#-----| Goto -> Block 2
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 285| Block 1
|
||||
# 285| v1_0(void) = ReturnVoid :
|
||||
# 285| v1_1(void) = UnmodeledUse : mu*
|
||||
# 285| v1_2(void) = ExitFunction :
|
||||
|
||||
# 288| Block 2
|
||||
# 288| m2_0(int) = Phi : from 0:m0_5, from 2:m2_6
|
||||
# 288| v2_1(void) = NoOp :
|
||||
# 287| r2_2(int) = Constant[1] :
|
||||
# 287| r2_3(glval<int>) = VariableAddress[i] :
|
||||
# 287| r2_4(int) = Load : r2_3, m2_0
|
||||
# 287| r2_5(int) = Add : r2_4, r2_2
|
||||
# 287| m2_6(int) = Store : r2_3, r2_5
|
||||
#-----| Goto -> Block 2
|
||||
# 288| Block 1
|
||||
# 288| m1_0(int) = Phi : from 0:m0_5, from 1:m1_6
|
||||
# 288| v1_1(void) = NoOp :
|
||||
# 287| r1_2(int) = Constant[1] :
|
||||
# 287| r1_3(glval<int>) = VariableAddress[i] :
|
||||
# 287| r1_4(int) = Load : r1_3, m1_0
|
||||
# 287| r1_5(int) = Add : r1_4, r1_2
|
||||
# 287| m1_6(int) = Store : r1_3, r1_5
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 292| For_InitCondition() -> void
|
||||
# 292| Block 0
|
||||
@@ -1279,10 +1261,7 @@ ir.cpp:
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 296| Block 3
|
||||
# 296| v3_0(void) = NoOp :
|
||||
# 292| v3_1(void) = ReturnVoid :
|
||||
# 292| v3_2(void) = UnmodeledUse : mu*
|
||||
# 292| v3_3(void) = ExitFunction :
|
||||
# 296| v3_0(void) = Unreached :
|
||||
|
||||
# 298| For_InitUpdate() -> void
|
||||
# 298| Block 0
|
||||
@@ -1292,22 +1271,17 @@ ir.cpp:
|
||||
# 299| r0_3(glval<int>) = VariableAddress[i] :
|
||||
# 299| r0_4(int) = Constant[0] :
|
||||
# 299| m0_5(int) = Store : r0_3, r0_4
|
||||
#-----| Goto -> Block 2
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 298| Block 1
|
||||
# 298| v1_0(void) = ReturnVoid :
|
||||
# 298| v1_1(void) = UnmodeledUse : mu*
|
||||
# 298| v1_2(void) = ExitFunction :
|
||||
|
||||
# 300| Block 2
|
||||
# 300| m2_0(int) = Phi : from 0:m0_5, from 2:m2_6
|
||||
# 300| v2_1(void) = NoOp :
|
||||
# 299| r2_2(int) = Constant[1] :
|
||||
# 299| r2_3(glval<int>) = VariableAddress[i] :
|
||||
# 299| r2_4(int) = Load : r2_3, m2_0
|
||||
# 299| r2_5(int) = Add : r2_4, r2_2
|
||||
# 299| m2_6(int) = Store : r2_3, r2_5
|
||||
#-----| Goto -> Block 2
|
||||
# 300| Block 1
|
||||
# 300| m1_0(int) = Phi : from 0:m0_5, from 1:m1_6
|
||||
# 300| v1_1(void) = NoOp :
|
||||
# 299| r1_2(int) = Constant[1] :
|
||||
# 299| r1_3(glval<int>) = VariableAddress[i] :
|
||||
# 299| r1_4(int) = Load : r1_3, m1_0
|
||||
# 299| r1_5(int) = Add : r1_4, r1_2
|
||||
# 299| m1_6(int) = Store : r1_3, r1_5
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 304| For_ConditionUpdate() -> void
|
||||
# 304| Block 0
|
||||
@@ -1500,22 +1474,18 @@ ir.cpp:
|
||||
# 335| r2_2(int) = Constant[5] :
|
||||
# 335| r2_3(bool) = CompareEQ : r2_1, r2_2
|
||||
# 335| v2_4(void) = ConditionalBranch : r2_3
|
||||
#-----| False -> Block 4
|
||||
#-----| True -> Block 3
|
||||
#-----| False -> Block 3
|
||||
#-----| True -> Block 4
|
||||
|
||||
# 336| Block 3
|
||||
# 336| v3_0(void) = NoOp :
|
||||
#-----| Goto -> Block 4
|
||||
|
||||
# 334| Block 4
|
||||
# 334| v4_0(void) = NoOp :
|
||||
# 334| Block 3
|
||||
# 334| v3_0(void) = NoOp :
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 336| Block 4
|
||||
# 336| v4_0(void) = Unreached :
|
||||
|
||||
# 339| Block 5
|
||||
# 339| v5_0(void) = NoOp :
|
||||
# 333| v5_1(void) = ReturnVoid :
|
||||
# 333| v5_2(void) = UnmodeledUse : mu*
|
||||
# 333| v5_3(void) = ExitFunction :
|
||||
# 339| v5_0(void) = Unreached :
|
||||
|
||||
# 341| Dereference(int *) -> int
|
||||
# 341| Block 0
|
||||
@@ -1725,74 +1695,62 @@ ir.cpp:
|
||||
# 386| r0_7(glval<int>) = VariableAddress[x] :
|
||||
# 386| r0_8(int) = Load : r0_7, m0_4
|
||||
# 386| v0_9(void) = Switch : r0_8
|
||||
#-----| Case[-1] -> Block 2
|
||||
#-----| Case[1] -> Block 3
|
||||
#-----| Case[2] -> Block 4
|
||||
#-----| Case[3] -> Block 5
|
||||
#-----| Case[4] -> Block 6
|
||||
#-----| Default -> Block 7
|
||||
#-----| Case[-1] -> Block 1
|
||||
#-----| Case[1] -> Block 2
|
||||
#-----| Case[2] -> Block 3
|
||||
#-----| Case[3] -> Block 4
|
||||
#-----| Case[4] -> Block 5
|
||||
#-----| Default -> Block 6
|
||||
|
||||
# 387| Block 1
|
||||
# 387| r1_0(int) = Constant[1234] :
|
||||
# 387| r1_1(glval<int>) = VariableAddress[y] :
|
||||
# 387| m1_2(int) = Store : r1_1, r1_0
|
||||
#-----| Goto -> Block 2
|
||||
# 389| Block 1
|
||||
# 389| v1_0(void) = NoOp :
|
||||
# 390| r1_1(int) = Constant[-1] :
|
||||
# 390| r1_2(glval<int>) = VariableAddress[y] :
|
||||
# 390| m1_3(int) = Store : r1_2, r1_1
|
||||
# 391| v1_4(void) = NoOp :
|
||||
#-----| Goto -> Block 7
|
||||
|
||||
# 389| Block 2
|
||||
# 389| v2_0(void) = NoOp :
|
||||
# 390| r2_1(int) = Constant[-1] :
|
||||
# 390| r2_2(glval<int>) = VariableAddress[y] :
|
||||
# 390| m2_3(int) = Store : r2_2, r2_1
|
||||
# 391| v2_4(void) = NoOp :
|
||||
#-----| Goto -> Block 9
|
||||
# 393| Block 2
|
||||
# 393| v2_0(void) = NoOp :
|
||||
#-----| Goto -> Block 3
|
||||
|
||||
# 393| Block 3
|
||||
# 393| v3_0(void) = NoOp :
|
||||
#-----| Goto -> Block 4
|
||||
# 394| Block 3
|
||||
# 394| v3_0(void) = NoOp :
|
||||
# 395| r3_1(int) = Constant[1] :
|
||||
# 395| r3_2(glval<int>) = VariableAddress[y] :
|
||||
# 395| m3_3(int) = Store : r3_2, r3_1
|
||||
# 396| v3_4(void) = NoOp :
|
||||
#-----| Goto -> Block 7
|
||||
|
||||
# 394| Block 4
|
||||
# 394| v4_0(void) = NoOp :
|
||||
# 395| r4_1(int) = Constant[1] :
|
||||
# 395| r4_2(glval<int>) = VariableAddress[y] :
|
||||
# 395| m4_3(int) = Store : r4_2, r4_1
|
||||
# 396| v4_4(void) = NoOp :
|
||||
#-----| Goto -> Block 9
|
||||
# 398| Block 4
|
||||
# 398| v4_0(void) = NoOp :
|
||||
# 399| r4_1(int) = Constant[3] :
|
||||
# 399| r4_2(glval<int>) = VariableAddress[y] :
|
||||
# 399| m4_3(int) = Store : r4_2, r4_1
|
||||
#-----| Goto -> Block 5
|
||||
|
||||
# 398| Block 5
|
||||
# 398| v5_0(void) = NoOp :
|
||||
# 399| r5_1(int) = Constant[3] :
|
||||
# 399| r5_2(glval<int>) = VariableAddress[y] :
|
||||
# 399| m5_3(int) = Store : r5_2, r5_1
|
||||
#-----| Goto -> Block 6
|
||||
# 400| Block 5
|
||||
# 400| v5_0(void) = NoOp :
|
||||
# 401| r5_1(int) = Constant[4] :
|
||||
# 401| r5_2(glval<int>) = VariableAddress[y] :
|
||||
# 401| m5_3(int) = Store : r5_2, r5_1
|
||||
# 402| v5_4(void) = NoOp :
|
||||
#-----| Goto -> Block 7
|
||||
|
||||
# 400| Block 6
|
||||
# 400| v6_0(void) = NoOp :
|
||||
# 401| r6_1(int) = Constant[4] :
|
||||
# 401| r6_2(glval<int>) = VariableAddress[y] :
|
||||
# 401| m6_3(int) = Store : r6_2, r6_1
|
||||
# 402| v6_4(void) = NoOp :
|
||||
#-----| Goto -> Block 9
|
||||
# 404| Block 6
|
||||
# 404| v6_0(void) = NoOp :
|
||||
# 405| r6_1(int) = Constant[0] :
|
||||
# 405| r6_2(glval<int>) = VariableAddress[y] :
|
||||
# 405| m6_3(int) = Store : r6_2, r6_1
|
||||
# 406| v6_4(void) = NoOp :
|
||||
#-----| Goto -> Block 7
|
||||
|
||||
# 404| Block 7
|
||||
# 404| v7_0(void) = NoOp :
|
||||
# 405| r7_1(int) = Constant[0] :
|
||||
# 405| r7_2(glval<int>) = VariableAddress[y] :
|
||||
# 405| m7_3(int) = Store : r7_2, r7_1
|
||||
# 406| v7_4(void) = NoOp :
|
||||
#-----| Goto -> Block 9
|
||||
|
||||
# 408| Block 8
|
||||
# 408| r8_0(int) = Constant[5678] :
|
||||
# 408| r8_1(glval<int>) = VariableAddress[y] :
|
||||
# 408| m8_2(int) = Store : r8_1, r8_0
|
||||
#-----| Goto -> Block 9
|
||||
|
||||
# 409| Block 9
|
||||
# 409| v9_0(void) = NoOp :
|
||||
# 410| v9_1(void) = NoOp :
|
||||
# 384| v9_2(void) = ReturnVoid :
|
||||
# 384| v9_3(void) = UnmodeledUse : mu*
|
||||
# 384| v9_4(void) = ExitFunction :
|
||||
# 409| Block 7
|
||||
# 409| v7_0(void) = NoOp :
|
||||
# 410| v7_1(void) = NoOp :
|
||||
# 384| v7_2(void) = ReturnVoid :
|
||||
# 384| v7_3(void) = UnmodeledUse : mu*
|
||||
# 384| v7_4(void) = ExitFunction :
|
||||
|
||||
# 422| ReturnStruct(Point) -> Point
|
||||
# 422| Block 0
|
||||
@@ -2592,7 +2550,7 @@ ir.cpp:
|
||||
# 560| m0_1(unknown) = AliasedDefinition :
|
||||
# 560| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 560| r0_3(glval<E>) = VariableAddress[e] :
|
||||
# 560| m0_4(E) = InitializeParameter[e] : r0_3
|
||||
# 560| mu0_4(E) = InitializeParameter[e] : r0_3
|
||||
# 561| r0_5(glval<E>) = VariableAddress[e] :
|
||||
# 561| r0_6(E) = Load : r0_5, mu0_2
|
||||
# 561| r0_7(int) = Convert : r0_6
|
||||
@@ -3211,7 +3169,7 @@ ir.cpp:
|
||||
# 728| r3_2(char *) = Convert : r3_1
|
||||
# 728| m3_3(char *) = Store : r3_0, r3_2
|
||||
# 728| v3_4(void) = ThrowValue : r3_0, m3_3
|
||||
#-----| Exception -> Block 9
|
||||
#-----| Exception -> Block 6
|
||||
|
||||
# 730| Block 4
|
||||
# 730| r4_0(glval<int>) = VariableAddress[x] :
|
||||
@@ -3219,83 +3177,57 @@ ir.cpp:
|
||||
# 730| r4_2(int) = Constant[2] :
|
||||
# 730| r4_3(bool) = CompareLT : r4_1, r4_2
|
||||
# 730| v4_4(void) = ConditionalBranch : r4_3
|
||||
#-----| False -> Block 8
|
||||
#-----| True -> Block 5
|
||||
#-----| False -> Block 5
|
||||
#-----| True -> Block 12
|
||||
|
||||
# 731| Block 5
|
||||
# 731| r5_0(glval<bool>) = VariableAddress[b] :
|
||||
# 731| r5_1(bool) = Load : r5_0, m0_4
|
||||
# 731| v5_2(void) = ConditionalBranch : r5_1
|
||||
#-----| False -> Block 7
|
||||
#-----| True -> Block 6
|
||||
# 733| Block 5
|
||||
# 733| r5_0(int) = Constant[7] :
|
||||
# 733| r5_1(glval<int>) = VariableAddress[x] :
|
||||
# 733| m5_2(int) = Store : r5_1, r5_0
|
||||
#-----| Goto -> Block 11
|
||||
|
||||
# 731| Block 6
|
||||
# 731| r6_0(int) = Constant[7] :
|
||||
# 731| r6_1(glval<int>) = VariableAddress[#temp731:11] :
|
||||
# 731| m6_2(int) = Store : r6_1, r6_0
|
||||
# 731| r6_3(glval<int>) = VariableAddress[#temp731:11] :
|
||||
# 731| r6_4(int) = Load : r6_3, m6_2
|
||||
# 731| r6_5(glval<int>) = VariableAddress[x] :
|
||||
# 731| m6_6(int) = Store : r6_5, r6_4
|
||||
#-----| Goto -> Block 8
|
||||
# 735| Block 6
|
||||
# 735| v6_0(void) = CatchByType[const char *] :
|
||||
#-----| Exception -> Block 8
|
||||
#-----| Goto -> Block 7
|
||||
|
||||
# 731| Block 7
|
||||
# 731| r7_0(glval<String>) = VariableAddress[#throw731:19] :
|
||||
# 731| r7_1(glval<unknown>) = FunctionAddress[String] :
|
||||
# 731| r7_2(glval<char[14]>) = StringConstant["String object"] :
|
||||
# 731| r7_3(char *) = Convert : r7_2
|
||||
# 731| v7_4(void) = Call : r7_1, this:r7_0, r7_3
|
||||
# 731| m7_5(unknown) = ^CallSideEffect : m0_1
|
||||
# 731| m7_6(unknown) = Chi : m0_1, m7_5
|
||||
# 731| v7_7(void) = ThrowValue : r7_0, mu0_2
|
||||
#-----| Exception -> Block 9
|
||||
|
||||
# 733| Block 8
|
||||
# 733| r8_0(int) = Constant[7] :
|
||||
# 733| r8_1(glval<int>) = VariableAddress[x] :
|
||||
# 733| m8_2(int) = Store : r8_1, r8_0
|
||||
#-----| Goto -> Block 14
|
||||
|
||||
# 735| Block 9
|
||||
# 735| m9_0(unknown) = Phi : from 3:m0_1, from 7:m7_6
|
||||
# 735| v9_1(void) = CatchByType[const char *] :
|
||||
#-----| Exception -> Block 11
|
||||
#-----| Goto -> Block 10
|
||||
|
||||
# 735| Block 10
|
||||
# 735| r10_0(glval<char *>) = VariableAddress[s] :
|
||||
# 735| m10_1(char *) = InitializeParameter[s] : r10_0
|
||||
# 736| r10_2(glval<String>) = VariableAddress[#throw736:5] :
|
||||
# 736| r10_3(glval<unknown>) = FunctionAddress[String] :
|
||||
# 736| r10_4(glval<char *>) = VariableAddress[s] :
|
||||
# 736| r10_5(char *) = Load : r10_4, m10_1
|
||||
# 736| v10_6(void) = Call : r10_3, this:r10_2, r10_5
|
||||
# 736| m10_7(unknown) = ^CallSideEffect : m9_0
|
||||
# 736| m10_8(unknown) = Chi : m9_0, m10_7
|
||||
# 736| v10_9(void) = ThrowValue : r10_2, mu0_2
|
||||
# 735| Block 7
|
||||
# 735| r7_0(glval<char *>) = VariableAddress[s] :
|
||||
# 735| m7_1(char *) = InitializeParameter[s] : r7_0
|
||||
# 736| r7_2(glval<String>) = VariableAddress[#throw736:5] :
|
||||
# 736| r7_3(glval<unknown>) = FunctionAddress[String] :
|
||||
# 736| r7_4(glval<char *>) = VariableAddress[s] :
|
||||
# 736| r7_5(char *) = Load : r7_4, m7_1
|
||||
# 736| v7_6(void) = Call : r7_3, this:r7_2, r7_5
|
||||
# 736| m7_7(unknown) = ^CallSideEffect : m0_1
|
||||
# 736| m7_8(unknown) = Chi : m0_1, m7_7
|
||||
# 736| v7_9(void) = ThrowValue : r7_2, mu0_2
|
||||
#-----| Exception -> Block 2
|
||||
|
||||
# 738| Block 11
|
||||
# 738| v11_0(void) = CatchByType[const String &] :
|
||||
#-----| Exception -> Block 13
|
||||
#-----| Goto -> Block 12
|
||||
# 738| Block 8
|
||||
# 738| v8_0(void) = CatchByType[const String &] :
|
||||
#-----| Exception -> Block 10
|
||||
#-----| Goto -> Block 9
|
||||
|
||||
# 738| Block 12
|
||||
# 738| r12_0(glval<String &>) = VariableAddress[e] :
|
||||
# 738| m12_1(String &) = InitializeParameter[e] : r12_0
|
||||
# 738| v12_2(void) = NoOp :
|
||||
#-----| Goto -> Block 14
|
||||
# 738| Block 9
|
||||
# 738| r9_0(glval<String &>) = VariableAddress[e] :
|
||||
# 738| m9_1(String &) = InitializeParameter[e] : r9_0
|
||||
# 738| v9_2(void) = NoOp :
|
||||
#-----| Goto -> Block 11
|
||||
|
||||
# 740| Block 13
|
||||
# 740| v13_0(void) = CatchAny :
|
||||
# 741| v13_1(void) = ReThrow :
|
||||
# 740| Block 10
|
||||
# 740| v10_0(void) = CatchAny :
|
||||
# 741| v10_1(void) = ReThrow :
|
||||
#-----| Exception -> Block 2
|
||||
|
||||
# 743| Block 14
|
||||
# 743| v14_0(void) = NoOp :
|
||||
# 724| v14_1(void) = ReturnVoid :
|
||||
# 743| Block 11
|
||||
# 743| v11_0(void) = NoOp :
|
||||
# 724| v11_1(void) = ReturnVoid :
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 731| Block 12
|
||||
# 731| v12_0(void) = Unreached :
|
||||
|
||||
# 745| Base::Base(const Base &) -> void
|
||||
# 745| Block 0
|
||||
# 745| v0_0(void) = EnterFunction :
|
||||
@@ -4153,32 +4085,24 @@ ir.cpp:
|
||||
# 906| r0_8(glval<int>) = VariableAddress[b] :
|
||||
# 906| r0_9(bool) = Constant[1] :
|
||||
# 906| v0_10(void) = ConditionalBranch : r0_9
|
||||
#-----| False -> Block 3
|
||||
#-----| True -> Block 2
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 1
|
||||
|
||||
# 906| Block 1
|
||||
# 906| m1_0(int) = Phi : from 2:m2_3, from 3:m3_3
|
||||
# 906| r1_1(glval<int>) = VariableAddress[#temp906:11] :
|
||||
# 906| r1_2(int) = Load : r1_1, m1_0
|
||||
# 906| m1_3(int) = Store : r0_8, r1_2
|
||||
# 907| v1_4(void) = NoOp :
|
||||
# 904| v1_5(void) = ReturnVoid :
|
||||
# 904| v1_6(void) = UnmodeledUse : mu*
|
||||
# 904| v1_7(void) = ExitFunction :
|
||||
# 906| r1_0(glval<int>) = VariableAddress[x] :
|
||||
# 906| r1_1(int) = Load : r1_0, m0_4
|
||||
# 906| r1_2(glval<int>) = VariableAddress[#temp906:11] :
|
||||
# 906| m1_3(int) = Store : r1_2, r1_1
|
||||
# 906| r1_4(glval<int>) = VariableAddress[#temp906:11] :
|
||||
# 906| r1_5(int) = Load : r1_4, m1_3
|
||||
# 906| m1_6(int) = Store : r0_8, r1_5
|
||||
# 907| v1_7(void) = NoOp :
|
||||
# 904| v1_8(void) = ReturnVoid :
|
||||
# 904| v1_9(void) = UnmodeledUse : mu*
|
||||
# 904| v1_10(void) = ExitFunction :
|
||||
|
||||
# 906| Block 2
|
||||
# 906| r2_0(glval<int>) = VariableAddress[x] :
|
||||
# 906| r2_1(int) = Load : r2_0, m0_4
|
||||
# 906| r2_2(glval<int>) = VariableAddress[#temp906:11] :
|
||||
# 906| m2_3(int) = Store : r2_2, r2_1
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 906| Block 3
|
||||
# 906| r3_0(glval<int>) = VariableAddress[x] :
|
||||
# 906| r3_1(int) = Load : r3_0, m0_4
|
||||
# 906| r3_2(glval<int>) = VariableAddress[#temp906:11] :
|
||||
# 906| m3_3(int) = Store : r3_2, r3_1
|
||||
#-----| Goto -> Block 1
|
||||
# 906| v2_0(void) = Unreached :
|
||||
|
||||
# 940| OperatorNew() -> void
|
||||
# 940| Block 0
|
||||
@@ -4618,3 +4542,82 @@ ir.cpp:
|
||||
# 1005| v6_13(void) = ReturnValue : r6_12, m6_11
|
||||
# 1005| v6_14(void) = UnmodeledUse : mu*
|
||||
# 1005| v6_15(void) = ExitFunction :
|
||||
|
||||
# 1021| UnreachableViaGoto() -> int
|
||||
# 1021| Block 0
|
||||
# 1021| v0_0(void) = EnterFunction :
|
||||
# 1021| m0_1(unknown) = AliasedDefinition :
|
||||
# 1021| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 1022| v0_3(void) = NoOp :
|
||||
# 1024| v0_4(void) = NoOp :
|
||||
# 1025| r0_5(glval<int>) = VariableAddress[#return] :
|
||||
# 1025| r0_6(int) = Constant[0] :
|
||||
# 1025| m0_7(int) = Store : r0_5, r0_6
|
||||
# 1021| r0_8(glval<int>) = VariableAddress[#return] :
|
||||
# 1021| v0_9(void) = ReturnValue : r0_8, m0_7
|
||||
# 1021| v0_10(void) = UnmodeledUse : mu*
|
||||
# 1021| v0_11(void) = ExitFunction :
|
||||
|
||||
# 1028| UnreachableIf(bool) -> int
|
||||
# 1028| Block 0
|
||||
# 1028| v0_0(void) = EnterFunction :
|
||||
# 1028| m0_1(unknown) = AliasedDefinition :
|
||||
# 1028| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 1028| r0_3(glval<bool>) = VariableAddress[b] :
|
||||
# 1028| m0_4(bool) = InitializeParameter[b] : r0_3
|
||||
# 1029| r0_5(glval<int>) = VariableAddress[x] :
|
||||
# 1029| r0_6(int) = Constant[5] :
|
||||
# 1029| m0_7(int) = Store : r0_5, r0_6
|
||||
# 1030| r0_8(glval<int>) = VariableAddress[y] :
|
||||
# 1030| r0_9(int) = Constant[10] :
|
||||
# 1030| m0_10(int) = Store : r0_8, r0_9
|
||||
# 1031| r0_11(glval<bool>) = VariableAddress[b] :
|
||||
# 1031| r0_12(bool) = Load : r0_11, m0_4
|
||||
# 1031| v0_13(void) = ConditionalBranch : r0_12
|
||||
#-----| False -> Block 4
|
||||
#-----| True -> Block 2
|
||||
|
||||
# 1028| Block 1
|
||||
# 1028| m1_0(int) = Phi : from 3:m3_2, from 5:m5_2
|
||||
# 1028| r1_1(glval<int>) = VariableAddress[#return] :
|
||||
# 1028| v1_2(void) = ReturnValue : r1_1, m1_0
|
||||
# 1028| v1_3(void) = UnmodeledUse : mu*
|
||||
# 1028| v1_4(void) = ExitFunction :
|
||||
|
||||
# 1032| Block 2
|
||||
# 1032| r2_0(glval<int>) = VariableAddress[x] :
|
||||
# 1032| r2_1(int) = Load : r2_0, m0_7
|
||||
# 1032| r2_2(glval<int>) = VariableAddress[y] :
|
||||
# 1032| r2_3(int) = Load : r2_2, m0_10
|
||||
# 1032| r2_4(bool) = CompareEQ : r2_1, r2_3
|
||||
# 1032| v2_5(void) = ConditionalBranch : r2_4
|
||||
#-----| False -> Block 3
|
||||
#-----| True -> Block 6
|
||||
|
||||
# 1036| Block 3
|
||||
# 1036| r3_0(glval<int>) = VariableAddress[#return] :
|
||||
# 1036| r3_1(int) = Constant[0] :
|
||||
# 1036| m3_2(int) = Store : r3_0, r3_1
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 1040| Block 4
|
||||
# 1040| r4_0(glval<int>) = VariableAddress[x] :
|
||||
# 1040| r4_1(int) = Load : r4_0, m0_7
|
||||
# 1040| r4_2(glval<int>) = VariableAddress[y] :
|
||||
# 1040| r4_3(int) = Load : r4_2, m0_10
|
||||
# 1040| r4_4(bool) = CompareLT : r4_1, r4_3
|
||||
# 1040| v4_5(void) = ConditionalBranch : r4_4
|
||||
#-----| False -> Block 7
|
||||
#-----| True -> Block 5
|
||||
|
||||
# 1041| Block 5
|
||||
# 1041| r5_0(glval<int>) = VariableAddress[#return] :
|
||||
# 1041| r5_1(int) = Constant[0] :
|
||||
# 1041| m5_2(int) = Store : r5_0, r5_1
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 1033| Block 6
|
||||
# 1033| v6_0(void) = Unreached :
|
||||
|
||||
# 1044| Block 7
|
||||
# 1044| v7_0(void) = Unreached :
|
||||
|
||||
@@ -1018,4 +1018,32 @@ int ChiPhiNode(Point *p, bool which1, bool which2) {
|
||||
return p->x + p->y;
|
||||
}
|
||||
|
||||
int UnreachableViaGoto() {
|
||||
goto skip;
|
||||
return 1;
|
||||
skip:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int UnreachableIf(bool b) {
|
||||
int x = 5;
|
||||
int y = 10;
|
||||
if (b) {
|
||||
if (x == y) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (x < y) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// semmle-extractor-options: -std=c++17
|
||||
|
||||
@@ -4420,3 +4420,96 @@ ir.cpp:
|
||||
# 1005| v6_12(void) = ReturnValue : r6_11, mu0_2
|
||||
# 1005| v6_13(void) = UnmodeledUse : mu*
|
||||
# 1005| v6_14(void) = ExitFunction :
|
||||
|
||||
# 1021| UnreachableViaGoto() -> int
|
||||
# 1021| Block 0
|
||||
# 1021| v0_0(void) = EnterFunction :
|
||||
# 1021| mu0_1(unknown) = AliasedDefinition :
|
||||
# 1021| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 1022| v0_3(void) = NoOp :
|
||||
# 1024| v0_4(void) = NoOp :
|
||||
# 1025| r0_5(glval<int>) = VariableAddress[#return] :
|
||||
# 1025| r0_6(int) = Constant[0] :
|
||||
# 1025| mu0_7(int) = Store : r0_5, r0_6
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 1021| Block 1
|
||||
# 1021| r1_0(glval<int>) = VariableAddress[#return] :
|
||||
# 1021| v1_1(void) = ReturnValue : r1_0, mu0_2
|
||||
# 1021| v1_2(void) = UnmodeledUse : mu*
|
||||
# 1021| v1_3(void) = ExitFunction :
|
||||
|
||||
# 1023| Block 2
|
||||
# 1023| r2_0(glval<int>) = VariableAddress[#return] :
|
||||
# 1023| r2_1(int) = Constant[1] :
|
||||
# 1023| mu2_2(int) = Store : r2_0, r2_1
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 1028| UnreachableIf(bool) -> int
|
||||
# 1028| Block 0
|
||||
# 1028| v0_0(void) = EnterFunction :
|
||||
# 1028| mu0_1(unknown) = AliasedDefinition :
|
||||
# 1028| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 1028| r0_3(glval<bool>) = VariableAddress[b] :
|
||||
# 1028| mu0_4(bool) = InitializeParameter[b] : r0_3
|
||||
# 1029| r0_5(glval<int>) = VariableAddress[x] :
|
||||
# 1029| r0_6(int) = Constant[5] :
|
||||
# 1029| mu0_7(int) = Store : r0_5, r0_6
|
||||
# 1030| r0_8(glval<int>) = VariableAddress[y] :
|
||||
# 1030| r0_9(int) = Constant[10] :
|
||||
# 1030| mu0_10(int) = Store : r0_8, r0_9
|
||||
# 1031| r0_11(glval<bool>) = VariableAddress[b] :
|
||||
# 1031| r0_12(bool) = Load : r0_11, mu0_2
|
||||
# 1031| v0_13(void) = ConditionalBranch : r0_12
|
||||
#-----| False -> Block 5
|
||||
#-----| True -> Block 2
|
||||
|
||||
# 1028| Block 1
|
||||
# 1028| r1_0(glval<int>) = VariableAddress[#return] :
|
||||
# 1028| v1_1(void) = ReturnValue : r1_0, mu0_2
|
||||
# 1028| v1_2(void) = UnmodeledUse : mu*
|
||||
# 1028| v1_3(void) = ExitFunction :
|
||||
|
||||
# 1032| Block 2
|
||||
# 1032| r2_0(glval<int>) = VariableAddress[x] :
|
||||
# 1032| r2_1(int) = Load : r2_0, mu0_2
|
||||
# 1032| r2_2(glval<int>) = VariableAddress[y] :
|
||||
# 1032| r2_3(int) = Load : r2_2, mu0_2
|
||||
# 1032| r2_4(bool) = CompareEQ : r2_1, r2_3
|
||||
# 1032| v2_5(void) = ConditionalBranch : r2_4
|
||||
#-----| False -> Block 4
|
||||
#-----| True -> Block 3
|
||||
|
||||
# 1033| Block 3
|
||||
# 1033| r3_0(glval<int>) = VariableAddress[#return] :
|
||||
# 1033| r3_1(int) = Constant[1] :
|
||||
# 1033| mu3_2(int) = Store : r3_0, r3_1
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 1036| Block 4
|
||||
# 1036| r4_0(glval<int>) = VariableAddress[#return] :
|
||||
# 1036| r4_1(int) = Constant[0] :
|
||||
# 1036| mu4_2(int) = Store : r4_0, r4_1
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 1040| Block 5
|
||||
# 1040| r5_0(glval<int>) = VariableAddress[x] :
|
||||
# 1040| r5_1(int) = Load : r5_0, mu0_2
|
||||
# 1040| r5_2(glval<int>) = VariableAddress[y] :
|
||||
# 1040| r5_3(int) = Load : r5_2, mu0_2
|
||||
# 1040| r5_4(bool) = CompareLT : r5_1, r5_3
|
||||
# 1040| v5_5(void) = ConditionalBranch : r5_4
|
||||
#-----| False -> Block 7
|
||||
#-----| True -> Block 6
|
||||
|
||||
# 1041| Block 6
|
||||
# 1041| r6_0(glval<int>) = VariableAddress[#return] :
|
||||
# 1041| r6_1(int) = Constant[0] :
|
||||
# 1041| mu6_2(int) = Store : r6_0, r6_1
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 1044| Block 7
|
||||
# 1044| r7_0(glval<int>) = VariableAddress[#return] :
|
||||
# 1044| r7_1(int) = Constant[1] :
|
||||
# 1044| mu7_2(int) = Store : r7_0, r7_1
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
| IR: Conditional | 4 |
|
||||
| IR: Conditional_LValue | 4 |
|
||||
| IR: Conditional_Void | 4 |
|
||||
| IR: ConstantConditions | 4 |
|
||||
| IR: ConstantConditions | 3 |
|
||||
| IR: Constants | 1 |
|
||||
| IR: Continue | 6 |
|
||||
| IR: DeclareObject | 1 |
|
||||
@@ -45,12 +45,12 @@
|
||||
| IR: For_ConditionUpdate | 4 |
|
||||
| IR: For_Continue_NoUpdate | 6 |
|
||||
| IR: For_Continue_Update | 6 |
|
||||
| IR: For_Empty | 3 |
|
||||
| IR: For_Init | 3 |
|
||||
| IR: For_Empty | 2 |
|
||||
| IR: For_Init | 2 |
|
||||
| IR: For_InitCondition | 4 |
|
||||
| IR: For_InitConditionUpdate | 4 |
|
||||
| IR: For_InitUpdate | 3 |
|
||||
| IR: For_Update | 3 |
|
||||
| IR: For_InitUpdate | 2 |
|
||||
| IR: For_Update | 2 |
|
||||
| IR: Func | 1 |
|
||||
| IR: FuncPtrConversions | 1 |
|
||||
| IR: FunctionReferences | 1 |
|
||||
@@ -88,11 +88,13 @@
|
||||
| IR: StaticMemberFunction | 1 |
|
||||
| IR: String | 1 |
|
||||
| IR: StringLiteral | 1 |
|
||||
| IR: Switch | 10 |
|
||||
| IR: Switch | 8 |
|
||||
| IR: TakeReference | 1 |
|
||||
| IR: TryCatch | 15 |
|
||||
| IR: TryCatch | 13 |
|
||||
| IR: UninitializedVariables | 1 |
|
||||
| IR: UnionInit | 1 |
|
||||
| IR: UnreachableIf | 8 |
|
||||
| IR: UnreachableViaGoto | 1 |
|
||||
| IR: VarArgUsage | 1 |
|
||||
| IR: VarArgs | 1 |
|
||||
| IR: VirtualMemberFunction | 1 |
|
||||
|
||||
@@ -1164,16 +1164,11 @@ ir.cpp:
|
||||
# 265| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 266| r0_3(glval<int>) = VariableAddress[j] :
|
||||
# 266| m0_4(int) = Uninitialized[j] : r0_3
|
||||
#-----| Goto -> Block 2
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 265| Block 1
|
||||
# 265| v1_0(void) = ReturnVoid :
|
||||
# 265| v1_1(void) = UnmodeledUse : mu*
|
||||
# 265| v1_2(void) = ExitFunction :
|
||||
|
||||
# 268| Block 2
|
||||
# 268| v2_0(void) = NoOp :
|
||||
#-----| Goto -> Block 2
|
||||
# 268| Block 1
|
||||
# 268| v1_0(void) = NoOp :
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 272| For_Init() -> void
|
||||
# 272| Block 0
|
||||
@@ -1183,16 +1178,11 @@ ir.cpp:
|
||||
# 273| r0_3(glval<int>) = VariableAddress[i] :
|
||||
# 273| r0_4(int) = Constant[0] :
|
||||
# 273| m0_5(int) = Store : r0_3, r0_4
|
||||
#-----| Goto -> Block 2
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 272| Block 1
|
||||
# 272| v1_0(void) = ReturnVoid :
|
||||
# 272| v1_1(void) = UnmodeledUse : mu*
|
||||
# 272| v1_2(void) = ExitFunction :
|
||||
|
||||
# 274| Block 2
|
||||
# 274| v2_0(void) = NoOp :
|
||||
#-----| Goto -> Block 2
|
||||
# 274| Block 1
|
||||
# 274| v1_0(void) = NoOp :
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 278| For_Condition() -> void
|
||||
# 278| Block 0
|
||||
@@ -1231,22 +1221,17 @@ ir.cpp:
|
||||
# 286| r0_3(glval<int>) = VariableAddress[i] :
|
||||
# 286| r0_4(int) = Constant[0] :
|
||||
# 286| m0_5(int) = Store : r0_3, r0_4
|
||||
#-----| Goto -> Block 2
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 285| Block 1
|
||||
# 285| v1_0(void) = ReturnVoid :
|
||||
# 285| v1_1(void) = UnmodeledUse : mu*
|
||||
# 285| v1_2(void) = ExitFunction :
|
||||
|
||||
# 288| Block 2
|
||||
# 288| m2_0(int) = Phi : from 0:m0_5, from 2:m2_6
|
||||
# 288| v2_1(void) = NoOp :
|
||||
# 287| r2_2(int) = Constant[1] :
|
||||
# 287| r2_3(glval<int>) = VariableAddress[i] :
|
||||
# 287| r2_4(int) = Load : r2_3, m2_0
|
||||
# 287| r2_5(int) = Add : r2_4, r2_2
|
||||
# 287| m2_6(int) = Store : r2_3, r2_5
|
||||
#-----| Goto -> Block 2
|
||||
# 288| Block 1
|
||||
# 288| m1_0(int) = Phi : from 0:m0_5, from 1:m1_6
|
||||
# 288| v1_1(void) = NoOp :
|
||||
# 287| r1_2(int) = Constant[1] :
|
||||
# 287| r1_3(glval<int>) = VariableAddress[i] :
|
||||
# 287| r1_4(int) = Load : r1_3, m1_0
|
||||
# 287| r1_5(int) = Add : r1_4, r1_2
|
||||
# 287| m1_6(int) = Store : r1_3, r1_5
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 292| For_InitCondition() -> void
|
||||
# 292| Block 0
|
||||
@@ -1285,22 +1270,17 @@ ir.cpp:
|
||||
# 299| r0_3(glval<int>) = VariableAddress[i] :
|
||||
# 299| r0_4(int) = Constant[0] :
|
||||
# 299| m0_5(int) = Store : r0_3, r0_4
|
||||
#-----| Goto -> Block 2
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 298| Block 1
|
||||
# 298| v1_0(void) = ReturnVoid :
|
||||
# 298| v1_1(void) = UnmodeledUse : mu*
|
||||
# 298| v1_2(void) = ExitFunction :
|
||||
|
||||
# 300| Block 2
|
||||
# 300| m2_0(int) = Phi : from 0:m0_5, from 2:m2_6
|
||||
# 300| v2_1(void) = NoOp :
|
||||
# 299| r2_2(int) = Constant[1] :
|
||||
# 299| r2_3(glval<int>) = VariableAddress[i] :
|
||||
# 299| r2_4(int) = Load : r2_3, m2_0
|
||||
# 299| r2_5(int) = Add : r2_4, r2_2
|
||||
# 299| m2_6(int) = Store : r2_3, r2_5
|
||||
#-----| Goto -> Block 2
|
||||
# 300| Block 1
|
||||
# 300| m1_0(int) = Phi : from 0:m0_5, from 1:m1_6
|
||||
# 300| v1_1(void) = NoOp :
|
||||
# 299| r1_2(int) = Constant[1] :
|
||||
# 299| r1_3(glval<int>) = VariableAddress[i] :
|
||||
# 299| r1_4(int) = Load : r1_3, m1_0
|
||||
# 299| r1_5(int) = Add : r1_4, r1_2
|
||||
# 299| m1_6(int) = Store : r1_3, r1_5
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 304| For_ConditionUpdate() -> void
|
||||
# 304| Block 0
|
||||
@@ -1713,74 +1693,62 @@ ir.cpp:
|
||||
# 386| r0_7(glval<int>) = VariableAddress[x] :
|
||||
# 386| r0_8(int) = Load : r0_7, m0_4
|
||||
# 386| v0_9(void) = Switch : r0_8
|
||||
#-----| Case[-1] -> Block 2
|
||||
#-----| Case[1] -> Block 3
|
||||
#-----| Case[2] -> Block 4
|
||||
#-----| Case[3] -> Block 5
|
||||
#-----| Case[4] -> Block 6
|
||||
#-----| Default -> Block 7
|
||||
#-----| Case[-1] -> Block 1
|
||||
#-----| Case[1] -> Block 2
|
||||
#-----| Case[2] -> Block 3
|
||||
#-----| Case[3] -> Block 4
|
||||
#-----| Case[4] -> Block 5
|
||||
#-----| Default -> Block 6
|
||||
|
||||
# 387| Block 1
|
||||
# 387| r1_0(int) = Constant[1234] :
|
||||
# 387| r1_1(glval<int>) = VariableAddress[y] :
|
||||
# 387| m1_2(int) = Store : r1_1, r1_0
|
||||
#-----| Goto -> Block 2
|
||||
# 389| Block 1
|
||||
# 389| v1_0(void) = NoOp :
|
||||
# 390| r1_1(int) = Constant[-1] :
|
||||
# 390| r1_2(glval<int>) = VariableAddress[y] :
|
||||
# 390| m1_3(int) = Store : r1_2, r1_1
|
||||
# 391| v1_4(void) = NoOp :
|
||||
#-----| Goto -> Block 7
|
||||
|
||||
# 389| Block 2
|
||||
# 389| v2_0(void) = NoOp :
|
||||
# 390| r2_1(int) = Constant[-1] :
|
||||
# 390| r2_2(glval<int>) = VariableAddress[y] :
|
||||
# 390| m2_3(int) = Store : r2_2, r2_1
|
||||
# 391| v2_4(void) = NoOp :
|
||||
#-----| Goto -> Block 9
|
||||
# 393| Block 2
|
||||
# 393| v2_0(void) = NoOp :
|
||||
#-----| Goto -> Block 3
|
||||
|
||||
# 393| Block 3
|
||||
# 393| v3_0(void) = NoOp :
|
||||
#-----| Goto -> Block 4
|
||||
# 394| Block 3
|
||||
# 394| v3_0(void) = NoOp :
|
||||
# 395| r3_1(int) = Constant[1] :
|
||||
# 395| r3_2(glval<int>) = VariableAddress[y] :
|
||||
# 395| m3_3(int) = Store : r3_2, r3_1
|
||||
# 396| v3_4(void) = NoOp :
|
||||
#-----| Goto -> Block 7
|
||||
|
||||
# 394| Block 4
|
||||
# 394| v4_0(void) = NoOp :
|
||||
# 395| r4_1(int) = Constant[1] :
|
||||
# 395| r4_2(glval<int>) = VariableAddress[y] :
|
||||
# 395| m4_3(int) = Store : r4_2, r4_1
|
||||
# 396| v4_4(void) = NoOp :
|
||||
#-----| Goto -> Block 9
|
||||
# 398| Block 4
|
||||
# 398| v4_0(void) = NoOp :
|
||||
# 399| r4_1(int) = Constant[3] :
|
||||
# 399| r4_2(glval<int>) = VariableAddress[y] :
|
||||
# 399| m4_3(int) = Store : r4_2, r4_1
|
||||
#-----| Goto -> Block 5
|
||||
|
||||
# 398| Block 5
|
||||
# 398| v5_0(void) = NoOp :
|
||||
# 399| r5_1(int) = Constant[3] :
|
||||
# 399| r5_2(glval<int>) = VariableAddress[y] :
|
||||
# 399| m5_3(int) = Store : r5_2, r5_1
|
||||
#-----| Goto -> Block 6
|
||||
# 400| Block 5
|
||||
# 400| v5_0(void) = NoOp :
|
||||
# 401| r5_1(int) = Constant[4] :
|
||||
# 401| r5_2(glval<int>) = VariableAddress[y] :
|
||||
# 401| m5_3(int) = Store : r5_2, r5_1
|
||||
# 402| v5_4(void) = NoOp :
|
||||
#-----| Goto -> Block 7
|
||||
|
||||
# 400| Block 6
|
||||
# 400| v6_0(void) = NoOp :
|
||||
# 401| r6_1(int) = Constant[4] :
|
||||
# 401| r6_2(glval<int>) = VariableAddress[y] :
|
||||
# 401| m6_3(int) = Store : r6_2, r6_1
|
||||
# 402| v6_4(void) = NoOp :
|
||||
#-----| Goto -> Block 9
|
||||
# 404| Block 6
|
||||
# 404| v6_0(void) = NoOp :
|
||||
# 405| r6_1(int) = Constant[0] :
|
||||
# 405| r6_2(glval<int>) = VariableAddress[y] :
|
||||
# 405| m6_3(int) = Store : r6_2, r6_1
|
||||
# 406| v6_4(void) = NoOp :
|
||||
#-----| Goto -> Block 7
|
||||
|
||||
# 404| Block 7
|
||||
# 404| v7_0(void) = NoOp :
|
||||
# 405| r7_1(int) = Constant[0] :
|
||||
# 405| r7_2(glval<int>) = VariableAddress[y] :
|
||||
# 405| m7_3(int) = Store : r7_2, r7_1
|
||||
# 406| v7_4(void) = NoOp :
|
||||
#-----| Goto -> Block 9
|
||||
|
||||
# 408| Block 8
|
||||
# 408| r8_0(int) = Constant[5678] :
|
||||
# 408| r8_1(glval<int>) = VariableAddress[y] :
|
||||
# 408| m8_2(int) = Store : r8_1, r8_0
|
||||
#-----| Goto -> Block 9
|
||||
|
||||
# 409| Block 9
|
||||
# 409| v9_0(void) = NoOp :
|
||||
# 410| v9_1(void) = NoOp :
|
||||
# 384| v9_2(void) = ReturnVoid :
|
||||
# 384| v9_3(void) = UnmodeledUse : mu*
|
||||
# 384| v9_4(void) = ExitFunction :
|
||||
# 409| Block 7
|
||||
# 409| v7_0(void) = NoOp :
|
||||
# 410| v7_1(void) = NoOp :
|
||||
# 384| v7_2(void) = ReturnVoid :
|
||||
# 384| v7_3(void) = UnmodeledUse : mu*
|
||||
# 384| v7_4(void) = ExitFunction :
|
||||
|
||||
# 422| ReturnStruct(Point) -> Point
|
||||
# 422| Block 0
|
||||
@@ -4007,32 +3975,24 @@ ir.cpp:
|
||||
# 906| r0_8(glval<int>) = VariableAddress[b] :
|
||||
# 906| r0_9(bool) = Constant[1] :
|
||||
# 906| v0_10(void) = ConditionalBranch : r0_9
|
||||
#-----| False -> Block 3
|
||||
#-----| True -> Block 2
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 1
|
||||
|
||||
# 906| Block 1
|
||||
# 906| m1_0(int) = Phi : from 2:m2_3, from 3:m3_3
|
||||
# 906| r1_1(glval<int>) = VariableAddress[#temp906:11] :
|
||||
# 906| r1_2(int) = Load : r1_1, m1_0
|
||||
# 906| m1_3(int) = Store : r0_8, r1_2
|
||||
# 907| v1_4(void) = NoOp :
|
||||
# 904| v1_5(void) = ReturnVoid :
|
||||
# 904| v1_6(void) = UnmodeledUse : mu*
|
||||
# 904| v1_7(void) = ExitFunction :
|
||||
# 906| r1_0(glval<int>) = VariableAddress[x] :
|
||||
# 906| r1_1(int) = Load : r1_0, m0_4
|
||||
# 906| r1_2(glval<int>) = VariableAddress[#temp906:11] :
|
||||
# 906| m1_3(int) = Store : r1_2, r1_1
|
||||
# 906| r1_4(glval<int>) = VariableAddress[#temp906:11] :
|
||||
# 906| r1_5(int) = Load : r1_4, m1_3
|
||||
# 906| m1_6(int) = Store : r0_8, r1_5
|
||||
# 907| v1_7(void) = NoOp :
|
||||
# 904| v1_8(void) = ReturnVoid :
|
||||
# 904| v1_9(void) = UnmodeledUse : mu*
|
||||
# 904| v1_10(void) = ExitFunction :
|
||||
|
||||
# 906| Block 2
|
||||
# 906| r2_0(glval<int>) = VariableAddress[x] :
|
||||
# 906| r2_1(int) = Load : r2_0, m0_4
|
||||
# 906| r2_2(glval<int>) = VariableAddress[#temp906:11] :
|
||||
# 906| m2_3(int) = Store : r2_2, r2_1
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 906| Block 3
|
||||
# 906| r3_0(glval<int>) = VariableAddress[x] :
|
||||
# 906| r3_1(int) = Load : r3_0, m0_4
|
||||
# 906| r3_2(glval<int>) = VariableAddress[#temp906:11] :
|
||||
# 906| m3_3(int) = Store : r3_2, r3_1
|
||||
#-----| Goto -> Block 1
|
||||
# 906| v2_0(void) = Unreached :
|
||||
|
||||
# 940| OperatorNew() -> void
|
||||
# 940| Block 0
|
||||
@@ -4441,3 +4401,88 @@ ir.cpp:
|
||||
# 1005| v6_12(void) = ReturnValue : r6_11, m6_10
|
||||
# 1005| v6_13(void) = UnmodeledUse : mu*
|
||||
# 1005| v6_14(void) = ExitFunction :
|
||||
|
||||
# 1021| UnreachableViaGoto() -> int
|
||||
# 1021| Block 0
|
||||
# 1021| v0_0(void) = EnterFunction :
|
||||
# 1021| mu0_1(unknown) = AliasedDefinition :
|
||||
# 1021| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 1022| v0_3(void) = NoOp :
|
||||
# 1024| v0_4(void) = NoOp :
|
||||
# 1025| r0_5(glval<int>) = VariableAddress[#return] :
|
||||
# 1025| r0_6(int) = Constant[0] :
|
||||
# 1025| m0_7(int) = Store : r0_5, r0_6
|
||||
# 1021| r0_8(glval<int>) = VariableAddress[#return] :
|
||||
# 1021| v0_9(void) = ReturnValue : r0_8, m0_7
|
||||
# 1021| v0_10(void) = UnmodeledUse : mu*
|
||||
# 1021| v0_11(void) = ExitFunction :
|
||||
|
||||
# 1028| UnreachableIf(bool) -> int
|
||||
# 1028| Block 0
|
||||
# 1028| v0_0(void) = EnterFunction :
|
||||
# 1028| mu0_1(unknown) = AliasedDefinition :
|
||||
# 1028| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 1028| r0_3(glval<bool>) = VariableAddress[b] :
|
||||
# 1028| m0_4(bool) = InitializeParameter[b] : r0_3
|
||||
# 1029| r0_5(glval<int>) = VariableAddress[x] :
|
||||
# 1029| r0_6(int) = Constant[5] :
|
||||
# 1029| m0_7(int) = Store : r0_5, r0_6
|
||||
# 1030| r0_8(glval<int>) = VariableAddress[y] :
|
||||
# 1030| r0_9(int) = Constant[10] :
|
||||
# 1030| m0_10(int) = Store : r0_8, r0_9
|
||||
# 1031| r0_11(glval<bool>) = VariableAddress[b] :
|
||||
# 1031| r0_12(bool) = Load : r0_11, m0_4
|
||||
# 1031| v0_13(void) = ConditionalBranch : r0_12
|
||||
#-----| False -> Block 5
|
||||
#-----| True -> Block 2
|
||||
|
||||
# 1028| Block 1
|
||||
# 1028| m1_0(int) = Phi : from 3:m3_2, from 4:m4_2, from 6:m6_2, from 7:m7_2
|
||||
# 1028| r1_1(glval<int>) = VariableAddress[#return] :
|
||||
# 1028| v1_2(void) = ReturnValue : r1_1, m1_0
|
||||
# 1028| v1_3(void) = UnmodeledUse : mu*
|
||||
# 1028| v1_4(void) = ExitFunction :
|
||||
|
||||
# 1032| Block 2
|
||||
# 1032| r2_0(glval<int>) = VariableAddress[x] :
|
||||
# 1032| r2_1(int) = Load : r2_0, m0_7
|
||||
# 1032| r2_2(glval<int>) = VariableAddress[y] :
|
||||
# 1032| r2_3(int) = Load : r2_2, m0_10
|
||||
# 1032| r2_4(bool) = CompareEQ : r2_1, r2_3
|
||||
# 1032| v2_5(void) = ConditionalBranch : r2_4
|
||||
#-----| False -> Block 4
|
||||
#-----| True -> Block 3
|
||||
|
||||
# 1033| Block 3
|
||||
# 1033| r3_0(glval<int>) = VariableAddress[#return] :
|
||||
# 1033| r3_1(int) = Constant[1] :
|
||||
# 1033| m3_2(int) = Store : r3_0, r3_1
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 1036| Block 4
|
||||
# 1036| r4_0(glval<int>) = VariableAddress[#return] :
|
||||
# 1036| r4_1(int) = Constant[0] :
|
||||
# 1036| m4_2(int) = Store : r4_0, r4_1
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 1040| Block 5
|
||||
# 1040| r5_0(glval<int>) = VariableAddress[x] :
|
||||
# 1040| r5_1(int) = Load : r5_0, m0_7
|
||||
# 1040| r5_2(glval<int>) = VariableAddress[y] :
|
||||
# 1040| r5_3(int) = Load : r5_2, m0_10
|
||||
# 1040| r5_4(bool) = CompareLT : r5_1, r5_3
|
||||
# 1040| v5_5(void) = ConditionalBranch : r5_4
|
||||
#-----| False -> Block 7
|
||||
#-----| True -> Block 6
|
||||
|
||||
# 1041| Block 6
|
||||
# 1041| r6_0(glval<int>) = VariableAddress[#return] :
|
||||
# 1041| r6_1(int) = Constant[0] :
|
||||
# 1041| m6_2(int) = Store : r6_0, r6_1
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 1044| Block 7
|
||||
# 1044| r7_0(glval<int>) = VariableAddress[#return] :
|
||||
# 1044| r7_1(int) = Constant[1] :
|
||||
# 1044| m7_2(int) = Store : r7_0, r7_1
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
@@ -499,7 +499,6 @@
|
||||
| test.c:367:15:367:17 | Constant: (unsigned int)... | positive strictlyPositive |
|
||||
| test.c:368:5:368:21 | Store: ... = ... | positive strictlyPositive |
|
||||
| test.c:368:10:368:21 | Load: ... ? ... : ... | positive strictlyPositive |
|
||||
| test.c:368:10:368:21 | Phi: ... ? ... : ... | positive strictlyPositive |
|
||||
| test.c:368:10:368:21 | Store: ... ? ... : ... | positive strictlyPositive |
|
||||
| test.c:368:11:368:11 | Load: x | positive |
|
||||
| test.c:368:11:368:13 | Add: ... + ... | positive strictlyPositive |
|
||||
@@ -508,7 +507,6 @@
|
||||
| test.c:369:5:369:36 | Store: ... = ... | positive strictlyPositive |
|
||||
| test.c:369:10:369:36 | Convert: (unsigned int)... | positive strictlyPositive |
|
||||
| test.c:369:10:369:36 | Load: ... ? ... : ... | positive strictlyPositive |
|
||||
| test.c:369:10:369:36 | Phi: ... ? ... : ... | positive strictlyPositive |
|
||||
| test.c:369:10:369:36 | Store: ... ? ... : ... | positive strictlyPositive |
|
||||
| test.c:369:11:369:30 | Convert: (unsigned char)... | positive |
|
||||
| test.c:369:27:369:27 | Load: x | positive |
|
||||
@@ -518,7 +516,6 @@
|
||||
| test.c:370:5:370:38 | Store: ... = ... | positive strictlyPositive |
|
||||
| test.c:370:10:370:38 | Convert: (unsigned int)... | positive strictlyPositive |
|
||||
| test.c:370:10:370:38 | Load: ... ? ... : ... | positive strictlyPositive |
|
||||
| test.c:370:10:370:38 | Phi: ... ? ... : ... | positive strictlyPositive |
|
||||
| test.c:370:10:370:38 | Store: ... ? ... : ... | positive strictlyPositive |
|
||||
| test.c:370:11:370:30 | Convert: (unsigned char)... | positive |
|
||||
| test.c:370:27:370:27 | Load: x | positive |
|
||||
@@ -528,7 +525,6 @@
|
||||
| test.c:371:5:371:39 | Store: ... = ... | positive strictlyPositive |
|
||||
| test.c:371:10:371:39 | Convert: (unsigned int)... | positive strictlyPositive |
|
||||
| test.c:371:10:371:39 | Load: ... ? ... : ... | positive strictlyPositive |
|
||||
| test.c:371:10:371:39 | Phi: ... ? ... : ... | positive strictlyPositive |
|
||||
| test.c:371:10:371:39 | Store: ... ? ... : ... | positive strictlyPositive |
|
||||
| test.c:371:11:371:31 | Convert: (unsigned short)... | positive |
|
||||
| test.c:371:28:371:28 | Load: x | positive |
|
||||
@@ -591,7 +587,6 @@
|
||||
| test.c:384:12:384:14 | Constant: (unsigned int)... | positive strictlyPositive |
|
||||
| test.c:385:5:385:21 | Store: ... = ... | positive strictlyPositive |
|
||||
| test.c:385:10:385:21 | Load: ... ? ... : ... | positive strictlyPositive |
|
||||
| test.c:385:10:385:21 | Phi: ... ? ... : ... | positive strictlyPositive |
|
||||
| test.c:385:10:385:21 | Store: ... ? ... : ... | positive strictlyPositive |
|
||||
| test.c:385:11:385:11 | Load: x | positive strictlyPositive |
|
||||
| test.c:385:11:385:15 | Sub: ... - ... | positive |
|
||||
@@ -599,7 +594,6 @@
|
||||
| test.c:385:21:385:21 | Constant: (unsigned int)... | positive strictlyPositive |
|
||||
| test.c:386:5:386:21 | Store: ... = ... | positive strictlyPositive |
|
||||
| test.c:386:10:386:21 | Load: ... ? ... : ... | positive strictlyPositive |
|
||||
| test.c:386:10:386:21 | Phi: ... ? ... : ... | positive strictlyPositive |
|
||||
| test.c:386:10:386:21 | Store: ... ? ... : ... | positive strictlyPositive |
|
||||
| test.c:386:11:386:11 | Load: x | positive strictlyPositive |
|
||||
| test.c:386:11:386:15 | Sub: ... - ... | positive |
|
||||
@@ -608,7 +602,6 @@
|
||||
| test.c:387:5:387:38 | Store: ... = ... | positive strictlyPositive |
|
||||
| test.c:387:10:387:38 | Convert: (unsigned int)... | positive strictlyPositive |
|
||||
| test.c:387:10:387:38 | Load: ... ? ... : ... | positive strictlyPositive |
|
||||
| test.c:387:10:387:38 | Phi: ... ? ... : ... | positive strictlyPositive |
|
||||
| test.c:387:10:387:38 | Store: ... ? ... : ... | positive strictlyPositive |
|
||||
| test.c:387:11:387:32 | Convert: (unsigned char)... | positive |
|
||||
| test.c:387:27:387:27 | Load: x | positive strictlyPositive |
|
||||
|
||||
Reference in New Issue
Block a user