mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
Merge pull request #1541 from jbj/ir-operand-exact
C++ IR: Make instruction operand getters have only exact results
This commit is contained in:
@@ -136,7 +136,7 @@ module TaintTracking {
|
||||
// Taint can flow through expressions that alter the value but preserve
|
||||
// more than one bit of it _or_ expressions that follow data through
|
||||
// pointer indirections.
|
||||
nodeTo.getAnOperand().getDefinitionInstruction() = nodeFrom and
|
||||
nodeTo.getAnOperand().getAnyDef() = nodeFrom and
|
||||
(
|
||||
nodeTo instanceof ArithmeticInstruction
|
||||
or
|
||||
@@ -145,6 +145,11 @@ module TaintTracking {
|
||||
nodeTo instanceof PointerArithmeticInstruction
|
||||
or
|
||||
nodeTo instanceof FieldAddressInstruction
|
||||
or
|
||||
// The `CopyInstruction` case is also present in non-taint data flow, but
|
||||
// that uses `getDef` rather than `getAnyDef`. For taint, we want flow
|
||||
// from a definition of `myStruct` to a `myStruct.myField` expression.
|
||||
nodeTo instanceof CopyInstruction
|
||||
)
|
||||
or
|
||||
nodeTo.(LoadInstruction).getSourceAddress() = nodeFrom
|
||||
|
||||
@@ -143,7 +143,7 @@ UninitializedNode uninitializedNode(LocalVariable v) { result.getLocalVariable()
|
||||
*/
|
||||
predicate localFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
nodeTo.(CopyInstruction).getSourceValue() = nodeFrom or
|
||||
nodeTo.(PhiInstruction).getAnOperand().getDefinitionInstruction() = nodeFrom or
|
||||
nodeTo.(PhiInstruction).getAnOperand().getDef() = nodeFrom or
|
||||
// Treat all conversions as flow, even conversions between different numeric types.
|
||||
nodeTo.(ConvertInstruction).getUnary() = nodeFrom
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ module InstructionSanity {
|
||||
query predicate missingOperandType(Operand operand, string message) {
|
||||
exists(Function func |
|
||||
not exists(operand.getType()) and
|
||||
func = operand.getUseInstruction().getEnclosingFunction() and
|
||||
func = operand.getUse().getEnclosingFunction() and
|
||||
message = "Operand missing type in function '" + getIdentityString(func) + "'."
|
||||
)
|
||||
}
|
||||
@@ -158,8 +158,8 @@ module InstructionSanity {
|
||||
* a different function.
|
||||
*/
|
||||
query predicate operandAcrossFunctions(Operand operand, Instruction instr, Instruction defInstr) {
|
||||
operand.getUseInstruction() = instr and
|
||||
operand.getDefinitionInstruction() = defInstr and
|
||||
operand.getUse() = instr and
|
||||
operand.getAnyDef() = defInstr and
|
||||
instr.getEnclosingIRFunction() != defInstr.getEnclosingIRFunction()
|
||||
}
|
||||
|
||||
@@ -480,17 +480,18 @@ class Instruction extends Construction::TInstruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all direct uses of the result of this instruction.
|
||||
* Gets all direct uses of the result of this instruction. The result can be
|
||||
* an `Operand` for which `isDefinitionInexact` holds.
|
||||
*/
|
||||
final Operand getAUse() {
|
||||
result.getDefinitionInstruction() = this
|
||||
result.getAnyDef() = this
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all of this instruction's operands.
|
||||
*/
|
||||
final Operand getAnOperand() {
|
||||
result.getUseInstruction() = this
|
||||
result.getUse() = this
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -509,13 +510,22 @@ class Instruction extends Construction::TInstruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the operand that holds the memory address to which the instruction stores its
|
||||
* Gets the operand that holds the memory address to which this instruction stores its
|
||||
* result, if any. For example, in `m3 = Store r1, r2`, the result of `getResultAddressOperand()`
|
||||
* is `r1`.
|
||||
*/
|
||||
final AddressOperand getResultAddressOperand() {
|
||||
getResultMemoryAccess().usesAddressOperand() and
|
||||
result.getUseInstruction() = this
|
||||
result.getUse() = this
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instruction that holds the exact memory address to which this instruction stores its
|
||||
* result, if any. For example, in `m3 = Store r1, r2`, the result of `getResultAddressOperand()`
|
||||
* is the instruction that defines `r1`.
|
||||
*/
|
||||
final Instruction getResultAddress() {
|
||||
result = getResultAddressOperand().getDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -698,7 +708,7 @@ class FieldAddressInstruction extends FieldInstruction {
|
||||
}
|
||||
|
||||
final Instruction getObjectAddress() {
|
||||
result = getObjectAddressOperand().getDefinitionInstruction()
|
||||
result = getObjectAddressOperand().getDef()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -763,7 +773,7 @@ class ReturnValueInstruction extends ReturnInstruction {
|
||||
}
|
||||
|
||||
final Instruction getReturnValue() {
|
||||
result = getReturnValueOperand().getDefinitionInstruction()
|
||||
result = getReturnValueOperand().getDef()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -777,7 +787,7 @@ class CopyInstruction extends Instruction {
|
||||
}
|
||||
|
||||
final Instruction getSourceValue() {
|
||||
result = getSourceValueOperand().getDefinitionInstruction()
|
||||
result = getSourceValueOperand().getDef()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -801,7 +811,7 @@ class LoadInstruction extends CopyInstruction {
|
||||
}
|
||||
|
||||
final Instruction getSourceAddress() {
|
||||
result = getSourceAddressOperand().getDefinitionInstruction()
|
||||
result = getSourceAddressOperand().getDef()
|
||||
}
|
||||
|
||||
override final LoadOperand getSourceValueOperand() {
|
||||
@@ -823,7 +833,7 @@ class StoreInstruction extends CopyInstruction {
|
||||
}
|
||||
|
||||
final Instruction getDestinationAddress() {
|
||||
result = getDestinationAddressOperand().getDefinitionInstruction()
|
||||
result = getDestinationAddressOperand().getDef()
|
||||
}
|
||||
|
||||
override final StoreValueOperand getSourceValueOperand() {
|
||||
@@ -841,7 +851,7 @@ class ConditionalBranchInstruction extends Instruction {
|
||||
}
|
||||
|
||||
final Instruction getCondition() {
|
||||
result = getConditionOperand().getDefinitionInstruction()
|
||||
result = getConditionOperand().getDef()
|
||||
}
|
||||
|
||||
final Instruction getTrueSuccessor() {
|
||||
@@ -907,11 +917,11 @@ class BinaryInstruction extends Instruction {
|
||||
}
|
||||
|
||||
final Instruction getLeft() {
|
||||
result = getLeftOperand().getDefinitionInstruction()
|
||||
result = getLeftOperand().getDef()
|
||||
}
|
||||
|
||||
final Instruction getRight() {
|
||||
result = getRightOperand().getDefinitionInstruction()
|
||||
result = getRightOperand().getDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1061,7 +1071,7 @@ class UnaryInstruction extends Instruction {
|
||||
}
|
||||
|
||||
final Instruction getUnary() {
|
||||
result = getUnaryOperand().getDefinitionInstruction()
|
||||
result = getUnaryOperand().getDef()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1291,7 +1301,7 @@ class SwitchInstruction extends Instruction {
|
||||
}
|
||||
|
||||
final Instruction getExpression() {
|
||||
result = getExpressionOperand().getDefinitionInstruction()
|
||||
result = getExpressionOperand().getDef()
|
||||
}
|
||||
|
||||
final Instruction getACaseSuccessor() {
|
||||
@@ -1326,7 +1336,7 @@ class CallInstruction extends Instruction {
|
||||
* function pointer.
|
||||
*/
|
||||
final Instruction getCallTarget() {
|
||||
result = getCallTargetOperand().getDefinitionInstruction()
|
||||
result = getCallTargetOperand().getDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1347,7 +1357,7 @@ class CallInstruction extends Instruction {
|
||||
* Gets all of the arguments of the call, including the `this` pointer, if any.
|
||||
*/
|
||||
final Instruction getAnArgument() {
|
||||
result = getAnArgumentOperand().getDefinitionInstruction()
|
||||
result = getAnArgumentOperand().getDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1361,7 +1371,7 @@ class CallInstruction extends Instruction {
|
||||
* Gets the `this` pointer argument of the call, if any.
|
||||
*/
|
||||
final Instruction getThisArgument() {
|
||||
result = getThisArgumentOperand().getDefinitionInstruction()
|
||||
result = getThisArgumentOperand().getDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1376,7 +1386,7 @@ class CallInstruction extends Instruction {
|
||||
* Gets the argument at the specified index.
|
||||
*/
|
||||
final Instruction getPositionalArgument(int index) {
|
||||
result = getPositionalArgumentOperand(index).getDefinitionInstruction()
|
||||
result = getPositionalArgumentOperand(index).getDef()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1532,7 +1542,7 @@ class ThrowValueInstruction extends ThrowInstruction {
|
||||
* Gets the address of the exception thrown by this instruction.
|
||||
*/
|
||||
final Instruction getExceptionAddress() {
|
||||
result = getExceptionAddressOperand().getDefinitionInstruction()
|
||||
result = getExceptionAddressOperand().getDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1546,7 +1556,7 @@ class ThrowValueInstruction extends ThrowInstruction {
|
||||
* Gets the exception thrown by this instruction.
|
||||
*/
|
||||
final Instruction getException() {
|
||||
result = getExceptionOperand().getDefinitionInstruction()
|
||||
result = getExceptionOperand().getDef()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1676,7 +1686,7 @@ class PhiInstruction extends Instruction {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final Instruction getAnInput() {
|
||||
result = this.getAnInputOperand().getDefinitionInstruction()
|
||||
result = this.getAnInputOperand().getDef()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1744,7 +1754,7 @@ class ChiInstruction extends Instruction {
|
||||
* memory write.
|
||||
*/
|
||||
final Instruction getTotal() {
|
||||
result = getTotalOperand().getDefinitionInstruction()
|
||||
result = getTotalOperand().getDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1758,7 +1768,7 @@ class ChiInstruction extends Instruction {
|
||||
* Gets the operand that represents the new value written by the memory write.
|
||||
*/
|
||||
final Instruction getPartial() {
|
||||
result = getPartialOperand().getDefinitionInstruction()
|
||||
result = getPartialOperand().getDef()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,25 +27,61 @@ class Operand extends TOperand {
|
||||
}
|
||||
|
||||
final Location getLocation() {
|
||||
result = getUseInstruction().getLocation()
|
||||
result = getUse().getLocation()
|
||||
}
|
||||
|
||||
final IRFunction getEnclosingIRFunction() {
|
||||
result = getUseInstruction().getEnclosingIRFunction()
|
||||
result = getUse().getEnclosingIRFunction()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the `Instruction` that consumes this operand.
|
||||
*/
|
||||
Instruction getUseInstruction() {
|
||||
Instruction getUse() {
|
||||
none()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `Instruction` whose result is the value of the operand. Unlike
|
||||
* `getDef`, this also has a result when `isDefinitionInexact` holds, which
|
||||
* means that the resulting instruction may only _partially_ or _potentially_
|
||||
* be the value of this operand.
|
||||
*/
|
||||
Instruction getAnyDef() {
|
||||
none()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `Instruction` whose result is the value of the operand. Unlike
|
||||
* `getAnyDef`, this also has no result when `isDefinitionInexact` holds,
|
||||
* which means that the resulting instruction must always be exactly the be
|
||||
* the value of this operand.
|
||||
*/
|
||||
final Instruction getDef() {
|
||||
result = this.getAnyDef() and
|
||||
getDefinitionOverlap() instanceof MustExactlyOverlap
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: renamed to `getUse`.
|
||||
*
|
||||
* Gets the `Instruction` that consumes this operand.
|
||||
*/
|
||||
deprecated
|
||||
final Instruction getUseInstruction() {
|
||||
result = getUse()
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this
|
||||
* predicate is `getAnyDef`, but most uses of this predicate should probably
|
||||
* be replaced with `getDef`.
|
||||
*
|
||||
* Gets the `Instruction` whose result is the value of the operand.
|
||||
*/
|
||||
Instruction getDefinitionInstruction() {
|
||||
none()
|
||||
deprecated
|
||||
final Instruction getDefinitionInstruction() {
|
||||
result = getAnyDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,7 +113,7 @@ class Operand extends TOperand {
|
||||
* For example: `this:r3_5`
|
||||
*/
|
||||
final string getDumpString() {
|
||||
result = getDumpLabel() + getInexactSpecifier() + getDefinitionInstruction().getResultId()
|
||||
result = getDumpLabel() + getInexactSpecifier() + getAnyDef().getResultId()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,7 +143,7 @@ class Operand extends TOperand {
|
||||
* has been cast to a different type.
|
||||
*/
|
||||
Type getType() {
|
||||
result = getDefinitionInstruction().getResultType()
|
||||
result = getAnyDef().getResultType()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,7 +154,7 @@ class Operand extends TOperand {
|
||||
* given by `getResultType()`.
|
||||
*/
|
||||
predicate isGLValue() {
|
||||
getDefinitionInstruction().isGLValue()
|
||||
getAnyDef().isGLValue()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,7 +194,7 @@ class MemoryOperand extends Operand {
|
||||
*/
|
||||
final AddressOperand getAddressOperand() {
|
||||
getMemoryAccess().usesAddressOperand() and
|
||||
result.getUseInstruction() = getUseInstruction()
|
||||
result.getUse() = getUse()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,11 +211,11 @@ class NonPhiOperand extends Operand {
|
||||
this = TNonPhiMemoryOperand(useInstr, tag, defInstr, _)
|
||||
}
|
||||
|
||||
override final Instruction getUseInstruction() {
|
||||
override final Instruction getUse() {
|
||||
result = useInstr
|
||||
}
|
||||
|
||||
override final Instruction getDefinitionInstruction() {
|
||||
override final Instruction getAnyDef() {
|
||||
result = defInstr
|
||||
}
|
||||
|
||||
@@ -437,11 +473,11 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand {
|
||||
result = "Phi"
|
||||
}
|
||||
|
||||
override final PhiInstruction getUseInstruction() {
|
||||
override final PhiInstruction getUse() {
|
||||
result = useInstr
|
||||
}
|
||||
|
||||
override final Instruction getDefinitionInstruction() {
|
||||
override final Instruction getAnyDef() {
|
||||
result = defInstr
|
||||
}
|
||||
|
||||
|
||||
@@ -10,16 +10,8 @@ int getConstantValue(Instruction instr) {
|
||||
result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or
|
||||
exists(PhiInstruction phi |
|
||||
phi = instr and
|
||||
result = max(Instruction def | def = phi.getAnInput() | getConstantValueToPhi(def)) and
|
||||
result = min(Instruction def | def = phi.getAnInput() | getConstantValueToPhi(def))
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
int getConstantValueToPhi(Instruction def) {
|
||||
exists(PhiInstruction phi |
|
||||
result = getConstantValue(def) and
|
||||
def = phi.getAnInput()
|
||||
result = max(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef())) and
|
||||
result = min(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef()))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -86,9 +86,12 @@ class ValueNumber extends TValueNumber {
|
||||
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets an `Operand` whose definition is exact and has this value number.
|
||||
*/
|
||||
final Operand getAUse() {
|
||||
this = valueNumber(result.getDefinitionInstruction())
|
||||
this = valueNumber(result.getDef())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,10 +231,11 @@ cached ValueNumber valueNumber(Instruction instr) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value number assigned to `instr`, if any. Returns at most one result.
|
||||
* Gets the value number assigned to the exact definition of `op`, if any.
|
||||
* Returns at most one result.
|
||||
*/
|
||||
ValueNumber valueNumberOfOperand(Operand op) {
|
||||
result = valueNumber(op.getDefinitionInstruction())
|
||||
result = valueNumber(op.getDef())
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -53,7 +53,7 @@ private predicate operandIsConsumedWithoutEscaping(Operand operand) {
|
||||
// loaded/stored value could).
|
||||
operand instanceof AddressOperand or
|
||||
exists (Instruction instr |
|
||||
instr = operand.getUseInstruction() and
|
||||
instr = operand.getUse() and
|
||||
(
|
||||
// Neither operand of a Compare escapes.
|
||||
instr instanceof CompareInstruction or
|
||||
@@ -72,7 +72,7 @@ private predicate operandEscapesDomain(Operand operand) {
|
||||
not operandIsPropagated(operand, _) and
|
||||
not isArgumentForParameter(_, operand, _) and
|
||||
not isOnlyEscapesViaReturnArgument(operand) and
|
||||
not operand.getUseInstruction() instanceof ReturnValueInstruction and
|
||||
not operand.getUse() instanceof ReturnValueInstruction and
|
||||
not operand instanceof PhiInputOperand
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ IntValue getPointerBitOffset(PointerOffsetInstruction instr) {
|
||||
*/
|
||||
private predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
|
||||
exists(Instruction instr |
|
||||
instr = operand.getUseInstruction() and
|
||||
instr = operand.getUse() and
|
||||
(
|
||||
// Converting to a non-virtual base class adds the offset of the base class.
|
||||
exists(ConvertToBaseInstruction convert |
|
||||
@@ -156,7 +156,7 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
|
||||
|
||||
private predicate operandEscapesNonReturn(Operand operand) {
|
||||
// The address is propagated to the result of the instruction, and that result itself is returned
|
||||
operandIsPropagated(operand, _) and resultEscapesNonReturn(operand.getUseInstruction())
|
||||
operandIsPropagated(operand, _) and resultEscapesNonReturn(operand.getUse())
|
||||
or
|
||||
// The operand is used in a function call which returns it, and the return value is then returned
|
||||
exists(CallInstruction ci, Instruction init |
|
||||
@@ -169,10 +169,10 @@ private predicate operandEscapesNonReturn(Operand operand) {
|
||||
)
|
||||
)
|
||||
or
|
||||
isOnlyEscapesViaReturnArgument(operand) and resultEscapesNonReturn(operand.getUseInstruction())
|
||||
isOnlyEscapesViaReturnArgument(operand) and resultEscapesNonReturn(operand.getUse())
|
||||
or
|
||||
operand instanceof PhiInputOperand and
|
||||
resultEscapesNonReturn(operand.getUseInstruction())
|
||||
resultEscapesNonReturn(operand.getUse())
|
||||
or
|
||||
operandEscapesDomain(operand)
|
||||
}
|
||||
@@ -180,7 +180,7 @@ private predicate operandEscapesNonReturn(Operand operand) {
|
||||
private predicate operandMayReachReturn(Operand operand) {
|
||||
// The address is propagated to the result of the instruction, and that result itself is returned
|
||||
operandIsPropagated(operand, _) and
|
||||
resultMayReachReturn(operand.getUseInstruction())
|
||||
resultMayReachReturn(operand.getUse())
|
||||
or
|
||||
// The operand is used in a function call which returns it, and the return value is then returned
|
||||
exists(CallInstruction ci, Instruction init |
|
||||
@@ -190,19 +190,19 @@ private predicate operandMayReachReturn(Operand operand) {
|
||||
)
|
||||
or
|
||||
// The address is returned
|
||||
operand.getUseInstruction() instanceof ReturnValueInstruction
|
||||
operand.getUse() instanceof ReturnValueInstruction
|
||||
or
|
||||
isOnlyEscapesViaReturnArgument(operand) and resultMayReachReturn(operand.getUseInstruction())
|
||||
isOnlyEscapesViaReturnArgument(operand) and resultMayReachReturn(operand.getUse())
|
||||
or
|
||||
operand instanceof PhiInputOperand and
|
||||
resultMayReachReturn(operand.getUseInstruction())
|
||||
resultMayReachReturn(operand.getUse())
|
||||
}
|
||||
|
||||
private predicate operandReturned(Operand operand, IntValue bitOffset) {
|
||||
// The address is propagated to the result of the instruction, and that result itself is returned
|
||||
exists(IntValue bitOffset1, IntValue bitOffset2 |
|
||||
operandIsPropagated(operand, bitOffset1) and
|
||||
resultReturned(operand.getUseInstruction(), bitOffset2) and
|
||||
resultReturned(operand.getUse(), bitOffset2) and
|
||||
bitOffset = Ints::add(bitOffset1, bitOffset2)
|
||||
)
|
||||
or
|
||||
@@ -216,16 +216,16 @@ private predicate operandReturned(Operand operand, IntValue bitOffset) {
|
||||
)
|
||||
or
|
||||
// The address is returned
|
||||
operand.getUseInstruction() instanceof ReturnValueInstruction and
|
||||
operand.getUse() instanceof ReturnValueInstruction and
|
||||
bitOffset = 0
|
||||
or
|
||||
isOnlyEscapesViaReturnArgument(operand) and resultReturned(operand.getUseInstruction(), _) and
|
||||
isOnlyEscapesViaReturnArgument(operand) and resultReturned(operand.getUse(), _) and
|
||||
bitOffset = Ints::unknown()
|
||||
}
|
||||
|
||||
private predicate isArgumentForParameter(CallInstruction ci, Operand operand, Instruction init) {
|
||||
exists(Function f |
|
||||
ci = operand.getUseInstruction() and
|
||||
ci = operand.getUse() and
|
||||
f = ci.getStaticCallTarget() and
|
||||
(
|
||||
init.(InitializeParameterInstruction).getParameter() = f.getParameter(operand.(PositionalArgumentOperand).getIndex())
|
||||
@@ -241,21 +241,21 @@ private predicate isArgumentForParameter(CallInstruction ci, Operand operand, In
|
||||
|
||||
private predicate isAlwaysReturnedArgument(Operand operand) {
|
||||
exists(AliasFunction f |
|
||||
f = operand.getUseInstruction().(CallInstruction).getStaticCallTarget() and
|
||||
f = operand.getUse().(CallInstruction).getStaticCallTarget() and
|
||||
f.parameterIsAlwaysReturned(operand.(PositionalArgumentOperand).getIndex())
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isOnlyEscapesViaReturnArgument(Operand operand) {
|
||||
exists(AliasFunction f |
|
||||
f = operand.getUseInstruction().(CallInstruction).getStaticCallTarget() and
|
||||
f = operand.getUse().(CallInstruction).getStaticCallTarget() and
|
||||
f.parameterEscapesOnlyViaReturn(operand.(PositionalArgumentOperand).getIndex())
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isNeverEscapesArgument(Operand operand) {
|
||||
exists(AliasFunction f |
|
||||
f = operand.getUseInstruction().(CallInstruction).getStaticCallTarget() and
|
||||
f = operand.getUse().(CallInstruction).getStaticCallTarget() and
|
||||
f.parameterNeverEscapes(operand.(PositionalArgumentOperand).getIndex())
|
||||
)
|
||||
}
|
||||
@@ -315,7 +315,7 @@ predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset)
|
||||
operand = instr.getAnOperand() and
|
||||
// If an operand is propagated, then the result points to the same variable,
|
||||
// offset by the bit offset from the propagation.
|
||||
resultPointsTo(operand.getDefinitionInstruction(), var, originalBitOffset) and
|
||||
resultPointsTo(operand.getAnyDef(), var, originalBitOffset) and
|
||||
(
|
||||
operandIsPropagated(operand, propagatedBitOffset)
|
||||
or
|
||||
|
||||
@@ -11,7 +11,7 @@ private class IntValue = Ints::IntValue;
|
||||
|
||||
private predicate hasResultMemoryAccess(Instruction instr, IRVariable var, Type type, IntValue startBitOffset,
|
||||
IntValue endBitOffset) {
|
||||
resultPointsTo(instr.getResultAddressOperand().getDefinitionInstruction(), var, startBitOffset) and
|
||||
resultPointsTo(instr.getResultAddress(), var, startBitOffset) and
|
||||
type = instr.getResultType() and
|
||||
if exists(instr.getResultSize()) then
|
||||
endBitOffset = Ints::add(startBitOffset, Ints::mul(instr.getResultSize(), 8))
|
||||
@@ -21,7 +21,7 @@ private predicate hasResultMemoryAccess(Instruction instr, IRVariable var, Type
|
||||
|
||||
private predicate hasOperandMemoryAccess(MemoryOperand operand, IRVariable var, Type type, IntValue startBitOffset,
|
||||
IntValue endBitOffset) {
|
||||
resultPointsTo(operand.getAddressOperand().getDefinitionInstruction(), var, startBitOffset) and
|
||||
resultPointsTo(operand.getAddressOperand().getAnyDef(), var, startBitOffset) and
|
||||
type = operand.getType() and
|
||||
if exists(operand.getSize()) then
|
||||
endBitOffset = Ints::add(startBitOffset, Ints::mul(operand.getSize(), 8))
|
||||
|
||||
@@ -69,7 +69,7 @@ cached private module Cached {
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
oldOperand = oldInstruction.getAnOperand() and
|
||||
tag = oldOperand.getOperandTag() and
|
||||
result = getNewInstruction(oldOperand.getDefinitionInstruction())
|
||||
result = getNewInstruction(oldOperand.getAnyDef())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ cached private module Cached {
|
||||
exists(OldInstruction oldDefinition |
|
||||
instruction instanceof UnmodeledUseInstruction and
|
||||
tag instanceof UnmodeledUseOperandTag and
|
||||
oldDefinition = oldOperand.getDefinitionInstruction() and
|
||||
oldDefinition = oldOperand.getAnyDef() and
|
||||
not exists(Alias::getResultMemoryLocation(oldDefinition)) and
|
||||
result = getNewInstruction(oldDefinition) and
|
||||
overlap instanceof MustTotallyOverlap
|
||||
|
||||
@@ -103,7 +103,7 @@ module InstructionSanity {
|
||||
query predicate missingOperandType(Operand operand, string message) {
|
||||
exists(Function func |
|
||||
not exists(operand.getType()) and
|
||||
func = operand.getUseInstruction().getEnclosingFunction() and
|
||||
func = operand.getUse().getEnclosingFunction() and
|
||||
message = "Operand missing type in function '" + getIdentityString(func) + "'."
|
||||
)
|
||||
}
|
||||
@@ -158,8 +158,8 @@ module InstructionSanity {
|
||||
* a different function.
|
||||
*/
|
||||
query predicate operandAcrossFunctions(Operand operand, Instruction instr, Instruction defInstr) {
|
||||
operand.getUseInstruction() = instr and
|
||||
operand.getDefinitionInstruction() = defInstr and
|
||||
operand.getUse() = instr and
|
||||
operand.getAnyDef() = defInstr and
|
||||
instr.getEnclosingIRFunction() != defInstr.getEnclosingIRFunction()
|
||||
}
|
||||
|
||||
@@ -480,17 +480,18 @@ class Instruction extends Construction::TInstruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all direct uses of the result of this instruction.
|
||||
* Gets all direct uses of the result of this instruction. The result can be
|
||||
* an `Operand` for which `isDefinitionInexact` holds.
|
||||
*/
|
||||
final Operand getAUse() {
|
||||
result.getDefinitionInstruction() = this
|
||||
result.getAnyDef() = this
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all of this instruction's operands.
|
||||
*/
|
||||
final Operand getAnOperand() {
|
||||
result.getUseInstruction() = this
|
||||
result.getUse() = this
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -509,13 +510,22 @@ class Instruction extends Construction::TInstruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the operand that holds the memory address to which the instruction stores its
|
||||
* Gets the operand that holds the memory address to which this instruction stores its
|
||||
* result, if any. For example, in `m3 = Store r1, r2`, the result of `getResultAddressOperand()`
|
||||
* is `r1`.
|
||||
*/
|
||||
final AddressOperand getResultAddressOperand() {
|
||||
getResultMemoryAccess().usesAddressOperand() and
|
||||
result.getUseInstruction() = this
|
||||
result.getUse() = this
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instruction that holds the exact memory address to which this instruction stores its
|
||||
* result, if any. For example, in `m3 = Store r1, r2`, the result of `getResultAddressOperand()`
|
||||
* is the instruction that defines `r1`.
|
||||
*/
|
||||
final Instruction getResultAddress() {
|
||||
result = getResultAddressOperand().getDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -698,7 +708,7 @@ class FieldAddressInstruction extends FieldInstruction {
|
||||
}
|
||||
|
||||
final Instruction getObjectAddress() {
|
||||
result = getObjectAddressOperand().getDefinitionInstruction()
|
||||
result = getObjectAddressOperand().getDef()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -763,7 +773,7 @@ class ReturnValueInstruction extends ReturnInstruction {
|
||||
}
|
||||
|
||||
final Instruction getReturnValue() {
|
||||
result = getReturnValueOperand().getDefinitionInstruction()
|
||||
result = getReturnValueOperand().getDef()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -777,7 +787,7 @@ class CopyInstruction extends Instruction {
|
||||
}
|
||||
|
||||
final Instruction getSourceValue() {
|
||||
result = getSourceValueOperand().getDefinitionInstruction()
|
||||
result = getSourceValueOperand().getDef()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -801,7 +811,7 @@ class LoadInstruction extends CopyInstruction {
|
||||
}
|
||||
|
||||
final Instruction getSourceAddress() {
|
||||
result = getSourceAddressOperand().getDefinitionInstruction()
|
||||
result = getSourceAddressOperand().getDef()
|
||||
}
|
||||
|
||||
override final LoadOperand getSourceValueOperand() {
|
||||
@@ -823,7 +833,7 @@ class StoreInstruction extends CopyInstruction {
|
||||
}
|
||||
|
||||
final Instruction getDestinationAddress() {
|
||||
result = getDestinationAddressOperand().getDefinitionInstruction()
|
||||
result = getDestinationAddressOperand().getDef()
|
||||
}
|
||||
|
||||
override final StoreValueOperand getSourceValueOperand() {
|
||||
@@ -841,7 +851,7 @@ class ConditionalBranchInstruction extends Instruction {
|
||||
}
|
||||
|
||||
final Instruction getCondition() {
|
||||
result = getConditionOperand().getDefinitionInstruction()
|
||||
result = getConditionOperand().getDef()
|
||||
}
|
||||
|
||||
final Instruction getTrueSuccessor() {
|
||||
@@ -907,11 +917,11 @@ class BinaryInstruction extends Instruction {
|
||||
}
|
||||
|
||||
final Instruction getLeft() {
|
||||
result = getLeftOperand().getDefinitionInstruction()
|
||||
result = getLeftOperand().getDef()
|
||||
}
|
||||
|
||||
final Instruction getRight() {
|
||||
result = getRightOperand().getDefinitionInstruction()
|
||||
result = getRightOperand().getDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1061,7 +1071,7 @@ class UnaryInstruction extends Instruction {
|
||||
}
|
||||
|
||||
final Instruction getUnary() {
|
||||
result = getUnaryOperand().getDefinitionInstruction()
|
||||
result = getUnaryOperand().getDef()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1291,7 +1301,7 @@ class SwitchInstruction extends Instruction {
|
||||
}
|
||||
|
||||
final Instruction getExpression() {
|
||||
result = getExpressionOperand().getDefinitionInstruction()
|
||||
result = getExpressionOperand().getDef()
|
||||
}
|
||||
|
||||
final Instruction getACaseSuccessor() {
|
||||
@@ -1326,7 +1336,7 @@ class CallInstruction extends Instruction {
|
||||
* function pointer.
|
||||
*/
|
||||
final Instruction getCallTarget() {
|
||||
result = getCallTargetOperand().getDefinitionInstruction()
|
||||
result = getCallTargetOperand().getDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1347,7 +1357,7 @@ class CallInstruction extends Instruction {
|
||||
* Gets all of the arguments of the call, including the `this` pointer, if any.
|
||||
*/
|
||||
final Instruction getAnArgument() {
|
||||
result = getAnArgumentOperand().getDefinitionInstruction()
|
||||
result = getAnArgumentOperand().getDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1361,7 +1371,7 @@ class CallInstruction extends Instruction {
|
||||
* Gets the `this` pointer argument of the call, if any.
|
||||
*/
|
||||
final Instruction getThisArgument() {
|
||||
result = getThisArgumentOperand().getDefinitionInstruction()
|
||||
result = getThisArgumentOperand().getDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1376,7 +1386,7 @@ class CallInstruction extends Instruction {
|
||||
* Gets the argument at the specified index.
|
||||
*/
|
||||
final Instruction getPositionalArgument(int index) {
|
||||
result = getPositionalArgumentOperand(index).getDefinitionInstruction()
|
||||
result = getPositionalArgumentOperand(index).getDef()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1532,7 +1542,7 @@ class ThrowValueInstruction extends ThrowInstruction {
|
||||
* Gets the address of the exception thrown by this instruction.
|
||||
*/
|
||||
final Instruction getExceptionAddress() {
|
||||
result = getExceptionAddressOperand().getDefinitionInstruction()
|
||||
result = getExceptionAddressOperand().getDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1546,7 +1556,7 @@ class ThrowValueInstruction extends ThrowInstruction {
|
||||
* Gets the exception thrown by this instruction.
|
||||
*/
|
||||
final Instruction getException() {
|
||||
result = getExceptionOperand().getDefinitionInstruction()
|
||||
result = getExceptionOperand().getDef()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1676,7 +1686,7 @@ class PhiInstruction extends Instruction {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final Instruction getAnInput() {
|
||||
result = this.getAnInputOperand().getDefinitionInstruction()
|
||||
result = this.getAnInputOperand().getDef()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1744,7 +1754,7 @@ class ChiInstruction extends Instruction {
|
||||
* memory write.
|
||||
*/
|
||||
final Instruction getTotal() {
|
||||
result = getTotalOperand().getDefinitionInstruction()
|
||||
result = getTotalOperand().getDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1758,7 +1768,7 @@ class ChiInstruction extends Instruction {
|
||||
* Gets the operand that represents the new value written by the memory write.
|
||||
*/
|
||||
final Instruction getPartial() {
|
||||
result = getPartialOperand().getDefinitionInstruction()
|
||||
result = getPartialOperand().getDef()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,25 +27,61 @@ class Operand extends TOperand {
|
||||
}
|
||||
|
||||
final Location getLocation() {
|
||||
result = getUseInstruction().getLocation()
|
||||
result = getUse().getLocation()
|
||||
}
|
||||
|
||||
final IRFunction getEnclosingIRFunction() {
|
||||
result = getUseInstruction().getEnclosingIRFunction()
|
||||
result = getUse().getEnclosingIRFunction()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the `Instruction` that consumes this operand.
|
||||
*/
|
||||
Instruction getUseInstruction() {
|
||||
Instruction getUse() {
|
||||
none()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `Instruction` whose result is the value of the operand. Unlike
|
||||
* `getDef`, this also has a result when `isDefinitionInexact` holds, which
|
||||
* means that the resulting instruction may only _partially_ or _potentially_
|
||||
* be the value of this operand.
|
||||
*/
|
||||
Instruction getAnyDef() {
|
||||
none()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `Instruction` whose result is the value of the operand. Unlike
|
||||
* `getAnyDef`, this also has no result when `isDefinitionInexact` holds,
|
||||
* which means that the resulting instruction must always be exactly the be
|
||||
* the value of this operand.
|
||||
*/
|
||||
final Instruction getDef() {
|
||||
result = this.getAnyDef() and
|
||||
getDefinitionOverlap() instanceof MustExactlyOverlap
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: renamed to `getUse`.
|
||||
*
|
||||
* Gets the `Instruction` that consumes this operand.
|
||||
*/
|
||||
deprecated
|
||||
final Instruction getUseInstruction() {
|
||||
result = getUse()
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this
|
||||
* predicate is `getAnyDef`, but most uses of this predicate should probably
|
||||
* be replaced with `getDef`.
|
||||
*
|
||||
* Gets the `Instruction` whose result is the value of the operand.
|
||||
*/
|
||||
Instruction getDefinitionInstruction() {
|
||||
none()
|
||||
deprecated
|
||||
final Instruction getDefinitionInstruction() {
|
||||
result = getAnyDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,7 +113,7 @@ class Operand extends TOperand {
|
||||
* For example: `this:r3_5`
|
||||
*/
|
||||
final string getDumpString() {
|
||||
result = getDumpLabel() + getInexactSpecifier() + getDefinitionInstruction().getResultId()
|
||||
result = getDumpLabel() + getInexactSpecifier() + getAnyDef().getResultId()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,7 +143,7 @@ class Operand extends TOperand {
|
||||
* has been cast to a different type.
|
||||
*/
|
||||
Type getType() {
|
||||
result = getDefinitionInstruction().getResultType()
|
||||
result = getAnyDef().getResultType()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,7 +154,7 @@ class Operand extends TOperand {
|
||||
* given by `getResultType()`.
|
||||
*/
|
||||
predicate isGLValue() {
|
||||
getDefinitionInstruction().isGLValue()
|
||||
getAnyDef().isGLValue()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,7 +194,7 @@ class MemoryOperand extends Operand {
|
||||
*/
|
||||
final AddressOperand getAddressOperand() {
|
||||
getMemoryAccess().usesAddressOperand() and
|
||||
result.getUseInstruction() = getUseInstruction()
|
||||
result.getUse() = getUse()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,11 +211,11 @@ class NonPhiOperand extends Operand {
|
||||
this = TNonPhiMemoryOperand(useInstr, tag, defInstr, _)
|
||||
}
|
||||
|
||||
override final Instruction getUseInstruction() {
|
||||
override final Instruction getUse() {
|
||||
result = useInstr
|
||||
}
|
||||
|
||||
override final Instruction getDefinitionInstruction() {
|
||||
override final Instruction getAnyDef() {
|
||||
result = defInstr
|
||||
}
|
||||
|
||||
@@ -437,11 +473,11 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand {
|
||||
result = "Phi"
|
||||
}
|
||||
|
||||
override final PhiInstruction getUseInstruction() {
|
||||
override final PhiInstruction getUse() {
|
||||
result = useInstr
|
||||
}
|
||||
|
||||
override final Instruction getDefinitionInstruction() {
|
||||
override final Instruction getAnyDef() {
|
||||
result = defInstr
|
||||
}
|
||||
|
||||
|
||||
@@ -10,16 +10,8 @@ int getConstantValue(Instruction instr) {
|
||||
result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or
|
||||
exists(PhiInstruction phi |
|
||||
phi = instr and
|
||||
result = max(Instruction def | def = phi.getAnInput() | getConstantValueToPhi(def)) and
|
||||
result = min(Instruction def | def = phi.getAnInput() | getConstantValueToPhi(def))
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
int getConstantValueToPhi(Instruction def) {
|
||||
exists(PhiInstruction phi |
|
||||
result = getConstantValue(def) and
|
||||
def = phi.getAnInput()
|
||||
result = max(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef())) and
|
||||
result = min(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef()))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -86,9 +86,12 @@ class ValueNumber extends TValueNumber {
|
||||
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets an `Operand` whose definition is exact and has this value number.
|
||||
*/
|
||||
final Operand getAUse() {
|
||||
this = valueNumber(result.getDefinitionInstruction())
|
||||
this = valueNumber(result.getDef())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,10 +231,11 @@ cached ValueNumber valueNumber(Instruction instr) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value number assigned to `instr`, if any. Returns at most one result.
|
||||
* Gets the value number assigned to the exact definition of `op`, if any.
|
||||
* Returns at most one result.
|
||||
*/
|
||||
ValueNumber valueNumberOfOperand(Operand op) {
|
||||
result = valueNumber(op.getDefinitionInstruction())
|
||||
result = valueNumber(op.getDef())
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -103,7 +103,7 @@ module InstructionSanity {
|
||||
query predicate missingOperandType(Operand operand, string message) {
|
||||
exists(Function func |
|
||||
not exists(operand.getType()) and
|
||||
func = operand.getUseInstruction().getEnclosingFunction() and
|
||||
func = operand.getUse().getEnclosingFunction() and
|
||||
message = "Operand missing type in function '" + getIdentityString(func) + "'."
|
||||
)
|
||||
}
|
||||
@@ -158,8 +158,8 @@ module InstructionSanity {
|
||||
* a different function.
|
||||
*/
|
||||
query predicate operandAcrossFunctions(Operand operand, Instruction instr, Instruction defInstr) {
|
||||
operand.getUseInstruction() = instr and
|
||||
operand.getDefinitionInstruction() = defInstr and
|
||||
operand.getUse() = instr and
|
||||
operand.getAnyDef() = defInstr and
|
||||
instr.getEnclosingIRFunction() != defInstr.getEnclosingIRFunction()
|
||||
}
|
||||
|
||||
@@ -480,17 +480,18 @@ class Instruction extends Construction::TInstruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all direct uses of the result of this instruction.
|
||||
* Gets all direct uses of the result of this instruction. The result can be
|
||||
* an `Operand` for which `isDefinitionInexact` holds.
|
||||
*/
|
||||
final Operand getAUse() {
|
||||
result.getDefinitionInstruction() = this
|
||||
result.getAnyDef() = this
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all of this instruction's operands.
|
||||
*/
|
||||
final Operand getAnOperand() {
|
||||
result.getUseInstruction() = this
|
||||
result.getUse() = this
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -509,13 +510,22 @@ class Instruction extends Construction::TInstruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the operand that holds the memory address to which the instruction stores its
|
||||
* Gets the operand that holds the memory address to which this instruction stores its
|
||||
* result, if any. For example, in `m3 = Store r1, r2`, the result of `getResultAddressOperand()`
|
||||
* is `r1`.
|
||||
*/
|
||||
final AddressOperand getResultAddressOperand() {
|
||||
getResultMemoryAccess().usesAddressOperand() and
|
||||
result.getUseInstruction() = this
|
||||
result.getUse() = this
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instruction that holds the exact memory address to which this instruction stores its
|
||||
* result, if any. For example, in `m3 = Store r1, r2`, the result of `getResultAddressOperand()`
|
||||
* is the instruction that defines `r1`.
|
||||
*/
|
||||
final Instruction getResultAddress() {
|
||||
result = getResultAddressOperand().getDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -698,7 +708,7 @@ class FieldAddressInstruction extends FieldInstruction {
|
||||
}
|
||||
|
||||
final Instruction getObjectAddress() {
|
||||
result = getObjectAddressOperand().getDefinitionInstruction()
|
||||
result = getObjectAddressOperand().getDef()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -763,7 +773,7 @@ class ReturnValueInstruction extends ReturnInstruction {
|
||||
}
|
||||
|
||||
final Instruction getReturnValue() {
|
||||
result = getReturnValueOperand().getDefinitionInstruction()
|
||||
result = getReturnValueOperand().getDef()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -777,7 +787,7 @@ class CopyInstruction extends Instruction {
|
||||
}
|
||||
|
||||
final Instruction getSourceValue() {
|
||||
result = getSourceValueOperand().getDefinitionInstruction()
|
||||
result = getSourceValueOperand().getDef()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -801,7 +811,7 @@ class LoadInstruction extends CopyInstruction {
|
||||
}
|
||||
|
||||
final Instruction getSourceAddress() {
|
||||
result = getSourceAddressOperand().getDefinitionInstruction()
|
||||
result = getSourceAddressOperand().getDef()
|
||||
}
|
||||
|
||||
override final LoadOperand getSourceValueOperand() {
|
||||
@@ -823,7 +833,7 @@ class StoreInstruction extends CopyInstruction {
|
||||
}
|
||||
|
||||
final Instruction getDestinationAddress() {
|
||||
result = getDestinationAddressOperand().getDefinitionInstruction()
|
||||
result = getDestinationAddressOperand().getDef()
|
||||
}
|
||||
|
||||
override final StoreValueOperand getSourceValueOperand() {
|
||||
@@ -841,7 +851,7 @@ class ConditionalBranchInstruction extends Instruction {
|
||||
}
|
||||
|
||||
final Instruction getCondition() {
|
||||
result = getConditionOperand().getDefinitionInstruction()
|
||||
result = getConditionOperand().getDef()
|
||||
}
|
||||
|
||||
final Instruction getTrueSuccessor() {
|
||||
@@ -907,11 +917,11 @@ class BinaryInstruction extends Instruction {
|
||||
}
|
||||
|
||||
final Instruction getLeft() {
|
||||
result = getLeftOperand().getDefinitionInstruction()
|
||||
result = getLeftOperand().getDef()
|
||||
}
|
||||
|
||||
final Instruction getRight() {
|
||||
result = getRightOperand().getDefinitionInstruction()
|
||||
result = getRightOperand().getDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1061,7 +1071,7 @@ class UnaryInstruction extends Instruction {
|
||||
}
|
||||
|
||||
final Instruction getUnary() {
|
||||
result = getUnaryOperand().getDefinitionInstruction()
|
||||
result = getUnaryOperand().getDef()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1291,7 +1301,7 @@ class SwitchInstruction extends Instruction {
|
||||
}
|
||||
|
||||
final Instruction getExpression() {
|
||||
result = getExpressionOperand().getDefinitionInstruction()
|
||||
result = getExpressionOperand().getDef()
|
||||
}
|
||||
|
||||
final Instruction getACaseSuccessor() {
|
||||
@@ -1326,7 +1336,7 @@ class CallInstruction extends Instruction {
|
||||
* function pointer.
|
||||
*/
|
||||
final Instruction getCallTarget() {
|
||||
result = getCallTargetOperand().getDefinitionInstruction()
|
||||
result = getCallTargetOperand().getDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1347,7 +1357,7 @@ class CallInstruction extends Instruction {
|
||||
* Gets all of the arguments of the call, including the `this` pointer, if any.
|
||||
*/
|
||||
final Instruction getAnArgument() {
|
||||
result = getAnArgumentOperand().getDefinitionInstruction()
|
||||
result = getAnArgumentOperand().getDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1361,7 +1371,7 @@ class CallInstruction extends Instruction {
|
||||
* Gets the `this` pointer argument of the call, if any.
|
||||
*/
|
||||
final Instruction getThisArgument() {
|
||||
result = getThisArgumentOperand().getDefinitionInstruction()
|
||||
result = getThisArgumentOperand().getDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1376,7 +1386,7 @@ class CallInstruction extends Instruction {
|
||||
* Gets the argument at the specified index.
|
||||
*/
|
||||
final Instruction getPositionalArgument(int index) {
|
||||
result = getPositionalArgumentOperand(index).getDefinitionInstruction()
|
||||
result = getPositionalArgumentOperand(index).getDef()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1532,7 +1542,7 @@ class ThrowValueInstruction extends ThrowInstruction {
|
||||
* Gets the address of the exception thrown by this instruction.
|
||||
*/
|
||||
final Instruction getExceptionAddress() {
|
||||
result = getExceptionAddressOperand().getDefinitionInstruction()
|
||||
result = getExceptionAddressOperand().getDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1546,7 +1556,7 @@ class ThrowValueInstruction extends ThrowInstruction {
|
||||
* Gets the exception thrown by this instruction.
|
||||
*/
|
||||
final Instruction getException() {
|
||||
result = getExceptionOperand().getDefinitionInstruction()
|
||||
result = getExceptionOperand().getDef()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1676,7 +1686,7 @@ class PhiInstruction extends Instruction {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final Instruction getAnInput() {
|
||||
result = this.getAnInputOperand().getDefinitionInstruction()
|
||||
result = this.getAnInputOperand().getDef()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1744,7 +1754,7 @@ class ChiInstruction extends Instruction {
|
||||
* memory write.
|
||||
*/
|
||||
final Instruction getTotal() {
|
||||
result = getTotalOperand().getDefinitionInstruction()
|
||||
result = getTotalOperand().getDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1758,7 +1768,7 @@ class ChiInstruction extends Instruction {
|
||||
* Gets the operand that represents the new value written by the memory write.
|
||||
*/
|
||||
final Instruction getPartial() {
|
||||
result = getPartialOperand().getDefinitionInstruction()
|
||||
result = getPartialOperand().getDef()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,25 +27,61 @@ class Operand extends TOperand {
|
||||
}
|
||||
|
||||
final Location getLocation() {
|
||||
result = getUseInstruction().getLocation()
|
||||
result = getUse().getLocation()
|
||||
}
|
||||
|
||||
final IRFunction getEnclosingIRFunction() {
|
||||
result = getUseInstruction().getEnclosingIRFunction()
|
||||
result = getUse().getEnclosingIRFunction()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the `Instruction` that consumes this operand.
|
||||
*/
|
||||
Instruction getUseInstruction() {
|
||||
Instruction getUse() {
|
||||
none()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `Instruction` whose result is the value of the operand. Unlike
|
||||
* `getDef`, this also has a result when `isDefinitionInexact` holds, which
|
||||
* means that the resulting instruction may only _partially_ or _potentially_
|
||||
* be the value of this operand.
|
||||
*/
|
||||
Instruction getAnyDef() {
|
||||
none()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `Instruction` whose result is the value of the operand. Unlike
|
||||
* `getAnyDef`, this also has no result when `isDefinitionInexact` holds,
|
||||
* which means that the resulting instruction must always be exactly the be
|
||||
* the value of this operand.
|
||||
*/
|
||||
final Instruction getDef() {
|
||||
result = this.getAnyDef() and
|
||||
getDefinitionOverlap() instanceof MustExactlyOverlap
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: renamed to `getUse`.
|
||||
*
|
||||
* Gets the `Instruction` that consumes this operand.
|
||||
*/
|
||||
deprecated
|
||||
final Instruction getUseInstruction() {
|
||||
result = getUse()
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this
|
||||
* predicate is `getAnyDef`, but most uses of this predicate should probably
|
||||
* be replaced with `getDef`.
|
||||
*
|
||||
* Gets the `Instruction` whose result is the value of the operand.
|
||||
*/
|
||||
Instruction getDefinitionInstruction() {
|
||||
none()
|
||||
deprecated
|
||||
final Instruction getDefinitionInstruction() {
|
||||
result = getAnyDef()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,7 +113,7 @@ class Operand extends TOperand {
|
||||
* For example: `this:r3_5`
|
||||
*/
|
||||
final string getDumpString() {
|
||||
result = getDumpLabel() + getInexactSpecifier() + getDefinitionInstruction().getResultId()
|
||||
result = getDumpLabel() + getInexactSpecifier() + getAnyDef().getResultId()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,7 +143,7 @@ class Operand extends TOperand {
|
||||
* has been cast to a different type.
|
||||
*/
|
||||
Type getType() {
|
||||
result = getDefinitionInstruction().getResultType()
|
||||
result = getAnyDef().getResultType()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,7 +154,7 @@ class Operand extends TOperand {
|
||||
* given by `getResultType()`.
|
||||
*/
|
||||
predicate isGLValue() {
|
||||
getDefinitionInstruction().isGLValue()
|
||||
getAnyDef().isGLValue()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,7 +194,7 @@ class MemoryOperand extends Operand {
|
||||
*/
|
||||
final AddressOperand getAddressOperand() {
|
||||
getMemoryAccess().usesAddressOperand() and
|
||||
result.getUseInstruction() = getUseInstruction()
|
||||
result.getUse() = getUse()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,11 +211,11 @@ class NonPhiOperand extends Operand {
|
||||
this = TNonPhiMemoryOperand(useInstr, tag, defInstr, _)
|
||||
}
|
||||
|
||||
override final Instruction getUseInstruction() {
|
||||
override final Instruction getUse() {
|
||||
result = useInstr
|
||||
}
|
||||
|
||||
override final Instruction getDefinitionInstruction() {
|
||||
override final Instruction getAnyDef() {
|
||||
result = defInstr
|
||||
}
|
||||
|
||||
@@ -437,11 +473,11 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand {
|
||||
result = "Phi"
|
||||
}
|
||||
|
||||
override final PhiInstruction getUseInstruction() {
|
||||
override final PhiInstruction getUse() {
|
||||
result = useInstr
|
||||
}
|
||||
|
||||
override final Instruction getDefinitionInstruction() {
|
||||
override final Instruction getAnyDef() {
|
||||
result = defInstr
|
||||
}
|
||||
|
||||
|
||||
@@ -10,16 +10,8 @@ int getConstantValue(Instruction instr) {
|
||||
result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or
|
||||
exists(PhiInstruction phi |
|
||||
phi = instr and
|
||||
result = max(Instruction def | def = phi.getAnInput() | getConstantValueToPhi(def)) and
|
||||
result = min(Instruction def | def = phi.getAnInput() | getConstantValueToPhi(def))
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
int getConstantValueToPhi(Instruction def) {
|
||||
exists(PhiInstruction phi |
|
||||
result = getConstantValue(def) and
|
||||
def = phi.getAnInput()
|
||||
result = max(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef())) and
|
||||
result = min(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef()))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -86,9 +86,12 @@ class ValueNumber extends TValueNumber {
|
||||
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets an `Operand` whose definition is exact and has this value number.
|
||||
*/
|
||||
final Operand getAUse() {
|
||||
this = valueNumber(result.getDefinitionInstruction())
|
||||
this = valueNumber(result.getDef())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,10 +231,11 @@ cached ValueNumber valueNumber(Instruction instr) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value number assigned to `instr`, if any. Returns at most one result.
|
||||
* Gets the value number assigned to the exact definition of `op`, if any.
|
||||
* Returns at most one result.
|
||||
*/
|
||||
ValueNumber valueNumberOfOperand(Operand op) {
|
||||
result = valueNumber(op.getDefinitionInstruction())
|
||||
result = valueNumber(op.getDef())
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -53,7 +53,7 @@ private predicate operandIsConsumedWithoutEscaping(Operand operand) {
|
||||
// loaded/stored value could).
|
||||
operand instanceof AddressOperand or
|
||||
exists (Instruction instr |
|
||||
instr = operand.getUseInstruction() and
|
||||
instr = operand.getUse() and
|
||||
(
|
||||
// Neither operand of a Compare escapes.
|
||||
instr instanceof CompareInstruction or
|
||||
@@ -72,7 +72,7 @@ private predicate operandEscapesDomain(Operand operand) {
|
||||
not operandIsPropagated(operand, _) and
|
||||
not isArgumentForParameter(_, operand, _) and
|
||||
not isOnlyEscapesViaReturnArgument(operand) and
|
||||
not operand.getUseInstruction() instanceof ReturnValueInstruction and
|
||||
not operand.getUse() instanceof ReturnValueInstruction and
|
||||
not operand instanceof PhiInputOperand
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ IntValue getPointerBitOffset(PointerOffsetInstruction instr) {
|
||||
*/
|
||||
private predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
|
||||
exists(Instruction instr |
|
||||
instr = operand.getUseInstruction() and
|
||||
instr = operand.getUse() and
|
||||
(
|
||||
// Converting to a non-virtual base class adds the offset of the base class.
|
||||
exists(ConvertToBaseInstruction convert |
|
||||
@@ -156,7 +156,7 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
|
||||
|
||||
private predicate operandEscapesNonReturn(Operand operand) {
|
||||
// The address is propagated to the result of the instruction, and that result itself is returned
|
||||
operandIsPropagated(operand, _) and resultEscapesNonReturn(operand.getUseInstruction())
|
||||
operandIsPropagated(operand, _) and resultEscapesNonReturn(operand.getUse())
|
||||
or
|
||||
// The operand is used in a function call which returns it, and the return value is then returned
|
||||
exists(CallInstruction ci, Instruction init |
|
||||
@@ -169,10 +169,10 @@ private predicate operandEscapesNonReturn(Operand operand) {
|
||||
)
|
||||
)
|
||||
or
|
||||
isOnlyEscapesViaReturnArgument(operand) and resultEscapesNonReturn(operand.getUseInstruction())
|
||||
isOnlyEscapesViaReturnArgument(operand) and resultEscapesNonReturn(operand.getUse())
|
||||
or
|
||||
operand instanceof PhiInputOperand and
|
||||
resultEscapesNonReturn(operand.getUseInstruction())
|
||||
resultEscapesNonReturn(operand.getUse())
|
||||
or
|
||||
operandEscapesDomain(operand)
|
||||
}
|
||||
@@ -180,7 +180,7 @@ private predicate operandEscapesNonReturn(Operand operand) {
|
||||
private predicate operandMayReachReturn(Operand operand) {
|
||||
// The address is propagated to the result of the instruction, and that result itself is returned
|
||||
operandIsPropagated(operand, _) and
|
||||
resultMayReachReturn(operand.getUseInstruction())
|
||||
resultMayReachReturn(operand.getUse())
|
||||
or
|
||||
// The operand is used in a function call which returns it, and the return value is then returned
|
||||
exists(CallInstruction ci, Instruction init |
|
||||
@@ -190,19 +190,19 @@ private predicate operandMayReachReturn(Operand operand) {
|
||||
)
|
||||
or
|
||||
// The address is returned
|
||||
operand.getUseInstruction() instanceof ReturnValueInstruction
|
||||
operand.getUse() instanceof ReturnValueInstruction
|
||||
or
|
||||
isOnlyEscapesViaReturnArgument(operand) and resultMayReachReturn(operand.getUseInstruction())
|
||||
isOnlyEscapesViaReturnArgument(operand) and resultMayReachReturn(operand.getUse())
|
||||
or
|
||||
operand instanceof PhiInputOperand and
|
||||
resultMayReachReturn(operand.getUseInstruction())
|
||||
resultMayReachReturn(operand.getUse())
|
||||
}
|
||||
|
||||
private predicate operandReturned(Operand operand, IntValue bitOffset) {
|
||||
// The address is propagated to the result of the instruction, and that result itself is returned
|
||||
exists(IntValue bitOffset1, IntValue bitOffset2 |
|
||||
operandIsPropagated(operand, bitOffset1) and
|
||||
resultReturned(operand.getUseInstruction(), bitOffset2) and
|
||||
resultReturned(operand.getUse(), bitOffset2) and
|
||||
bitOffset = Ints::add(bitOffset1, bitOffset2)
|
||||
)
|
||||
or
|
||||
@@ -216,16 +216,16 @@ private predicate operandReturned(Operand operand, IntValue bitOffset) {
|
||||
)
|
||||
or
|
||||
// The address is returned
|
||||
operand.getUseInstruction() instanceof ReturnValueInstruction and
|
||||
operand.getUse() instanceof ReturnValueInstruction and
|
||||
bitOffset = 0
|
||||
or
|
||||
isOnlyEscapesViaReturnArgument(operand) and resultReturned(operand.getUseInstruction(), _) and
|
||||
isOnlyEscapesViaReturnArgument(operand) and resultReturned(operand.getUse(), _) and
|
||||
bitOffset = Ints::unknown()
|
||||
}
|
||||
|
||||
private predicate isArgumentForParameter(CallInstruction ci, Operand operand, Instruction init) {
|
||||
exists(Function f |
|
||||
ci = operand.getUseInstruction() and
|
||||
ci = operand.getUse() and
|
||||
f = ci.getStaticCallTarget() and
|
||||
(
|
||||
init.(InitializeParameterInstruction).getParameter() = f.getParameter(operand.(PositionalArgumentOperand).getIndex())
|
||||
@@ -241,21 +241,21 @@ private predicate isArgumentForParameter(CallInstruction ci, Operand operand, In
|
||||
|
||||
private predicate isAlwaysReturnedArgument(Operand operand) {
|
||||
exists(AliasFunction f |
|
||||
f = operand.getUseInstruction().(CallInstruction).getStaticCallTarget() and
|
||||
f = operand.getUse().(CallInstruction).getStaticCallTarget() and
|
||||
f.parameterIsAlwaysReturned(operand.(PositionalArgumentOperand).getIndex())
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isOnlyEscapesViaReturnArgument(Operand operand) {
|
||||
exists(AliasFunction f |
|
||||
f = operand.getUseInstruction().(CallInstruction).getStaticCallTarget() and
|
||||
f = operand.getUse().(CallInstruction).getStaticCallTarget() and
|
||||
f.parameterEscapesOnlyViaReturn(operand.(PositionalArgumentOperand).getIndex())
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isNeverEscapesArgument(Operand operand) {
|
||||
exists(AliasFunction f |
|
||||
f = operand.getUseInstruction().(CallInstruction).getStaticCallTarget() and
|
||||
f = operand.getUse().(CallInstruction).getStaticCallTarget() and
|
||||
f.parameterNeverEscapes(operand.(PositionalArgumentOperand).getIndex())
|
||||
)
|
||||
}
|
||||
@@ -315,7 +315,7 @@ predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset)
|
||||
operand = instr.getAnOperand() and
|
||||
// If an operand is propagated, then the result points to the same variable,
|
||||
// offset by the bit offset from the propagation.
|
||||
resultPointsTo(operand.getDefinitionInstruction(), var, originalBitOffset) and
|
||||
resultPointsTo(operand.getAnyDef(), var, originalBitOffset) and
|
||||
(
|
||||
operandIsPropagated(operand, propagatedBitOffset)
|
||||
or
|
||||
|
||||
@@ -69,7 +69,7 @@ cached private module Cached {
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
oldOperand = oldInstruction.getAnOperand() and
|
||||
tag = oldOperand.getOperandTag() and
|
||||
result = getNewInstruction(oldOperand.getDefinitionInstruction())
|
||||
result = getNewInstruction(oldOperand.getAnyDef())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ cached private module Cached {
|
||||
exists(OldInstruction oldDefinition |
|
||||
instruction instanceof UnmodeledUseInstruction and
|
||||
tag instanceof UnmodeledUseOperandTag and
|
||||
oldDefinition = oldOperand.getDefinitionInstruction() and
|
||||
oldDefinition = oldOperand.getAnyDef() and
|
||||
not exists(Alias::getResultMemoryLocation(oldDefinition)) and
|
||||
result = getNewInstruction(oldDefinition) and
|
||||
overlap instanceof MustTotallyOverlap
|
||||
|
||||
@@ -8,12 +8,12 @@ private import semmle.code.cpp.ir.internal.Overlap
|
||||
private class IntValue = Ints::IntValue;
|
||||
|
||||
private predicate hasResultMemoryAccess(Instruction instr, IRVariable var, Type type, IntValue bitOffset) {
|
||||
resultPointsTo(instr.getResultAddressOperand().getDefinitionInstruction(), var, bitOffset) and
|
||||
resultPointsTo(instr.getResultAddressOperand().getAnyDef(), var, bitOffset) and
|
||||
type = instr.getResultType()
|
||||
}
|
||||
|
||||
private predicate hasOperandMemoryAccess(MemoryOperand operand, IRVariable var, Type type, IntValue bitOffset) {
|
||||
resultPointsTo(operand.getAddressOperand().getDefinitionInstruction(), var, bitOffset) and
|
||||
resultPointsTo(operand.getAddressOperand().getAnyDef(), var, bitOffset) and
|
||||
type = operand.getType()
|
||||
}
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ private predicate boundFlowStepSsa(
|
||||
) {
|
||||
exists(IRGuardCondition guard, boolean testIsTrue |
|
||||
guard = boundFlowCond(valueNumberOfOperand(op2), op1, delta, upper, testIsTrue) and
|
||||
guard.controls(op2.getUseInstruction().getBlock(), testIsTrue) and
|
||||
guard.controls(op2.getUse().getBlock(), testIsTrue) and
|
||||
reason = TCondReason(guard)
|
||||
)
|
||||
}
|
||||
@@ -269,8 +269,8 @@ private predicate boundFlowStep(Instruction i, NonPhiOperand op, int delta, bool
|
||||
i.(AddInstruction).getAnOperand() = x and
|
||||
op != x
|
||||
|
|
||||
not exists(getValue(getConstantValue(op.getUseInstruction()))) and
|
||||
not exists(getValue(getConstantValue(x.getUseInstruction()))) and
|
||||
not exists(getValue(getConstantValue(op.getUse()))) and
|
||||
not exists(getValue(getConstantValue(x.getUse()))) and
|
||||
if(strictlyPositive(x))
|
||||
then (
|
||||
upper = false and delta = 1
|
||||
@@ -293,7 +293,7 @@ private predicate boundFlowStep(Instruction i, NonPhiOperand op, int delta, bool
|
||||
)
|
||||
|
|
||||
// `x` with constant value is covered by valueFlowStep
|
||||
not exists(getValue(getConstantValue(x.getUseInstruction()))) and
|
||||
not exists(getValue(getConstantValue(x.getUse()))) and
|
||||
if strictlyPositive(x)
|
||||
then (
|
||||
upper = true and delta = -1
|
||||
@@ -353,7 +353,7 @@ private predicate boundedNonPhiOperand(NonPhiOperand op, Bound b, int delta, boo
|
||||
delta = d1 + d2
|
||||
)
|
||||
or
|
||||
boundedInstruction(op.getDefinitionInstruction(), b, delta, upper, fromBackEdge, origdelta, reason)
|
||||
boundedInstruction(op.getDef(), b, delta, upper, fromBackEdge, origdelta, reason)
|
||||
or
|
||||
exists(int d, Reason r1, Reason r2 |
|
||||
boundedNonPhiOperand(op, b, d, upper, fromBackEdge, origdelta, r2)
|
||||
@@ -379,14 +379,14 @@ private predicate boundedNonPhiOperand(NonPhiOperand op, Bound b, int delta, boo
|
||||
private predicate boundFlowStepPhi(
|
||||
PhiInputOperand op2, Operand op1, int delta, boolean upper, Reason reason
|
||||
) {
|
||||
op2.getDefinitionInstruction().(CopyInstruction).getSourceValueOperand() = op1 and
|
||||
op2.getDef().(CopyInstruction).getSourceValueOperand() = op1 and
|
||||
(upper = true or upper = false) and
|
||||
reason = TNoReason() and
|
||||
delta = 0
|
||||
or
|
||||
exists(IRGuardCondition guard, boolean testIsTrue |
|
||||
guard = boundFlowCond(valueNumberOfOperand(op2), op1, delta, upper, testIsTrue) and
|
||||
guard.controlsEdge(op2.getPredecessorBlock(), op2.getUseInstruction().getBlock(), testIsTrue) and
|
||||
guard.controlsEdge(op2.getPredecessorBlock(), op2.getUse().getBlock(), testIsTrue) and
|
||||
reason = TCondReason(guard)
|
||||
)
|
||||
}
|
||||
@@ -403,10 +403,10 @@ private predicate boundedPhiOperand(
|
||||
(if r1 instanceof NoReason then reason = r2 else reason = r1)
|
||||
)
|
||||
or
|
||||
boundedInstruction(op.getDefinitionInstruction(), b, delta, upper, fromBackEdge, origdelta, reason)
|
||||
boundedInstruction(op.getDef(), b, delta, upper, fromBackEdge, origdelta, reason)
|
||||
or
|
||||
exists(int d, Reason r1, Reason r2 |
|
||||
boundedInstruction(op.getDefinitionInstruction(), b, d, upper, fromBackEdge, origdelta, r2)
|
||||
boundedInstruction(op.getDef(), b, d, upper, fromBackEdge, origdelta, r2)
|
||||
|
|
||||
unequalOperand(op, b, d, r1) and
|
||||
(
|
||||
@@ -427,7 +427,7 @@ private predicate unequalFlowStep(
|
||||
) {
|
||||
exists(IRGuardCondition guard, boolean testIsTrue |
|
||||
guard = eqFlowCond(valueNumberOfOperand(op2), op1, delta, false, testIsTrue) and
|
||||
guard.controls(op2.getUseInstruction().getBlock(), testIsTrue) and
|
||||
guard.controls(op2.getUse().getBlock(), testIsTrue) and
|
||||
reason = TCondReason(guard)
|
||||
)
|
||||
}
|
||||
@@ -476,7 +476,7 @@ private predicate boundedPhiInp(
|
||||
exists(int d, boolean fromBackEdge0 |
|
||||
boundedPhiOperand(op, b, d, upper, fromBackEdge0, origdelta, reason)
|
||||
or
|
||||
b.(ValueNumberBound).getInstruction() = op.getDefinitionInstruction() and
|
||||
b.(ValueNumberBound).getInstruction() = op.getDef() and
|
||||
d = 0 and
|
||||
(upper = true or upper = false) and
|
||||
fromBackEdge0 = false and
|
||||
|
||||
@@ -22,8 +22,8 @@ IntValue getConstantValue(Instruction instr) {
|
||||
result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or
|
||||
exists(PhiInstruction phi |
|
||||
phi = instr and
|
||||
result = max(PhiInputOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction())) and
|
||||
result = min(PhiInputOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction()))
|
||||
result = max(PhiInputOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDef())) and
|
||||
result = min(PhiInputOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDef()))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -35,14 +35,14 @@ predicate valueFlowStep(Instruction i, Operand op, int delta) {
|
||||
i.(AddInstruction).getAnOperand() = x and
|
||||
op != x
|
||||
|
|
||||
delta = getValue(getConstantValue(x.getDefinitionInstruction()))
|
||||
delta = getValue(getConstantValue(x.getDef()))
|
||||
)
|
||||
or
|
||||
exists(Operand x |
|
||||
i.(SubInstruction).getLeftOperand() = op and
|
||||
i.(SubInstruction).getRightOperand() = x
|
||||
|
|
||||
delta = -getValue(getConstantValue(x.getDefinitionInstruction()))
|
||||
delta = -getValue(getConstantValue(x.getDef()))
|
||||
)
|
||||
or
|
||||
exists(Operand x |
|
||||
@@ -51,7 +51,7 @@ predicate valueFlowStep(Instruction i, Operand op, int delta) {
|
||||
op != x
|
||||
|
|
||||
delta = i.(PointerAddInstruction).getElementSize() *
|
||||
getValue(getConstantValue(x.getDefinitionInstruction()))
|
||||
getValue(getConstantValue(x.getDef()))
|
||||
)
|
||||
or
|
||||
exists(Operand x |
|
||||
@@ -59,7 +59,7 @@ predicate valueFlowStep(Instruction i, Operand op, int delta) {
|
||||
i.(PointerSubInstruction).getRightOperand() = x
|
||||
|
|
||||
delta = i.(PointerSubInstruction).getElementSize() *
|
||||
-getValue(getConstantValue(x.getDefinitionInstruction()))
|
||||
-getValue(getConstantValue(x.getDef()))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -221,7 +221,7 @@ private predicate unknownSign(Instruction i) {
|
||||
*/
|
||||
private predicate lowerBound(IRGuardCondition comp, Operand lowerbound, Operand bounded, boolean isStrict) {
|
||||
exists(int adjustment, Operand compared |
|
||||
valueNumber(bounded.getDefinitionInstruction()) = valueNumber(compared.getDefinitionInstruction()) and
|
||||
valueNumberOfOperand(bounded) = valueNumberOfOperand(compared) and
|
||||
(
|
||||
isStrict = true and
|
||||
adjustment = 0
|
||||
@@ -229,7 +229,7 @@ private predicate lowerBound(IRGuardCondition comp, Operand lowerbound, Operand
|
||||
isStrict = false and
|
||||
adjustment = 1
|
||||
) and
|
||||
comp.ensuresLt(lowerbound, compared, adjustment, bounded.getUseInstruction().getBlock(), true)
|
||||
comp.ensuresLt(lowerbound, compared, adjustment, bounded.getUse().getBlock(), true)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ private predicate lowerBound(IRGuardCondition comp, Operand lowerbound, Operand
|
||||
*/
|
||||
private predicate upperBound(IRGuardCondition comp, Operand upperbound, Operand bounded, boolean isStrict) {
|
||||
exists(int adjustment, Operand compared |
|
||||
valueNumber(bounded.getDefinitionInstruction()) = valueNumber(compared.getDefinitionInstruction()) and
|
||||
valueNumberOfOperand(bounded) = valueNumberOfOperand(compared) and
|
||||
(
|
||||
isStrict = true and
|
||||
adjustment = 0
|
||||
@@ -248,7 +248,7 @@ private predicate upperBound(IRGuardCondition comp, Operand upperbound, Operand
|
||||
isStrict = false and
|
||||
adjustment = 1
|
||||
) and
|
||||
comp.ensuresLt(compared, upperbound, adjustment, bounded.getUseInstruction().getBlock(), true)
|
||||
comp.ensuresLt(compared, upperbound, adjustment, bounded.getUse().getBlock(), true)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -261,8 +261,8 @@ private predicate upperBound(IRGuardCondition comp, Operand upperbound, Operand
|
||||
*/
|
||||
private predicate eqBound(IRGuardCondition guard, Operand eqbound, Operand bounded, boolean isEq) {
|
||||
exists(Operand compared |
|
||||
valueNumber(bounded.getDefinitionInstruction()) = valueNumber(compared.getDefinitionInstruction()) and
|
||||
guard.ensuresEq(compared, eqbound, 0, bounded.getUseInstruction().getBlock(), isEq)
|
||||
valueNumberOfOperand(bounded) = valueNumberOfOperand(compared) and
|
||||
guard.ensuresEq(compared, eqbound, 0, bounded.getUse().getBlock(), isEq)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -331,12 +331,12 @@ private predicate binaryOpSigns(BinaryInstruction i, Sign lhs, Sign rhs) {
|
||||
}
|
||||
|
||||
private Sign unguardedOperandSign(Operand operand) {
|
||||
result = instructionSign(operand.getDefinitionInstruction()) and
|
||||
result = instructionSign(operand.getDef()) and
|
||||
not hasGuard(operand, result)
|
||||
}
|
||||
|
||||
private Sign guardedOperandSign(Operand operand) {
|
||||
result = instructionSign(operand.getDefinitionInstruction()) and
|
||||
result = instructionSign(operand.getDef()) and
|
||||
hasGuard(operand, result)
|
||||
}
|
||||
|
||||
@@ -368,6 +368,9 @@ cached module SignAnalysisCached {
|
||||
or
|
||||
result = guardedOperandSign(operand) and
|
||||
result = guardedOperandSignOk(operand)
|
||||
or
|
||||
// `result` is unconstrained if the definition is inexact. Then any sign is possible.
|
||||
operand.isDefinitionInexact()
|
||||
}
|
||||
|
||||
cached
|
||||
|
||||
@@ -65,7 +65,7 @@ query predicate irGuardsCompare(int startLine, string msg) {
|
||||
guard.comparesEq(left, right, k, false, sense) and op = " != "
|
||||
)
|
||||
and startLine = guard.getLocation().getStartLine()
|
||||
and msg = left.getDefinitionInstruction().getUnconvertedResultExpression() + op + right.getDefinitionInstruction().getUnconvertedResultExpression() + "+" + k + " when " + guard + " is " + which
|
||||
and msg = left.getAnyDef().getUnconvertedResultExpression() + op + right.getAnyDef().getUnconvertedResultExpression() + "+" + k + " when " + guard + " is " + which
|
||||
)
|
||||
}
|
||||
query predicate irGuardsControl(IRGuardCondition guard, boolean sense, int start, int end) {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
| test.cpp:89:28:89:34 | test.cpp:92:8:92:14 | IR only |
|
||||
| test.cpp:100:13:100:18 | test.cpp:103:10:103:12 | AST only |
|
||||
| test.cpp:109:9:109:14 | test.cpp:110:10:110:12 | IR only |
|
||||
| test.cpp:122:18:122:30 | test.cpp:132:22:132:23 | IR only |
|
||||
| test.cpp:122:18:122:30 | test.cpp:140:22:140:23 | IR only |
|
||||
| test.cpp:136:27:136:32 | test.cpp:137:27:137:28 | AST only |
|
||||
| test.cpp:136:27:136:32 | test.cpp:140:22:140:23 | AST only |
|
||||
| test.cpp:142:32:142:37 | test.cpp:145:10:145:11 | IR only |
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
| test.cpp:110:10:110:12 | Load: (reference dereference) | test.cpp:109:9:109:14 | Call: call to source |
|
||||
| test.cpp:126:8:126:19 | Convert: (const int *)... | test.cpp:120:9:120:20 | InitializeParameter: sourceArray1 |
|
||||
| test.cpp:126:8:126:19 | Load: sourceArray1 | test.cpp:120:9:120:20 | InitializeParameter: sourceArray1 |
|
||||
| test.cpp:132:22:132:23 | Load: m1 | test.cpp:122:18:122:30 | InitializeParameter: sourceStruct1 |
|
||||
| test.cpp:140:22:140:23 | Load: m1 | test.cpp:122:18:122:30 | InitializeParameter: sourceStruct1 |
|
||||
| test.cpp:145:10:145:11 | Load: m2 | test.cpp:142:32:142:37 | Call: call to source |
|
||||
| test.cpp:153:17:153:18 | Load: m2 | test.cpp:151:35:151:40 | Call: call to source |
|
||||
| test.cpp:188:8:188:8 | Load: y | test.cpp:186:27:186:32 | Call: call to source |
|
||||
|
||||
Reference in New Issue
Block a user