1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
#ifndef GU_BITS_H_
#define GU_BITS_H_
#include <gu/defs.h>
#include <gu/assert.h>
#define GU_WORD_BITS (sizeof(GuWord) * CHAR_BIT)
/*
* Based on the Bit Twiddling Hacks collection by Sean Eron Anderson
* <http://graphics.stanford.edu/~seander/bithacks.html>
*/
unsigned gu_ceil2e(unsigned i);
static inline int
gu_sign(int i) {
return (i > 0) - (i < 0);
}
static inline size_t
gu_ceildiv(size_t size, size_t div)
{
return (size + div - 1) / div;
}
static inline bool
gu_aligned(uintptr_t addr, size_t alignment)
{
gu_require(alignment == gu_ceil2e(alignment));
return (addr & (alignment - 1)) == 0;
}
static inline uintptr_t
gu_align_forward(uintptr_t addr, size_t alignment) {
gu_require(alignment == gu_ceil2e(alignment));
uintptr_t mask = alignment - 1;
return (addr + mask) & ~mask;
}
static inline uintptr_t
gu_align_backward(uintptr_t addr, size_t alignment) {
gu_require(alignment == gu_ceil2e(alignment));
return addr & ~(alignment - 1);
}
static inline bool
gu_bits_test(const GuWord* bitmap, int idx) {
return !!(bitmap[idx / GU_WORD_BITS] & 1 << (idx % GU_WORD_BITS));
}
static inline void
gu_bits_set(GuWord* bitmap, int idx) {
bitmap[idx / GU_WORD_BITS] |= ((GuWord) 1) << (idx % GU_WORD_BITS);
}
static inline void
gu_bits_clear(GuWord* bitmap, int idx) {
bitmap[idx / GU_WORD_BITS] &= ~(((GuWord) 1) << (idx % GU_WORD_BITS));
}
static inline size_t
gu_bits_size(size_t n_bits) {
return gu_ceildiv(n_bits, GU_WORD_BITS) * sizeof(GuWord);
}
static inline void*
gu_word_ptr(GuWord w)
{
return (void*) w;
}
static inline GuWord
gu_ptr_word(void* p)
{
return (GuWord) p;
}
#define GuOpaque() struct { GuWord w_; }
typedef GuWord GuTagged;
#define GU_TAG_MAX (sizeof(GuWord) - 1)
static inline size_t
gu_tagged_tag(GuTagged t) {
return (int) (t & (sizeof(GuWord) - 1));
}
static inline void*
gu_tagged_ptr(GuTagged w) {
return (void*) gu_align_backward(w, sizeof(GuWord));
}
static inline GuTagged
gu_tagged(void* ptr, size_t tag) {
gu_require(tag < sizeof(GuWord));
uintptr_t u = (uintptr_t) ptr;
gu_require(gu_align_backward(u, sizeof(GuWord)) == u);
return (GuWord) { u | tag };
}
#include <gu/exn.h>
#include <gu/type.h>
extern GU_DECLARE_TYPE(GuIntDecodeExn, abstract);
#define GU_DECODE_2C_(u_, t_, umax_, posmax_, tmin_, err_) \
(((u_) <= (posmax_)) \
? (t_) (u_) \
: (tmin_) + ((t_) ((umax_) - (u_))) < 0 \
? (t_) (-1 - ((t_) ((umax_) - (u_)))) \
: (t_) (gu_raise(err_, GuIntDecodeExn), -1))
static inline int8_t
gu_decode_2c8(uint8_t u, GuExn* err)
{
return GU_DECODE_2C_(u, int8_t, UINT8_C(0xff),
UINT8_C(0x7f), INT8_MIN, err);
}
static inline int16_t
gu_decode_2c16(uint16_t u, GuExn* err)
{
return GU_DECODE_2C_(u, int16_t, UINT16_C(0xffff),
UINT16_C(0x7fff), INT16_MIN, err);
}
static inline int32_t
gu_decode_2c32(uint32_t u, GuExn* err)
{
return GU_DECODE_2C_(u, int32_t, UINT32_C(0xffffffff),
UINT32_C(0x7fffffff), INT32_MIN, err);
}
static inline int64_t
gu_decode_2c64(uint64_t u, GuExn* err)
{
return GU_DECODE_2C_(u, int64_t, UINT64_C(0xffffffffffffffff),
UINT64_C(0x7fffffffffffffff), INT64_MIN, err);
}
double
gu_decode_double(uint64_t u);
#endif // GU_BITS_H_
|