Skip to content

Commit 3512829

Browse files
committed
Fixes cutils.h for MSVC
Signed-off-by: Yonggang Luo <[email protected]>
1 parent b5e6289 commit 3512829

File tree

1 file changed

+85
-2
lines changed

1 file changed

+85
-2
lines changed

cutils.h

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,32 @@
2828
#include <stdlib.h>
2929
#include <inttypes.h>
3030

31+
#ifdef _MSC_VER
32+
#include <intrin.h>
33+
#include <malloc.h>
34+
#else
35+
#include <alloca.h>
36+
#endif
37+
3138
/* set if CPU is big endian */
3239
#undef WORDS_BIGENDIAN
3340

41+
#if defined(_MSC_VER)
42+
#define likely(x) (x)
43+
#define unlikely(x) (x)
44+
#define force_inline __forceinline
45+
#define no_inline __declspec(noinline)
46+
#define __maybe_unused
47+
#define __attribute__(x)
48+
#define __attribute(x)
49+
typedef intptr_t ssize_t;
50+
#else
3451
#define likely(x) __builtin_expect(!!(x), 1)
3552
#define unlikely(x) __builtin_expect(!!(x), 0)
3653
#define force_inline inline __attribute__((always_inline))
3754
#define no_inline __attribute__((noinline))
3855
#define __maybe_unused __attribute__((unused))
56+
#endif
3957

4058
#define xglue(x, y) x ## y
4159
#define glue(x, y) xglue(x, y)
@@ -114,27 +132,91 @@ static inline int64_t min_int64(int64_t a, int64_t b)
114132
/* WARNING: undefined if a = 0 */
115133
static inline int clz32(unsigned int a)
116134
{
135+
#ifdef _MSC_VER
136+
unsigned long idx;
137+
_BitScanReverse(&idx, a);
138+
return 31 ^ idx;
139+
#else
117140
return __builtin_clz(a);
141+
#endif
118142
}
119143

120144
/* WARNING: undefined if a = 0 */
121145
static inline int clz64(uint64_t a)
122146
{
123-
return __builtin_clzll(a);
147+
#ifdef _MSC_VER
148+
unsigned long where;
149+
// BitScanReverse scans from MSB to LSB for first set bit.
150+
// Returns 0 if no set bit is found.
151+
#if INTPTR_MAX >= INT64_MAX // 64-bit
152+
if (_BitScanReverse64(&where, a))
153+
return (int)(63 - where);
154+
#else
155+
// Scan the high 32 bits.
156+
if (_BitScanReverse(&where, (uint32_t)(a >> 32)))
157+
return (int)(63 - (where + 32)); // Create a bit offset from the MSB.
158+
// Scan the low 32 bits.
159+
if (_BitScanReverse(&where, (uint32_t)(a)))
160+
return (int)(63 - where);
161+
#endif
162+
return 64; // Undefined Behavior.
163+
#else
164+
return __builtin_clzll(a);
165+
#endif
124166
}
125167

126168
/* WARNING: undefined if a = 0 */
127169
static inline int ctz32(unsigned int a)
128170
{
171+
#ifdef _MSC_VER
172+
unsigned long idx;
173+
_BitScanForward(&idx, a);
174+
return idx;
175+
#else
129176
return __builtin_ctz(a);
177+
#endif
130178
}
131179

132180
/* WARNING: undefined if a = 0 */
133181
static inline int ctz64(uint64_t a)
134182
{
135-
return __builtin_ctzll(a);
183+
#ifdef _MSC_VER
184+
unsigned long where;
185+
// Search from LSB to MSB for first set bit.
186+
// Returns zero if no set bit is found.
187+
#if INTPTR_MAX >= INT64_MAX // 64-bit
188+
if (_BitScanForward64(&where, a))
189+
return (int)(where);
190+
#else
191+
// Win32 doesn't have _BitScanForward64 so emulate it with two 32 bit calls.
192+
// Scan the Low Word.
193+
if (_BitScanForward(&where, (uint32_t)(a)))
194+
return (int)(where);
195+
// Scan the High Word.
196+
if (_BitScanForward(&where, (uint32_t)(a >> 32)))
197+
return (int)(where + 32); // Create a bit offset from the LSB.
198+
#endif
199+
return 64;
200+
#else
201+
return __builtin_ctzll(a);
202+
#endif
136203
}
137204

205+
#ifdef _MSC_VER
206+
#pragma pack(push, 1)
207+
struct packed_u64 {
208+
uint64_t v;
209+
};
210+
211+
struct packed_u32 {
212+
uint32_t v;
213+
};
214+
215+
struct packed_u16 {
216+
uint16_t v;
217+
};
218+
#pragma pack(pop)
219+
#else
138220
struct __attribute__((packed)) packed_u64 {
139221
uint64_t v;
140222
};
@@ -146,6 +228,7 @@ struct __attribute__((packed)) packed_u32 {
146228
struct __attribute__((packed)) packed_u16 {
147229
uint16_t v;
148230
};
231+
#endif
149232

150233
static inline uint64_t get_u64(const uint8_t *tab)
151234
{

0 commit comments

Comments
 (0)