Skip to content

Commit 6bc4e78

Browse files
authored
Merge pull request #5739 from diffblue/rolror
rol and ror expressions
2 parents 2311e90 + 3e3e857 commit 6bc4e78

File tree

6 files changed

+190
-3
lines changed

6 files changed

+190
-3
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#include <assert.h>
2+
#include <limits.h>
3+
#include <stdint.h>
4+
5+
#define rol(type, x, d) \
6+
((type)(((x) << (d)) | ((x) >> ((8 * sizeof(type)) - (d)))))
7+
8+
#define ror(type, x, d) \
9+
((type)(((x) >> (d)) | ((x) << ((8 * sizeof(type)) - (d)))))
10+
11+
#ifdef __clang__
12+
void check_left8(void)
13+
{
14+
uint8_t op;
15+
assert(__builtin_rotateleft8(op, 1) == rol(uint8_t, op, 1));
16+
assert(__builtin_rotateleft8(op, 2) == rol(uint8_t, op, 2));
17+
assert(__builtin_rotateleft8(op, 3) == rol(uint8_t, op, 3));
18+
assert(__builtin_rotateleft8(op, 4) == rol(uint8_t, op, 4));
19+
}
20+
21+
void check_left16(void)
22+
{
23+
uint16_t op;
24+
assert(__builtin_rotateleft16(op, 1) == rol(uint16_t, op, 1));
25+
assert(__builtin_rotateleft16(op, 2) == rol(uint16_t, op, 2));
26+
assert(__builtin_rotateleft16(op, 3) == rol(uint16_t, op, 3));
27+
assert(__builtin_rotateleft16(op, 4) == rol(uint16_t, op, 4));
28+
}
29+
30+
void check_left32(void)
31+
{
32+
uint32_t op;
33+
assert(__builtin_rotateleft32(op, 1) == rol(uint32_t, op, 1));
34+
assert(__builtin_rotateleft32(op, 2) == rol(uint32_t, op, 2));
35+
assert(__builtin_rotateleft32(op, 3) == rol(uint32_t, op, 3));
36+
assert(__builtin_rotateleft32(op, 4) == rol(uint32_t, op, 4));
37+
}
38+
39+
void check_left64(void)
40+
{
41+
uint64_t op;
42+
assert(__builtin_rotateleft64(op, 1) == rol(uint64_t, op, 1));
43+
assert(__builtin_rotateleft64(op, 2) == rol(uint64_t, op, 2));
44+
assert(__builtin_rotateleft64(op, 3) == rol(uint64_t, op, 3));
45+
assert(__builtin_rotateleft64(op, 4) == rol(uint64_t, op, 4));
46+
}
47+
48+
void check_right8(void)
49+
{
50+
uint8_t op;
51+
assert(__builtin_rotateright8(op, 1) == ror(uint8_t, op, 1));
52+
assert(__builtin_rotateright8(op, 2) == ror(uint8_t, op, 2));
53+
assert(__builtin_rotateright8(op, 3) == ror(uint8_t, op, 3));
54+
assert(__builtin_rotateright8(op, 4) == ror(uint8_t, op, 4));
55+
}
56+
57+
void check_right16(void)
58+
{
59+
uint16_t op;
60+
assert(__builtin_rotateright16(op, 1) == ror(uint16_t, op, 1));
61+
assert(__builtin_rotateright16(op, 2) == ror(uint16_t, op, 2));
62+
assert(__builtin_rotateright16(op, 3) == ror(uint16_t, op, 3));
63+
assert(__builtin_rotateright16(op, 4) == ror(uint16_t, op, 4));
64+
}
65+
66+
void check_right32(void)
67+
{
68+
uint32_t op;
69+
assert(__builtin_rotateright32(op, 1) == ror(uint32_t, op, 1));
70+
assert(__builtin_rotateright32(op, 2) == ror(uint32_t, op, 2));
71+
assert(__builtin_rotateright32(op, 3) == ror(uint32_t, op, 3));
72+
assert(__builtin_rotateright32(op, 4) == ror(uint32_t, op, 4));
73+
}
74+
75+
void check_right64(void)
76+
{
77+
uint64_t op;
78+
assert(__builtin_rotateright64(op, 1) == ror(uint64_t, op, 1));
79+
assert(__builtin_rotateright64(op, 2) == ror(uint64_t, op, 2));
80+
assert(__builtin_rotateright64(op, 3) == ror(uint64_t, op, 3));
81+
assert(__builtin_rotateright64(op, 4) == ror(uint64_t, op, 4));
82+
}
83+
#endif
84+
85+
int main(void)
86+
{
87+
#ifdef __clang__
88+
check_left8();
89+
check_left16();
90+
check_left32();
91+
check_left64();
92+
check_right8();
93+
check_right16();
94+
check_right32();
95+
check_right64();
96+
#endif
97+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CORE gcc-only
2+
rotate.c
3+
4+
^VERIFICATION SUCCESSFUL$
5+
^EXIT=0$
6+
^SIGNAL=0$

src/ansi-c/c_typecheck_expr.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2314,6 +2314,38 @@ exprt c_typecheck_baset::do_special_functions(
23142314

23152315
return std::move(bswap_expr);
23162316
}
2317+
else if(
2318+
identifier == "__builtin_rotateleft8" ||
2319+
identifier == "__builtin_rotateleft16" ||
2320+
identifier == "__builtin_rotateleft32" ||
2321+
identifier == "__builtin_rotateleft64" ||
2322+
identifier == "__builtin_rotateright8" ||
2323+
identifier == "__builtin_rotateright16" ||
2324+
identifier == "__builtin_rotateright32" ||
2325+
identifier == "__builtin_rotateright64")
2326+
{
2327+
// clang only
2328+
if(expr.arguments().size() != 2)
2329+
{
2330+
error().source_location = f_op.source_location();
2331+
error() << identifier << " expects two operands" << eom;
2332+
throw 0;
2333+
}
2334+
2335+
typecheck_function_call_arguments(expr);
2336+
2337+
irep_idt id = (identifier == "__builtin_rotateleft8" ||
2338+
identifier == "__builtin_rotateleft16" ||
2339+
identifier == "__builtin_rotateleft32" ||
2340+
identifier == "__builtin_rotateleft64")
2341+
? ID_rol
2342+
: ID_ror;
2343+
2344+
shift_exprt rotate_expr(expr.arguments()[0], id, expr.arguments()[1]);
2345+
rotate_expr.add_source_location() = source_location;
2346+
2347+
return std::move(rotate_expr);
2348+
}
23172349
else if(identifier=="__builtin_nontemporal_load")
23182350
{
23192351
if(expr.arguments().size()!=1)

src/ansi-c/clang_builtin_headers.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,15 @@ void __builtin_nontemporal_store();
88
void __builtin_nontemporal_load();
99

1010
int __builtin_flt_rounds(void);
11+
12+
// clang-format off
13+
unsigned char __builtin_rotateleft8(unsigned char, unsigned char);
14+
unsigned short __builtin_rotateleft16(unsigned short, unsigned short);
15+
unsigned int __builtin_rotateleft32(unsigned int, unsigned int);
16+
unsigned long long __builtin_rotateleft64(unsigned long long, unsigned long long);
17+
18+
unsigned char __builtin_rotateright8(unsigned char, unsigned char);
19+
unsigned short __builtin_rotateright16(unsigned short, unsigned short);
20+
unsigned int __builtin_rotateright32(unsigned int, unsigned int);
21+
unsigned long long __builtin_rotateright64(unsigned long long, unsigned long long);
22+
// clang-format on

src/solvers/smt2/smt2_conv.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,46 @@ void smt2_convt::convert_expr(const exprt &expr)
13621362
"unsupported type for " + shift_expr.id_string() + ": " +
13631363
type.id_string());
13641364
}
1365+
else if(expr.id() == ID_rol || expr.id() == ID_ror)
1366+
{
1367+
const shift_exprt &shift_expr = to_shift_expr(expr);
1368+
const typet &type = shift_expr.type();
1369+
1370+
if(
1371+
type.id() == ID_unsignedbv || type.id() == ID_signedbv ||
1372+
type.id() == ID_bv)
1373+
{
1374+
// SMT-LIB offers rotate_left and rotate_right, but these require a
1375+
// constant distance.
1376+
if(shift_expr.id() == ID_rol)
1377+
out << "((_ rotate_left";
1378+
else if(shift_expr.id() == ID_ror)
1379+
out << "((_ rotate_right";
1380+
else
1381+
UNREACHABLE;
1382+
1383+
out << ' ';
1384+
1385+
auto distance_int_op = numeric_cast<mp_integer>(shift_expr.distance());
1386+
1387+
if(distance_int_op.has_value())
1388+
{
1389+
out << distance_int_op.value();
1390+
}
1391+
else
1392+
UNEXPECTEDCASE(
1393+
"distance type for " + shift_expr.id_string() + "must be constant");
1394+
1395+
out << ") ";
1396+
convert_expr(shift_expr.op());
1397+
1398+
out << ")"; // rotate_*
1399+
}
1400+
else
1401+
UNEXPECTEDCASE(
1402+
"unsupported type for " + shift_expr.id_string() + ": " +
1403+
type.id_string());
1404+
}
13651405
else if(expr.id()==ID_with)
13661406
{
13671407
convert_with(to_with_expr(expr));

src/util/std_expr.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2503,8 +2503,7 @@ inline bitand_exprt &to_bitand_expr(exprt &expr)
25032503
return static_cast<bitand_exprt &>(expr);
25042504
}
25052505

2506-
2507-
/// \brief A base class for shift operators
2506+
/// \brief A base class for shift and rotate operators
25082507
class shift_exprt:public binary_exprt
25092508
{
25102509
public:
@@ -2539,7 +2538,8 @@ class shift_exprt:public binary_exprt
25392538
template <>
25402539
inline bool can_cast_expr<shift_exprt>(const exprt &base)
25412540
{
2542-
return base.id() == ID_shl || base.id() == ID_ashr || base.id() == ID_lshr;
2541+
return base.id() == ID_shl || base.id() == ID_ashr || base.id() == ID_lshr ||
2542+
base.id() == ID_ror || base.id() == ID_rol;
25432543
}
25442544

25452545
inline void validate_expr(const shift_exprt &value)

0 commit comments

Comments
 (0)