C++: switch to using ValueNumbers as bounds

This reduces the number of bounds computed, and will simplify use of the
library. The resulting locations in the tests may be slightly strange,
because the example `Instruction` for a `ValueNumber` is the first
appearing in the IR, regardless of source order, and may not be the most
closely related `Instruction` to the bounded value. I think that's worth
doing for the performance and usability benefits.
This commit is contained in:
Robert Marsh
2018-12-12 17:07:45 -08:00
parent 89148a9ec7
commit 2f8ca8802b
3 changed files with 56 additions and 38 deletions

View File

@@ -1,11 +1,33 @@
import cpp
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.ir.ValueNumbering
private newtype TBound =
TBoundZero() or
TBoundInstruction(Instruction i) {
i.getResultType() instanceof IntegralType or
i.getResultType() instanceof PointerType
TBoundValueNumber(ValueNumber vn) {
exists(Instruction i |
vn.getAnInstruction() = i and
(
i.getResultType() instanceof IntegralType or
i.getResultType() instanceof PointerType
)
|
i instanceof PhiInstruction
or
i instanceof InitializeParameterInstruction
or
i instanceof CallInstruction
or
i instanceof VariableAddressInstruction
or
i instanceof FieldAddressInstruction
or
i.(LoadInstruction).getSourceAddress() instanceof VariableAddressInstruction
or
i.(LoadInstruction).getSourceAddress() instanceof FieldAddressInstruction
or
i.getAUse() instanceof ArgumentOperand
)
}
/**
@@ -20,12 +42,9 @@ abstract class Bound extends TBound {
/** Gets an expression that equals this bound. */
Instruction getInstruction() { result = getInstruction(0) }
predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
path = "" and sl = 0 and sc = 0 and el = 0 and ec = 0
}
abstract Location getLocation();
}
/**
* The bound that corresponds to the integer 0. This is used to represent all
* integer bounds as bounds are always accompanied by an added integer delta.
@@ -34,18 +53,27 @@ class ZeroBound extends Bound, TBoundZero {
override string toString() { result = "0" }
override Instruction getInstruction(int delta) { result.(ConstantValueInstruction).getValue().toInt() = delta }
override Location getLocation() {
result instanceof UnknownDefaultLocation
}
}
/**
* A bound corresponding to the value of an `Instruction`.
*/
class InstructionBound extends Bound, TBoundInstruction {
/** Gets the SSA variable that equals this bound. */
override Instruction getInstruction(int delta) { this = TBoundInstruction(result) and delta = 0}
override string toString() { result = getInstruction().toString() }
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
getInstruction().getLocation().hasLocationInfo(path, sl, sc, el, ec)
class ValueNumberBound extends Bound, TBoundValueNumber {
ValueNumber vn;
ValueNumberBound() {
this = TBoundValueNumber(vn)
}
}
/** Gets the SSA variable that equals this bound. */
override Instruction getInstruction(int delta) { this = TBoundValueNumber(valueNumber(result)) and delta = 0}
override string toString() { result = vn.getExampleInstruction().toString() }
override Location getLocation() {
result = vn.getLocation()
}
}

View File

@@ -465,7 +465,7 @@ private predicate boundedPhiInp(
exists(int d, boolean fromBackEdge0 |
boundedPhiOperand(op, b, d, upper, fromBackEdge0, origdelta, reason)
or
b.(InstructionBound).getInstruction() = op.getDefinitionInstruction() and
b.(ValueNumberBound).getInstruction() = op.getDefinitionInstruction() and
d = 0 and
(upper = true or upper = false) and
fromBackEdge0 = false and
@@ -494,7 +494,7 @@ private predicate boundedPhiInp1(
}
private predicate selfBoundedPhiInp(PhiInstruction phi, PhiOperand op, boolean upper) {
exists(int d, InstructionBound phibound |
exists(int d, ValueNumberBound phibound |
phibound.getInstruction() = phi and
boundedPhiInp(phi, op, phibound, d, upper, _, _, _) and
(