I found this link quite detailed on the subject, but restricted to C++
(not entirely sure C compiler produces exactly the same...)

http://www.shell-storm.org/papers/files/657.pdf

See table 7 for the case of returning objects...

See also stack cleanup by, 32 bit gcc use hybrid method for structure
passed by values thru a pointer...

Nicolas

2012/5/4 Igor Stasenko <[email protected]>:
> On 4 May 2012 19:18, Nicolas Cellier <[email protected]> 
> wrote:
>> Yes, on max too
>> https://developer.apple.com/library/mac/#documentation/developertools/Conceptual/LowLevelABI/130-IA-32_Function_Calling_Conventions/IA32.html
>>
>> Structures. The called function returns structures according to their
>> aligned size.
>>
>>    Structures 1 or 2 bytes in size are placed in EAX.
>>
>>    Structures 4 or 8 bytes in size are placed in: EAX and EDX.
>>
>
> okay.. i fixed it in  NativeBoost-Core-IgorStasenko.58
>
>>    Structures of other sizes are placed at the address supplied by
>> the caller. For example, the C++ language occasionally forces the
>> compiler to return a value in memory when it would normally be
>> returned in registers. See “Passing Arguments” for more information.
>>
>> I wonder if a structure of size 3 bytes can exist or is automatically
>> extended on 4 bytes...
>>
> yes.. struct alignment is what i fear of..
> IMO it is actually silly to not return struct in registers if it less
> than 8 bytes
> but not power of 2..
>
> sounds like an artefact of establishing the standards :)
>
>> $ cat > test_call.c <<END
>>
>> #include <stdio.h>
>> typedef struct { char a,b,c; } abc;
>> int main() {
>>    abc x;
>>    printf("sizeof(abc)=%d\n",sizeof x);
>>    return 0;
>> }
>> END
>>
>> $ gcc test_call.c
>> $ ./a.exe
>> sizeof(abc)=3
>>
>> And what would be the calling conventions of cygwin gcc ?
>>
>> $ cat > test_call.c <<END
>>
>> #include <stdio.h>
>> typedef struct { char a,b,c; } abc;
>> abc sub() {
>>   abc result;
>>   result.a='a';
>>   result.b='b';
>>   result.c='c';
>>   return result;
>> }
>> int main() {
>>    abc x=sub();
>>    printf("sizeof(abc)=%d abc.a=$c\n",sizeof x,x.a);
>>    return 0;
>> }
>> END
>>
>> $ gcc test_call.c
>> $ ./a.exe
>> sizeof(abc)=3 abc.a=a
>>
>> $ gcc -S test_call.c
>> $ cat test_call.S
>>
>>        .file   "test_call.c"
>>        .text
>> .globl _sub
>>        .def    _sub;   .scl    2;      .type   32;     .endef
>> _sub:
>>        pushl   %ebp
>>        movl    %esp, %ebp
>>        subl    $16, %esp
>>        movl    8(%ebp), %eax
>>        movb    $97, -3(%ebp)
>>        movb    $98, -2(%ebp)
>>        movb    $99, -1(%ebp)
>>        movzwl  -3(%ebp), %edx
>>        movw    %dx, (%eax)
>>        movzbl  -1(%ebp), %edx
>>        movb    %dl, 2(%eax)
>>        leave
>>        ret     $4
>>        .def    ___main;        .scl    2;      .type   32;     .endef
>>        .section .rdata,"dr"
>> LC0:
>>        .ascii "sizeof(abc)=%d\12\0"
>>        .text
>> .globl _main
>>        .def    _main;  .scl    2;      .type   32;     .endef
>> _main:
>>        leal    4(%esp), %ecx
>>        andl    $-16, %esp
>>        pushl   -4(%ecx)
>>        pushl   %ebp
>>        movl    %esp, %ebp
>>        pushl   %ecx
>>        subl    $36, %esp
>>        call    ___main
>>        leal    -11(%ebp), %eax
>>        movl    %eax, (%esp)
>>        call    _sub
>>        subl    $4, %esp
>>        movl    $3, 4(%esp)
>>        movl    $LC0, (%esp)
>>        call    _printf
>>        movl    $0, %eax
>>        movl    -4(%ebp), %ecx
>>        leave
>>        leal    -4(%ecx), %esp
>>        ret
>>        .def    _printf;        .scl    2;      .type   32;     .endef
>>
>> But of course, you already were faster than me...
>>
>> Nicolas
>>
>> 2012/5/4 Igor Stasenko <[email protected]>:
>>> On 4 May 2012 18:37, Eliot Miranda <[email protected]> wrote:
>>>>
>>>>
>>>> On Fri, May 4, 2012 at 6:13 AM, Igor Stasenko <[email protected]> wrote:
>>>>>
>>>>> On 4 May 2012 10:38, Luc Fabresse <[email protected]> wrote:
>>>>> > Hi Igor,
>>>>> >
>>>>> >>
>>>>> >> there is a workaround.
>>>>> >> all structs in C is returned via pointer.
>>>>> >> so, actually a true return type of a function is CvSize*
>>>>> >
>>>>> >
>>>>> > I agree that usually structs are returned through pointers.
>>>>> > But here it is not the case.
>>>>> >
>>>>> > I want to wrap this function:
>>>>> > CvSize cvGetSize( const CvArr* arr );
>>>>> >
>>>>> > and the CvSize struct is returned by value. Am I wrong?
>>>>> >
>>>>>
>>>>> i don't know.. this is a bit shady part of C ABI.
>>>>> Some compilers use return-by-value, some return by pointer
>>>>> by forcing a caller to pass a hidden implicit argument as a pointer to
>>>>> the struct, which then filled with values by
>>>>> the function you call.
>>>>
>>>>
>>>> IIRC x86 ABIs (all the ones I encountered at least, windows, mac, linux,
>>>> solaris)  support structure return (by-value structure return) by passing a
>>>> hidden first argument which is a pointer to a structure into which to copy
>>>> the result.  The callee copies the result back through this pointer.
>>>>
>>>> Where these ABIs differ is in returning small structures.  On win32
>>>> structures a power-of-two in size of 8 bytes or less are returned in
>>>> EAX:EDX.  IIRC on linux and mac all structures are returned through the
>>>> hidden first argument pointer.  See
>>>> ThreadedIA32FFIPlugin>>returnStructInRegisters:
>>>>
>>> on macs (at least what gcc generates) it also returns structs <=8
>>> bytes size in registers:
>>>
>>>
>>> so , currently i implemented it like that:
>>> if sizeof(struct) <= 8 then i assume function returns it in EAX: EDX
>>> otherwise via hidden pointer.
>>>
>>>>>
>>>>>
>>>>> It is easy to add support for that, but to make it work correctly can
>>>>> be tricky.
>>>>> See this, for example:
>>>>>
>>>>> http://stackoverflow.com/questions/161788/are-there-any-downsides-to-passing-structs-by-value-in-c-rather-than-passing-a
>>>>>
>>>>>
>>>>> >>
>>>>> >>
>>>>> >> so, what you do is to change the return value to simple void*
>>>>> >> and then copy the contents of struct into instance of corresponding
>>>>> >> NBExternalStructure subclass
>>>>> >> using #fromPointer: method.. to conveniently access its fields values.
>>>>> >
>>>>> >
>>>>> > yes I saw that in NB tests.
>>>>> >
>>>>> >>
>>>>> >>
>>>>> >>
>>>>> >> but this is in general, in your case this function is actually inlined
>>>>> >> by compiler (as CV_INLINE suggests), so there could be even no
>>>>> >> exported symbol for it in dynamic library.
>>>>> >> and the function is actually so simple, that you don't need to wrap it
>>>>> >> at
>>>>> >> all.
>>>>> >> you can just create a subclass of NBExternalStructure , named CvSize,
>>>>> >> implement fieldDesc method as:
>>>>> >>
>>>>> >> fieldsDesc
>>>>> >> ^ #(
>>>>> >> int width;
>>>>> >> int height
>>>>> >> )
>>>>> >>
>>>>> >>
>>>>> >> and if you invoke:
>>>>> >>
>>>>> >> CvSize new width: 1 height:2
>>>>> >>
>>>>> >> it will be equivalent as if you will call cvSize(1,2) function.
>>>>> >
>>>>> >
>>>>> > yes it is exactly what I did.
>>>>> >
>>>>> > So my problem is:
>>>>> >
>>>>> > NBCvSize implemented as a subclass of NBExternalStruct with fieldDesc
>>>>> > correctly set up.
>>>>> > Then wrap the function cvGetSize:
>>>>> >
>>>>> > getSize
>>>>> >       self nbCall: #(NBCvSize cvGetSize(IplImage self)) module: LIB_CV.
>>>>> >
>>>>> > But I get a debugger because:
>>>>> >
>>>>> > NBExternalStruct>>coerceReturn: gen
>>>>> > " ... should we support handling return of external structures? "
>>>>> > self error: 'returning pointer to structure?'
>>>>> >
>>>>> > And I have no idea how to implement this (black magic EAX pop push ;-))
>>>>> > to
>>>>> > coerce result of struct.
>>>>> >
>>>>>
>>>>>
>>>>> you don't. if function takes an implicit struct pointer, you can just
>>>>> rewrite the function signature from
>>>>> NBCvSize cvGetSize(IplImage self)
>>>>> to:
>>>>>
>>>>> void cvGetSize(NBCvSize hidden, IplImage self)
>>>>>
>>>>> and so, you pass a fresh instance of NBCvSize as argument, which
>>>>> function then fill.
>>>>> But if C compiler using registers to return struct.. then you're screwed
>>>>> :)
>>>>>
>>>>> Anyways, Luc i will try to read docs about C ABI and see if we can
>>>>> easily add support for that.
>>>>>
>>>>> --
>>>>> Best regards,
>>>>> Igor Stasenko.
>>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> best,
>>>> Eliot
>>>>
>>>
>>>
>>>
>>> --
>>> Best regards,
>>> Igor Stasenko.
>>
>
>
>
> --
> Best regards,
> Igor Stasenko.
>

Reply via email to