Spec-Zone.ru › GCC 14

6.48.5.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-14.2.0/gcc/Global-Register-Variables.html

Spec-Zone.ru

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