2016-11-17 73 views
6

我比较了2个C函数返回一个结构。我们知道,在ABI级别上,大结构将作为第一个函数参数传递指针。sret实际上意味着什么?

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; 
} 

对于这些函数,我检查了x86_64 Linux和Windows的程序集。​​被宣布为void @fsret(%struct.S* sret %s)

比较这两个变体,被调用方没有区别。但是,在函数内,​​还将其第一个参数(指向结构的指针)复制到RAX寄存器。为什么?

+0

如果你做'如果(fsret()字[0] == 10){do_something(); ''?在这种情况下编译器需要返回值(不确定,只是一个想法) –

回答

4

原因在于this回顾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. 

使被叫方,以填补由主叫方提供的内存和返回它传递以及指针。

这由x86_64 R252系统V ABI文件

返回值的确认的值的返回根据以下 算法完成:

  1. 分类返回类型与分类算法。
  2. 如果该类型有类MEMORY (ndMarco:即大的东西),那么调用者的返回 值提供了空间,并就好像它是第一 函数参数通过这个存储在%RDI的地址。实际上,这个地址变成了一个“隐藏的”第一个参数。 此存储不得与通过 以外的其他名称与被调用方可见的任何数据重叠。 退货时,%rax将包含 调用方以%rdi传入的地址。
+1

很好的答案!你知道其他目标是否有类似的要求? –

+0

@PawełBylica[o32和eabi](http://www.brunocardoso.cc/blog/?p=27),很多ABI文件都很差 –

相关问题