[squeak-dev] Alien primFFICall returning struct with 64bit vm
Nicolas Cellier
nicolas.cellier.aka.nice at gmail.com
Wed Nov 6 19:14:55 UTC 2019
I have opened https://github.com/OpenSmalltalk/opensmalltalk-vm/issues/443
because it won't be solved that easily... It might take some time.
Le mer. 6 nov. 2019 à 14:16, Nicolas Cellier <
nicolas.cellier.aka.nice at gmail.com> a écrit :
> 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/e6a8f1d1/attachment.html>
More information about the Squeak-dev
mailing list
|