Соглашения о вызовах функции ARM64

В целом iOS придерживается универсального ABI, указанного ARM для архитектуры ARM64. Однако, существует некоторый выбор, который будет сделан в той платформе и некоторых расхождениях от нее. Этот документ описывает эти проблемы.

Выбор, сделанный в универсальном стандарте вызова процедуры

Стандарт Вызова процедуры для ARM 64-разрядная Архитектура делегирует определенные решения разработчикам платформы. Решения, принятые для iOS, описаны ниже.

Расхождения от универсального стандарта вызова процедуры

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  Размер и выравнивание целочисленных типов данных

Тип данных

Размер (в байтах)

Естественное выравнивание (в байтах)

BOOL, bool

1

1

char

1

1

short

2

2

int

4

4

long

8

8

long long

8

8

указатель

8

8

size_t

8

8

NSInteger

8

8

CFIndex

8

8

fpos_t

8

8

off_t

8

8