2016-11-17 6 views
6

Я сравнил 2 функции C, возвращающие структуру. Мы знаем, что на уровне ABI большие структуры будут проходить по указателю в качестве первого аргумента функции.Что на самом деле означает?

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. fsret объявлен как void @fsret(%struct.S* sret %s).

Сравнивая эти два варианта, нет разницы на стороне вызываемого абонента. Однако внутри функций fsret дополнительно копирует свой первый аргумент (указатель на структуру) в регистр RAX. Зачем?

+0

, что если вы делаете 'если (fsret() слова [0] == 10.) {Do_something(); } '? компилятор нуждается в возвращаемом значении в этом случае (не уверен, просто идея) –

ответ

4

Причина заключается в this обзора дифф:

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 System V ABI

Возвращение значений Возвращение значений осуществляется в соответствии со следующим алгоритму:

  1. классифицируют тип возвращаемого с классификацией алгоритм.
  2. Если тип имеет класс памяти (ndMarco: т.е. большие вещи), то вызывающий абонент предоставляет пространство для возвращаемого значения и передает адрес этой памяти в% RDI, как если бы это был первый аргумент функции , По сути, этот адрес становится «скрытым» первым аргументом. Это хранилище не должно перекрывать любые данные, видимые вызываемому лицу, через другие имена, кроме этого аргумента. При возврате% rax будет содержать адрес, который был передан вызывающим абонентом в% rdi.
+1

Отличный ответ! Знаете ли вы, есть ли аналогичные требования для других целей? –

+0

@ PawełBylica [o32 и eabi] (http://www.brunocardoso.cc/blog/?p=27), многие документы ABI довольно бедны –

 Смежные вопросы

  • Нет связанных вопросов^_^