www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 9969] New: dmd ABI mistake (cfloat static array initialisation)

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9969

           Summary: dmd ABI mistake (cfloat static array initialisation)
           Product: D
           Version: D2
          Platform: x86_64
        OS/Version: Linux
            Status: NEW
          Severity: major
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: john.loughran.colvin gmail.com


--- Comment #0 from John Colvin <john.loughran.colvin gmail.com> 2013-04-20
16:22:40 BST ---
test.d:

import std.stdio;
void main()
{
    cfloat a[2];
}

$ dmd test.d
$ ./test
Segmentation fault (core dumped)

The problem is here:

0000000000000000 <_Dmain>:
   0:   55                      push   rbp
   1:   48 8b ec                mov    rbp,rsp
   4:   48 83 ec 10             sub    rsp,0x10
   8:   48 83 ec 08             sub    rsp,0x8
   c:   48 be 02 00 00 00 00    movabs rsi,0x2
  13:   00 00 00
  16:   ff 35 00 00 00 00    push   QWORD PTR [rip+0x0]        # 1c <_Dmain$
                        18: R_X86_64_PC32    .rodata-0x4
  1c:   48 8d 7d f0             lea    rdi,[rbp-0x10]
  20:   e8 00 00 00 00          call   25 <_Dmain+0x25>
                        21: R_X86_64_PC32    _memset64-0x4
  25:   48 83 c4 10             add    rsp,0x10
  29:   31 c0                   xor    eax,eax
  2b:   c9                      leave
  2c:   c3                      ret
  2d:   0f 1f 00                nop    DWORD PTR [rax]

0000000000000000 <_memset64>:
   0:   55                      push   rbp
   1:   48 8b ec                mov    rbp,rsp
   4:   48 83 ec 10             sub    rsp,0x10
   8:   49 89 f8                mov    r8,rdi
   b:   49 89 f1                mov    r9,rsi
   e:   48 89 f8                mov    rax,rdi
  11:   49 8d 0c d0             lea    rcx,[r8+rdx*8]
  15:   4c 3b c1                cmp    r8,rcx
  18:   73 0c                   jae    26 <_memset64+0x26>
  1a:   4d 89 08                mov    QWORD PTR [r8],r9
  1d:   49 83 c0 08             add    r8,0x8
  21:   49 39 c8                cmp    r8,rcx
  24:   72 f4                   jb     1a <_memset64+0x1a>
  26:   48 8b e5                mov    rsp,rbp
  29:   5d                      pop    rbp
  2a:   c3                      ret

long *_memset64(long *p, long value, size_t count)

_memset64 is extern(C). Dmd passes "p" correctly, but then tries to pass
"value" on the stack and passes the value for "count" as the second argument.
_memset64 attempts to use rdx as the count, which is garbage. Hence, segfault.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 20 2013
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9969


Maxim Fomin <maxim maxim-fomin.ru> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |maxim maxim-fomin.ru


--- Comment #1 from Maxim Fomin <maxim maxim-fomin.ru> 2013-04-20 09:18:30 PDT
---
Looks like an issue 9449.

I think the problem isn't  "ABI mistake" (or a codegen bug as often mentioned
here - many people who can spot an error from asm output tend to blame backend)
but absence of crosstalk between how dmd assumes memset functions look like and
how they are actually defined in druntime.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 20 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9969



--- Comment #2 from John Colvin <john.loughran.colvin gmail.com> 2013-04-20
18:14:12 BST ---
(In reply to comment #1)
 Looks like an issue 9449.
 
 I think the problem isn't  "ABI mistake" (or a codegen bug as often mentioned
 here - many people who can spot an error from asm output tend to blame backend)
 but absence of crosstalk between how dmd assumes memset functions look like and
 how they are actually defined in druntime.
I'm confused as to how trying to pass a variable on the stack to an extern(C) function with less than 6 arguments on linux x64 is not a codegen error of some sorts. It's using the wrong calling convention... -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 20 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9969



--- Comment #3 from John Colvin <john.loughran.colvin gmail.com> 2013-04-20
18:16:49 BST ---
(In reply to comment #2)
 (In reply to comment #1)
 Looks like an issue 9449.
 
 I think the problem isn't  "ABI mistake" (or a codegen bug as often mentioned
 here - many people who can spot an error from asm output tend to blame backend)
 but absence of crosstalk between how dmd assumes memset functions look like and
 how they are actually defined in druntime.
I'm confused as to how trying to pass a variable on the stack to an extern(C) function with less than 6 arguments on linux x64 is not a codegen error of some sorts. It's using the wrong calling convention...
s/codegen/ABI -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 20 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9969



--- Comment #4 from Maxim Fomin <maxim maxim-fomin.ru> 2013-04-20 11:12:35 PDT
---
(In reply to comment #2)
 (In reply to comment #1)
 Looks like an issue 9449.
 
 I think the problem isn't  "ABI mistake" (or a codegen bug as often mentioned
 here - many people who can spot an error from asm output tend to blame backend)
 but absence of crosstalk between how dmd assumes memset functions look like and
 how they are actually defined in druntime.
I'm confused as to how trying to pass a variable on the stack to an extern(C) function with less than 6 arguments on linux x64 is not a codegen error of some sorts. It's using the wrong calling convention...
I do not think that if you can see that compiler passes arguments wrong you may conclude that it is codegen or ABI bug. That is what actually often happens: somebody see error in asm output and blames backend while the problem is really in frontend. From what I know after debugging issue 9449 there is likely error in scope of AssignExp::toElem (https://github.com/D-Programming-Language/dmd/blob/master/src/e2ir.c#L2688) (or setArray()) which does not handle properly cases like this. The problem is in frontend assumption that druntime defines memset function as taking dynamic array. The backend just does what it is told to generate. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 20 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9969



--- Comment #5 from John Colvin <john.loughran.colvin gmail.com> 2013-04-20
23:18:54 BST ---
(In reply to comment #4)
 (In reply to comment #2)
 (In reply to comment #1)
 Looks like an issue 9449.
 
 I think the problem isn't  "ABI mistake" (or a codegen bug as often mentioned
 here - many people who can spot an error from asm output tend to blame backend)
 but absence of crosstalk between how dmd assumes memset functions look like and
 how they are actually defined in druntime.
I'm confused as to how trying to pass a variable on the stack to an extern(C) function with less than 6 arguments on linux x64 is not a codegen error of some sorts. It's using the wrong calling convention...
I do not think that if you can see that compiler passes arguments wrong you may conclude that it is codegen or ABI bug. That is what actually often happens: somebody see error in asm output and blames backend while the problem is really in frontend. From what I know after debugging issue 9449 there is likely error in scope of AssignExp::toElem (https://github.com/D-Programming-Language/dmd/blob/master/src/e2ir.c#L2688) (or setArray()) which does not handle properly cases like this. The problem is in frontend assumption that druntime defines memset function as taking dynamic array. The backend just does what it is told to generate.
I concede that there may well be a frontend problem as well, but in my limited experience a properly functioning backend should never emit the code we see here. System V dictates that the first 6 integer/pointer arguments passed in RDI, RSI, RDX, RCX, R8, and R9, the first 8 floating point arguments are passed in XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6 and XMM7 an any further arguments are passed on the stack. If the compiler emits code passing 3 arguments to an extern(C) function, 2 in ESI and EDI and 1 on the stack, then it's a problem relating to the ABI. The actual signature/behaviour of the target function is irrelevant, AFAIK there is no possible System V compliant target function for which that argument passing would be correct. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 20 2013
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9969


Maxim Fomin <maxim maxim-fomin.ru> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Severity|major                       |critical


--- Comment #6 from Maxim Fomin <maxim maxim-fomin.ru> 2013-04-21 04:33:59 PDT
---
(In reply to comment #5)
 I concede that there may well be a frontend problem as well, but in my limited
 experience a properly functioning backend should never emit the code we see
 here.
What backend generates isn't determined only by it, bugs in frontend may lead to incorrect instructions. Look at: extern(C) int printf(const char*, ... ); extern(C) long *_memset64(long *p, long value, size_t count); void main() { long[2] arr = void; _memset64(arr.ptr, 1, 2); printf("%d %d\n", arr[0], arr[1]); //cfloat[2] bug; } and _Dmain. In this case call to memset is constructed by CallExp and things are done right, but in case of cfloat[2] call is constructed by AssignExp and setArray (https://github.com/D-Programming-Language/dmd/blob/master/src/e2ir.c#L757) and invalid code is generated. Anyway, this is critical. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 21 2013