What sret actually means?
Asked Answered
E

1

8

I compared 2 C functions returning a struct. We know that on ABI level big structs are going to be passes by pointer as the first function argument.

struct S {
    int words[8];
};

struct S fsret() {
    struct S s;
    s.words[0] = 1;
    return s;
}

void fout(struct S* s) {
    s->words[0] = 1;
}

For these functions I checked the assembly for x86_64 Linux and Windows. The fsret is declared as void @fsret(%struct.S* sret %s).

Comparing these two variants, there is no difference on the callee side. However, inside the functions the fsret additionally copies its first argument (the pointer to the struct) to the RAX register. Why?

Experimental answered 17/11, 2016 at 18:44 Comment(1)
what if you do if (fsret().words[0]==10) { do_something(); } ? the compiler needs a return value in that case (not sure, just an idea)Openeyed
S
6

The reason lies in this review diff:

if (Subtarget->is64Bit() || Subtarget->isTargetKnownWindowsMSVC()) {
  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
    // The x86-64 ABIs require that for returning structs by value we copy
    // the sret argument into %rax/%eax (depending on ABI) for the return.
    // Win32 requires us to put the sret argument to %eax as well.
    // Save the argument into a virtual register so that we can access it
    // from the return points.

so the callee has to fill the memory supplied by the caller and return the pointer that it was passed as well.

This is confirmed by the x86_64 r252 System V ABI document

Returning of Values The returning of values is done according to the following algorithm:

  1. Classify the return type with the classification algorithm.
  2. If the type has class MEMORY (ndMarco: i.e. big stuff), then the caller provides space for the return value and passes the address of this storage in %rdi as if it were the first argument to the function. In effect, this address becomes a “hidden” first argument. This storage must not overlap any data visible to the callee through other names than this argument. On return %rax will contain the address that has been passed in by the caller in %rdi.
Scimitar answered 17/11, 2016 at 19:3 Comment(2)
Great answer! Do you know if there are similar requirements for other targets?Aware
@PawełBylica o32 and eabi, many ABI documentations are rather poorScimitar

© 2022 - 2024 — McMap. All rights reserved.