Skip to content

Commit 3e3e857

Browse files
committed
clang __builtin_rotateleftX/__builtin_rotaterightX
This adds clang's rotate builtins.
1 parent ead32e8 commit 3e3e857

File tree

4 files changed

+147
-0
lines changed

4 files changed

+147
-0
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

0 commit comments

Comments
 (0)