[pkg-d-commits] [ldc] 63/95: Let LLVM parse floating-point literals instead of host C runtime

Matthias Klumpp mak at moszumanska.debian.org
Thu Jul 13 20:54:01 UTC 2017


This is an automated email from the git hooks/post-receive script.

mak pushed a commit to annotated tag v1.3.0-beta1
in repository ldc.

commit fdf74b6d6aa2581f75e437ad2af5a638b2515627
Author: Martin <noone at nowhere.com>
Date:   Sat Mar 25 14:56:40 2017 +0100

    Let LLVM parse floating-point literals instead of host C runtime
---
 ddmd/root/ctfloat.d | 21 ++++++++++++
 ddmd/root/ctfloat.h |  4 +++
 ddmd/root/port.d    | 16 +++++++++
 gen/ctfloat.cpp     | 99 +++++++++++++++++++++++++++++++++++++++++++++--------
 4 files changed, 126 insertions(+), 14 deletions(-)

diff --git a/ddmd/root/ctfloat.d b/ddmd/root/ctfloat.d
index 5a75467..3718fa7 100644
--- a/ddmd/root/ctfloat.d
+++ b/ddmd/root/ctfloat.d
@@ -81,6 +81,11 @@ extern (C++) struct CTFloat
     static real_t ceil(real_t x) { return std.math.ceil(x); }
     static real_t trunc(real_t x) { return std.math.trunc(x); }
     static real_t round(real_t x) { return std.math.round(x); }
+
+    static void _init();
+
+    static bool isFloat32LiteralOutOfRange(const(char)* literal);
+    static bool isFloat64LiteralOutOfRange(const(char)* literal);
   }
 
     static bool isIdentical(real_t a, real_t b)
@@ -118,6 +123,13 @@ extern (C++) struct CTFloat
         return r is real_t.infinity || r is -real_t.infinity;
     }
 
+version (IN_LLVM)
+{
+    // implemented in gen/ctfloat.cpp
+    static real_t parse(const(char)* literal, bool* isOutOfRange = null);
+}
+else
+{
     static real_t parse(const(char)* literal, bool* isOutOfRange = null)
     {
         errno = 0;
@@ -136,6 +148,7 @@ extern (C++) struct CTFloat
             *isOutOfRange = (errno == ERANGE);
         return r;
     }
+}
 
     static int sprint(char* str, char fmt, real_t x)
     {
@@ -170,3 +183,11 @@ extern (C++) struct CTFloat
     static __gshared real_t minusone = real_t(-1);
     static __gshared real_t half = real_t(0.5);
 }
+
+version (IN_LLVM)
+{
+    shared static this()
+    {
+        CTFloat._init();
+    }
+}
diff --git a/ddmd/root/ctfloat.h b/ddmd/root/ctfloat.h
index ba85497..a5ff08f 100644
--- a/ddmd/root/ctfloat.h
+++ b/ddmd/root/ctfloat.h
@@ -50,7 +50,11 @@ struct CTFloat
     static real_t round(real_t x);
 
     // implemented in gen/ctfloat.cpp
+    static void _init();
     static void toAPFloat(real_t src, llvm::APFloat &dst);
+
+    static bool isFloat32LiteralOutOfRange(const char *literal);
+    static bool isFloat64LiteralOutOfRange(const char *literal);
 #endif
 
     static bool isIdentical(real_t a, real_t b);
diff --git a/ddmd/root/port.d b/ddmd/root/port.d
index b15697f..7902356 100644
--- a/ddmd/root/port.d
+++ b/ddmd/root/port.d
@@ -67,6 +67,13 @@ extern (C++) struct Port
 
     static bool isFloat32LiteralOutOfRange(const(char)* s)
     {
+      version (IN_LLVM)
+      {
+        import ddmd.root.ctfloat;
+        return CTFloat.isFloat32LiteralOutOfRange(s);
+      }
+      else
+      {
         errno = 0;
         version (CRuntime_DigitalMars)
         {
@@ -86,10 +93,18 @@ extern (C++) struct Port
         }
         version (CRuntime_DigitalMars) __locale_decpoint = save;
         return errno == ERANGE;
+      }
     }
 
     static bool isFloat64LiteralOutOfRange(const(char)* s)
     {
+      version (IN_LLVM)
+      {
+        import ddmd.root.ctfloat;
+        return CTFloat.isFloat64LiteralOutOfRange(s);
+      }
+      else
+      {
         errno = 0;
         version (CRuntime_DigitalMars)
         {
@@ -109,6 +124,7 @@ extern (C++) struct Port
         }
         version (CRuntime_DigitalMars) __locale_decpoint = save;
         return errno == ERANGE;
+      }
     }
 
     // Little endian
diff --git a/gen/ctfloat.cpp b/gen/ctfloat.cpp
index 055b6fc..a59cf96 100644
--- a/gen/ctfloat.cpp
+++ b/gen/ctfloat.cpp
@@ -12,33 +12,104 @@
 
 using llvm::APFloat;
 
+#if LDC_LLVM_VER >= 400
+#define AP_SEMANTICS_PARENS ()
+#else
+#define AP_SEMANTICS_PARENS
+#endif
+
+namespace {
+
+const llvm::fltSemantics *apSemantics = nullptr;
+
+constexpr unsigned numUint64Parts = (sizeof(real_t) + 7) / 8;
+union CTFloatUnion {
+  real_t fp;
+  uint64_t bits[numUint64Parts];
+};
+
+APFloat parseLiteral(const llvm::fltSemantics &semantics, const char *literal,
+                     bool *isOutOfRange = nullptr) {
+  APFloat ap(semantics, APFloat::uninitialized);
+  const auto r = ap.convertFromString(literal, APFloat::rmNearestTiesToEven);
+  if (isOutOfRange) {
+    *isOutOfRange = (r & (APFloat::opOverflow | APFloat::opUnderflow)) != 0;
+  }
+  return ap;
+}
+
+} // anonymous namespace
+
+////////////////////////////////////////////////////////////////////////////////
+
+void CTFloat::_init() {
+  static_assert(sizeof(real_t) >= 8, "real_t < 64 bits?");
+
+  if (sizeof(real_t) == 8) {
+    apSemantics = &(APFloat::IEEEdouble AP_SEMANTICS_PARENS);
+    return;
+  }
+
+#if __i386__ || __x86_64__
+  apSemantics = &(APFloat::x87DoubleExtended AP_SEMANTICS_PARENS);
+#elif __aarch64__
+  apSemantics = &(APFloat::IEEEquad AP_SEMANTICS_PARENS);
+#elif __ppc__ || __ppc64__
+  apSemantics = &(APFloat::PPCDoubleDouble AP_SEMANTICS_PARENS);
+#else
+  llvm_unreachable("Unknown host real_t type for compile-time reals");
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
 void CTFloat::toAPFloat(const real_t src, APFloat &dst) {
   if (sizeof(real_t) == 8) {
     dst = APFloat(static_cast<double>(src));
     return;
   }
 
-  assert(sizeof(real_t) > 8 && "real_t < 64 bits?");
-
-  union {
-    real_t fp;
-    uint64_t bits[(sizeof(real_t) + 7) / 8];
-  } u;
+  CTFloatUnion u;
   u.fp = src;
 
-#if LDC_LLVM_VER >= 400
-  #define PARENS ()
+#if LDC_LLVM_VER >= 307
+  const unsigned sizeInBits = APFloat::getSizeInBits(*apSemantics);
 #else
-  #define PARENS
-#endif
-
 #if __i386__ || __x86_64__
-  dst = APFloat(APFloat::x87DoubleExtended PARENS, APInt(80, 2, u.bits));
+  const unsigned sizeInBits = 80;
 #elif __aarch64__
-  dst = APFloat(APFloat::IEEEquad PARENS, APInt(128, 2, u.bits));
+  const unsigned sizeInBits = 128;
 #elif __ppc__ || __ppc64__
-  dst = APFloat(APFloat::PPCDoubleDouble PARENS, APInt(128, 2, u.bits));
+  const unsigned sizeInBits = 128;
 #else
   llvm_unreachable("Unknown host real_t type for compile-time reals");
 #endif
+#endif
+
+  const APInt bits = APInt(sizeInBits, numUint64Parts, u.bits);
+
+  dst = APFloat(*apSemantics, bits);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+real_t CTFloat::parse(const char *literal, bool *isOutOfRange) {
+  const APFloat ap = parseLiteral(*apSemantics, literal, isOutOfRange);
+  const APInt bits = ap.bitcastToAPInt();
+
+  CTFloatUnion u;
+  memcpy(u.bits, bits.getRawData(), bits.getBitWidth() / 8);
+  return u.fp;
+}
+
+bool CTFloat::isFloat32LiteralOutOfRange(const char *literal) {
+  bool isOutOfRange;
+  parseLiteral(APFloat::IEEEsingle AP_SEMANTICS_PARENS, literal, &isOutOfRange);
+  return isOutOfRange;
+}
+
+bool CTFloat::isFloat64LiteralOutOfRange(const char *literal) {
+  bool isOutOfRange;
+  parseLiteral(APFloat::IEEEdouble AP_SEMANTICS_PARENS, literal, &isOutOfRange);
+  return isOutOfRange;
 }

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-d/ldc.git



More information about the pkg-d-commits mailing list