From 5687cb512c79b65b1167c23b517aadddaa3d8a50 Mon Sep 17 00:00:00 2001 From: Abdelrahman Said Date: Thu, 29 Oct 2026 02:15:17 +0000 Subject: [PATCH] Fix MSVC build issues --- CHANGELOG.md | 6 +++++ VERSION | 2 +- src/base/array/array.c | 4 ++- src/base/hash/hasher/hasher.h | 2 ++ src/base/hash/hasher/murmur3.c | 2 +- src/base/hash/table/table.c | 36 +++++++++++++++++++++----- src/base/hash/table/table.h | 7 +++-- src/base/mem/allocator/mem_allocator.c | 1 + src/log/log.c | 26 ++++++++++++++----- src/log/log.h | 2 +- src/prng/splitmix64/splitmix64.c | 2 +- src/prng/xorshift/xorshift.c | 5 +++- tests/hasher/MurmurHash3.c | 5 ++++ tests/hasher/MurmurHash3.cc | 5 ++++ tests/hasher/siphash.cc | 2 +- tests/hasher/test_hasher.c | 6 ++--- tests/hasher/test_hasher.cc | 6 ++--- tests/hashmap/test_hashmap.c | 4 +++ tests/hashmap/test_hashmap.cc | 4 +++ tests/hashset/test_hashset.c | 4 +++ tests/hashset/test_hashset.cc | 4 +++ 21 files changed, 108 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 959391e..61b3958 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [3.3.1] - 2026-10-29 + +### Fixed + +- MSVC build issues + ## [3.3.0] - 2026-10-24 ### Added diff --git a/VERSION b/VERSION index 15a2799..bea438e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.3.0 +3.3.1 diff --git a/src/base/array/array.c b/src/base/array/array.c index 311b07d..e77aab7 100644 --- a/src/base/array/array.c +++ b/src/base/array/array.c @@ -205,7 +205,9 @@ void arrayRemoveSwapEnd(WpArray array, u64 index, u64 item_size) { u64 last_item_index = header->count - 1; - if (index < last_item_index) { + // NOTE (Abdelrahman): Extract into a variable to get rid of MSVC Spectre mitigation warnings + b8 is_last_item = index == last_item_index; + if (!is_last_item) { void *cur_item = arrayGetItemWithOffset(array, header->item_size * index); void *last_item = arrayGetItemWithOffset(array, header->item_size * last_item_index); diff --git a/src/base/hash/hasher/hasher.h b/src/base/hash/hasher/hasher.h index 36b236a..072ab01 100644 --- a/src/base/hash/hasher/hasher.h +++ b/src/base/hash/hasher/hasher.h @@ -5,6 +5,7 @@ #include "../../stream/stream.h" #include "../../../common/aliases/aliases.h" +#include "../../../common/misc/misc_utils.h" #ifdef WP_PLATFORM_CPP BEGIN_C_LINKAGE @@ -30,6 +31,7 @@ typedef struct WpSiphashCtx { typedef struct WpHasherCtx { WpHasherCtxType type; + u8 padding[4]; union { WpSiphashCtx siphash; void *user; diff --git a/src/base/hash/hasher/murmur3.c b/src/base/hash/hasher/murmur3.c index ea536a1..f6c6032 100644 --- a/src/base/hash/hasher/murmur3.c +++ b/src/base/hash/hasher/murmur3.c @@ -29,7 +29,7 @@ WpHasher wpX64Mur3HasherWithSeed(u32 seed) { WpU128 wpX64Mur3GetHash128(WpU8Stream *bytes, WpHasherCtx ctx) { validateMur3HasherCtx(&ctx); - const i32 nblocks = (bytes->count * bytes->item_size) / 16; + const i32 nblocks = (const i32)((bytes->count * bytes->item_size) / 16); u64 h1 = ctx.murmur3; u64 h2 = ctx.murmur3; diff --git a/src/base/hash/table/table.c b/src/base/hash/table/table.c index 285a378..a9fce09 100644 --- a/src/base/hash/table/table.c +++ b/src/base/hash/table/table.c @@ -119,12 +119,20 @@ void hashTableGrow(const WpAllocator *allocator, WpHashTable *table, u64 key_siz table->buckets = buckets; table->bucket_mask = mask; - for (u64 i = 0; i < wpArrayCount(old_keys); ++i) { - void *key = arrayGet(old_keys, i, key_size); - void *value = table->has_values ? arrayGet(old_values, i, value_size) : NULL; + // NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of + // MSVC Spectre mitigation warnings + u64 count = wpArrayCount(old_keys); + u64 index = 0; + b8 running = true; + while (running) { + void *key = arrayGet(old_keys, index, key_size); + void *value = table->has_values ? arrayGet(old_values, index, value_size) : NULL; u64 hash = hashTableCalcHash(table, key, key_size); WpHashBucketRef ref = hashTableBucketRef(table, hash); hashTableInsert(table, key, value, ref, key_size, value_size); + + ++index; + running = index < count; } } @@ -132,7 +140,9 @@ WpHashLookupResult hashTableLookup(WpHashTable *table, void *key, WpHashBucketRe hashTableValidate(table, key_size, 0); wpDebugAssert(key != NULL, "`key` should not be NULL"); - while (true) { + u64 initial_bucket_index = ref.bucket_index; + b8 running = true; + while (running) { WpHashBucket *bucket = &table->buckets[ref.bucket_index]; if (ref.dist_and_tag == bucket->dist_and_tag) { @@ -152,7 +162,16 @@ WpHashLookupResult hashTableLookup(WpHashTable *table, void *key, WpHashBucketRe ref.dist_and_tag = hashTableDistInc(ref.dist_and_tag); ref.bucket_index = hashTableNextBucket(table, ref.bucket_index); + + // Break if we loop back to the start bucket index + running = ref.bucket_index != initial_bucket_index; } + + return (WpHashLookupResult){ + .ref.dist_and_tag = ref.dist_and_tag, + .ref.bucket_index = ref.bucket_index, + .found = false, + }; } void hashTableUpdate(WpHashTable *table, void *value, WpHashBucketRef ref, u64 value_size) { @@ -172,7 +191,10 @@ void hashTableInsert(WpHashTable *table, void *key, void *value, WpHashBucketRef wpDebugAssert(key != NULL, "`key` should not be NULL"); u64 index = wpArrayCount(table->keys); - while (true) { + + // NOTE (Abdelrahman): Extract into a variable to satisfy MSVC + b8 running = true; + while (running) { WpHashBucket *bucket = &table->buckets[ref.bucket_index]; if (bucket->dist_and_tag == 0) { @@ -202,7 +224,9 @@ void hashTableRemove(WpHashTable *table, WpHashBucketRef ref, u64 key_size, u64 u64 last_item_index = wpArrayCount(table->keys) - 1; - if (bucket->item_index < last_item_index) { + // NOTE (Abdelrahman): Extract into a variable to get rid of MSVC Spectre mitigation warnings + b8 is_last_item = bucket->item_index == last_item_index; + if (!is_last_item) { // Update the bucket for the last item before swapping u64 hash = hashTableCalcHash(table, arrayGet(table->keys, last_item_index, key_size), key_size); diff --git a/src/base/hash/table/table.h b/src/base/hash/table/table.h index 30ce60c..9207156 100644 --- a/src/base/hash/table/table.h +++ b/src/base/hash/table/table.h @@ -25,6 +25,7 @@ #include "../../stream/stream.h" #include "../../../common/aliases/aliases.h" #include "../../../common/platform/platform.h" +#include "../../../common/misc/misc_utils.h" #ifdef WP_PLATFORM_CPP BEGIN_C_LINKAGE @@ -56,7 +57,7 @@ typedef struct WpHashTable { u64 magic; u64 bucket_mask; f32 load_factor; - b8 has_values; + b32 has_values; } WpHashTable; typedef struct WpHashBucketRef { @@ -66,7 +67,9 @@ typedef struct WpHashBucketRef { typedef struct WpHashLookupResult { WpHashBucketRef ref; - b8 found; + b32 found; + + wpMiscUtilsReservePadding(sizeof(WpHashBucketRef) + sizeof(b32)); } WpHashLookupResult; void hashTableAlloc(const WpAllocator *allocator, WpHashTable *table, diff --git a/src/base/mem/allocator/mem_allocator.c b/src/base/mem/allocator/mem_allocator.c index 107637d..5a12af3 100644 --- a/src/base/mem/allocator/mem_allocator.c +++ b/src/base/mem/allocator/mem_allocator.c @@ -94,6 +94,7 @@ b8 wpMemAllocatorOpSupported(const WpAllocator *allocator, WpMemOp op) { return allocator->temp_begin != NULL; case WP_MEM_OP_TEMP_END: return allocator->temp_end != NULL; + case COUNT_MEM_OPS: default: break; } diff --git a/src/log/log.c b/src/log/log.c index a366857..c58e323 100644 --- a/src/log/log.c +++ b/src/log/log.c @@ -3,6 +3,7 @@ #include "log.h" #include "../base/strings/str8/str8.h" #include "../common/aliases/aliases.h" +#include "../common/platform/platform.h" #include "../common/assert/assert.h" #include "../common/misc/misc_utils.h" #include "../os/file/file.h" @@ -11,9 +12,9 @@ #define MIN_LOG_MSG_LENGTH 128 #define TIME_BUF_CAPACITY 70 -wp_intern WpStr8RO L_BRACKET = wpStr8LitRo("["); -wp_intern WpStr8RO R_BRACKET_SPACE = wpStr8LitRo("] "); -wp_intern WpStr8RO R_BRACKET_NEWLINE = wpStr8LitRo("]\n"); +wp_intern WpStr8RO L_BRACKET = wpStr8LitRoInitialiserList("["); +wp_intern WpStr8RO R_BRACKET_SPACE = wpStr8LitRoInitialiserList("] "); +wp_intern WpStr8RO R_BRACKET_NEWLINE = wpStr8LitRoInitialiserList("]\n"); typedef struct LogConfig { WpFile *outlog; @@ -101,14 +102,20 @@ wp_intern void getCurrentTimeString(WpStr8 *dst) { char buf[TIME_BUF_CAPACITY]; time_t now = time(NULL); struct tm utc; + +#ifdef WP_PLATFORM_WINDOWS + gmtime_s(&utc, &now); +#else gmtime_r(&now, &utc); +#endif + strftime(buf, sizeof(buf), "%FT%TZ ", &utc); wpStr8CopyCstrCapped(dst, buf); } wp_intern void writeLogLine(WpFile *fp, const WpLogger *logger, WpStr8 msg, WpLogLevel level) { WpStr8 padding = wpStr8Buf(MIN_LOG_MSG_LENGTH); - u32 padding_size = msg.size < MIN_LOG_MSG_LENGTH ? MIN_LOG_MSG_LENGTH - msg.size + 1 : 0; + u32 padding_size = (u32)(msg.size < MIN_LOG_MSG_LENGTH ? MIN_LOG_MSG_LENGTH - msg.size + 1 : 0); wpStr8Format(&padding, "%-*s", padding_size, " "); WpStr8 time_str = wpStr8Buf(TIME_BUF_CAPACITY); @@ -127,7 +134,14 @@ wp_intern void writeLogLine(WpFile *fp, const WpLogger *logger, WpStr8 msg, WpLo &R_BRACKET_NEWLINE ); - for (u64 i = 0; i < wpArrayCount(strings); ++i) { - wpFileWriteStr8(strings[i], fp); + // NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of + // MSVC Spectre mitigation warnings + u64 count = wpArrayCount(strings); + u64 index = 0; + b8 running = true; + while (running) { + wpFileWriteStr8(strings[index], fp); + ++index; + running = index < count; } } diff --git a/src/log/log.h b/src/log/log.h index bac9e15..794bd4a 100644 --- a/src/log/log.h +++ b/src/log/log.h @@ -23,7 +23,7 @@ typedef enum WpLogLevel { } WpLogLevel; typedef struct WpLogger { - WpStr8RO name; + WpStr8 name; } WpLogger; #ifdef WP_PLATFORM_CPP diff --git a/src/prng/splitmix64/splitmix64.c b/src/prng/splitmix64/splitmix64.c index 9549b0e..af06b0b 100644 --- a/src/prng/splitmix64/splitmix64.c +++ b/src/prng/splitmix64/splitmix64.c @@ -67,7 +67,7 @@ wp_intern void seedOsGenerator(u64 seed) { seed = (u64)ts.tv_nsec; } - srand(seed); + srand((u32)seed); } wp_intern u64 genRandomNumber(void) { diff --git a/src/prng/xorshift/xorshift.c b/src/prng/xorshift/xorshift.c index 74a0787..e91e5c2 100644 --- a/src/prng/xorshift/xorshift.c +++ b/src/prng/xorshift/xorshift.c @@ -13,7 +13,10 @@ WpXor256State wpPrngXorshiftInit(void) { WpXor256State wpPrngXorshiftInitWithSeed(u64 seed) { WpSplitmix64State sm64; - if (seed > 0) { + + // NOTE (Abdelrahman): Extract into a variable to get rid of MSVC Spectre mitigation warnings + b8 seed_not_zero = seed > 0; + if (seed_not_zero) { sm64 = wpPrngSplitmix64InitWithSeed(seed); } else { sm64 = wpPrngSplitmix64Init(); diff --git a/tests/hasher/MurmurHash3.c b/tests/hasher/MurmurHash3.c index 2393fa9..997def0 100644 --- a/tests/hasher/MurmurHash3.c +++ b/tests/hasher/MurmurHash3.c @@ -7,8 +7,13 @@ // compile and run any of them on any platform, but your performance with the // non-native version will be less than optimal. +#include "wapp.h" #include "MurmurHash3.h" +#ifdef WP_PLATFORM_WINDOWS +#pragma warning(disable:5045) +#endif + //----------------------------------------------------------------------------- // Platform-specific functions and macros diff --git a/tests/hasher/MurmurHash3.cc b/tests/hasher/MurmurHash3.cc index aa7982d..acf0916 100644 --- a/tests/hasher/MurmurHash3.cc +++ b/tests/hasher/MurmurHash3.cc @@ -7,8 +7,13 @@ // compile and run any of them on any platform, but your performance with the // non-native version will be less than optimal. +#include "wapp.h" #include "MurmurHash3.h" +#ifdef WP_PLATFORM_WINDOWS +#pragma warning(disable:5045) +#endif + //----------------------------------------------------------------------------- // Platform-specific functions and macros diff --git a/tests/hasher/siphash.cc b/tests/hasher/siphash.cc index c6d16e2..f1a8431 100644 --- a/tests/hasher/siphash.cc +++ b/tests/hasher/siphash.cc @@ -102,7 +102,7 @@ int siphash(const void *in, const size_t inlen, const void *k, uint8_t *out, uint64_t m; int i; const unsigned char *end = ni + inlen - (inlen % sizeof(uint64_t)); - const int left = inlen & 7; + const int left = (const int)(inlen & 7); uint64_t b = ((uint64_t)inlen) << 56; v3 ^= k1; v2 ^= k0; diff --git a/tests/hasher/test_hasher.c b/tests/hasher/test_hasher.c index b2c6439..2c35a44 100644 --- a/tests/hasher/test_hasher.c +++ b/tests/hasher/test_hasher.c @@ -22,19 +22,19 @@ WpTestFuncResult test_murmur3(void) { // Sring hash WpU128 mur_hash = hasher.func(&str_bytes, hasher.ctx); - MurmurHash3_x64_128(str_bytes.data, str_bytes.count * str_bytes.item_size, hasher.ctx.murmur3, (void *)hash); + MurmurHash3_x64_128(str_bytes.data, (i32)(str_bytes.count * str_bytes.item_size), hasher.ctx.murmur3, (void *)hash); result = result && mur_hash.value[0] == hash[0] && mur_hash.value[1] == hash[1]; // Array hash mur_hash = hasher.func(&arr_bytes, hasher.ctx); - MurmurHash3_x64_128(arr_bytes.data, arr_bytes.count * arr_bytes.item_size, hasher.ctx.murmur3, (void *)hash); + MurmurHash3_x64_128(arr_bytes.data, (i32)(arr_bytes.count * arr_bytes.item_size), hasher.ctx.murmur3, (void *)hash); result = result && mur_hash.value[0] == hash[0] && mur_hash.value[1] == hash[1]; // Number hash mur_hash = hasher.func(&num_bytes, hasher.ctx); - MurmurHash3_x64_128(num_bytes.data, num_bytes.count * num_bytes.item_size, hasher.ctx.murmur3, (void *)hash); + MurmurHash3_x64_128(num_bytes.data, (i32)(num_bytes.count * num_bytes.item_size), hasher.ctx.murmur3, (void *)hash); result = result && mur_hash.value[0] == hash[0] && mur_hash.value[1] == hash[1]; diff --git a/tests/hasher/test_hasher.cc b/tests/hasher/test_hasher.cc index 6212d46..3719fb7 100644 --- a/tests/hasher/test_hasher.cc +++ b/tests/hasher/test_hasher.cc @@ -22,19 +22,19 @@ WpTestFuncResult test_murmur3(void) { // Sring hash WpU128 mur_hash = hasher.func(&str_bytes, hasher.ctx); - MurmurHash3_x64_128(str_bytes.data, str_bytes.count * str_bytes.item_size, hasher.ctx.murmur3, (void *)hash); + MurmurHash3_x64_128(str_bytes.data, (i32)(str_bytes.count * str_bytes.item_size), hasher.ctx.murmur3, (void *)hash); result = result && mur_hash.value[0] == hash[0] && mur_hash.value[1] == hash[1]; // Array hash mur_hash = hasher.func(&arr_bytes, hasher.ctx); - MurmurHash3_x64_128(arr_bytes.data, arr_bytes.count * arr_bytes.item_size, hasher.ctx.murmur3, (void *)hash); + MurmurHash3_x64_128(arr_bytes.data, (i32)(arr_bytes.count * arr_bytes.item_size), hasher.ctx.murmur3, (void *)hash); result = result && mur_hash.value[0] == hash[0] && mur_hash.value[1] == hash[1]; // Number hash mur_hash = hasher.func(&num_bytes, hasher.ctx); - MurmurHash3_x64_128(num_bytes.data, num_bytes.count * num_bytes.item_size, hasher.ctx.murmur3, (void *)hash); + MurmurHash3_x64_128(num_bytes.data, (i32)(num_bytes.count * num_bytes.item_size), hasher.ctx.murmur3, (void *)hash); result = result && mur_hash.value[0] == hash[0] && mur_hash.value[1] == hash[1]; diff --git a/tests/hashmap/test_hashmap.c b/tests/hashmap/test_hashmap.c index 633cf55..6fec1aa 100644 --- a/tests/hashmap/test_hashmap.c +++ b/tests/hashmap/test_hashmap.c @@ -3,6 +3,10 @@ #include "wapp.h" #include "test_hashmap.h" +#ifdef WP_PLATFORM_WINDOWS +#pragma warning(disable:5045) +#endif + wp_persist inline WpU8Stream encoder(void *data); wp_persist inline b8 key_eq(void *a, void *b); diff --git a/tests/hashmap/test_hashmap.cc b/tests/hashmap/test_hashmap.cc index 2f6ca8e..aa091ac 100644 --- a/tests/hashmap/test_hashmap.cc +++ b/tests/hashmap/test_hashmap.cc @@ -3,6 +3,10 @@ #include "wapp.h" #include "test_hashmap.h" +#ifdef WP_PLATFORM_WINDOWS +#pragma warning(disable:5045) +#endif + wp_persist inline WpU8Stream encoder(void *data); wp_persist inline b8 key_eq(void *a, void *b); diff --git a/tests/hashset/test_hashset.c b/tests/hashset/test_hashset.c index ac8c13c..86a9fb7 100644 --- a/tests/hashset/test_hashset.c +++ b/tests/hashset/test_hashset.c @@ -3,6 +3,10 @@ #include "wapp.h" #include "test_hashset.h" +#ifdef WP_PLATFORM_WINDOWS +#pragma warning(disable:5045) +#endif + wp_persist inline WpU8Stream encoder(void *data); wp_persist inline b8 key_eq(void *a, void *b); diff --git a/tests/hashset/test_hashset.cc b/tests/hashset/test_hashset.cc index f921a08..781da0e 100644 --- a/tests/hashset/test_hashset.cc +++ b/tests/hashset/test_hashset.cc @@ -3,6 +3,10 @@ #include "wapp.h" #include "test_hashset.h" +#ifdef WP_PLATFORM_WINDOWS +#pragma warning(disable:5045) +#endif + wp_persist inline WpU8Stream encoder(void *data); wp_persist inline b8 key_eq(void *a, void *b);