Skip to content

Commit 77c5230

Browse files
Add support for gccs __builtin_mul_overflow
Not the generic version
1 parent d33d348 commit 77c5230

File tree

3 files changed

+220
-0
lines changed

3 files changed

+220
-0
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#include <assert.h>
2+
#include <limits.h>
3+
#include <stdint.h>
4+
5+
#ifdef __CPROVER
6+
# define assume(X) __CPROVER_assume(X)
7+
#else
8+
# define assume(X) \
9+
do \
10+
{ \
11+
} while(0)
12+
#endif
13+
14+
#define A_VALUE_X_SO_THAT_X_TIMES_X_DOES_NOT_OVERFLOW(T) \
15+
(((T)(1)) << (sizeof(T) * CHAR_BIT) / 2 - 1)
16+
17+
void check_int(void)
18+
{
19+
int result;
20+
assert(!__builtin_smul_overflow(1, 1, &result));
21+
assert(result == 1);
22+
int const lt_isqrt_of_int_max =
23+
A_VALUE_X_SO_THAT_X_TIMES_X_DOES_NOT_OVERFLOW(int);
24+
assert(!__builtin_smul_overflow(
25+
lt_isqrt_of_int_max, lt_isqrt_of_int_max, &result));
26+
assert(result == lt_isqrt_of_int_max * lt_isqrt_of_int_max);
27+
assert(__builtin_smul_overflow(
28+
lt_isqrt_of_int_max << 1, lt_isqrt_of_int_max << 1, &result));
29+
assert(0 && "reachability");
30+
}
31+
32+
void check_long(void)
33+
{
34+
long result;
35+
assert(!__builtin_smull_overflow(1l, 1l, &result));
36+
assert(result == 1l);
37+
long const lt_isqrt_of_long_max =
38+
A_VALUE_X_SO_THAT_X_TIMES_X_DOES_NOT_OVERFLOW(long);
39+
assert(!__builtin_smull_overflow(
40+
lt_isqrt_of_long_max, lt_isqrt_of_long_max, &result));
41+
assert(result == lt_isqrt_of_long_max * lt_isqrt_of_long_max);
42+
assert(__builtin_smull_overflow(
43+
lt_isqrt_of_long_max << 1, lt_isqrt_of_long_max << 1, &result));
44+
assert(0 && "reachability");
45+
}
46+
47+
void check_long_long(void)
48+
{
49+
long long result;
50+
assert(!__builtin_smulll_overflow(1ll, 1ll, &result));
51+
assert(result == 1ll);
52+
long long const lt_isqrt_of_long_long_max =
53+
A_VALUE_X_SO_THAT_X_TIMES_X_DOES_NOT_OVERFLOW(long long);
54+
assert(!__builtin_smulll_overflow(
55+
lt_isqrt_of_long_long_max, lt_isqrt_of_long_long_max, &result));
56+
assert(result == lt_isqrt_of_long_long_max * lt_isqrt_of_long_long_max);
57+
assert(__builtin_smulll_overflow(
58+
lt_isqrt_of_long_long_max << 1, lt_isqrt_of_long_long_max << 1, &result));
59+
assert(0 && "reachability");
60+
}
61+
62+
void check_unsigned(void)
63+
{
64+
unsigned result;
65+
assert(!__builtin_umul_overflow(1u, 1u, &result));
66+
assert(result == 1u);
67+
unsigned const lt_isqrt_of_unsigned_max =
68+
A_VALUE_X_SO_THAT_X_TIMES_X_DOES_NOT_OVERFLOW(unsigned);
69+
assert(!__builtin_umul_overflow(
70+
lt_isqrt_of_unsigned_max, lt_isqrt_of_unsigned_max, &result));
71+
assert(result == lt_isqrt_of_unsigned_max * lt_isqrt_of_unsigned_max);
72+
assert(__builtin_umul_overflow(
73+
lt_isqrt_of_unsigned_max << 1, lt_isqrt_of_unsigned_max << 1, &result));
74+
assert(0 && "reachability");
75+
}
76+
77+
void check_unsigned_long(void)
78+
{
79+
unsigned long result;
80+
assert(!__builtin_umull_overflow(1ul, 1ul, &result));
81+
assert(result == 1ul);
82+
unsigned long const lt_isqrt_of_unsigned_long_max =
83+
A_VALUE_X_SO_THAT_X_TIMES_X_DOES_NOT_OVERFLOW(unsigned long);
84+
assert(!__builtin_umull_overflow(
85+
lt_isqrt_of_unsigned_long_max, lt_isqrt_of_unsigned_long_max, &result));
86+
assert(
87+
result == lt_isqrt_of_unsigned_long_max * lt_isqrt_of_unsigned_long_max);
88+
assert(__builtin_umull_overflow(
89+
lt_isqrt_of_unsigned_long_max << 1,
90+
lt_isqrt_of_unsigned_long_max << 1,
91+
&result));
92+
assert(0 && "reachability");
93+
}
94+
95+
void check_unsigned_long_long(void)
96+
{
97+
unsigned long long result;
98+
assert(!__builtin_umulll_overflow(1ull, 1ull, &result));
99+
assert(result == 1ull);
100+
unsigned long long const lt_isqrt_of_unsigned_long_long_max =
101+
A_VALUE_X_SO_THAT_X_TIMES_X_DOES_NOT_OVERFLOW(unsigned long long);
102+
assert(!__builtin_umulll_overflow(
103+
lt_isqrt_of_unsigned_long_long_max,
104+
lt_isqrt_of_unsigned_long_long_max,
105+
&result));
106+
assert(
107+
result ==
108+
lt_isqrt_of_unsigned_long_long_max * lt_isqrt_of_unsigned_long_long_max);
109+
assert(__builtin_umulll_overflow(
110+
lt_isqrt_of_unsigned_long_long_max << 1,
111+
lt_isqrt_of_unsigned_long_long_max << 1,
112+
&result));
113+
assert(0 && "reachability");
114+
}
115+
116+
int main(void)
117+
{
118+
check_int();
119+
check_long();
120+
check_long_long();
121+
check_unsigned();
122+
check_unsigned_long();
123+
check_unsigned_long_long();
124+
return 0;
125+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
CORE gcc-only
2+
main.c
3+
4+
\[check_int.assertion.1\] line \d+ assertion !__builtin_smul_overflow\(1, 1, &result\): SUCCESS
5+
\[check_int.assertion.2\] line \d+ assertion result == 1: SUCCESS
6+
\[check_int.assertion.3\] line \d+ assertion !__builtin_smul_overflow\( lt_isqrt_of_int_max, lt_isqrt_of_int_max, &result\): SUCCESS
7+
\[check_int.assertion.4\] line \d+ assertion result == lt_isqrt_of_int_max \* lt_isqrt_of_int_max: SUCCESS
8+
\[check_int.assertion.5\] line \d+ assertion __builtin_smul_overflow\( lt_isqrt_of_int_max << 1, lt_isqrt_of_int_max << 1, &result\): SUCCESS
9+
\[check_int.assertion.6\] line \d+ assertion 0 && "reachability": FAILURE
10+
\[check_long.assertion.1\] line \d+ assertion !__builtin_smull_overflow\(1l, 1l, &result\): SUCCESS
11+
\[check_long.assertion.2\] line \d+ assertion result == 1l: SUCCESS
12+
\[check_long.assertion.3\] line \d+ assertion !__builtin_smull_overflow\( lt_isqrt_of_long_max, lt_isqrt_of_long_max, &result\): SUCCESS
13+
\[check_long.assertion.4\] line \d+ assertion result == lt_isqrt_of_long_max \* lt_isqrt_of_long_max: SUCCESS
14+
\[check_long.assertion.5\] line \d+ assertion __builtin_smull_overflow\( lt_isqrt_of_long_max << 1, lt_isqrt_of_long_max << 1, &result\): SUCCESS
15+
\[check_long.assertion.6\] line \d+ assertion 0 && "reachability": FAILURE
16+
\[check_long_long.assertion.1\] line \d+ assertion !__builtin_smulll_overflow\(1ll, 1ll, &result\): SUCCESS
17+
\[check_long_long.assertion.2\] line \d+ assertion result == 1ll: SUCCESS
18+
\[check_long_long.assertion.3\] line \d+ assertion !__builtin_smulll_overflow\( lt_isqrt_of_long_long_max, lt_isqrt_of_long_long_max, &result\): SUCCESS
19+
\[check_long_long.assertion.4\] line \d+ assertion result == lt_isqrt_of_long_long_max \* lt_isqrt_of_long_long_max: SUCCESS
20+
\[check_long_long.assertion.5\] line \d+ assertion __builtin_smulll_overflow\( lt_isqrt_of_long_long_max << 1, lt_isqrt_of_long_long_max << 1, &result\): SUCCESS
21+
\[check_long_long.assertion.6\] line \d+ assertion 0 && "reachability": FAILURE
22+
\[check_unsigned.assertion.1\] line \d+ assertion !__builtin_umul_overflow\(1u, 1u, &result\): SUCCESS
23+
\[check_unsigned.assertion.2\] line \d+ assertion result == 1u: SUCCESS
24+
\[check_unsigned.assertion.3\] line \d+ assertion !__builtin_umul_overflow\( lt_isqrt_of_unsigned_max, lt_isqrt_of_unsigned_max, &result\): SUCCESS
25+
\[check_unsigned.assertion.4\] line \d+ assertion result == lt_isqrt_of_unsigned_max \* lt_isqrt_of_unsigned_max: SUCCESS
26+
\[check_unsigned.assertion.5\] line \d+ assertion __builtin_umul_overflow\( lt_isqrt_of_unsigned_max << 1, lt_isqrt_of_unsigned_max << 1, &result\): SUCCESS
27+
\[check_unsigned.assertion.6\] line \d+ assertion 0 && "reachability": FAILURE
28+
\[check_unsigned_long.assertion.1\] line \d+ assertion !__builtin_umull_overflow\(1ul, 1ul, &result\): SUCCESS
29+
\[check_unsigned_long.assertion.2\] line \d+ assertion result == 1ul: SUCCESS
30+
\[check_unsigned_long.assertion.3\] line \d+ assertion !__builtin_umull_overflow\( lt_isqrt_of_unsigned_long_max, lt_isqrt_of_unsigned_long_max, &result\): SUCCESS
31+
\[check_unsigned_long.assertion.4\] line \d+ assertion result == lt_isqrt_of_unsigned_long_max \* lt_isqrt_of_unsigned_long_max: SUCCESS
32+
\[check_unsigned_long.assertion.5\] line \d+ assertion __builtin_umull_overflow\( lt_isqrt_of_unsigned_long_max << 1, lt_isqrt_of_unsigned_long_max << 1, &result\): SUCCESS
33+
\[check_unsigned_long.assertion.6\] line \d+ assertion 0 && "reachability": FAILURE
34+
\[check_unsigned_long_long.assertion.1\] line \d+ assertion !__builtin_umulll_overflow\(1ull, 1ull, &result\): SUCCESS
35+
\[check_unsigned_long_long.assertion.2\] line \d+ assertion result == 1ull: SUCCESS
36+
\[check_unsigned_long_long.assertion.3\] line \d+ assertion !__builtin_umulll_overflow\( lt_isqrt_of_unsigned_long_long_max, lt_isqrt_of_unsigned_long_long_max, &result\): SUCCESS
37+
\[check_unsigned_long_long.assertion.4\] line \d+ assertion result == lt_isqrt_of_unsigned_long_long_max \* lt_isqrt_of_unsigned_long_long_max: SUCCESS
38+
\[check_unsigned_long_long.assertion.5\] line \d+ assertion __builtin_umulll_overflow\( lt_isqrt_of_unsigned_long_long_max << 1, lt_isqrt_of_unsigned_long_long_max << 1, &result\): SUCCESS
39+
\[check_unsigned_long_long.assertion.6\] line \d+ assertion 0 && "reachability": FAILURE
40+
^EXIT=10$
41+
^SIGNAL=0$

src/ansi-c/library/math.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2406,3 +2406,57 @@ _Bool __builtin_usubll_overflow(
24062406
*res = a - b;
24072407
return __CPROVER_overflow_minus(a, b);
24082408
}
2409+
2410+
/* FUNCTION: __builtin_smul_overflow */
2411+
2412+
_Bool __builtin_smul_overflow(int a, int b, int *res)
2413+
{
2414+
*res = a * b;
2415+
return __CPROVER_overflow_mult(a, b);
2416+
}
2417+
2418+
/* FUNCTION: __builtin_smull_overflow */
2419+
2420+
_Bool __builtin_smull_overflow(long a, long b, long *res)
2421+
{
2422+
*res = a * b;
2423+
return __CPROVER_overflow_mult(a, b);
2424+
}
2425+
2426+
/* FUNCTION: __builtin_smulll_overflow */
2427+
2428+
_Bool __builtin_smulll_overflow(long long a, long long b, long long *res)
2429+
{
2430+
*res = a * b;
2431+
return __CPROVER_overflow_mult(a, b);
2432+
}
2433+
2434+
/* FUNCTION: __builtin_umul_overflow */
2435+
2436+
_Bool __builtin_umul_overflow(unsigned a, unsigned b, unsigned *res)
2437+
{
2438+
*res = a * b;
2439+
return __CPROVER_overflow_mult(a, b);
2440+
}
2441+
2442+
/* FUNCTION: __builtin_umull_overflow */
2443+
2444+
_Bool __builtin_umull_overflow(
2445+
unsigned long a,
2446+
unsigned long b,
2447+
unsigned long *res)
2448+
{
2449+
*res = a * b;
2450+
return __CPROVER_overflow_mult(a, b);
2451+
}
2452+
2453+
/* FUNCTION: __builtin_umulll_overflow */
2454+
2455+
_Bool __builtin_umulll_overflow(
2456+
unsigned long long a,
2457+
unsigned long long b,
2458+
unsigned long long *res)
2459+
{
2460+
*res = a * b;
2461+
return __CPROVER_overflow_mult(a, b);
2462+
}

0 commit comments

Comments
 (0)