Соглашения о вызовах с составными типами дат

Я понимаю соглашения о вызовах для передачи 32-битных и 64-битных целых чисел (и указателей), чисел с плавающей запятой и удвоений для 64-битного кода для Microsoft и System V AMD64 ABI. Но мне непонятно, какие существуют соглашения о вызовах для составных типов данных.

Чтобы было понятнее, каковы соглашения о вызовах для передачи структур, классов и объединений по значению в функциях с внешней связью (т. е. не static inline функций)? Меня особенно интересуют простые структуры, такие как

typedef struct doublefloat { float hi; float lo; } doublefloat;
typedef struct doubledouble { double hi; double lo; } doubledouble;
typedef struct int128 { int64_t hi; int64_t lo; } int128; 

doublefloat foof(float a, float b);    
doubledouble food(double a, double b);
float foo3(doubledouble a, doubledouble b);    
int128 fooi(int64_t a, int64_t b);

Вот что я наблюдал в GCC (с -O3)

  • foof возвращает hi и lo, упакованные в первые 64 бита XMM0.
  • food возвращает hi и lo в XMM0 и XMM1.
  • foo3 проходит hi и lo из a и b в XMM0, XMM1, XMM2 и XMM3.
  • fooi возвращает hi и lo в rda и rdx

Агнер Фог описывает детали (которые согласуются с наблюдениями) для каждого компилятора на http://www.agner.org/optimize/calling_conventions.pdf

См. Таблица 6. Методы передачи объектов структуры, класса и объединения и Таблица 7. Методы возврата объектов структуры, класса и объединения.

Для 64-битного кода его таблицы разделены на Windows и Linux/BSD/Mac, а не на компилятор, поэтому для меня это означает, что существует некий стандарт для составных типов данных. Правильно ли это или передача и возврат составного типа данных потенциально определяются каждым компилятором или каждой версией компилятора (т. е. могут измениться в следующей версии).

Обратите внимание, что я понимаю, что на практике во многих из этих случаев, вероятно, лучше всего использовать static inline. Также обратите внимание, что хотя в C нет классов, меня все равно интересует, как структуры и объединения передаются по значению в C, а не только в C++, поэтому я включил тег C.


person Z boson    schedule 18.05.2015    source источник


Ответы (1)


Некоторые стандарты существуют. Например, документ SystemV AMD64 ABI довольно подробно описывает передачу параметров для агрегатов ( начиная со страницы 17). Я не буду копировать соответствующую часть текста здесь, так как там несколько страниц.

Не все платформы, вероятно, будут так хорошо документированы.

person gsg    schedule 18.05.2015
comment
Спасибо. Я вижу, что SystemV AMD64 ABI на самом деле определяет гораздо больше, чем я думал (мне не следовало утверждать, что я это понимаю). Таким образом, агрегатные типы кажутся определенными. Это объясняет, почему в таблице Агнера есть значения для каждой ОС (в 64-битном режиме), а не для компилятора. - person Z boson; 18.05.2015
comment
Также есть стандарт для ARM по адресу infocenter.arm.com. /help/topic/com.arm.doc.ihi0042e/, но у меня возникли проблемы с получением документа, описывающего сопоставление с C/C++... - person gsg; 18.05.2015