On 4 May 2012 20:27, Nicolas Cellier <[email protected]> wrote:
> 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
>
thanks for the link, nicolas.. the information about these conventions
are really sparse.

> 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.
>>
>



-- 
Best regards,
Igor Stasenko.

Reply via email to