[Issue 16243] wrong C++ argument passing with empty struct and 6 integers

via Digitalmars-d-bugs digitalmars-d-bugs at puremagic.com
Sat May 20 03:13:23 PDT 2017


https://issues.dlang.org/show_bug.cgi?id=16243

--- Comment #13 from Joakim <dbugz at joakim.fea.st> ---
I spent a little time looking into this again.  The issue now appears to only
be reproducible if clang compiles without any optimizations, which is what the
dmd testsuite does.  When run without any optimizations, clang assumes the
empty struct will not be passed in and only passes along the first six
arguments, ie arg0 through arg5.  Since arg6 is not passed back to check13956,
it asserts.

These issues only crop up on 32-bit arches, including ARM32, as kinke noted
last summer, which explains why Jacob hasn't seen this on 64-bit OS X.

Here is the disassembly for what clang produces on linux/x86 without
optimization:

00000000 <_Z9func139566S13956iiiiii>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   53                      push   %ebx
   4:   57                      push   %edi
   5:   56                      push   %esi
   6:   83 ec 3c                sub    $0x3c,%esp
   9:   8b 45 1c                mov    0x1c(%ebp),%eax
   c:   8b 4d 18                mov    0x18(%ebp),%ecx
   f:   8b 55 14                mov    0x14(%ebp),%edx
  12:   8b 75 10                mov    0x10(%ebp),%esi
  15:   8b 7d 0c                mov    0xc(%ebp),%edi
  18:   8b 5d 08                mov    0x8(%ebp),%ebx
  1b:   89 5d ec                mov    %ebx,-0x14(%ebp)
  1e:   89 7d e8                mov    %edi,-0x18(%ebp)
  21:   89 75 e4                mov    %esi,-0x1c(%ebp)
  24:   89 55 e0                mov    %edx,-0x20(%ebp)
  27:   89 4d dc                mov    %ecx,-0x24(%ebp)
  2a:   89 45 d8                mov    %eax,-0x28(%ebp)
  2d:   8b 45 ec                mov    -0x14(%ebp),%eax
  30:   8b 4d e8                mov    -0x18(%ebp),%ecx
  33:   8b 55 e4                mov    -0x1c(%ebp),%edx
  36:   8b 75 e0                mov    -0x20(%ebp),%esi
  39:   8b 7d dc                mov    -0x24(%ebp),%edi
  3c:   8b 5d d8                mov    -0x28(%ebp),%ebx
  3f:   89 04 24                mov    %eax,(%esp)
  42:   89 4c 24 04             mov    %ecx,0x4(%esp)
  46:   89 54 24 08             mov    %edx,0x8(%esp)
  4a:   89 74 24 0c             mov    %esi,0xc(%esp)
  4e:   89 7c 24 10             mov    %edi,0x10(%esp)
  52:   89 5c 24 14             mov    %ebx,0x14(%esp)
  56:   e8 fc ff ff ff          call   57 <_Z9func139566S13956iiiiii+0x57>
  57: R_386_PC32  _Z10check139566S13956iiiiii
  5b:   83 c4 3c                add    $0x3c,%esp
  5e:   5e                      pop    %esi
  5f:   5f                      pop    %edi
  60:   5b                      pop    %ebx
  61:   5d                      pop    %ebp
  62:   c3                      ret

Conversely, here's what gcc produces:

00000000 <_Z9func139566S13956iiiiii>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 ec 08                sub    $0x8,%esp
   6:   83 ec 04                sub    $0x4,%esp
   9:   ff 75 20                pushl  0x20(%ebp)
   c:   ff 75 1c                pushl  0x1c(%ebp)
   f:   ff 75 18                pushl  0x18(%ebp)
  12:   ff 75 14                pushl  0x14(%ebp)
  15:   ff 75 10                pushl  0x10(%ebp)
  18:   ff 75 0c                pushl  0xc(%ebp)
  1b:   50                      push   %eax
  1c:   e8 fc ff ff ff          call   1d <_Z9func139566S13956iiiiii+0x1d>
                        1d: R_386_PC32  _Z10check139566S13956iiiiii
  21:   83 c4 20                add    $0x20,%esp
  24:   90                      nop
  25:   c9                      leave
  26:   c3                      ret

When clang is run with optimization, it just calls the D function directly,
which happens to avoid the problem, though likely the underlying assumption is
still there:

00000000 <_Z9func139566S13956iiiiii>:
   0:   e9 fc ff ff ff          jmp    1 <_Z9func139566S13956iiiiii+0x1>
                        1: R_386_PC32   _Z10check139566S13956iiiiii

I'm not sure if clang with optimization always did this: just don't remember if
I tried it before, maybe not.

As kinke said, clang and gcc assume different argument passing for empty
structs on 32-bit arches, confirmed for both x86 and ARM32.  dmd and ldc work
with the gcc approach, but not clang's.

--


More information about the Digitalmars-d-bugs mailing list