summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorNobuyoshi Nakada <[email protected]>2024-11-13 14:45:49 +0900
committerNobuyoshi Nakada <[email protected]>2024-12-17 20:25:06 +0900
commit5a7a1a4a13ae11e4cef274c98e0c5bbcb7b1d192 (patch)
tree9071ea2eee048636f457ef960ab381f98770d0ca /include
parent36c36d0486b0c884759c038ceaf4aa495785996a (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.h13
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);