Merge pull request #1567 from jbj/ir-operand-cycles

C++ IR: guard against cycles in operand graph
This commit is contained in:
Dave Bartolomeo 2019-07-11 13:14:10 -07:00 коммит произвёл GitHub
Родитель c73b516862 523fc9c1ce
Коммит 1b38208bab
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 78 добавлений и 6 удалений

Просмотреть файл

@ -9,15 +9,39 @@ private import semmle.code.cpp.ir.internal.OperandTag
cached
private newtype TOperand =
TRegisterOperand(Instruction useInstr, RegisterOperandTag tag, Instruction defInstr) {
defInstr = Construction::getRegisterOperandDefinition(useInstr, tag)
defInstr = Construction::getRegisterOperandDefinition(useInstr, tag) and
not isInCycle(useInstr)
} or
TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap) {
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap)
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
not isInCycle(useInstr)
} or
TPhiOperand(PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap) {
defInstr = Construction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap)
}
/** Gets a non-phi instruction that defines an operand of `instr`. */
private Instruction getNonPhiOperandDef(Instruction instr) {
result = Construction::getRegisterOperandDefinition(instr, _)
or
result = Construction::getMemoryOperandDefinition(instr, _, _)
}
/**
* Holds if `instr` is part of a cycle in the operand graph that doesn't go
* through a phi instruction and therefore should be impossible.
*
* If such cycles are present, either due to a programming error in the IR
* generation or due to a malformed database, it can cause infinite loops in
* analyses that assume a cycle-free graph of non-phi operands. Therefore it's
* better to remove these operands than to leave cycles in the operand graph.
*/
pragma[noopt]
private predicate isInCycle(Instruction instr) {
instr instanceof Instruction and
getNonPhiOperandDef+(instr) = instr
}
/**
* A source operand of an `Instruction`. The operand represents a value consumed by the instruction.
*/

Просмотреть файл

@ -9,15 +9,39 @@ private import semmle.code.cpp.ir.internal.OperandTag
cached
private newtype TOperand =
TRegisterOperand(Instruction useInstr, RegisterOperandTag tag, Instruction defInstr) {
defInstr = Construction::getRegisterOperandDefinition(useInstr, tag)
defInstr = Construction::getRegisterOperandDefinition(useInstr, tag) and
not isInCycle(useInstr)
} or
TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap) {
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap)
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
not isInCycle(useInstr)
} or
TPhiOperand(PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap) {
defInstr = Construction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap)
}
/** Gets a non-phi instruction that defines an operand of `instr`. */
private Instruction getNonPhiOperandDef(Instruction instr) {
result = Construction::getRegisterOperandDefinition(instr, _)
or
result = Construction::getMemoryOperandDefinition(instr, _, _)
}
/**
* Holds if `instr` is part of a cycle in the operand graph that doesn't go
* through a phi instruction and therefore should be impossible.
*
* If such cycles are present, either due to a programming error in the IR
* generation or due to a malformed database, it can cause infinite loops in
* analyses that assume a cycle-free graph of non-phi operands. Therefore it's
* better to remove these operands than to leave cycles in the operand graph.
*/
pragma[noopt]
private predicate isInCycle(Instruction instr) {
instr instanceof Instruction and
getNonPhiOperandDef+(instr) = instr
}
/**
* A source operand of an `Instruction`. The operand represents a value consumed by the instruction.
*/

Просмотреть файл

@ -9,15 +9,39 @@ private import semmle.code.cpp.ir.internal.OperandTag
cached
private newtype TOperand =
TRegisterOperand(Instruction useInstr, RegisterOperandTag tag, Instruction defInstr) {
defInstr = Construction::getRegisterOperandDefinition(useInstr, tag)
defInstr = Construction::getRegisterOperandDefinition(useInstr, tag) and
not isInCycle(useInstr)
} or
TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap) {
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap)
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
not isInCycle(useInstr)
} or
TPhiOperand(PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap) {
defInstr = Construction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap)
}
/** Gets a non-phi instruction that defines an operand of `instr`. */
private Instruction getNonPhiOperandDef(Instruction instr) {
result = Construction::getRegisterOperandDefinition(instr, _)
or
result = Construction::getMemoryOperandDefinition(instr, _, _)
}
/**
* Holds if `instr` is part of a cycle in the operand graph that doesn't go
* through a phi instruction and therefore should be impossible.
*
* If such cycles are present, either due to a programming error in the IR
* generation or due to a malformed database, it can cause infinite loops in
* analyses that assume a cycle-free graph of non-phi operands. Therefore it's
* better to remove these operands than to leave cycles in the operand graph.
*/
pragma[noopt]
private predicate isInCycle(Instruction instr) {
instr instanceof Instruction and
getNonPhiOperandDef+(instr) = instr
}
/**
* A source operand of an `Instruction`. The operand represents a value consumed by the instruction.
*/