Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
d0026f9
C++: separate IR ValueNumber newtype and interface
Oct 9, 2019
da732d5
C++: add IR-based wrapper for value numbering
Dec 17, 2019
48cff3b
C++: Change toString predicate and add hasLocationInfo predicate on V…
MathiasVP Jan 29, 2020
de0a6d6
C++: Added getKind predicate
MathiasVP Jan 30, 2020
8fc9a71
C++: Added IR global value numbering uniqueness test
MathiasVP Jan 30, 2020
f586719
C++: Sync'd unaliased_ssa and aliased_ssa files
MathiasVP Jan 30, 2020
4b74d11
C++: Added getAnExpr predicate to ValueNumber class
MathiasVP Jan 30, 2020
c01a4b7
C++: Added getAnExpr test
MathiasVP Jan 30, 2020
6f0a521
C++: Fix incorrect merge conflict resolution
MathiasVP Jan 30, 2020
26dbf05
C#: Sync files
MathiasVP Jan 30, 2020
ea2f653
C++: Fix new formatting (hopefully)
MathiasVP Jan 30, 2020
2a7fad7
Update csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/int…
Jan 31, 2020
e2348e0
Update csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_s…
Jan 31, 2020
c70deb1
Update cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/i…
Jan 31, 2020
61d5c2a
Update cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/i…
Jan 31, 2020
9968d76
C++: Updated ir_uniqueness test based on Robert's comments (and accep…
MathiasVP Jan 31, 2020
2adc658
C++: Accepted ir_gvn output after changing toString implemenetation
MathiasVP Jan 31, 2020
8b91c2d
C++/C#: Sync identical files
MathiasVP Jan 31, 2020
46e1fbc
C++: Fix bad merge
MathiasVP Jan 31, 2020
a6dfe9d
C++: Use getDebugString instead of toString in ValueNumberPropertyPro…
MathiasVP Jan 31, 2020
50030bc
C++: Accept output
MathiasVP Jan 31, 2020
72f469a
C++: Fix new formatting
MathiasVP Jan 31, 2020
02be5fc
C++/C#: Sync identical files
MathiasVP Jan 31, 2020
0f71d83
C++: Fix new formatting
MathiasVP Jan 31, 2020
5243a6a
C++: Modify Bound.qll to use hasLocationInfo instead of getLocation o…
MathiasVP Jan 31, 2020
fba14f8
C++: Sync identical files
MathiasVP Jan 31, 2020
a4977a9
C++: Accept output. Currently too many locations are being reported d…
MathiasVP Jan 31, 2020
77b888f
C++: Fix formatting
MathiasVP Feb 3, 2020
a605fec
C++: Replace rank[1] with min
MathiasVP Feb 3, 2020
cb52388
C++: Replace implementation of hasLocationInfo with getLocation
MathiasVP Feb 3, 2020
c7617f5
C++: GVN should use getUnconverted[...] instead of getConverted[...]
MathiasVP Feb 3, 2020
b7eb23a
C++: Fix spelling
MathiasVP Feb 3, 2020
f0521dd
C++: Don't call getUnconvertedResultExpression in ValueNumbering's ge…
MathiasVP Feb 3, 2020
9cd2c23
C++: Accept test output
MathiasVP Feb 3, 2020
2ec0d72
C++: Add charpred to ASTValueNumbering class to ensure that only valu…
MathiasVP Feb 3, 2020
f5c95c8
C++: Accepted test output for test_ir_expr
MathiasVP Feb 3, 2020
ac1b19b
C++: Formatting
MathiasVP Feb 3, 2020
d06f130
C++: Fix imports
MathiasVP Feb 3, 2020
2a21627
C++/C#: Sync identical files
MathiasVP Feb 3, 2020
94a089c
Accept test output
MathiasVP Feb 3, 2020
cb9c0cf
C#: Sync identical files
MathiasVP Feb 3, 2020
3c9c2b2
C#: Move imports from ValueNumberingImports to ValueNumberingInternal…
MathiasVP Feb 4, 2020
0bb900c
Add a getAConvertedExpr predicate for obtaining converted expressions…
MathiasVP Feb 4, 2020
b690e14
C#: Fix import
MathiasVP Feb 4, 2020
19b68fe
C++/C#: Sync identical files
MathiasVP Feb 4, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion config/identical-files.json
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,12 @@
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/PrintSSA.qll",
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll"
],
"IR ValueNumber": [
"C++ IR ValueNumberInternal": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingInternal.qll"
],
"C++ IR ValueNumber": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/ValueNumbering.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
private import internal.ValueNumberingInternal
private import internal.ValueNumberingImports
private import IR

/**
* Provides additional information about value numbering in IR dumps.
Expand All @@ -10,57 +9,34 @@ class ValueNumberPropertyProvider extends IRPropertyProvider {
exists(ValueNumber vn |
vn = valueNumber(instr) and
key = "valnum" and
if strictcount(vn.getAnInstruction()) > 1 then result = vn.toString() else result = "unique"
if strictcount(vn.getAnInstruction()) > 1
then result = vn.getDebugString()
else result = "unique"
)
}
}

newtype TValueNumber =
TVariableAddressValueNumber(IRFunction irFunc, IRVariable var) {
variableAddressValueNumber(_, irFunc, var)
} or
TInitializeParameterValueNumber(IRFunction irFunc, IRVariable var) {
initializeParameterValueNumber(_, irFunc, var)
} or
TInitializeThisValueNumber(IRFunction irFunc) { initializeThisValueNumber(_, irFunc) } or
TConstantValueNumber(IRFunction irFunc, IRType type, string value) {
constantValueNumber(_, irFunc, type, value)
} or
TStringConstantValueNumber(IRFunction irFunc, IRType type, string value) {
stringConstantValueNumber(_, irFunc, type, value)
} or
TFieldAddressValueNumber(IRFunction irFunc, Language::Field field, ValueNumber objectAddress) {
fieldAddressValueNumber(_, irFunc, field, objectAddress)
} or
TBinaryValueNumber(
IRFunction irFunc, Opcode opcode, IRType type, ValueNumber leftOperand, ValueNumber rightOperand
) {
binaryValueNumber(_, irFunc, opcode, type, leftOperand, rightOperand)
} or
TPointerArithmeticValueNumber(
IRFunction irFunc, Opcode opcode, IRType type, int elementSize, ValueNumber leftOperand,
ValueNumber rightOperand
) {
pointerArithmeticValueNumber(_, irFunc, opcode, type, elementSize, leftOperand, rightOperand)
} or
TUnaryValueNumber(IRFunction irFunc, Opcode opcode, IRType type, ValueNumber operand) {
unaryValueNumber(_, irFunc, opcode, type, operand)
} or
TInheritanceConversionValueNumber(
IRFunction irFunc, Opcode opcode, Language::Class baseClass, Language::Class derivedClass,
ValueNumber operand
) {
inheritanceConversionValueNumber(_, irFunc, opcode, baseClass, derivedClass, operand)
} or
TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) }

/**
* The value number assigned to a particular set of instructions that produce equivalent results.
*/
class ValueNumber extends TValueNumber {
final string toString() { result = getExampleInstruction().getResultId() }
final string toString() { result = "GVN" }

final Language::Location getLocation() { result = getExampleInstruction().getLocation() }
final Language::Location getLocation() {
result =
min(Language::Location l |
l = getAnInstruction().getLocation()
|
l
order by
l.getFile().getAbsolutePath(), l.getStartLine(), l.getStartColumn(), l.getEndLine(),
l.getEndColumn()
)
}

final string getDebugString() {
result = "ValueNumber: " + strictconcat(this.getAnInstruction().getResultId(), ", ")
}

/**
* Gets the instructions that have been assigned this value number. This will always produce at
Expand All @@ -85,236 +61,45 @@ class ValueNumber extends TValueNumber {
* Gets an `Operand` whose definition is exact and has this value number.
*/
final Operand getAUse() { this = valueNumber(result.getDef()) }
}

/**
* A `CopyInstruction` whose source operand's value is congruent to the definition of that source
* operand.
* For example:
* ```
* Point p = { 1, 2 };
* Point q = p;
* int a = p.x;
* ```
* The use of `p` on line 2 is linked to the definition of `p` on line 1, and is congruent to that
* definition because it accesses the exact same memory.
* The use of `p.x` on line 3 is linked to the definition of `p` on line 1 as well, but is not
* congruent to that definition because `p.x` accesses only a subset of the memory defined by `p`.
*/
private class CongruentCopyInstruction extends CopyInstruction {
CongruentCopyInstruction() {
this.getSourceValueOperand().getDefinitionOverlap() instanceof MustExactlyOverlap
final string getKind() {
this instanceof TVariableAddressValueNumber and result = "VariableAddress"
or
this instanceof TInitializeParameterValueNumber and result = "InitializeParameter"
or
this instanceof TInitializeThisValueNumber and result = "InitializeThis"
or
this instanceof TStringConstantValueNumber and result = "StringConstant"
or
this instanceof TFieldAddressValueNumber and result = "FieldAddress"
or
this instanceof TBinaryValueNumber and result = "Binary"
or
this instanceof TPointerArithmeticValueNumber and result = "PointerArithmetic"
or
this instanceof TUnaryValueNumber and result = "Unary"
or
this instanceof TInheritanceConversionValueNumber and result = "InheritanceConversion"
or
this instanceof TUniqueValueNumber and result = "Unique"
}
}

/**
* Holds if this library knows how to assign a value number to the specified instruction, other than
* a `unique` value number that is never shared by multiple instructions.
*/
private predicate numberableInstruction(Instruction instr) {
instr instanceof VariableAddressInstruction
or
instr instanceof InitializeParameterInstruction
or
instr instanceof InitializeThisInstruction
or
instr instanceof ConstantInstruction
or
instr instanceof StringConstantInstruction
or
instr instanceof FieldAddressInstruction
or
instr instanceof BinaryInstruction
or
instr instanceof UnaryInstruction and not instr instanceof CopyInstruction
or
instr instanceof PointerArithmeticInstruction
or
instr instanceof CongruentCopyInstruction
}
Language::Expr getAnExpr() { result = getAnUnconvertedExpr() }

private predicate variableAddressValueNumber(
VariableAddressInstruction instr, IRFunction irFunc, IRVariable var
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getIRVariable() = var
}

private predicate initializeParameterValueNumber(
InitializeParameterInstruction instr, IRFunction irFunc, IRVariable var
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getIRVariable() = var
}

private predicate initializeThisValueNumber(InitializeThisInstruction instr, IRFunction irFunc) {
instr.getEnclosingIRFunction() = irFunc
}

private predicate constantValueNumber(
ConstantInstruction instr, IRFunction irFunc, IRType type, string value
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getResultIRType() = type and
instr.getValue() = value
}

private predicate stringConstantValueNumber(
StringConstantInstruction instr, IRFunction irFunc, IRType type, string value
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getResultIRType() = type and
instr.getValue().getValue() = value
}

private predicate fieldAddressValueNumber(
FieldAddressInstruction instr, IRFunction irFunc, Language::Field field, ValueNumber objectAddress
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getField() = field and
valueNumber(instr.getObjectAddress()) = objectAddress
}

private predicate binaryValueNumber(
BinaryInstruction instr, IRFunction irFunc, Opcode opcode, IRType type, ValueNumber leftOperand,
ValueNumber rightOperand
) {
instr.getEnclosingIRFunction() = irFunc and
not instr instanceof PointerArithmeticInstruction and
instr.getOpcode() = opcode and
instr.getResultIRType() = type and
valueNumber(instr.getLeft()) = leftOperand and
valueNumber(instr.getRight()) = rightOperand
}

private predicate pointerArithmeticValueNumber(
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, IRType type,
int elementSize, ValueNumber leftOperand, ValueNumber rightOperand
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getOpcode() = opcode and
instr.getResultIRType() = type and
instr.getElementSize() = elementSize and
valueNumber(instr.getLeft()) = leftOperand and
valueNumber(instr.getRight()) = rightOperand
}

private predicate unaryValueNumber(
UnaryInstruction instr, IRFunction irFunc, Opcode opcode, IRType type, ValueNumber operand
) {
instr.getEnclosingIRFunction() = irFunc and
not instr instanceof InheritanceConversionInstruction and
not instr instanceof CopyInstruction and
instr.getOpcode() = opcode and
instr.getResultIRType() = type and
valueNumber(instr.getUnary()) = operand
}
Language::Expr getAnUnconvertedExpr() {
result = getAnInstruction().getUnconvertedResultExpression()
}

private predicate inheritanceConversionValueNumber(
InheritanceConversionInstruction instr, IRFunction irFunc, Opcode opcode,
Language::Class baseClass, Language::Class derivedClass, ValueNumber operand
) {
instr.getEnclosingIRFunction() = irFunc and
instr.getOpcode() = opcode and
instr.getBaseClass() = baseClass and
instr.getDerivedClass() = derivedClass and
valueNumber(instr.getUnary()) = operand
}

/**
* Holds if `instr` should be assigned a unique value number because this library does not know how
* to determine if two instances of that instruction are equivalent.
*/
private predicate uniqueValueNumber(Instruction instr, IRFunction irFunc) {
instr.getEnclosingIRFunction() = irFunc and
not instr.getResultIRType() instanceof IRVoidType and
not numberableInstruction(instr)
Language::Expr getAConvertedExpr() { result = getAnInstruction().getConvertedResultExpression() }
}

/**
* Gets the value number assigned to `instr`, if any. Returns at most one result.
*/
cached
ValueNumber valueNumber(Instruction instr) {
result = nonUniqueValueNumber(instr)
or
exists(IRFunction irFunc |
uniqueValueNumber(instr, irFunc) and
result = TUniqueValueNumber(irFunc, instr)
)
}
ValueNumber valueNumber(Instruction instr) { result = tvalueNumber(instr) }

/**
* 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.getDef()) }

/**
* Gets the value number assigned to `instr`, if any, unless that instruction is assigned a unique
* value number.
*/
private ValueNumber nonUniqueValueNumber(Instruction instr) {
exists(IRFunction irFunc |
irFunc = instr.getEnclosingIRFunction() and
(
exists(IRVariable var |
variableAddressValueNumber(instr, irFunc, var) and
result = TVariableAddressValueNumber(irFunc, var)
)
or
exists(IRVariable var |
initializeParameterValueNumber(instr, irFunc, var) and
result = TInitializeParameterValueNumber(irFunc, var)
)
or
initializeThisValueNumber(instr, irFunc) and
result = TInitializeThisValueNumber(irFunc)
or
exists(IRType type, string value |
constantValueNumber(instr, irFunc, type, value) and
result = TConstantValueNumber(irFunc, type, value)
)
or
exists(IRType type, string value |
stringConstantValueNumber(instr, irFunc, type, value) and
result = TStringConstantValueNumber(irFunc, type, value)
)
or
exists(Language::Field field, ValueNumber objectAddress |
fieldAddressValueNumber(instr, irFunc, field, objectAddress) and
result = TFieldAddressValueNumber(irFunc, field, objectAddress)
)
or
exists(Opcode opcode, IRType type, ValueNumber leftOperand, ValueNumber rightOperand |
binaryValueNumber(instr, irFunc, opcode, type, leftOperand, rightOperand) and
result = TBinaryValueNumber(irFunc, opcode, type, leftOperand, rightOperand)
)
or
exists(Opcode opcode, IRType type, ValueNumber operand |
unaryValueNumber(instr, irFunc, opcode, type, operand) and
result = TUnaryValueNumber(irFunc, opcode, type, operand)
)
or
exists(
Opcode opcode, Language::Class baseClass, Language::Class derivedClass, ValueNumber operand
|
inheritanceConversionValueNumber(instr, irFunc, opcode, baseClass, derivedClass, operand) and
result = TInheritanceConversionValueNumber(irFunc, opcode, baseClass, derivedClass, operand)
)
or
exists(
Opcode opcode, IRType type, int elementSize, ValueNumber leftOperand,
ValueNumber rightOperand
|
pointerArithmeticValueNumber(instr, irFunc, opcode, type, elementSize, leftOperand,
rightOperand) and
result =
TPointerArithmeticValueNumber(irFunc, opcode, type, elementSize, leftOperand, rightOperand)
)
or
// The value number of a copy is just the value number of its source value.
result = valueNumber(instr.(CongruentCopyInstruction).getSourceValue())
)
)
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
import semmle.code.cpp.ir.implementation.aliased_ssa.IR
import semmle.code.cpp.ir.internal.Overlap
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
Loading