1

In C++ you can return a user-defined type by value. In x86-64 ASM return by value is implemented by moving the return value to RAX and popping the stored previous value of RIP into RIP to return to the caller. How can a struct or really any type of array that is larger than RAX be returned by value?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • Did you consider reading [wikipedia](https://en.wikipedia.org/wiki/X86_calling_conventions#x86-64_calling_conventions) which documents multiple calling conventions (i.e. there's not *an* x86-64 calling convention) and does discuss larger sized return values. – Damien_The_Unbeliever Jul 19 '22 at 06:41
  • Agner has a good summary on different calling conventions. https://www.agner.org/optimize/calling_conventions.pdf The short answer is: A hidden pointer argument is added to the function and it is expected to fill the pointer with the return value – Homer512 Jul 19 '22 at 06:41
  • 1
    Related, answering a more complex question about extra copying or not: [How are oversized struct returned on the stack?](https://stackoverflow.com/q/67824821). Near duplicate of [how c compiler treats a struct return value from a function, in ASM](https://stackoverflow.com/q/24741218) – Peter Cordes Jul 19 '22 at 13:24

1 Answers1

2

The SYSV x86_64 calling conventions (used by everyone except Microsoft) allow structures of up to 16 bytes and INTEGER classification to be returned in the RAX/RDX register pair, while those of SSE classification and up to 32 bytes can be returned in the XMM0/XMM1 register pair.

The classification of a struct depends on the types of the fields in the struct, but basically integer and pointer types will be INTEGER while float and double will be SSE.

Larger structs will get MEMORY classification, so will require an extra hidden argument (passed in RDI, so prepended to the existing arguments) specifying a pointer to memory that the return value will be written to. This pointer will be returned in RAX.

This is all detailed in the SYSV x86_64 ABI doc

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226