Соглашения о вызовах функции ARM64
В целом iOS придерживается универсального ABI, указанного ARM для архитектуры ARM64. Однако, существует некоторый выбор, который будет сделан в той платформе и некоторых расхождениях от нее. Этот документ описывает эти проблемы.
Выбор, сделанный в универсальном стандарте вызова процедуры
Стандарт Вызова процедуры для ARM 64-разрядная Архитектура делегирует определенные решения разработчикам платформы. Решения, принятые для iOS, описаны ниже.
Регистр x18 резервируется для платформы. Программное обеспечение Conforming не должно использовать его.
wchar_t
является 32-разрядным иlong
64-разрядный тип.Где применимо,
__fp16
тип является форматом IEEE754-2008.Регистр указателя кадра (x29) должен всегда адресовать запись допустимого кадра, несмотря на то, что некоторые функции — такие как листовые функции или последние вызовы — могут выбрать не создавать запись в этом списке. В результате отслеживания стека всегда будут значимы, даже без отладочной информации.
Пустые типы структуры проигнорированы в целях передачи параметров. Это поведение применяется к расширению GNU в C и, где разрешено языком, в C++. (Эта проблема непосредственно не указана универсальным стандартом вызова процедуры, но решение требовалось.)
Расхождения от универсального стандарта вызова процедуры
iOS отличает от Стандарта Вызова процедуры для ARM 64-разрядную Архитектуру несколькими способами, как описано сюда.
Передача параметров в целом
В универсальном стандарте вызова процедуры все аргументы функции передали штабель, используют слоты в сети магазинов 8 байтов. В iOS отбрасывается это требование, и значения занимают только требуемое место. Например, на записи в функцию в Перечислении 1, s0 занимает 1 байт в SP, и s1 занимает 1 байт в sp+1. Дополнение все еще вставляется на штабеле для удовлетворения требований выравнивания параметров.
Пример перечисления 1 пространства занят значениями
void two_stack_args(char w0, char w1, char w2, char w3, char w4, char w5, char w6, char w7, char s0, char s1) {}
Универсальный стандарт вызова процедуры требует, чтобы параметры с 16-байтовым выравниванием, переданным в целочисленных регистрах, начались в четном xN, пропустив предыдущий xN с нечетным номером при необходимости. iOS ABI отбрасывает это требование. Например, в Перечислении 2, параметре
x1_x2
действительно становится переданным в x1 и x2 вместо x2 и x3.Пример перечисления 2 16-разрядных выровненных параметров передается в целочисленных регистрах
void large_type(int x0, __int128 x1_x2) {}
Общий ABI указывает, что это - ответственность вызываемого подписать или обнулить - расширяют параметры, имеющие меньше чем 32 бита, и что неиспользованные биты в регистре являются неуказанными. В iOS, однако, вызывающая сторона должна выполнить такие расширения, до 32 битов.
Функции Variadic
iOS ABI для функций, берущих переменное число параметров, полностью отличается от универсальной версии.
Этапы A и B универсального стандарта вызова процедуры выполняются, как обычно — в частности даже variadic агрегируется больше, чем 16 байтов передаются через ссылку на временную память, выделенную вызывающей стороной. После этого фиксированные параметры выделяются регистрам и складывают слоты, как обычно, в iOS.
NSRN тогда окружен к следующему кратному числу 8 байтов, и каждый variadic параметр присваивается надлежащему числу 8-байтовых слотов штабеля.
Язык C требует параметров, меньших, чем int
чтобы быть продвинутыми перед вызовом, но кроме того, неиспользованные байты на штабеле не указаны этим ABI.
В результате этого изменения, типа va_list
псевдоним для char *
вместо для типа структуры указан в универсальном PCS. Это находится также не в пространстве имен станд. при компиляции кода C++.
Основной принцип C типы
Версия iOS ABI имеет следующие различия от универсального ABI в фундаментальных типах, предоставленных языком C.
Обычно
long double
квадратическая точность двоичный файл IEEE754 тип с плавающей точкой. В iOS, однако, это - двойная точность двоичный файл IEEE754 тип с плавающей точкой. Другими словами,long double
идентичноdouble
в iOS.В iOS, как с другими Дарвинскими платформами, обоими
char
иwchar_t
подписываются типы.
Красная зона
ARM64 iOS красная зона сразу состоит из 128 байтов ниже SP указателя вершины стека. Как с x86-64 ABI, операционная система фиксировала не изменять эти байты во время исключений. Программы непривилегированного режима могут полагаться на них для не изменения неожиданно и могут потенциально использовать пространство для локальных переменных.
При некоторых обстоятельствах этот подход может сохранить инструкцию обновления SP на функциональном входе и выходе.
Расхождения от универсального C++ ABI
Универсальный ABI C++ ARM64 указан в Двоичном Стандарте Интерфейса Приложения C++ для ARM 64-разрядная архитектура, которая является поочередно на основе C++ Itanium ABI, используемым многими подобными UNIX системами.
Некоторые разделы специфичны для ELF и не применимы к формату основного объекта, используемому iOS. Существуют, однако, некоторые существенные различия от этих спецификаций в iOS.
Искажение имени
При компиляции кода C++ типы включены на имена функций в процессе, называемом «искажением». iOS ABI отличается от универсальной спецификации следующими маленькими способами.
Поскольку
va_list
псевдоним дляchar *
, это искажается таким же образом — какPc
вместоSt9__va_list
.Типы векторов NEON искажаются таким же образом как их 32-разрядные дубликаты ARM, вместо того, чтобы использовать 64-разрядную схему. Например, использование iOS
17__simd128_int32_t
вместо обобщения11__Int32x4_t
.
Другие расхождения Itanium
В универсальном ABI обрабатываются пустые структуры, как агрегируется с единственным элементом байта для передачи параметров. В iOS, однако, они проигнорированы, если у них нет нетривиального деструктора или конструктора копии. Если у них действительно есть такие функции, их рассматривают, как агрегируется с однобайтовым элементом универсальным способом.
Как с ARM 32-разрядный C++ ABI, iOS требует, чтобы возвратился полный объект (C1) и базовый объект (C2) конструкторы
this
к их вызывающим сторонам. Точно так же полный объект (D1) и базовый объект (D2) возврат деструкторовthis
. Это требование не сделано универсальным C++ ARM64 ABI.В универсальном C++ ABI cookie массива изменяют свой размер и выравнивание согласно выделяемому типу. Как с 32-разрядным ARM, iOS обеспечивает фиксированный макет два
size_t
слова, без дополнительных требований выравнивания.В iOS объектная защита инициализации номинально
uint64_t
вместоint64_t
. Это влияет на прототипы функций__cxa_guard_acquire
,__cxa_guard_release
и__cxa_guard_abort
.В универсальном ARM64 ABI, указатели функции, тип которых отличается только по тому, чтобы быть
extern "C"
илиextern "C++
«являются взаимозаменяемыми. Дело обстоит не так в iOS.
Типы данных и выравнивание данных
Используя правильные типы данных для Ваших переменных помогает максимизировать производительность и мобильность Ваших программ. Выравнивание данных указывает, как данные размечаются в памяти. Естественное выравнивание типа данных указывает выравнивание по умолчанию значений того того типа.
Таблица 1 перечисляет целочисленные типы данных и их размеры и естественное выравнивание в среде ARM64.
Тип данных | Размер (в байтах) | Естественное выравнивание (в байтах) |
---|---|---|
| 1 | 1 |
| 1 | 1 |
| 2 | 2 |
| 4 | 4 |
| 8 | 8 |
| 8 | 8 |
указатель | 8 | 8 |
| 8 | 8 |
| 8 | 8 |
| 8 | 8 |
| 8 | 8 |
| 8 | 8 |