On Sat, Jul 30, 2022 at 8:08 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Robert Haas <robertmhaas@gmail.com> writes:
> > I was taught that when programming in C one should avoid returning a
> > struct type, as BufTagGetRelFileLocator does.
>
> FWIW, I think that was invalid pre-ANSI-C, and maybe even in C89.
> C99 and later requires it. But it is pass-by-value and you have
> to think twice about whether you want the struct to be copied.
C89 had that.
As for what it actually does in a non-inlined function: on all modern
Unix-y systems, 128 bit first arguments and return values are
transferred in register pairs[1]. So if you define a struct that
holds uint32_t, uint32_t, uint64_t and compile a function that takes
one and returns it, you see the struct being transferred directly from
input registers to output registers:
0x0000000000000000 <+0>: mov %rdi,%rax
0x0000000000000003 <+3>: mov %rsi,%rdx
0x0000000000000006 <+6>: ret
Similar on ARM64. There it's an empty function, so it must be using
the same register in and out[2].
The MSVC calling convention is different and doesn't seem to be able
to pass it through registers, so it schleps it out to memory at a
return address[3]. But that's pretty similar to the proposed
alternative anyway, so surely no worse. *shrug* And of course those
"constructor"-like functions are inlined anyway.
[1] https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI
[2] https://gcc.godbolt.org/z/qfPzhW7YM
[3] https://gcc.godbolt.org/z/WqvYz6xjs