3.17 Параметры соглашений о генерации кода
Эти независимые от машины параметры управляют соглашениями интерфейса, используемыми при генерации кода.
Большинство из них имеют положительную и отрицательную формы; отрицательная форма -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 -
Этот параметр указывает компилятору предположить, что переполнение при арифметических операциях со знаком сложения, вычитания и умножения происходит с обходом (wraps around) с использованием представления со знаком дополнения до двух. Этот флаг включает некоторые оптимизации и отключает другие. Параметры -ftrapv и -fwrapv перекрывают друг друга, поэтому использование -ftrapv -fwrapv в командной строке приводит к тому, что эффективным является -fwrapv. Обратите внимание, что только активные параметры перекрывают, поэтому использование -ftrapv -fwrapv -fno-wrapv в командной строке приводит к тому, что эффективным является -ftrapv.
-
-fwrapv-pointer -
Этот параметр указывает компилятору предположить, что переполнение при арифметике указателей при сложении и вычитании происходит с обходом (wraps around) с использованием представления со знаком дополнения до двух. Этот флаг отключает некоторые оптимизации, которые предполагают, что переполнение указателей недопустимо.
-
-fstrict-overflow -
Этот параметр подразумевает -fno-wrapv -fno-wrapv-pointer и при отрицании подразумевает -fwrapv -fwrapv-pointer.
-
-fexceptions -
Включает обработку исключений. Генерирует дополнительный код, необходимый для распространения исключений. Для некоторых целевых платформ это подразумевает, что GCC генерирует информацию о разматывании стека (frame unwind) для всех функций, что может привести к значительному увеличению размера данных, хотя не влияет на выполнение. Если вы не укажете этот параметр, GCC включит его по умолчанию для языков, таких как C++, которые обычно требуют обработки исключений, и отключит его для языков, таких как C, которые обычно её не требуют. Однако вам может потребоваться включить этот параметр при компиляции кода C, который должен правильно взаимодействовать с обработчиками исключений, написанными на C++. Вы также можете отключить этот параметр, если вы компилируете старые программы C++, которые не используют обработку исключений.
-
-fnon-call-exceptions -
Генерирует код, позволяющий инструкциям ловушки (trapping instructions) выбрасывать исключения. Обратите внимание, что для этого требуется поддержка платформенного времени выполнения, которая не существует везде. Кроме того, он позволяет выбрасывать исключения только инструкциям ловушки (trapping instructions), то есть инструкциям обращения к памяти или инструкциям работы с плавающей точкой. Он не позволяет выбрасывать исключения из произвольных обработчиков сигналов, таких как
SIGALRM. Это включает -fexceptions. -
-fdelete-dead-exceptions -
Учитывается, что инструкции, которые могут вызывать исключения, но не вносят никакого иного вклада в выполнение программы, могут быть оптимизированы. Это не затрагивает вызовы функций, за исключением тех, у которых есть атрибуты
pureилиconst. Этот параметр включён по умолчанию для компиляторов Ada и C++, как разрешено спецификациями языка. Проходы оптимизации, которые приводят к удалению мёртвых исключений, включаются независимо на различных уровнях оптимизации. -
-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 генерировать код, который не является бинарно совместимым с кодом, сгенерированным без этого параметра. Используйте его для соответствия нестандартному интерфейсу приложения.
-
-fcommon -
В коде C этот параметр управляет размещением глобальных переменных, определённых без инициализатора, известных как пробные определения (tentative definitions) в стандарте C. Пробные определения отличаются от объявлений переменной с ключевым словом
extern, которые не выделяют памяти.Значение по умолчанию — -fno-common, которое указывает компилятору разместить неинициализированные глобальные переменные в разделе BSS объектного файла. Это препятствует объединению пробных определений линковщиком, поэтому вы получите ошибку множественного определения, если одна и та же переменная случайно определена в нескольких единицах компиляции.
Параметр -fcommon размещает неинициализированные глобальные переменные в общем блоке (common block). Это позволяет линковщику объединить все пробные определения одной и той же переменной в разных единицах компиляции в один объект или в не-пробное определение. Это поведение не согласуется с 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 и вывод результата напрямую в стандартный вывод с помощью -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, но сгенерированный позиционно-независимый код может быть связан только с исполняемыми файлами. Обычно эти параметры используются для компиляции кода, который будет связан с помощью параметра -pie GCC.
-fpie и -fPIE оба определяют макросы
__pie__и__PIE__. Макросы имеют значение 1 для -fpie и 2 для -fPIE. -
-fno-plt -
Не использовать PLT для вызовов внешних функций в позиционно-независимом коде. Вместо этого загружать адрес вызываемой функции в местах вызова из GOT и переходить к нему. Это приводит к более эффективному коду за счет устранения PLT-подпрограмм и предоставления оптимизаторам доступа к загрузкам GOT. На таких архитектурах, как 32-разрядный x86, где PLT-подпрограммы ожидают указатель GOT в определенном регистре, это дает компилятору больше свободы при распределении регистров.
Альтернативно, можно использовать атрибут функции
noplt, чтобы избежать вызовов через PLT для определенных внешних функций.В позиционно-зависимом коде несколько целевых платформ также преобразуют вызовы функций, помеченные как не использующие PLT, в использование GOT вместо этого.
-
-fno-jump-tables -
Не использовать таблицы переходов для операторов switch, даже в тех случаях, когда это было бы эффективнее, чем другие стратегии генерации кода. Этот параметр полезен в сочетании с -fpic или -fPIC для построения кода, который является частью динамического загрузчика и не может ссылаться на адрес таблицы переходов.
-
-fno-bit-tests -
Не использовать битовые тесты для операторов switch, даже в тех случаях, когда это было бы эффективнее, чем другие стратегии генерации кода.
-
-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 -
Изменить используемую модель локального хранения потоков (см. Локальное хранилище потоков). Аргумент 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» всегда означает public; т.е. доступно для связи извне общего объекта. «protected» и «internal» практически бесполезны в реальном использовании, поэтому единственным другим часто используемым параметром является «hidden». По умолчанию, если -fvisibility не указан, это «default», т.е. сделать каждый символ public.
Хорошее объяснение преимуществ обеспечения правильной видимости ELF-символов дано в «Как писать общие библиотеки» Ульрихом Дреппером (который можно найти по адресу https://www.akkadia.org/drepper/) — однако, более совершенное решение, реализованное с помощью этого параметра, заключается в том, чтобы сделать по умолчанию hidden и пометить вещи public. Это стандарт для DLL на Windows, и с -fvisibility=hidden и
__attribute__ ((visibility("default")))вместо__declspec(dllexport)вы получите практически идентичную семантику с идентичным синтаксисом. Это большое преимущество для тех, кто работает с кроссплатформенными проектами.Для тех, кто добавляет поддержку видимости в существующий код, вам может пригодиться
#pragma GCC visibility. Это работает так, что вы заключаете объявления, для которых хотите установить видимость, в (например)#pragma GCC visibility push(hidden)и#pragma GCC visibility pop. Помните, что видимость символов следует рассматривать как часть контракта интерфейса API, и, следовательно, весь новый код всегда должен указывать видимость, если она не является по умолчанию; т.е. объявления, предназначенные только для использования внутри локального DSO, всегда должны быть явно помечены как hidden, чтобы избежать накладных расходов на PLT indirection — это также делает код более читабельным и самодокументирующим. Обратите внимание, что из-за требований спецификации 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 bit-fields (или другим полям структуры, хотя компилятор обычно соблюдает эти типы), должен использовать один доступ шириной типа поля, выровненный по естественному выравниванию, если это возможно. Например, цели с отображенными в памяти периферийными регистрами могут потребовать, чтобы все такие обращения имели ширину 16 бит; с этим флагом вы можете объявить все периферийные bit-fields как
unsigned short(предполагая, что short имеет 16 бит на этих целях), чтобы заставить GCC использовать 16-битные обращения вместо, возможно, более эффективного 32-битного обращения.Если этот параметр отключен, компилятор использует наиболее эффективный инструкцию. В предыдущем примере это может быть 32-битная команда загрузки, даже если она обращается к байтам, не содержащим никакой части bit-field, или к периферийным регистрам, не связанным с обновляемым.
В некоторых случаях, например, когда атрибут
packedприменен к полю структуры, доступ к полю может быть невозможен с помощью одного чтения или записи, корректно выровненного для целевой машины. В этом случае GCC отступает и генерирует несколько обращений вместо кода, который может вызвать сбой или обрезать результат во время выполнения.Примечание: из-за ограничений модели памяти C/C++11 записи не разрешены для изменения не bit-field членов. Поэтому рекомендуется определить все биты типа поля как члены bit-field.
Значение этого параметра по умолчанию определяется интерфейсом приложения для целевого процессора.
-
-fsync-libcalls -
Этот параметр управляет тем, может ли какая-либо внестрочная реализация функций семейства
__syncбыть использована для реализации функций семейства__atomicC++11.Значение этого параметра по умолчанию включено, поэтому единственная полезная форма параметра — -fno-sync-libcalls. Этот параметр используется в реализации библиотеки времени выполнения libatomic.
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Code-Gen-Options.html