Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What sret actually means?

Tags:

c

abi

llvm

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?

like image 490
Paweł Bylica Avatar asked Nov 17 '16 18:11

Paweł Bylica


1 Answers

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.
like image 115
Marco A. Avatar answered Sep 19 '22 13:09

Marco A.