Bug 18573 – cast(void) leads to floating point return value not being popped from FPU stack

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2018-03-07T21:47:15Z
Last change time
2019-02-18T02:36:46Z
Keywords
wrong-code
Assigned to
No Owner
Creator
Matthew Gamble
See also
https://issues.dlang.org/show_bug.cgi?id=19676

Comments

Comment #0 by gamblemj — 2018-03-07T21:47:15Z
Seems to be a problem with using "each" under 32bit which can be fixed by using foreach or switching to x64. Let to a long discussion on the learn forum that went past my pay grade: https://forum.dlang.org/post/[email protected] Below is a silly case, that replicates the error. (i.e. I know I could use iota(0,9,2).array), but that does not demonstrate the potential bug and would not fix my actual program.) import std.range; import std.algorithm; import std.stdio; unittest { auto a = new double[9]; a[0] = 0; iota(1,a.length).each!(i => a[i] = a[i-1] + 2); writeln(a); } //x86, wrong, error //[-nan, 2, 4, 6, 8, 10, 12, 14, 16] //First-chance exception: std.format.FormatException Unterminated format specifier: "%" at C:\D\dmd2\windows\bin\..\..\src\phobos\std\format.d(1175) //x64, correct //[0, 2, 4, 6, 8, 10, 12, 14, 16] unittest { auto a = new double[9]; a[0] = 0; foreach(i; 1..a.length) a[i] = a[i - 1] + 2; writeln(a); } //x86, correct //[0, 2, 4, 6, 8, 10, 12, 14, 16] //x64, correct //[0, 2, 4, 6, 8, 10, 12, 14, 16] Originally found on windows 10, DMD v2.076.1, but now confirmed by others on linux and current version.
Comment #1 by ketmar — 2018-03-07T22:05:11Z
some clarification: basically, this boils down to codegen bug: if we have function that returns some floating point value, and FPU is involved, and caller does `cast(void)myfunc()`, result is not popped from FPU stack. note that `cast(void)` is vital here: everything is ok without it. also, as X86_64 doesn't use FPU for floats and doubled, you need to use `real` there to trigger the bug. minified sample by ag0aep6g: double f() { return 1; } void main() { cast(void) f(); cast(void) f(); cast(void) f(); cast(void) f(); cast(void) f(); cast(void) f(); cast(void) f(); double b = 2; assert(b == 2); /* fails; should pass */ }
Comment #2 by ketmar — 2018-03-07T22:06:52Z
p.s.: as this bug affects x86_64 too (albeit only with `real`s), i changed arch to all.
Comment #3 by ag0aep6g — 2019-02-14T20:54:05Z
*** Issue 19437 has been marked as a duplicate of this issue. ***
Comment #4 by bugzilla — 2019-02-14T23:13:31Z
The test case: real foo(); void test1() { cast(void)foo(); } void test2() { foo(); } compiles to: __D4test5test1FZv: call __D4test3fooFZe ret __D4test5test2FZv: call __D4test3fooFZe fstp ST ret which nicely illustrates the problem.
Comment #5 by bugzilla — 2019-02-15T01:45:57Z
Comment #6 by dlang-bot — 2019-02-18T02:36:46Z
dlang/dmd pull request #9362 "fix Issue 18573 - cast(void) leads to floating point return value not…" was merged: https://github.com/dlang/dmd/pull/9362