3.18 Параметры соглашений генерации кода
Эти машинно-независимые параметры управляют соглашениями о взаимодействии, используемыми при генерации кода.
Большинство из них имеют положительную и отрицательную формы; отрицательная форма -ffoo — это -fno-foo. В таблице ниже указана только одна из форм — та, которая не используется по умолчанию. Другую форму можно получить, удалив «no-» или добавив его.
-
-fstack-reuse=reuse-level -
Этот параметр управляет повторным использованием стековой памяти для объявленных пользователем локальных переменных/переменных с классом хранения auto и временных объектов, создаваемых компилятором. 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 -
Этот параметр генерирует ловушки при знаковом переполнении в операциях сложения, вычитания и умножения. Параметры -ftrapv и -fwrapv переопределяют друг друга, поэтому при указании в командной строке -ftrapv -fwrapv действует -fwrapv. Обратите внимание, что переопределяют друг друга только активные параметры, поэтому при указании в командной строке -ftrapv -fwrapv -fno-wrapv действует -ftrapv.
-
-fwrapv -
Этот параметр указывает компилятору предполагать, что знаковое арифметическое переполнение при сложении, вычитании и умножении циклически оборачивается с использованием дополнительного кода. Этот флаг включает одни оптимизации и отключает другие. Параметры -ftrapv и -fwrapv переопределяют друг друга, поэтому при указании в командной строке -ftrapv -fwrapv действует -fwrapv. Обратите внимание, что переопределяют друг друга только активные параметры, поэтому при указании в командной строке -ftrapv -fwrapv -fno-wrapv действует -ftrapv.
-
-fwrapv-pointer -
Этот параметр указывает компилятору предполагать, что переполнение при арифметике указателей в операциях сложения и вычитания циклически оборачивается с использованием дополнительного кода. Этот флаг отключает некоторые оптимизации, предполагающие, что переполнение указателя недопустимо.
-
-fstrict-overflow -
Этот параметр подразумевает -fno-wrapv -fno-wrapv-pointer, а его отключённая форма подразумевает -fwrapv -fwrapv-pointer.
-
-fexceptions -
Включить обработку исключений. Генерирует дополнительный код, необходимый для распространения исключений. Для некоторых целевых платформ это означает, что GCC генерирует информацию для раскрутки стековых кадров для всех функций, что может значительно увеличить объём данных, хотя и не влияет на выполнение. Если этот параметр не указан, GCC включает его по умолчанию для таких языков, как C++, которым обычно требуется обработка исключений, и отключает для таких языков, как C, которым она обычно не требуется. Однако этот параметр может понадобиться при компиляции кода на C, который должен корректно взаимодействовать с обработчиками исключений, написанными на C++. Этот параметр также можно отключить при компиляции старых программ на C++, в которых не используется обработка исключений.
-
-fnon-call-exceptions -
Генерировать код, позволяющий инструкциям, вызывающим ловушки, возбуждать исключения. Обратите внимание, что для этого необходима специфичная для платформы поддержка во время выполнения, которая есть не везде. Кроме того, это позволяет возбуждать исключения только из инструкций, вызывающих ловушки, то есть из обращений к памяти или инструкций с плавающей точкой. Это не позволяет возбуждать исключения из произвольных обработчиков сигналов, например
SIGALRM. Этот параметр включает -fexceptions. -
-fdelete-dead-exceptions -
Считать, что инструкции, которые могут возбуждать исключения, но в остальном не влияют на выполнение программы, можно оптимизировать и удалить. Это не влияет на вызовы функций, за исключением функций с атрибутами
pureилиconst. Этот параметр включён по умолчанию для компиляторов Ada и C++, как допускают спецификации этих языков. Проходы оптимизации, удаляющие неиспользуемые исключения, независимо включаются на разных уровнях оптимизации. -
-funwind-tables -
Аналогичен -fexceptions, за исключением того, что генерирует только необходимые статические данные и никак иначе не влияет на сгенерированный код. Обычно включать этот параметр не нужно: вместо этого его включает за вас обработчик языка, которому требуется такая обработка.
-
-fasynchronous-unwind-tables -
Генерировать таблицу раскрутки в формате DWARF, если целевая машина его поддерживает. Таблица точна на каждой границе инструкций, поэтому её можно использовать для раскрутки стека при асинхронных событиях (например, при работе отладчика или сборщика мусора).
-
-fno-gnu-unique -
В системах с современными GNU assembler и библиотекой C компилятор C++ использует связывание
STB_GNU_UNIQUE, чтобы гарантировать уникальность определений статических членов данных шаблонов и статических локальных переменных во встроенных функциях даже при наличииRTLD_LOCAL; это необходимо для предотвращения проблем с библиотекой, используемой двумя разными плагинамиRTLD_LOCAL, которые зависят от определения в одном из них и поэтому расходятся во мнении со вторым о связывании символа. Однако для затронутых DSO это приводит к игнорированиюdlclose; если ваша программа полагается на повторную инициализацию 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 генерировать код, несовместимый на уровне двоичного кода с кодом, созданным без этого параметра. Используйте его для соответствия нестандартному двоичному интерфейсу приложения.
-
-fcommon -
В коде на C этот параметр управляет размещением глобальных переменных, определённых без инициализатора и называемых в стандарте C предварительными определениями. Предварительные определения отличаются от объявлений переменной с ключевым словом
extern, которые не выделяют память.По умолчанию используется -fno-common, указывающий компилятору размещать неинициализированные глобальные переменные в секции BSS объектного файла. Это препятствует объединению предварительных определений компоновщиком, поэтому при случайном определении одной и той же переменной в нескольких единицах трансляции возникает ошибка повторного определения.
Параметр -fcommon размещает неинициализированные глобальные переменные в общем блоке. Это позволяет компоновщику связывать все предварительные определения одной и той же переменной в разных единицах трансляции с одним и тем же объектом или с непредварительным определением. Такое поведение не согласуется с C++, а на многих целевых платформах приводит к снижению скорости и увеличению размера кода при обращении к глобальным переменным. В основном этот параметр нужен для компоновки устаревшего кода без ошибок.
-
-fno-ident -
Игнорировать директиву
#ident. -
-finhibit-size-directive -
Не выводить директиву ассемблера
.sizeи ничего другого, что может вызвать проблемы, если функция будет разделена посередине, а её части окажутся в далеко отстоящих друг от друга областях памяти. Этот параметр используется при компиляции crtstuff.c; в остальных случаях он не должен требоваться. -
-fverbose-asm -
Добавлять в сгенерированный ассемблерный код дополнительные комментарии, чтобы сделать его более читабельным. Этот параметр обычно полезен только тем, кому действительно нужно читать сгенерированный ассемблерный код (например, при отладке самого компилятора).
-fno-verbose-asm, используемый по умолчанию, отключает вывод дополнительной информации и полезен при сравнении двух ассемблерных файлов.
Добавляемые комментарии содержат:
- сведения о версии компилятора и параметрах командной строки;
- строки исходного кода, соответствующие инструкциям ассемблера, в формате ИМЯ_ФАЙЛА:НОМЕР_СТРОКИ:СОДЕРЖИМОЕ_СТРОКИ;
- подсказки о том, каким высокоуровневым выражениям соответствуют различные операнды инструкций ассемблера.
Например, для следующего исходного файла на C:
int test (int n) { int i; int total = 0; for (i = 0; i < n; i++) total += i * i; return total; }компиляция в ассемблерный код (x86_64) с помощью -S и вывод результата непосредственно в stdout с помощью -o -
gcc -S test.c -fverbose-asm -Os -o -
даёт результат, подобный следующему:
.file "test.c" # GNU C11 (GCC) version 7.0.0 20160809 (experimental) (x86_64-pc-linux-gnu) [...snip...] # options passed: [...snip...] .text .globl test .type test, @function test: .LFB0: .cfi_startproc # test.c:4: int total = 0; xorl %eax, %eax # <retval> # test.c:6: for (i = 0; i < n; i++) xorl %edx, %edx # i .L2: # test.c:6: for (i = 0; i < n; i++) cmpl %edi, %edx # n, i jge .L5 #, # test.c:7: total += i * i; movl %edx, %ecx # i, tmp92 imull %edx, %ecx # i, tmp92 # test.c:6: for (i = 0; i < n; i++) incl %edx # i # test.c:7: total += i * i; addl %ecx, %eax # tmp92, <retval> jmp .L2 # .L5: # test.c:10: } ret .cfi_endproc .LFE0: .size test, .-test .ident "GCC: (GNU) 7.0.0 20160809 (experimental)" .section .note.GNU-stack,"",@progbits
Комментарии предназначены для людей, а не для машин, поэтому точный формат комментариев может меняться.
-
-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, но сгенерированный позиционно-независимый код можно компоновать только с исполняемыми файлами. Обычно их используют для компиляции кода, который будет скомпонован с помощью параметра GCC -pie.
-fpie и -fPIE определяют макросы
__pie__и__PIE__. Для -fpie макросы имеют значение 1, а для -fPIE — 2. -
-fno-plt -
Не использовать PLT для внешних вызовов функций в позиционно-независимом коде. Вместо этого загружать адрес вызываемой функции в месте вызова из GOT и передавать ей управление. Это повышает эффективность кода, устраняя заглушки PLT и позволяя оптимизировать загрузки GOT. На таких архитектурах, как 32-разрядная x86, где заглушкам PLT требуется указатель GOT в определённом регистре, это даёт компилятору больше свободы при распределении регистров. Отложенная привязка требует использования PLT; при указании -fno-plt все внешние символы разрешаются во время загрузки.
Также можно использовать атрибут функции
noplt, чтобы избежать вызовов через PLT для конкретных внешних функций.В позиционно-зависимом коде для некоторых целевых платформ вызовы функций, помеченных как не использующие PLT, также преобразуются в вызовы через GOT.
-
-fno-jump-tables -
Не использовать таблицы переходов для операторов switch, даже если это эффективнее других способов генерации кода. Этот параметр полезен в сочетании с -fpic или -fPIC при сборке кода, входящего в состав динамического компоновщика и не имеющего возможности ссылаться на адрес таблицы переходов. На некоторых целевых платформах таблицам переходов не требуется GOT, и этот параметр не нужен.
-
-fno-bit-tests -
Не использовать битовые тесты для операторов switch, даже если это эффективнее других способов генерации кода.
-
-ffixed-reg -
Считать регистр с именем reg фиксированным; сгенерированный код не должен обращаться к нему (за исключением возможного использования в качестве указателя стека, указателя кадра или в другой фиксированной роли).
reg должно быть именем регистра. Допустимые имена регистров зависят от машины и определяются макросом
REGISTER_NAMESв файле макросов описания машины.У этого флага нет отрицательной формы, поскольку он задаёт один из трёх вариантов.
-
-fcall-used-reg -
Считать регистр с именем reg доступным для распределения регистров и сохраняемым при вызовах функций. Его можно выделять для временных значений или переменных, время жизни которых не охватывает вызов функции. Функции, скомпилированные таким образом, не сохраняют и не восстанавливают регистр reg.
Использовать этот флаг с указателем кадра или указателем стека нельзя. Использование этого флага для других регистров, играющих постоянную важную роль в модели выполнения машины, приводит к катастрофическим последствиям.
У этого флага нет отрицательной формы, поскольку он задаёт один из трёх вариантов.
-
-fcall-saved-reg -
Считать регистр с именем reg доступным для распределения регистров и сохраняемым функциями. Его можно выделять даже для временных значений или переменных, время жизни которых охватывает вызов функции. Если функция использует этот регистр, она сохраняет и восстанавливает его.
Использовать этот флаг с указателем кадра или указателем стека нельзя. Использование этого флага для других регистров, играющих постоянную важную роль в модели выполнения машины, приводит к катастрофическим последствиям.
Использование этого флага для регистра, в котором могут возвращаться значения функций, приводит к последствиям другого рода, но столь же катастрофическим.
У этого флага нет отрицательной формы, поскольку он задаёт один из трёх вариантов.
-
-fpack-struct[=n] -
Если значение не указано, упаковывать все члены структуры вместе, без промежутков. Если указано значение (оно должно быть небольшой степенью двойки), упаковывать члены структуры в соответствии с ним, задавая максимальное выравнивание (то есть объекты с требованиями к выравниванию по умолчанию, превышающими это значение, размещаются в следующем подходящем месте, возможно, без выравнивания).
Предупреждение: параметр -fpack-struct заставляет GCC генерировать код, несовместимый на уровне двоичного кода с кодом, созданным без этого параметра. Кроме того, он ухудшает эффективность кода. Используйте его для соответствия нестандартному двоичному интерфейсу приложения.
-
-fleading-underscore -
Этот параметр и его аналог -fno-leading-underscore принудительно изменяют способ представления символов C в объектном файле. Например, это позволяет упростить компоновку с устаревшим кодом на ассемблере.
Предупреждение: параметр -fleading-underscore заставляет GCC генерировать код, несовместимый на уровне двоичного кода с кодом, созданным без этого параметра. Используйте его для соответствия нестандартному двоичному интерфейсу приложения. Не все целевые платформы полностью поддерживают этот параметр.
-
-ftls-model=model -
Изменить используемую модель локального хранилища потоков (см. Локальное хранилище потоков). Аргумент model должен иметь одно из следующих значений: «global-dynamic», «local-dynamic», «initial-exec» или «local-exec». Обратите внимание, что выбор зависит от оптимизации: для символов, невидимых за пределами единицы трансляции, или если в командной строке не указан -fpic, компилятор может использовать более эффективную модель.
По умолчанию без -fpic используется «initial-exec», а с -fpic — «global-dynamic».
-
-ftrampolines -
Для целевых платформ, которым обычно нужны трамплины для вложенных функций, всегда генерировать их вместо использования дескрипторов. На целевых платформах, которым трамплины не нужны, например HP-PA или IA-64, этот параметр ничего не делает.
Трамплин — это небольшой фрагмент кода, создаваемый во время выполнения в стеке при получении адреса вложенной функции и используемый для косвенного вызова этой функции. Поэтому для корректной работы программы стек должен быть исполняемым.
-fno-trampolines включается по умолчанию отдельно для каждого языка, чтобы компилятор мог избежать генерации трамплинов, если считает это безопасным, и заменить их дескрипторами. Дескрипторы состоят только из данных, но сгенерированный код должен быть подготовлен к работе с ними. На момент написания документации -fno-trampolines включён по умолчанию только для Ada.
Кроме того, код, скомпилированный с -ftrampolines, и код, скомпилированный с -fno-trampolines, несовместимы на уровне двоичного кода, если используются вложенные функции. Поэтому этот параметр нужно задавать для всей программы и изменять с особой осторожностью.
Для языков, отличных от Ada, параметры
-ftrampolinesи-fno-trampolinesв настоящее время не действуют, и на платформах, которым требуются трамплины для вложенных функций, они всегда генерируются. -
-ftrampoline-impl=[stack|heap] -
По умолчанию трамплины генерируются в стеке. Однако некоторые платформы (например, Apple M1) не допускают исполняемый стек. Компиляция с параметром -ftrampoline-impl=heap приводит к генерации вызовов
__gcc_nested_func_ptr_createdи__gcc_nested_func_ptr_deletedдля выделения и освобождения памяти трамплинов в исполняемой куче. Эти функции реализованы в libgcc и предоставляются только для определённых целевых платформ: x86_64 Darwin, x86_64 и aarch64 Linux. ОБРАТИТЕ ВНИМАНИЕ: корректное освобождение памяти трамплинов в куче не гарантируется, если выsetjmp, создаёте экземпляры вложенных функций, а затем возвращаетесь с помощьюlongjmpв состояние, предшествовавшее выделению памяти для этих вложенных функций. -
-fvisibility=[default|internal|hidden|protected] -
Задать указанную видимость символов по умолчанию для образа ELF — все символы помечаются ею, если код не переопределяет это значение. Использование этой возможности может значительно ускорить компоновку и загрузку общих объектных библиотек, обеспечить более оптимизированный код, почти идеальный экспорт API и предотвратить конфликты символов. Настоятельно рекомендуется использовать этот параметр для всех распространяемых вами общих объектных файлов.
Несмотря на название, «default» всегда означает общедоступность, то есть возможность компоновки с символом извне общего объектного файла. «protected» и «internal» практически бесполезны в реальных проектах, поэтому единственный другой часто используемый вариант — «hidden». Если -fvisibility не указан, по умолчанию используется «default», то есть все символы общедоступны.
Полезное объяснение преимуществ, которые даёт правильная видимость символов ELF, содержится в статье «How To Write Shared Libraries» Ульриха Дреппера (Ulrich Drepper), доступной по адресу https://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.
Обзор этих методов, их преимуществ и способов применения доступен по адресу https://gcc.gnu.org/wiki/Visibility.
-
-fstrict-volatile-bitfields -
Этот параметр следует использовать, если доступ к volatile-полям битовых полей (или другим полям структур, хотя компилятор обычно и так соблюдает типы таких полей) должен выполняться одной операцией доступа шириной с тип поля и, если возможно, с естественным выравниванием. Например, для периферийных регистров, отображённых в память, может потребоваться, чтобы все такие обращения имели ширину 16 бит; с этим флагом можно объявить все битовые поля периферийных регистров как
unsigned short(при условии, что на этих целевых платформах short имеет ширину 16 бит), чтобы заставить GCC использовать 16-разрядные обращения вместо, возможно, более эффективного 32-разрядного обращения.Если этот параметр отключён, компилятор использует наиболее эффективную инструкцию. В предыдущем примере это может быть 32-разрядная инструкция загрузки, даже если она обращается к байтам, не содержащим ни одной части битового поля, или к регистрам, отображённым в память и не связанным с обновляемым регистром.
В некоторых случаях, например если к полю структуры применён атрибут
packed, может оказаться невозможным выполнить чтение или запись поля одной операцией с выравниванием, соответствующим требованиям целевой машины. В этом случае GCC генерирует несколько обращений вместо кода, который вызовет ошибку или усечёт результат во время выполнения.Примечание: из-за ограничений модели памяти C/C++11 операции записи не могут затрагивать члены, не являющиеся битовыми полями. Поэтому рекомендуется определять все биты типа поля как члены-битовые поля.
Значение этого параметра по умолчанию определяется двоичным интерфейсом приложения для целевого процессора.
-
-fsync-libcalls -
Этот параметр управляет тем, можно ли использовать для реализации семейства функций C++11
__atomicкакой-либо отдельный экземпляр семейства функций__sync.По умолчанию этот параметр включён, поэтому единственная полезная его форма — -fno-sync-libcalls. Этот параметр используется при реализации библиотеки времени выполнения libatomic.
-
-fzero-init-padding-bits=value
-
Гарантировать нулевую инициализацию битов заполнения в инициализаторах автоматических переменных. Некоторые языки гарантируют нулевую инициализацию битов заполнения в определённых случаях, например C23 при использовании пустых инициализаторов (
{}) или C++ при нулевой инициализации, а также C гарантирует нулевую инициализацию битов заполнения полей, не указанных в инициализаторе. Этот параметр позволяет изменить случаи, в которых гарантируется нулевая инициализация битов заполнения в инициализаторах. По умолчанию используется значение-fzero-init-padding-bits=standard, которое не даёт дополнительных гарантий сверх требований соответствующего стандарта. Например:struct A { char a; unsigned long long b; char c; }; union B { char a; unsigned long long b; }; struct A a = {}; // C23 guarantees padding bits are zero. struct A b = { 1, 2, 3 }; // No guarantees. union B c = {}; // C23 guarantees padding bits are zero. union B d = { 1 }; // No guarantees.-fzero-init-padding-bits=unionsгарантирует нулевую инициализацию битов заполнения в объединениях сверх гарантий стандартов, если инициализатор объединения пуст (тогда все биты объединения инициализируются нулём) или если инициализируемый член объединения меньше размера объединения (в этом случае гарантируется нулевая инициализация битов заполнения за пределами инициализируемого члена). Таково было поведение GCC до GCC 15; в приведённом выше примере гарантируется нулевая инициализация последнихsizeof (unsigned long long) - 1байт в объединении.-fzero-init-padding-bits=allдополнительно гарантирует нулевую инициализацию битов заполнения других агрегатов, то есть заполнения междуb.aиb.b(если оно есть), а также хвостового заполнения структуры (если оно есть).
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-15.3.0/gcc/Code-Gen-Options.html