Skip to content

Commit 84c1341

Browse files
committed
C++: Support builtin expect in IRGuards.
1 parent d767004 commit 84c1341

File tree

1 file changed

+58
-0
lines changed

1 file changed

+58
-0
lines changed

cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,12 +923,68 @@ private predicate unary_simple_comparison_eq(
923923
)
924924
}
925925

926+
/** A call to the builtin operation `__builtin_expect`. */
927+
private class BuiltinExpectCallInstruction extends CallInstruction {
928+
BuiltinExpectCallInstruction() { this.getStaticCallTarget().hasName("__builtin_expect") }
929+
}
930+
931+
/**
932+
* Holds if `left == right + k` is `areEqual` if `cmp` evaluates to `value`,
933+
* and `cmp` is nested inside a call to `__builtin_expect`.
934+
*/
935+
private predicate builtin_expect_eq(
936+
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
937+
) {
938+
exists(
939+
BuiltinExpectCallInstruction call, ConvertInstruction arg, Instruction const,
940+
AbstractValue innerValue
941+
|
942+
int_value(const) = 0 and
943+
cmp.hasOperands(call.getAUse(), const.getAUse()) and
944+
arg = call.getArgument(0) and
945+
compares_eq(arg.getUnary(), left, right, k, areEqual, innerValue)
946+
|
947+
cmp instanceof CompareNEInstruction and
948+
value = innerValue
949+
or
950+
cmp instanceof CompareEQInstruction and
951+
value.getDualValue() = innerValue
952+
)
953+
}
954+
926955
private predicate complex_eq(
927956
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
928957
) {
929958
sub_eq(cmp, left, right, k, areEqual, value)
930959
or
931960
add_eq(cmp, left, right, k, areEqual, value)
961+
or
962+
builtin_expect_eq(cmp, left, right, k, areEqual, value)
963+
}
964+
965+
/**
966+
* Holds if `op == k` is `areEqual` if `cmp` evaluates to `value`, and
967+
* `cmp` is nested inside a call to `__builtin_expect`.
968+
*/
969+
private predicate unary_builtin_expect_eq(
970+
CompareInstruction cmp, Operand op, int k, boolean areEqual, boolean inNonZeroCase,
971+
AbstractValue value
972+
) {
973+
exists(
974+
BuiltinExpectCallInstruction call, ConvertInstruction arg, Instruction const,
975+
AbstractValue innerValue
976+
|
977+
int_value(const) = 0 and
978+
cmp.hasOperands(call.getAUse(), const.getAUse()) and
979+
arg = call.getArgument(0) and
980+
unary_compares_eq(arg.getUnary(), op, k, areEqual, inNonZeroCase, innerValue)
981+
|
982+
cmp instanceof CompareNEInstruction and
983+
value = innerValue
984+
or
985+
cmp instanceof CompareEQInstruction and
986+
value.getDualValue() = innerValue
987+
)
932988
}
933989

934990
private predicate unary_complex_eq(
@@ -937,6 +993,8 @@ private predicate unary_complex_eq(
937993
unary_sub_eq(test, op, k, areEqual, inNonZeroCase, value)
938994
or
939995
unary_add_eq(test, op, k, areEqual, inNonZeroCase, value)
996+
or
997+
unary_builtin_expect_eq(test, op, k, areEqual, inNonZeroCase, value)
940998
}
941999

9421000
/*

0 commit comments

Comments
 (0)