Подтвердить что ты не робот

Что ABI, если таковые имеются, ограничивает размер [u] intmax_t?

Начиная с выпуска 1999 года, стандарт ISO C определяет стандартный заголовок <stdint.h>, который, среди прочего, определяет typedefs intmax_t и uintmax_t. Они обозначают, соответственно, "целочисленный тип (подписанный | без знака), способный представлять любое значение любого (подписанного | беззнакового) целочисленного типа".

Например, если, как это обычно бывает, самые широкие целочисленные типы с подписью и без знака являются long long int и unsigned long long int, оба из которых обычно являются 64 битами, тогда intmax_t и uintmax_t могут быть определены в <stdint.h> следующим образом:

typedef long long int intmax_t;
typedef unsigned long long int uintmax_t;

Существует ограниченный набор предопределенных стандартных и беззнаковых целочисленных типов, начиная от signed, unsigned и обычного char до signed и unsigned long long int.

C99 и C11 также позволяют реализациям определять расширенные целочисленные типы, которые отличаются от любого из стандартных типов и имеют имена, которые являются ключевыми словами, определяемыми реализацией.

Оба gcc и clang, для некоторых, но не для всех целей, поддерживают типы __int128 и unsigned __int128. Они действуют как 128-битные целочисленные типы, но они не рассматриваются как расширенные целочисленные типы, а документация для обоих компиляторов заявляет, что они не поддерживают расширенные целые типы. Поскольку они не являются целыми типами, поскольку стандарт определяет этот термин, typedefs intmax_t и uintmax_t относятся к 64-разрядным типам, а не к 128-битным типам.

Ничто из этого не нарушает стандарт C (для реализации не требуются какие-либо расширенные целочисленные типы, и им разрешено иметь произвольные расширения, если они не нарушают каких-либо строго соответствующих программ). Но мне кажется, что для __int128 и unsigned __int128 было бы разумным рассматривать как расширенные целые типы, а для intmax_t и uintmax_t - 128-битные типы.

Обоснование этого не означает, что изменение размера intmax_t и uintmax_t будет "несовместимым с ABI изменением".

страница статуса Clang С++ в сноске (5):

Никаких изменений компилятора не требуется для реализации, такой как Clang, которая не предоставляет никаких расширенных целочисленных типов. __int128 не рассматривается как расширенный целочисленный тип, поскольку изменение intmax_t будет несовместимым с ABI изменением.

(Да, это в первую очередь обсуждает С++, но правила те же, что и для C.)

В отчете gcc bug утверждается, что:

sizeof(intmax_t) фиксируется различными LPI AB64 и не может быть изменен

В обоих случаях для этой заявки не приводится никаких ссылок.

x86_64 ABI document под названием "Бинарный интерфейс приложения System V, приложение для архитектуры архитектуры AMD64, черновик версии 0.99.6" не упоминает intmax_t или uintmax_t, или даже заголовок <stdint.h>. Он задает размеры и выравнивания для предопределенных целых типов (на рис. 3.1).

Наконец, мой вопрос: является ли утверждение, что размеры intmax_t и uintmax_t ограничены ABI действительными? Если да, то какое ABI налагает такое требование? (И, кстати, почему?)

(На мой взгляд, такое требование, если оно существует, неразумно. Оно побеждает цель стандартного разрешения C для определения расширенных целочисленных типов и предполагаемого значения intmax_t и uintmax_t. гораздо сложнее использовать 128-битные целочисленные типы эффективно для систем, которые их поддерживают, а также возвращаются к более узким типам в других системах.)

Литература:

4b9b3361

Ответ 1

Как отмечает полковник Тридцать Два, компилятор, в одностороннем порядке, внесший это изменение, нарушит вызовы между единицами компиляции, которые передают параметры uintmax_t или возвращают значения uintmax_t. Несмотря на то, что SysV ABI не определяет, как эти типы передаются, в качестве практичности сохранение их определений является частью соответствия платформе ABI.

Даже если бы не эта проблема с ABI, компилятор все равно не мог в одностороннем порядке выполнить это изменение, потому что для этого потребовались бы соответствующие изменения для каждой стандартной библиотеки стандартной платформы C. В частности, он, по крайней мере, потребует обновлений семейства функций printf и scanf, imaxabs, imaxdiv и strtoimax и strtoumax и их вариантов.

Ответ 2

Изменение типов типа intmax_t и uintmax_t также изменяет ABI всех программ, которые их используют, поскольку теперь они относятся к разным типам.

Скажем, у вас есть программа A, которая использует функцию в общей библиотеке B с параметром uintmax_t. Если GCC изменяет определение uintmax_t, а A (но не B) перекомпилируется, то uintmax_t в и uintmax_t в B теперь относятся к двум различным типам, нарушая ABI.