Win32: Fix rbimpl_size_mul_overflow on arm64

`_umul128` is specific to x86_64 platform, see higher words by
`__umulh` on arm64.
This commit is contained in:
Nobuyoshi Nakada 2024-11-13 14:45:49 +09:00
parent 36c36d0486
commit 5a7a1a4a13
No known key found for this signature in database
GPG Key ID: 3582D74E1FEE4465
Notes: git 2024-12-17 11:56:50 +00:00

View File

@ -38,9 +38,14 @@
# include <alloca.h>
#endif
#if defined(_MSC_VER) && defined(_M_AMD64)
#if defined(_MSC_VER) && defined(_WIN64)
# include <intrin.h>
# if defined(_M_AMD64)
# pragma intrinsic(_umul128)
# endif
# if defined(_M_ARM64)
# pragma intrinsic(__umulh)
# endif
#endif
#include "ruby/internal/attr/alloc_size.h"
@ -581,12 +586,16 @@ rbimpl_size_mul_overflow(size_t x, size_t y)
ret.left = dz > SIZE_MAX;
ret.right = RBIMPL_CAST((size_t)dz);
#elif defined(_MSC_VER) && defined(_WIN64)
#elif defined(_MSC_VER) && defined(_M_AMD64)
unsigned __int64 dp = 0;
unsigned __int64 dz = _umul128(x, y, &dp);
ret.left = RBIMPL_CAST((bool)dp);
ret.right = RBIMPL_CAST((size_t)dz);
#elif defined(_MSC_VER) && defined(_M_ARM64)
ret.left = __umulh(x, y) != 0;
ret.right = x * y;
#else
/* https://wiki.sei.cmu.edu/confluence/display/c/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap */
ret.left = (y != 0) && (x > SIZE_MAX / y);