newCTFE Status November 2018

Joakim dlang at joakim.fea.st
Sun Dec 9 15:23:30 UTC 2018


On Sunday, 9 December 2018 at 14:48:31 UTC, H. S. Teoh wrote:
> On Sat, Dec 08, 2018 at 05:19:59PM +0000, Joakim via 
> Digitalmars-d wrote: [...]
>> On Saturday, 8 December 2018 at 15:42:43 UTC, H. S. Teoh wrote:
>> > On Sat, Dec 08, 2018 at 04:06:11AM +0000, Joakim via 
>> > Digitalmars-d wrote: [...]
>> > > Btw, do you know some way to get the current compile-time 
>> > > real's precision in D code? It would be useful to avoid 
>> > > static asserts from overflowing when the runtime real's 
>> > > precision exceeds the compile-time real's precision, which 
>> > > doesn't happen with dmd but can with ldc:
>> > > 
>> > > https://github.com/dlang/phobos/pull/6790#discussion_r238633160
>> > 
>> > Doesn't real.dig give the (approximate) precision of real? 
>> > Or is
>> > that hard-coded in the frontend?
>> 
>> Just so we're clear, the issue is what the precision of reals 
>> are when running CTFE code to initialize a constant, as 
>> opposed to the precision of the real at runtime. For dmd, this 
>> doesn't really matter since it only supports x86/x64 chips, 
>> but ldc uses the host's real at compile-time, which can 
>> obviously vary from the target. That's why I mentioned to you 
>> in another thread that some stdlib math tests assert when 
>> cross-compiling from x64 to Android/AArch64, because of that 
>> mismatch in host->target precision for reals.
>
> Ahhh, so *that's* the reason for the failure.

Specifically, real.max overflows when it tries to evaluate that 
expression, as it tries to stick the 128-bit real.max in the 
80-bit x87 real and overflows to Inf, tripping the static assert.

> But I'd think that's more than just a floating-point issue; 
> wouldn't CTFE in general be problematic if there's a mismatch 
> between host built-in types vs. target built-in types when 
> cross-compiling? I suppose D's fixed-sized types help a lot in 
> this regard (imagine the mess if `int` varies in size across 
> host/target archs -- the kind of mess C/C++ have to deal with). 
> But `real` is a fly in the ointment.

Yes, this is called out in the spec:

"Functions executed via CTFE can give different results from run 
time in the following scenarios:

- floating point computations may be done at a higher precision 
than run time"
https://dlang.org/spec/function.html#interpretation

Of course, that was likely written before we started supporting 
64-bit and 128-bit reals, so it was probably assumed that 80-bit 
x87 reals would always be used at compile-time and at worst would 
be _more_ precise. That's not the case with ldc anymore, since 
ldc running on an ARM host will do CTFE at 64-bit precision and 
80-bit on an x64 host isn't enough when cross-compiling to 
128-bit AArch64 reals.

> I'd imagine difference in endianness would be another cause of 
> problems in cross-compilation, though for the most part typical 
> D code wouldn't be affected by this at least as far as CTFE is 
> concerned (since casting / reinterpretation of unions is not 
> currently allowed).

Unsure.

>> real.dig has the same problem as real.mant_dig above, it only 
>> gives the target's precision. Compiling this snippet with ldc, 
>> `void main() { pragma(msg, "precision is ", real.dig);}`, I 
>> get 18 when compiling natively on linux/x64, but 33 when 
>> cross-compiling to Android/AArch64, ie it always gives the 
>> target real's precision.
>
> Which it should, since any code that depends on real.dig is 
> ostensibly expecting the target arch's precision, not the 
> host's which may change depending on which host you use to 
> compile it.

I tried various other ways before, like checking an enum's 
precision or inside a __ctfe block, but they all give the 
target's precision, as kinke says, even though they're running at 
compile-time.

> Looks like we'll somehow need a way to tell the CTFE engine 
> what the target arch should be, and when something doesn't 
> match the host type, it should run a software emulation instead 
> of using the host's `real`.

Yes, Iain says gdc already uses such multi-precision soft-float, 
and kinke mentioned earlier in this thread that he'd like to do 
the same with ldc. The reason I brought this issue up is that 
Stefan initially mentioned doing something similar for dmd.


More information about the Digitalmars-d mailing list