The LLVM optimizer replaces a call to pow(2, x) back into a call to
exp2(x), which ends up in an infinite loop/recursion here. To avoid
the issue, one could either build exp2.c (or easier to accomplish, all
of libmingwex.a) using -fno-builtin or -ffreestanding, or produce the
exp2() function wrappers using assembly instead, to force a function
call to the real pow/powf functions.
---
 mingw-w64-crt/math/arm/exp2.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/mingw-w64-crt/math/arm/exp2.c b/mingw-w64-crt/math/arm/exp2.c
index 6be1fba..8fc80c4 100644
--- a/mingw-w64-crt/math/arm/exp2.c
+++ b/mingw-w64-crt/math/arm/exp2.c
@@ -44,6 +44,33 @@
 
 #include <math.h>
 
+#if defined(__aarch64__) || defined(_ARM64_)
+
+// On aarch64, LLVM optimizes a pow(2, x) call back into a call to exp2(x).
+// To avoid this, we could either build without optimization, using 
-fno-builtin
+// or -ffreestanding (or -fno-builtin-pow -fno-builtin-powf), but ideally only
+// this file, or produce the exp2 wrappers  with assembly.
+asm(
+    ".def exp2;  .scl 2; .type 32; .endef\n\t"
+    ".def exp2f; .scl 2; .type 32; .endef\n\t"
+
+    ".text\n\t"
+    ".align 4\n\t"
+    ".globl exp2\n\t"
+    ".globl exp2f\n\t"
+
+    "exp2:\n\t"
+    "fmov d1, d0\n\t"
+    "fmov d0, #2.0\n\t"
+    "b pow\n\t"
+
+    "exp2f:\n\t"
+    "fmov s1, s0\n\t"
+    "fmov s0, #2.0\n\t"
+    "b powf\n\t");
+
+#else
+
 double exp2(double x)
 {
     return pow(2, x);
@@ -53,6 +80,7 @@ float exp2f(float x)
 {
     return powf(2, x);
 }
+#endif
 
 long double exp2l(long double x)
 {
-- 
2.7.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to