diff options
author | Nobuyoshi Nakada <[email protected]> | 2024-11-13 14:45:49 +0900 |
---|---|---|
committer | Nobuyoshi Nakada <[email protected]> | 2024-12-17 20:25:06 +0900 |
commit | 5a7a1a4a13ae11e4cef274c98e0c5bbcb7b1d192 (patch) | |
tree | 9071ea2eee048636f457ef960ab381f98770d0ca /include | |
parent | 36c36d0486b0c884759c038ceaf4aa495785996a (diff) |
Win32: Fix `rbimpl_size_mul_overflow` on arm64
`_umul128` is specific to x86_64 platform, see higher words by
`__umulh` on arm64.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/12367
Diffstat (limited to 'include')
-rw-r--r-- | include/ruby/internal/memory.h | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/include/ruby/internal/memory.h b/include/ruby/internal/memory.h index 64e850c65e..d231e62982 100644 --- a/include/ruby/internal/memory.h +++ b/include/ruby/internal/memory.h @@ -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); |