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

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Wed Nov 6 13:16:14 UTC 2019


Wikipedia tells that ou assumptions are wrong:

https://en.wikipedia.org/wiki/X86_calling_conventions

or if you prefer going to the reference:

https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf

You'll see that the rules are quite complex!
Notably, page 21, the structure has class MEMORY if longer than eight
eightbyte (that's 64 bytes !).
So you should open bug report on Smalltalk side...
And we lack many tests...

Le mer. 6 nov. 2019 à 13:56, Nicolas Cellier <
nicolas.cellier.aka.nice at gmail.com> a écrit :

>  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/e6d4376a/attachment.html>


More information about the Squeak-dev mailing list