[pkg-d-commits] [ldc] 141/149: Let LLVM parse floating-point literals instead of host C runtime
Matthias Klumpp
mak at moszumanska.debian.org
Sun Apr 23 22:37:07 UTC 2017
This is an automated email from the git hooks/post-receive script.
mak pushed a commit to annotated tag v1.2.0
in repository ldc.
commit edb82a8bb96d57a51628414605f93a610f09523d
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