Make MSVC version testable

This commit is contained in:
Yu-Sheng Lin 2026-03-26 00:23:11 +08:00
parent 04e4f7b63d
commit c2540f0577
4 changed files with 52 additions and 33 deletions

View File

@ -13,6 +13,17 @@
#include <string>
// Other libraries' .h files.
// Your project's .h files.
#if defined(MSC_VER_) || defined(FORCE_MSC_VER_)
# define USE_GCC_INTRINSIC 0
// Note: we do not support MSVC intrinsic for now
# define USE_MSVC_INTRINSIC 0
#elif defined(__GNUC__) || defined(__clang__)
# define USE_GCC_INTRINSIC 1
# define USE_MSVC_INTRINSIC 0
#else
# define USE_GCC_INTRINSIC 0
# define USE_MSVC_INTRINSIC 0
#endif
// Remove these when we upgrade to C++20
#pragma GCC diagnostic ignored "-Wpragmas"

View File

@ -102,16 +102,12 @@
// Compatibility layer for unreachable code hint
#if defined(__cplusplus) && __cplusplus >= 202302L
// Prefer the standard library version if available
# include <utility>
# define FST_UNREACHABLE std::unreachable()
#elif defined(__GNUC__) || defined(__clang__)
// --- GCC / Clang ---
#elif USE_GCC_INTRINSIC
# define FST_UNREACHABLE __builtin_unreachable()
#elif defined(_MSC_VER)
// --- MSVC ---
# define FST_UNREACHABLE __assume(0)
// TODO: implement MSVC version
// #elif USE_MSVC_INTRINSIC
#else
// --- Fallback ---
# define FST_UNREACHABLE std::abort()
#endif

View File

@ -6,10 +6,10 @@
#pragma once
// direct include
// C system headers
#ifdef _MSC_VER
# include <intrin.h>
#endif
// C++ standard library headers
#if defined(__cplusplus) && __cplusplus >= 202302L
# include <bit>
#endif
#include <cstdint>
#include <cstring>
#include <vector>
@ -28,22 +28,24 @@ namespace platform {
// clang-format off
template <typename U> U to_big_endian(U u) { return u; }
#else
#if defined(__GNUC__) || defined(__clang__)
#if defined(__cplusplus) && __cplusplus >= 202302L
template <typename U, size_t S>
U to_big_endian(U u, std::integral_constant<size_t, S>) {
return std::byteswap(u);
}
#elif USE_GCC_INTRINSIC
template<typename U> U to_big_endian(U u, std::integral_constant<size_t, 1>) { return u; }
template<typename U> U to_big_endian(U u, std::integral_constant<size_t, 2>) { return __builtin_bswap16(u); }
template<typename U> U to_big_endian(U u, std::integral_constant<size_t, 4>) { return __builtin_bswap32(u); }
template<typename U> U to_big_endian(U u, std::integral_constant<size_t, 8>) { return __builtin_bswap64(u); }
#elif defined(_MSC_VER) // MSVC
template<typename U> U to_big_endian(U u, std::integral_constant<size_t, 1>) { return u; }
template<typename U> U to_big_endian(U u, std::integral_constant<size_t, 2>) { return _byteswap_ushort(u); }
template<typename U> U to_big_endian(U u, std::integral_constant<size_t, 4>) { return _byteswap_ulong(u); }
template<typename U> U to_big_endian(U u, std::integral_constant<size_t, 8>) { return _byteswap_uint64(u); }
// TODO: implement MSVC version
// #elif USE_MSVC_INTRINSIC
#else
template<typename U, size_t S> U to_big_endian(U u, std::integral_constant<size_t, S>) {
U ret{ 0 };
template <typename U, size_t S>
U to_big_endian(U u, std::integral_constant<size_t, S>) {
U ret{0};
for (size_t i = 0; i < S; ++i) {
ret |= u & 0xff;
ret <<= 8;
ret = (ret << 8) | (u & 0xff);
u >>= 8;
}
return ret;

View File

@ -7,10 +7,10 @@
// direct include
#include "fstcpp/fstcpp.h"
// C system headers
#ifdef _MSC_VER
# include <intrin.h>
#endif
// C++ standard library headers
#if defined(__cplusplus) && __cplusplus >= 202002L
# include <bit>
#endif
#include <algorithm>
#include <cstdint>
#include <limits>
@ -26,19 +26,29 @@ namespace platform {
// Can be replaced with std::bit_width when C++20 is available
inline uint64_t clog2(uint64_t x) {
#if defined(__GNUC__) || defined(__clang__)
return 64 - __builtin_clzll(x - 1);
#elif defined(_MSC_VER) // MSVC
if (x <= 1) return 0;
unsigned long index;
_BitScanReverse64(&index, x - 1);
return static_cast<uint64_t>(index + 1);
#if defined(__cplusplus) && __cplusplus >= 202002L
return std::bit_width(x - 1);
#elif USE_GCC_INTRINSIC
return 64 - __builtin_clzll(x - 1);
// TODO: implement MSVC version
// #elif USE_MSVC_INTRINSIC
#else
uint64_t r = 0;
while (x > 1) {
x >>= 1;
r++;
}
x -= 1;
auto CheckAndShift = [&](uint64_t shift) {
if (x >> shift) {
r += shift;
x >>= shift;
}
};
CheckAndShift(32);
CheckAndShift(16);
CheckAndShift(8);
CheckAndShift(4);
CheckAndShift(2);
CheckAndShift(1);
r += x;
return r;
#endif
}