mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-04 00:55:49 +03:00
Limited support for arbitrary target reals
While parsing of floating-point literals and CTFE still operate with the host LDC's real type, compile-time reals can in principle be emitted in arbitrary precision via LLVM software conversion, therefore paving the way for cross-compilation to all targets. The representable constants are still limited by the compile-time real_t precision. E.g., LDC on Windows with its 64-bit reals can't hold and emit an 80-bit `real.max` when cross-compiling to a non-Windows x86(_64) target; the compile-time value will silently overflow to infinity and later be emitted as 80-bit infinity. LDC on AArch64 with its 128-bit quad-precision reals on the other hand can hold and emit reals for all targets, making it a universal cross-compiler with quad-precision compile-time reals in hardware. We don't use the strange 2x64-bit PPC double-double format (see `getRealType()` in `ir/irtype.cpp`), but would more or less support it (the type properties (max, min_normal...) still need to be determined; LLVM isn't sure about those either...).
This commit is contained in:
parent
c051d8d829
commit
0e71a760ae
7 changed files with 115 additions and 60 deletions
48
gen/ctfloat.cpp
Normal file
48
gen/ctfloat.cpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
//===-- ctfloat.cpp -------------------------------------------------------===//
|
||||
//
|
||||
// LDC – the LLVM D compiler
|
||||
//
|
||||
// This file is distributed under the BSD-style LDC license. See the LICENSE
|
||||
// file for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ctfloat.h"
|
||||
#include "gen/llvm.h"
|
||||
|
||||
using llvm::APFloat;
|
||||
|
||||
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;
|
||||
u.fp = src;
|
||||
|
||||
#if LDC_LLVM_VER >= 400
|
||||
const auto &x87DoubleExtended = APFloat::x87DoubleExtended();
|
||||
const auto &IEEEquad = APFloat::IEEEquad();
|
||||
const auto &PPCDoubleDouble = APFloat::PPCDoubleDouble();
|
||||
#else
|
||||
const auto &x87DoubleExtended = APFloat::x87DoubleExtended;
|
||||
const auto &IEEEquad = APFloat::IEEEquad;
|
||||
const auto &PPCDoubleDouble = APFloat::PPCDoubleDouble;
|
||||
#endif
|
||||
|
||||
#if __i386__ || __x86_64__
|
||||
dst = APFloat(x87DoubleExtended, APInt(80, 2, u.bits));
|
||||
#elif __aarch64__
|
||||
dst = APFloat(IEEEquad, APInt(128, 2, u.bits));
|
||||
#elif __ppc__ || __ppc64__
|
||||
dst = APFloat(PPCDoubleDouble, APInt(128, 2, u.bits));
|
||||
#else
|
||||
llvm_unreachable("Unknown host real_t type for compile-time reals");
|
||||
#endif
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue