[squeak-dev] Alien primFFICall returning struct with 64bit vm

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Wed Nov 6 12:56:10 UTC 2019


 Hi Balazs,
I confirm what you observe.
If I compile the source with:

    clang --shared -o libalientest.so -Os alientest.c

then disassemble with:

    objdump -D libalientest.so  | less

I get this:

    000000000000057c <atv>:
     57c:   c3                      retq

    000000000000057d <at34>:
     57d:   f2 0f 10 05 1b 00 00    movsd  0x1b(%rip),%xmm0        # 5a0
<_fini+0x10>
     584:   00
     585:   f2 0f 10 0d 1b 00 00    movsd  0x1b(%rip),%xmm1        # 5a8
<_fini+0x18>
     58c:   00
     58d:   c3                      retq

Code is highly suspicious for atv...
at34 just load the constants in dregs, then do nothing (inline atv).
So this does not work as advertized...

The non optimized version is very convoluted:

0000000000000580 <atv>:
 580:   55                      push   %rbp
 581:   48 89 e5                mov    %rsp,%rbp
 584:   f2 0f 11 45 e8          movsd  %xmm0,-0x18(%rbp)
 589:   f2 0f 11 4d e0          movsd  %xmm1,-0x20(%rbp)
 58e:   f2 0f 10 45 e8          movsd  -0x18(%rbp),%xmm0
 593:   f2 0f 11 45 d0          movsd  %xmm0,-0x30(%rbp)
 598:   f2 0f 10 45 e0          movsd  -0x20(%rbp),%xmm0
 59d:   f2 0f 11 45 d8          movsd  %xmm0,-0x28(%rbp)
 5a2:   0f 10 45 d0             movups -0x30(%rbp),%xmm0
 5a6:   0f 29 45 f0             movaps %xmm0,-0x10(%rbp)
 5aa:   f2 0f 10 45 f0          movsd  -0x10(%rbp),%xmm0
 5af:   f2 0f 10 4d f8          movsd  -0x8(%rbp),%xmm1
 5b4:   5d                      pop    %rbp
 5b5:   c3                      retq
 5b6:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
 5bd:   00 00 00

00000000000005c0 <at34>:
 5c0:   55                      push   %rbp
 5c1:   48 89 e5                mov    %rsp,%rbp
 5c4:   48 83 ec 10             sub    $0x10,%rsp
 5c8:   f2 0f 10 05 38 00 00    movsd  0x38(%rip),%xmm0        # 608
<_fini+0x10>
 5cf:   00
 5d0:   f2 0f 10 0d 38 00 00    movsd  0x38(%rip),%xmm1        # 610
<_fini+0x18>
 5d7:   00
 5d8:   e8 a3 ff ff ff          callq  580 <atv>
 5dd:   f2 0f 11 45 f0          movsd  %xmm0,-0x10(%rbp)
 5e2:   f2 0f 11 4d f8          movsd  %xmm1,-0x8(%rbp)
 5e7:   f2 0f 10 45 f0          movsd  -0x10(%rbp),%xmm0
 5ec:   f2 0f 10 4d f8          movsd  -0x8(%rbp),%xmm1
 5f1:   48 83 c4 10             add    $0x10,%rsp
 5f5:   5d                      pop    %rbp
 5f6:   c3                      retq

It's clear that the resulting structure is passed via first 2 dregs (xmm0
and xmm1).
Doesn't it qualify as a clang bug? Or is our interpretation of ABI
erroneous?
I would opt for the later...

Le mar. 5 nov. 2019 à 23:54, Balázs Kósi <rebmekop at gmail.com> a écrit :

> Hi all,
>
> I'm having trouble with calling struct returning functions with alien on a
> 64bit linux vm using the hidden first argument mechanism [1]. The function
> gets called, but the result is not copied into the struct pointed by the
> hidden argument.
>
> I tried to debug what happens with gdb, but everything looks fine, except
> not getting the result back. The address is copied into %rdi (regs[0]) in
> dax64business.h:92 [2], which is exactly what the spec says [3].
>
> Here is a minimal example calling a C function returning a struct with two
> doubles:
>
> at34 := Alien lookup: 'at34' inLibrary: 'libalientest.so'.
> at34 primFFICallResult: nil with: (r := Alien newC: 16) pointer.
> vec := (r doubleAt: 1) @ (r doubleAt: 9). r free. vec " 0.0 at 0.0 "
>
> returns 0.0 at 0.0 instead of 3.0 at 4.0
>
> the C code goes like this:
>
> typedef struct atvect{double x, y;} atvect;
>
> atvect atv(double x, double y) {
>   atvect v = {x, y};
>   return v;
> }
>
> atvect at34() {
>   return atv(3.0, 4.0);
> }
>
> The vm is sqcogspur64linuxht 5.0-201910291408. The image is a recent trunk
> image (update: #19142), image format 68021 (64 bit). Alien is
> Alien-Core-TorstenBergmann.101.mcz.
>
> What am I missing?
>
> Thanks, Balázs
>
> [1] "The rules for structure results vary slightly by platform. Most
> functions returning structures expect a “hidden” first parameter holding
> the result struct’s address. Because the FFI provides no abstraction one
> must pass this parameter explicitly. ... On linux all struct results are
> re-turned through the hidden first argument mechanism ... ".
>
> https://wiki.squeak.org/squeak/uploads/6100/Alien%20FFI.2.pdf
>
> [2]
> https://github.com/OpenSmalltalk/opensmalltalk-vm/blob/a8a1dc1e33267e0fa2dab22959e41d0a072420d9/platforms/Cross/plugins/IA32ABI/dax64business.h#L92
>
> [3] "2. If the type has class MEMORY, then the caller provides space for
> the return value and passes the address of this storage in %rdi as if it
> were the first
> argument to the function. In effect, this address becomes a “hidden” first
> ar-
> gument. This storage must not overlap any data visible to the callee
> through
> other names than this argument.
> On return %rax will contain the address that has been passed in by the
> caller in %rdi."
>
> https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf p.24.
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20191106/b21fffe5/attachment.html>


More information about the Squeak-dev mailing list