Spec-Zone.ru › GCC 15

6.11.6.1 Определение глобальных регистровых переменных

Вы можете определить глобальную регистровую переменную и связать её с указанным регистром следующим образом:

register int *foo asm ("r12");

Здесь r12 — имя регистра, который следует использовать. Обратите внимание, что используется тот же синтаксис, что и для определения локальных регистровых переменных, однако для глобальной переменной объявление находится вне функции. Ключевое слово register обязательно и не может сочетаться с static. Имя регистра должно быть допустимым именем регистра для целевой платформы.

Не используйте квалификаторы типов, такие как const и volatile, поскольку результат может оказаться неожиданным. В частности, использование квалификатора volatile не позволяет полностью предотвратить оптимизацию обращений к регистру компилятором.

В большинстве систем регистры являются ограниченным ресурсом, и обычно наилучший код получается, когда компилятор сам управляет их использованием. Однако при особых обстоятельствах имеет смысл зарезервировать некоторые регистры глобально. Например, это может быть полезно в таких программах, как интерпретаторы языков программирования, где есть несколько глобальных переменных, к которым обращаются очень часто.

После определения глобальной регистровой переменной в текущей единице компиляции:

  • Если регистр сохраняется при вызовах, это затрагивает ABI вызовов: после присваивания переменной регистр не будет восстанавливаться в эпилогах функций. Поэтому функции не могут безопасно возвращаться к вызывающим функциям, которые предполагают использование стандартного ABI.
  • И наоборот, если регистр разрушается при вызовах, вызовы функций, использующих стандартный ABI, могут привести к потере содержимого переменной. Такие вызовы могут быть созданы компилятором, даже если в исходной программе они явно не присутствуют, например когда функции libgcc используются для эмуляции отсутствующих инструкций.
  • Обращения к переменной могут оптимизироваться обычным образом, а регистр остаётся доступным для выделения и использования в любых вычислениях, если наблюдаемые значения переменной при этом не изменяются.
  • Если переменная используется во встроенном ассемблере, тип обращения необходимо сообщить компилятору с помощью ограничений (см. Ограничения для операндов asm). Обращения из базовых блоков ассемблера не поддерживаются.

Обратите внимание, что эти пункты применяются только к коду, скомпилированному с этим определением. Поведение кода, который лишь компонуется с ним (например, кода из библиотек), не меняется.

Если вы хотите перекомпилировать исходные файлы, которые фактически не используют глобальную регистровую переменную, чтобы они не использовали указанный регистр для других целей, добавлять объявление глобального регистра в их исходный код не требуется. Достаточно указать параметр компилятора -ffixed-reg (см. Параметры соглашений генерации кода), чтобы зарезервировать регистр.

Объявление переменной

Глобальным регистровым переменным нельзя задавать начальные значения, поскольку исполняемый файл не может задать начальное содержимое регистра.

При выборе регистра отдайте предпочтение тому, который обычно сохраняется и восстанавливается при вызовах функций на вашей машине. Это гарантирует, что код, не знающий о резервировании (например, библиотечные подпрограммы), восстановит его перед возвратом.

На машинах с окнами регистров обязательно выберите глобальный регистр, на который не влияет механизм вызова функций.

Использование переменной

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

Аналогично, небезопасно обращаться к глобальным регистровым переменным из обработчиков сигналов или из нескольких потоков управления. Если специально не перекомпилировать системные библиотечные подпрограммы для данной задачи, они могут временно использовать регистр для других целей. Кроме того, поскольку регистр зарезервирован не исключительно для этой переменной, обращения к нему из обработчиков асинхронных сигналов могут увидеть не связанные с ней временные значения, находящиеся в регистре.

На большинстве машин longjmp восстанавливает для каждой глобальной регистровой переменной значение, которое она имела во время setjmp. Однако на некоторых машинах longjmp не изменяет значения глобальных регистровых переменных. Для переносимости функция, вызвавшая setjmp, должна предусмотреть другой способ сохранения значений глобальных регистровых переменных и их восстановления в longjmp. Так результат будет одинаковым независимо от того, что делает longjmp.

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-15.3.0/gcc/Global-Register-Variables.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API