Skip to content

Commit 690b7ef

Browse files
committed
QL: QL: Add a basic GVN library.
1 parent 4795cbb commit 690b7ef

1 file changed

Lines changed: 136 additions & 0 deletions

File tree

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
private import ql
2+
private import codeql_ql.ast.internal.Predicate
3+
private import codeql_ql.ast.internal.Type
4+
private import codeql_ql.ast.internal.Builtins
5+
6+
private newtype TValueNumber =
7+
TVariableValueNumber(VarDecl var) { variableAccessValueNumber(_, var) } or
8+
TPredicateValueNumber(PredicateOrBuiltin pred, ValueNumberList args) {
9+
predicateCallValueNumber(_, pred, args)
10+
} or
11+
TLiteralValueNumber(string value, Type t) { literalValueNumber(_, value, t) } or
12+
TBinaryOpValueNumber(FunctionSymbol symbol, ValueNumber leftOperand, ValueNumber rightOperand) {
13+
binaryOperandValueNumber(_, symbol, leftOperand, rightOperand)
14+
} or
15+
TUnaryOpValueNumber(FunctionSymbol symbol, ValueNumber operand) {
16+
unaryOperandValueNumber(_, symbol, operand)
17+
} or
18+
TUniqueValueNumber(Expr e) { uniqueValueNumber(e) }
19+
20+
private newtype ValueNumberList =
21+
MkNil() or
22+
MkCons(ValueNumber head, ValueNumberList tail) { globalValueNumbers(_, _, head, tail) }
23+
24+
private ValueNumberList globalValueNumbers(Call call, int start) {
25+
start = call.getNumberOfArguments() and
26+
result = MkNil()
27+
or
28+
exists(ValueNumber head, ValueNumberList tail |
29+
globalValueNumbers(call, start, head, tail) and
30+
result = MkCons(head, tail)
31+
)
32+
}
33+
34+
private predicate globalValueNumbers(Call call, int start, ValueNumber head, ValueNumberList tail) {
35+
head = valueNumber(call.getArgument(start)) and
36+
tail = globalValueNumbers(call, start + 1)
37+
}
38+
39+
/**
40+
* A value number. A value number represents a collection of expressions that compute to the same value
41+
* at runtime.
42+
*/
43+
class ValueNumber extends TValueNumber {
44+
string toString() { result = "GVN" }
45+
46+
/** Gets an expression that has this value number. */
47+
final Expr getAnExpr() { this = valueNumber(result) }
48+
}
49+
50+
private predicate uniqueValueNumber(Expr e) { not numberable(e) }
51+
52+
private predicate numberable(Expr e) {
53+
e instanceof VarAccess or
54+
e instanceof Call or
55+
e instanceof Literal or
56+
e instanceof BinOpExpr or
57+
e instanceof UnaryExpr
58+
}
59+
60+
private predicate variableAccessValueNumber(VarAccess access, VarDecl var) {
61+
access.getDeclaration() = var
62+
}
63+
64+
private predicate predicateCallValueNumber(Call call, PredicateOrBuiltin pred, ValueNumberList args) {
65+
exists(pred.getReturnType()) and
66+
call.getTarget() = pred and
67+
args = globalValueNumbers(call, 0)
68+
}
69+
70+
private predicate literalValueNumber(Literal lit, string value, Type t) {
71+
lit.(String).getValue() = value and
72+
t instanceof StringClass
73+
or
74+
lit.(Integer).getValue().toString() = value and
75+
t instanceof IntClass
76+
or
77+
lit.(Float).getValue().toString() = value and
78+
t instanceof FloatClass
79+
or
80+
lit.(Boolean).isFalse() and
81+
value = "false" and
82+
t instanceof BooleanClass
83+
or
84+
lit.(Boolean).isTrue() and
85+
value = "true" and
86+
t instanceof BooleanClass
87+
}
88+
89+
private predicate binaryOperandValueNumber(
90+
BinOpExpr e, FunctionSymbol symbol, ValueNumber leftOperand, ValueNumber rightOperand
91+
) {
92+
e.getOperator() = symbol and
93+
valueNumber(e.getLeftOperand()) = leftOperand and
94+
valueNumber(e.getRightOperand()) = rightOperand
95+
}
96+
97+
private predicate unaryOperandValueNumber(UnaryExpr e, FunctionSymbol symbol, ValueNumber operand) {
98+
e.getOperator() = symbol and
99+
valueNumber(e.getOperand()) = operand
100+
}
101+
102+
private TValueNumber nonUniqueValueNumber(Expr e) {
103+
exists(VarDecl var |
104+
variableAccessValueNumber(e, var) and
105+
result = TVariableValueNumber(var)
106+
)
107+
or
108+
exists(PredicateOrBuiltin pred, ValueNumberList args |
109+
predicateCallValueNumber(e, pred, args) and
110+
result = TPredicateValueNumber(pred, args)
111+
)
112+
or
113+
exists(string value, Type t |
114+
literalValueNumber(e, value, t) and
115+
result = TLiteralValueNumber(value, t)
116+
)
117+
or
118+
exists(FunctionSymbol symbol, ValueNumber leftOperand, ValueNumber rightOperand |
119+
binaryOperandValueNumber(e, symbol, leftOperand, rightOperand) and
120+
result = TBinaryOpValueNumber(symbol, leftOperand, rightOperand)
121+
)
122+
or
123+
exists(FunctionSymbol symbol, ValueNumber operand |
124+
unaryOperandValueNumber(e, symbol, operand) and
125+
result = TUnaryOpValueNumber(symbol, operand)
126+
)
127+
}
128+
129+
/** Gets the value number of an expression `e`. */
130+
cached
131+
TValueNumber valueNumber(Expr e) {
132+
result = nonUniqueValueNumber(e)
133+
or
134+
uniqueValueNumber(e) and
135+
result = TUniqueValueNumber(e)
136+
}

0 commit comments

Comments
 (0)