Spec-Zone.ru › GCC 11

Далее: Указание регистров для локальных переменных, Вверх: Переменные в указанных регистрах [Оглавление][Индекс]

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

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

register int *foo asm ("r12");

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

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

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

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

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

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

Если вы хотите перекомпилировать исходные файлы, которые фактически не используют вашу глобальную регистровую переменную, чтобы они не использовали указанный регистр для других целей, вам не нужно фактически добавлять объявление глобальной регистровой переменной в их исходный код. Достаточно указать опцию компилятора -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-11.4.0/gcc/Global-Register-Variables.html

Spec-Zone.ru

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