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