Skip to content

Fixes cutils.h for MSVC #85

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 88 additions & 2 deletions cutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,35 @@
#include <stdlib.h>
#include <inttypes.h>

#ifdef _WIN32
#include <intrin.h>
#include <malloc.h>
#else
#include <alloca.h>
#endif

/* set if CPU is big endian */
#undef WORDS_BIGENDIAN

#if defined(_MSC_VER)
#define likely(x) (x)
#define unlikely(x) (x)
#define force_inline __forceinline
#define no_inline __declspec(noinline)
#define __maybe_unused
#define __attribute__(x)
#define __attribute(x)
#ifndef SSIZE_MAX
#define SSIZE_MAX INTPTR_MAX
typedef intptr_t ssize_t;
#endif
#else
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#define force_inline inline __attribute__((always_inline))
#define no_inline __attribute__((noinline))
#define __maybe_unused __attribute__((unused))
#endif

#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)
Expand Down Expand Up @@ -114,27 +135,91 @@ static inline int64_t min_int64(int64_t a, int64_t b)
/* WARNING: undefined if a = 0 */
static inline int clz32(unsigned int a)
{
#ifdef _MSC_VER
unsigned long idx;
_BitScanReverse(&idx, a);
return 31 ^ idx;
#else
return __builtin_clz(a);
#endif
}

/* WARNING: undefined if a = 0 */
static inline int clz64(uint64_t a)
{
return __builtin_clzll(a);
#ifdef _MSC_VER
unsigned long where;
// BitScanReverse scans from MSB to LSB for first set bit.
// Returns 0 if no set bit is found.
#if INTPTR_MAX >= INT64_MAX // 64-bit
if (_BitScanReverse64(&where, a))
return (int)(63 - where);
#else
// Scan the high 32 bits.
if (_BitScanReverse(&where, (uint32_t)(a >> 32)))
return (int)(63 - (where + 32)); // Create a bit offset from the MSB.
// Scan the low 32 bits.
if (_BitScanReverse(&where, (uint32_t)(a)))
return (int)(63 - where);
#endif
return 64; // Undefined Behavior.
#else
return __builtin_clzll(a);
#endif
}

/* WARNING: undefined if a = 0 */
static inline int ctz32(unsigned int a)
{
#ifdef _MSC_VER
unsigned long idx;
_BitScanForward(&idx, a);
return idx;
#else
return __builtin_ctz(a);
#endif
}

/* WARNING: undefined if a = 0 */
static inline int ctz64(uint64_t a)
{
return __builtin_ctzll(a);
#ifdef _MSC_VER
unsigned long where;
// Search from LSB to MSB for first set bit.
// Returns zero if no set bit is found.
#if INTPTR_MAX >= INT64_MAX // 64-bit
if (_BitScanForward64(&where, a))
return (int)(where);
#else
// Win32 doesn't have _BitScanForward64 so emulate it with two 32 bit calls.
// Scan the Low Word.
if (_BitScanForward(&where, (uint32_t)(a)))
return (int)(where);
// Scan the High Word.
if (_BitScanForward(&where, (uint32_t)(a >> 32)))
return (int)(where + 32); // Create a bit offset from the LSB.
#endif
return 64;
#else
return __builtin_ctzll(a);
#endif
}

#ifdef _MSC_VER
#pragma pack(push, 1)
struct packed_u64 {
uint64_t v;
};

struct packed_u32 {
uint32_t v;
};

struct packed_u16 {
uint16_t v;
};
#pragma pack(pop)
#else
struct __attribute__((packed)) packed_u64 {
uint64_t v;
};
Expand All @@ -146,6 +231,7 @@ struct __attribute__((packed)) packed_u32 {
struct __attribute__((packed)) packed_u16 {
uint16_t v;
};
#endif

static inline uint64_t get_u64(const uint8_t *tab)
{
Expand Down