3.16 Параметры для соглашений о генерации кода
Эти независимые от машины параметры управляют соглашениями интерфейса, используемыми при генерации кода.
Большинство из них имеют положительную и отрицательную формы; отрицательная форма -ffoo имеет вид -fno-foo. В таблице ниже приведена только одна форма — та, которая не является стандартной. Вы можете определить другую форму, либо удалив «no-», либо добавив ее.
-fstack-reuse=reuse-level-
Этот параметр управляет повторным использованием стековой памяти для локальных/автоматических переменных, объявленных пользователем, и временных переменных, сгенерированных компилятором. reuse_level может принимать значения ‘all’, ‘named_vars’ или ‘none’. ‘all’ включает повторное использование стека для всех локальных переменных и временных переменных, ‘named_vars’ включает повторное использование только для локальных переменных пользователя с именами, а ‘none’ полностью отключает повторное использование стека. Значение по умолчанию — ‘all’. Этот параметр необходим, когда программа расширяет срок жизни локальной переменной области видимости или временной переменной, сгенерированной компилятором, за пределами точки, определенной языком. Когда срок жизни переменной заканчивается, и если переменная находится в памяти, оптимизирующий компилятор имеет право повторно использовать её стековую память для других временных переменных или локальных переменных области видимости, срок жизни которых не перекрывается с ней. Код, расширяющий срок жизни локальных переменных, вероятно, вызовет ошибки при оптимизации повторного использования стека.
Например,
int *p; { int local1; p = &local1; local1 = 10; .... } { int local2; local2 = 20; ... } if (*p == 10) // out of scope use of local1 { }Другой пример:
struct A { A(int k) : i(k), j(k) { } int i; int j; }; A *ap; void foo(const A& ar) { ap = &ar; } void bar() { foo(A(10)); // temp object's lifetime ends when foo returns { A a(20); .... } ap->i+= 10; // ap references out of scope temp whose space // is reused with a. What is the value of ap->i? }Срок жизни временной переменной, сгенерированной компилятором, чётко определён стандартом C++. Когда срок жизни временной переменной заканчивается, и если временная переменная находится в памяти, оптимизирующий компилятор имеет право повторно использовать её стековую память для других временных переменных или локальных переменных области видимости, срок жизни которых не перекрывается с ней. Однако некоторые старые программы полагаются на поведение более старых компиляторов, в которых стековая память временных переменных не переиспользуется; агрессивное повторное использование стека может привести к ошибкам во время выполнения. Этот параметр используется для управления оптимизацией повторного использования стековой памяти временных переменных.
-ftrapv-
Этот параметр генерирует ловушки (traps) для переполнения знаковых чисел при операциях сложения, вычитания и умножения. Параметры -ftrapv и -fwrapv переопределяют друг друга; использование -ftrapv -fwrapv в командной строке приводит к тому, что эффективным является -fwrapv. Обратите внимание, что переопределяют только активные параметры, поэтому использование -ftrapv -fwrapv -fno-wrapv в командной строке приводит к тому, что эффективным является -ftrapv.
-fwrapv-
Этот параметр сообщает компилятору, что переполнение знаковых чисел при операциях сложения, вычитания и умножения обнуляется (wrapping) с использованием представления со знаком минус. Этот флаг включает некоторые оптимизации и отключает другие. Этот параметр включён по умолчанию для фронтенда Java, как это требуется спецификацией языка Java. Параметры -ftrapv и -fwrapv переопределяют друг друга; использование -ftrapv -fwrapv в командной строке приводит к тому, что эффективным является -fwrapv. Обратите внимание, что переопределяют только активные параметры, поэтому использование -ftrapv -fwrapv -fno-wrapv в командной строке приводит к тому, что эффективным является -ftrapv.
-fexceptions-
Включить обработку исключений. Генерирует дополнительный код, необходимый для распространения исключений. Для некоторых целей это подразумевает, что GCC генерирует информацию о разворачивании стека для всех функций, что может привести к существенному увеличению размера данных, хотя это не влияет на выполнение. Если этот параметр не указан, GCC включает его по умолчанию для языков, таких как C++, которые обычно требуют обработки исключений, и отключает его для языков, таких как C, которые обычно её не требуют. Однако вам может потребоваться включить этот параметр при компиляции кода C, который должен корректно взаимодействовать с обработчиками исключений, написанными на C++. Вы также можете захотеть отключить этот параметр, если вы компилируете более старые программы C++, которые не используют обработку исключений.
-fnon-call-exceptions-
Генерирует код, который позволяет инструкциям ловушек выбрасывать исключения. Обратите внимание, что это требует платформенной поддержки времени выполнения, которая не существует везде. Более того, он позволяет выбрасывать исключения только инструкциям ловушек, т.е. обращениям к памяти или инструкциям с плавающей точкой. Он не позволяет выбрасывать исключения из произвольных обработчиков сигналов, таких как
SIGALRM. -fdelete-dead-exceptions-
Предполагается, что инструкции, которые могут выбрасывать исключения, но в противном случае не влияют на выполнение программы, могут быть оптимизированы. Этот параметр включён по умолчанию для фронтенда Ada, так как это разрешено спецификацией языка Ada. Проходы оптимизации, которые приводят к удалению мёртвых исключений, включены независимо на разных уровнях оптимизации.
-funwind-tables-
Аналогично -fexceptions, за исключением того, что он просто генерирует любые необходимые статические данные, но не влияет на сгенерированный код каким-либо другим образом. Обычно нет необходимости включать этот параметр; вместо этого процессор языка, которому требуется такая обработка, включает его от вашего имени.
-fasynchronous-unwind-tables-
Генерировать таблицу разворачивания стека в формате DWARF, если это поддерживается целевой машиной. Таблица является точной на границе каждой инструкции, поэтому её можно использовать для разворачивания стека из асинхронных событий (таких как отладчик или сборщик мусора).
-fno-gnu-unique-
На системах с недавней версией GNU ассемблера и C библиотеки, C++ компилятор использует привязку
STB_GNU_UNIQUE, чтобы убедиться, что определения статических членов шаблонов и статических локальных переменных в инлайновых функциях уникальны даже при наличииRTLD_LOCAL; это необходимо для избежания проблем с библиотекой, используемой двумя различнымиRTLD_LOCALплагинами, зависящими от определения в одном из них и, следовательно, не согласующихся с другим относительно привязки символа. Но это приводит к тому, чтоdlcloseигнорируется для соответствующих DSO; если ваша программа полагается на повторную инициализацию DSO черезdlcloseиdlopen, вы можете использовать -fno-gnu-unique. -fpcc-struct-return-
Возвращать “короткие”
structиunionзначения в памяти, как и более длинные, а не в регистрах. Такая конвенция менее эффективна, но имеет преимущество в межвызываемости между файлами, скомпилированными GCC, и файлами, скомпилированными другими компиляторами, особенно Portable C Compiler (pcc).Точная конвенция для возвращения структур в памяти зависит от макросов конфигурации целевой системы.
Короткие структуры и объединения — это те, размер и выравнивание которых совпадают с некоторым целочисленным типом.
Предупреждение: код, скомпилированный с ключом -fpcc-struct-return, несовместим в двоичном формате с кодом, скомпилированным с ключом -freg-struct-return. Используйте его для соответствия нестандартному прикладному интерфейсу.
-freg-struct-return-
Возвращать
structиunionзначения в регистрах, когда это возможно. Это более эффективно для небольших структур, чем -fpcc-struct-return.Если вы не указали ни -fpcc-struct-return, ни -freg-struct-return, GCC по умолчанию выбирает ту конвенцию, которая является стандартной для целевой системы. Если стандартной конвенции нет, GCC по умолчанию использует -fpcc-struct-return, за исключением целей, где GCC является основным компилятором. В этих случаях мы можем выбрать стандарт, и мы выбрали более эффективную альтернативу с возвращением в регистры.
Предупреждение: код, скомпилированный с ключом -freg-struct-return, несовместим в двоичном формате с кодом, скомпилированным с ключом -fpcc-struct-return. Используйте его для соответствия нестандартному прикладному интерфейсу.
-fshort-enums-
Выделить типу
enumтолько столько байтов, сколько нужно для объявленного диапазона возможных значений. В частности, типenumэквивалентен самому малому целочисленному типу, который имеет достаточно места.Предупреждение: ключ -fshort-enums заставляет GCC генерировать код, который несовместим в двоичном формате с кодом, сгенерированным без этого ключа. Используйте его для соответствия нестандартному прикладному интерфейсу.
-fshort-wchar-
Переопределить базовый тип для
wchar_tнаshort unsigned intвместо значения по умолчанию для целевой системы. Этот параметр полезен для построения программ для работы под WINE.Предупреждение: ключ -fshort-wchar заставляет GCC генерировать код, который несовместим в двоичном формате с кодом, сгенерированным без этого ключа. Используйте его для соответствия нестандартному прикладному интерфейсу.
-fno-common-
В коде C управляет размещением неинициализированных глобальных переменных. Компиляторы Unix C традиционно позволяли множественные определения таких переменных в различных единицах компиляции, помещая переменные в общий блок. Это поведение задаётся -fcommon и является по умолчанию для GCC на большинстве целей. С другой стороны, это поведение не требуется стандартом ISO C, и на некоторых целевых системах может привести к снижению скорости или увеличению размера кода при обращении к переменным. Параметр -fno-common указывает, что компилятор должен помещать неинициализированные глобальные переменные в раздел данных файла объекта, а не генерировать их как общие блоки. Это означает, что если одна и та же переменная объявлена (без
extern) в двух разных компиляциях, при линковке вы получите ошибку множественного определения. В этом случае нужно скомпилировать с -fcommon. Компиляция с -fno-common полезна на целевых системах, для которых это обеспечивает лучшую производительность, или если вы хотите проверить, будет ли программа работать на других системах, которые всегда обрабатывают объявления неинициализированных переменных таким образом. -fno-ident-
Игнорировать директиву
#ident. -finhibit-size-directive-
Не выводить директиву ассемблера
.size, или что-либо ещё, что может вызвать проблемы, если функция разбита посередине, и две половины помещены в места памяти, находящиеся далеко друг от друга. Этот параметр используется при компиляции crtstuff.c; вам не должно потребоваться использовать его для чего-либо ещё. -fverbose-asm-
Вставлять дополнительную информационную комментарии в сгенерированный ассемблерный код, чтобы сделать его более читабельным. Этот параметр, как правило, полезен только тем, кому действительно необходимо читать сгенерированный ассемблерный код (возможно, при отладке самого компилятора).
-fno-verbose-asm, значение по умолчанию, не вставляет дополнительную информацию и полезна при сравнении двух файлов ассемблера.
-frecord-gcc-switches
-
Этот переключатель заставляет компилятор записывать используемую командную строку в создаваемый объектный файл. Этот переключатель реализован только на некоторых целевых платформах, и точный формат записи зависит от целевой платформы и формата двоичного файла, но обычно он принимает форму раздела, содержащего текст в ASCII. Этот переключатель связан с переключателем -fverbose-asm, но этот переключатель записывает информацию только в выходной файл ассемблера в виде комментариев, поэтому он никогда не попадает в объектный файл. См. также -grecord-gcc-switches для другого способа хранения параметров компилятора в объектный файл.
-fpic-
Генерировать позиционно-независимый код (PIC), подходящий для использования в динамической библиотеке, если это поддерживается для целевой машины. Такой код обращается ко всем константным адресам через таблицу глобальных смещений (GOT). Динамический загрузчик разрешает записи GOT при запуске программы (динамический загрузчик не является частью GCC; он является частью операционной системы). Если размер GOT для связанного исполняемого файла превышает машино-зависимый максимальный размер, вы получите сообщение об ошибке от компоновщика, указывающее, что -fpic не работает; в этом случае перекомпилируйте с -fPIC вместо этого. (Эти максимумы составляют 8 КБ на SPARC, 28 КБ на AArch64 и 32 КБ на m68k и RS/6000. У x86 нет такого ограничения.)
Позиционно-независимый код требует специальной поддержки и поэтому работает только на определенных машинах. Для x86 GCC поддерживает PIC для System V, но не для Sun 386i. Код, сгенерированный для IBM RS/6000, всегда позиционно-независимый.
При установке этого флага макросы
__pic__и__PIC__определяются как 1. -fPIC-
Если это поддерживается для целевой машины, генерировать позиционно-независимый код, подходящий для динамической компоновки и избегающий любых ограничений на размер таблицы глобальных смещений. Этот параметр имеет значение на AArch64, m68k, PowerPC и SPARC.
Позиционно-независимый код требует специальной поддержки и поэтому работает только на определенных машинах.
При установке этого флага макросы
__pic__и__PIC__определяются как 2. -fpie-fPIE-
Эти параметры аналогичны -fpic и -fPIC, но сгенерированный позиционно-независимый код может быть связан только в исполняемые файлы. Обычно эти параметры используются, когда параметр -pie GCC используется во время компоновки.
-fpie и -fPIE оба определяют макросы
__pie__и__PIE__. Макросы имеют значение 1 для -fpie и 2 для -fPIE. -fno-plt-
Не использовать PLT для вызовов внешних функций в позиционно-независимом коде. Вместо этого загружать адрес вызываемого объекта в местах вызова из GOT и переходить к нему. Это приводит к более эффективному коду, исключая PLT-подпрограммы и раскрывая загрузки GOT для оптимизации. На архитектурах, таких как 32-битный x86, где PLT-подпрограммы ожидают указатель GOT в определённом регистре, это даёт больше свободы для распределения регистров компилятору. Ленивая привязка требует использования PLT; с -fno-plt все внешние символы разрешаются во время загрузки.
В качестве альтернативы, можно использовать атрибут функции
nopltдля предотвращения вызовов через PLT для определённых внешних функций.В позиционно-зависимом коде некоторые целевые платформы также преобразуют вызовы функций, отмеченных как не использующие PLT, в использование GOT вместо этого.
-fno-jump-tables-
Не использовать таблицы переходов для операторов switch, даже там, где это было бы эффективнее, чем другие стратегии генерации кода. Этот параметр полезен в сочетании с -fpic или -fPIC для создания кода, являющегося частью динамического загрузчика и не способного ссылаться на адрес таблицы переходов. На некоторых целевых платформах таблицы переходов не требуют GOT, и этот параметр не нужен.
-ffixed-reg-
Обращаться к регистру с именем reg как к фиксированному регистру; сгенерированный код не должен ссылаться на него (кроме, возможно, как на указатель стека, указатель фрейма или в какой-либо другой фиксированной роли).
reg должно быть именем регистра. Принимаемые имена регистров зависят от машины и определяются в макросе
REGISTER_NAMESв файле макросов описания машины.У этого флага нет отрицательной формы, так как он определяет трёхсторонний выбор.
-fcall-used-reg-
Обращаться к регистру с именем reg как к регистру, который может быть выделен и который перекрывается вызовами функций. Он может быть выделен для временных переменных или переменных, которые не существуют после вызова. Функции, скомпилированные таким образом, не сохраняют и не восстанавливают регистр reg.
Использование этого флага с указателем фрейма или указателем стека является ошибкой. Использование этого флага для других регистров, которые играют фиксированную роль в модели выполнения машины, приводит к катастрофическим последствиям.
У этого флага нет отрицательной формы, так как он определяет трёхсторонний выбор.
-fcall-saved-reg-
Обращаться к регистру с именем reg как к регистру, который может быть выделен и который сохраняется функциями. Он может быть выделен даже для временных переменных или переменных, которые существуют после вызова. Функции, скомпилированные таким образом, сохраняют и восстанавливают регистр reg, если они его используют.
Использование этого флага с указателем фрейма или указателем стека является ошибкой. Использование этого флага для других регистров, которые играют фиксированную роль в модели выполнения машины, приводит к катастрофическим последствиям.
Другой вид катастрофы возникает при использовании этого флага для регистра, в котором могут возвращаться значения функций.
У этого флага нет отрицательной формы, так как он определяет трёхсторонний выбор.
-fpack-struct[=n]-
Без указанного значения все члены структуры упаковываются вместе без промежутков. Когда задано значение (которое должно быть малой степенью двойки), члены структуры упаковываются в соответствии с этим значением, представляющим максимальное выравнивание (то есть объекты с требованиями к выравниванию по умолчанию, превышающими это значение, выводятся потенциально невыровненными в следующем подходящем месте).
Предупреждение: переключатель -fpack-struct заставляет GCC генерировать код, который не совместим с кодом, сгенерированным без этого переключателя. Кроме того, это делает код не оптимальным. Используйте его для соответствия нестандартному интерфейсу приложений.
-fleading-underscore-
Этот параметр и его аналог -fno-leading-underscore принудительно изменяют способ представления C-символов в объектном файле. Одним из применений является помощь при компоновке с устаревшим ассемблерным кодом.
Предупреждение: переключатель -fleading-underscore заставляет GCC генерировать код, который не совместим с кодом, сгенерированным без этого переключателя. Используйте его для соответствия нестандартному интерфейсу приложений. Не все целевые платформы полностью поддерживают этот переключатель.
-ftls-model=model-
Изменить используемую модель локального хранения потока (см. Thread-Local). Аргумент model должен быть одним из ‘global-dynamic’, ‘local-dynamic’, ‘initial-exec’ или ‘local-exec’. Обратите внимание, что выбор подвержен оптимизации: компилятор может использовать более эффективную модель для символов, не видимых за пределами трансляционной единицы, или если -fpic не указан в командной строке.
По умолчанию без -fpic — ‘initial-exec’; с -fpic значение по умолчанию — ‘global-dynamic’.
-fvisibility=[default|internal|hidden|protected]-
Установить видимость символов в формате ELF по умолчанию на указанный параметр — все символы отмечаются этим, если не переопределено в коде. Использование этой функции может существенно улучшить время компоновки и загрузки динамических библиотек, сгенерировать более оптимизированный код, обеспечить почти идеальный экспорт API и предотвратить конфликты символов. Настоятельно рекомендуется использовать это в любых распространяемых вами динамических объектах.
Несмотря на номенклатуру, ‘default’ всегда означает общедоступный; т.е., доступный для связи извне динамической библиотеки. ‘protected’ и ‘internal’ практически бесполезны в реальном использовании, поэтому единственный другой часто используемый параметр — ‘hidden’. Значение по умолчанию, если -fvisibility не указано, равно ‘default’, т.е. сделать все символы общедоступными.
Хорошее объяснение преимуществ, обеспечиваемых гарантией правильной видимости символов ELF, даётся в статье «Как писать динамические библиотеки» Ульриха Дреппера (которую можно найти по адресу http://www.akkadia.org/drepper/) — однако более надёжное решение, предлагаемое этим параметром, заключается в том, чтобы сделать значение по умолчанию скрытым и отмечать символы как публичные. Таков стандарт для DLL на Windows, и с помощью -fvisibility=hidden и
__attribute__ ((visibility("default")))вместо__declspec(dllexport)вы получите практически идентичную семантику с идентичным синтаксисом. Это большая польза для тех, кто работает с кроссплатформенными проектами.Для тех, кто добавляет поддержку видимости в существующий код, может пригодиться
#pragma GCC visibility. Это работает путём заключения объявлений, для которых вы хотите установить видимость, в (например)#pragma GCC visibility push(hidden)и#pragma GCC visibility pop. Имейте в виду, что видимость символов следует рассматривать как часть контракта интерфейса API, поэтому весь новый код всегда должен указывать видимость, если она не является по умолчанию; т.е. объявления, предназначенные только для использования внутри локального DSO, всегда должны быть явно помечены как скрытые, чтобы избежать накладных расходов на косвенные обращения PLT — это также способствует удобочитаемости и самодокументированию кода. Обратите внимание, что в силу требований спецификации ISO C++,operator newиoperator deleteвсегда должны быть стандартной видимости.Помните, что заголовки извне вашего проекта, особенно системные заголовки и заголовки из любой другой используемой вами библиотеки, могут не ожидать компиляции с видимостью, отличной от стандартной. Возможно, вам потребуется явно указать
#pragma GCC visibility push(default)перед включением таких заголовков.Объявления
externне затрагиваются -fvisibility, поэтому большое количество кода можно перекомпилировать с -fvisibility=hidden без изменений. Однако это означает, что вызовыexternфункций без явной видимости используют PLT, поэтому эффективнее использовать__attribute ((visibility))и/или#pragma GCC visibilityдля указания компилятору, какиеexternобъявления следует обрабатывать как скрытые.Обратите внимание, что -fvisibility влияет на неявные C++ сущности. Например, класс исключений, который выбрасывается между DSO, должен быть явно помечен как имеющий стандартную видимость, чтобы узлы «type_info» были унифицированы между DSO.
Обзор этих методов, их преимуществ и способов использования находится по адресу http://gcc.gnu.org/wiki/Visibility.
-fstrict-volatile-bitfields
-
Этот параметр следует использовать, если доступ к переменным типа volatile bit-fields (или другим полям структуры, хотя компилятор обычно поддерживает эти типы в любом случае) должен использовать одно обращение к ширине типа поля, выровненное по естественному выравниванию, если это возможно. Например, целевые платформы с регистровыми периферийными устройствами памяти могут потребовать, чтобы все такие обращения имели ширину 16 бит; с этим флагом вы можете объявить все битовые поля периферийных устройств как
unsigned short(предполагая, что short имеет 16 бит на этих целевых платформах), чтобы заставить GCC использовать 16-битные обращения вместо, возможно, более эффективного 32-битного обращения.Если этот параметр отключен, компилятор использует наиболее эффективный инструкцию. В предыдущем примере это может быть инструкция загрузки на 32 бита, даже если она обращается к байтам, которые не содержат никакой части битового поля, или к регистрам периферийных устройств памяти, не связанным с тем, которое обновляется.
В некоторых случаях, например, когда атрибут
packedприменяется к полю структуры, может быть невозможно получить доступ к полю с помощью единственного чтения или записи, которое правильно выровнено для целевой машины. В этом случае GCC переходит к генерации нескольких обращений вместо кода, который приведет к ошибке или обрезанию результата во время выполнения.Примечание: из-за ограничений модели памяти C/C++11 записи не разрешено касаться членов, которые не являются битовыми полями. Поэтому рекомендуется определять все биты типа поля как члены битовых полей.
Значение по умолчанию для этого параметра определяется интерфейсом двоичного приложения для целевого процессора.
-fsync-libcalls-
Этот параметр управляет тем, могут ли любые внестрочные экземпляры семейства функций
__syncиспользоваться для реализации семейства функций C++11__atomic.Значение параметра по умолчанию включено, поэтому единственной полезной формой параметра является -fno-sync-libcalls. Этот параметр используется в реализации библиотеки времени выполнения libatomic.
Далее: Параметры разработчика, Предыдущее: Параметры директорий, Вернуться к: Вызов GCC [Содержание][Индекс]
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-6.5.0/gcc/Code-Gen-Options.html