Атрибуты генерации кода
Следующие атрибуты используются для управления генерацией кода.
Атрибут inline
Атрибут inline предлагает, следует ли разместить копию кода функции в месте вызова вместо генерации вызова функции.
Example
#![allow(unused)] fn main() { #[inline] pub fn example1() {} #[inline(always)] pub fn example2() {} #[inline(never)] pub fn example3() {} }
Note
rustcавтоматически встраивает функции, когда это кажется целесообразным. Используйте этот атрибут осторожно, так как неправильные решения о том, что встраивать, могут замедлить программы.
Синтаксис атрибута inline:
Syntax
InlineAttribute →
inline ( always )
| inline ( never )
| inline
Атрибут inline может применяться только к функциям с телами — замыканиям, async блокам, свободным функциям, ассоциированным функциям в неявной реализации или реализации трейта, и ассоциированным функциям в определении трейта, когда эти функции имеют определение по умолчанию.
Note
rustcигнорирует использование в других позициях, но выдает предупреждение. В будущем это может стать ошибкой.
Note
Хотя атрибут может применяться к замыканиям и async блокам, полезность этого ограничена, так как мы ещё не поддерживаем атрибуты на выражениях.
#![allow(unused)] fn main() { // Мы разрешаем атрибуты на операторах. #[inline] || (); // OK #[inline] async {}; // OK }#![allow(unused)] fn main() { // Мы ещё не разрешаем атрибуты на выражениях. let f = #[inline] || (); // ERROR }
Только первое использование inline на функции имеет эффект.
Note
rustcвыдает предупреждение на любое использование после первого. В будущем это может стать ошибкой.
Атрибут inline поддерживает следующие режимы:
#[inline]предлагает выполнить встраивание (inline expansion).#[inline(always)]предлагает, что встраивание должно выполняться всегда.#[inline(never)]предлагает, что встраивание никогда не должно выполняться.
Note
В каждой форме атрибут является подсказкой. Компилятор может проигнорировать её.
Когда inline применяется к функции в трейте, он применяется только к коду определения по умолчанию.
Когда inline применяется к async функции или async замыканию, он применяется только к коду сгенерированной функции poll.
Note
Для более подробной информации см. Rust issue #129347.
Атрибут inline игнорируется, если функция экспортируется внешне с no_mangle или export_name.
Атрибут cold
Атрибут cold предполагает, что функция вряд ли будет вызвана, что может помочь компилятору генерировать лучший код.
Example
#![allow(unused)] fn main() { #[cold] pub fn example() {} }
Атрибут cold использует синтаксис MetaWord.
Атрибут cold может применяться только к функциям с телами — замыканиям, async блокам, свободным функциям, ассоциированным функциям в неявной реализации или реализации трейта, и ассоциированным функциям в определении трейта, когда эти функции имеют определение по умолчанию.
Note
rustcигнорирует использование в других позициях, но выдает предупреждение. В будущем это может стать ошибкой.
Note
Хотя атрибут может применяться к замыканиям и async блокам, полезность этого ограничена, так как мы ещё не поддерживаем атрибуты на выражениях.
Только первое использование cold на функции имеет эффект.
Note
rustcвыдает предупреждение на любое использование после первого. В будущем это может стать ошибкой.
Когда cold применяется к функции в трейте, он применяется только к коду определения по умолчанию.
Атрибут naked
Атрибут naked предотвращает генерацию компилятором пролога и эпилога функции.
Тело функции должно состоять ровно из одного вызова макроса naked_asm!.
Для функции с атрибутом не генерируется пролог или эпилог. Ассемблерный код в блоке naked_asm! составляет полное тело naked-функции.
Атрибут naked является небезопасным атрибутом. Аннотирование функции с #[unsafe(naked)] накладывает обязательство безопасности, что тело должно учитывать соглашение о вызовах функции, соблюдать её сигнатуру и либо возвращаться, либо расходиться (т.е. не проходить через конец ассемблерного кода).
Ассемблерный код может предполагать, что стек вызовов и состояние регистров действительны при входе в соответствии с сигнатурой и соглашением о вызовах функции.
Ассемблерный код не может быть дублирован компилятором, кроме случаев мономорфизации полиморфных функций.
Note
Гарантирование того, когда ассемблерный код может или не может быть дублирован, важно для naked-функций, которые определяют символы.
Линт unused_variables подавляется внутри naked-функций.
Атрибут inline не может быть применён к naked-функции.
Атрибут track_caller не может быть применён к naked-функции.
Атрибуты тестирования не могут быть применены к naked-функции.
Атрибут no_builtins
Атрибут no_builtins отключает оптимизацию определённых шаблонов кода, связанных с вызовами библиотечных функций, которые предполагаются существующими.
Example
#![allow(unused)] #![no_builtins] fn main() { }
Атрибут no_builtins использует синтаксис MetaWord.
Атрибут no_builtins может применяться только к корню крейта.
Только первое использование атрибута no_builtins имеет эффект.
Note
rustcвыдает предупреждение на любое использование после первого.
Атрибут target_feature
Атрибут target_feature может применяться к функции для включения генерации кода этой функции для определённых функций архитектуры платформы. Он использует синтаксис MetaListNameValueStr с единственным ключом enable, значение которого — строка с разделёнными запятыми именами функций для включения.
#![allow(unused)] fn main() { #[cfg(target_feature = "avx2")] #[target_feature(enable = "avx2")] fn foo_avx2() {} }
Каждая целевая архитектура имеет набор функций, которые могут быть включены. Ошибкой указывать функцию для целевой архитектуры, для которой крейт не компилируется.
Замыкания, определённые внутри функции с аннотацией target_feature, наследуют атрибут от включающей функции.
Неопределённое поведение — вызывать функцию, которая скомпилирована с функцией, не поддерживаемой на текущей платформе, на которой выполняется код, за исключением случаев, когда платформа явно документирует, что это безопасно.
Следующие ограничения применяются, если иное не указано в правилах платформы ниже:
- Безопасные функции
#[target_feature](и замыкания, которые наследуют атрибут) могут быть безопасно вызваны только внутри вызывающего, который включает всеtarget_feature, которые включает вызываемый. Это ограничение не применяется в небезопасном контексте. - Безопасные функции
#[target_feature](и замыкания, которые наследуют атрибут) могут быть приведены к безопасным указателям на функции только в контекстах, которые включают всеtarget_feature, которые включает приводимый. Это ограничение не применяется к небезопасным указателям на функции.
Неявно включённые функции включаются в это правило. Например, функция sse2 может вызывать функции, помеченные sse.
#![allow(unused)] fn main() { #[cfg(target_feature = "sse2")] { #[target_feature(enable = "sse")] fn foo_sse() {} fn bar() { // Вызов `foo_sse` здесь небезопасен, так как мы должны сначала убедиться, что SSE // доступен, даже если `sse` включен по умолчанию на целевой // платформе или вручную включен как флаги компилятора. unsafe { foo_sse(); } } #[target_feature(enable = "sse")] fn bar_sse() { // Вызов `foo_sse` здесь безопасен. foo_sse(); || foo_sse(); } #[target_feature(enable = "sse2")] fn bar_sse2() { // Вызов `foo_sse` здесь безопасен, потому что `sse2` подразумевает `sse`. foo_sse(); } } }
Функция с атрибутом #[target_feature] никогда не реализует семейство трейтов Fn, хотя замыкания, наследущие функции от включающей функции, делают это.
Атрибут #[target_feature] не разрешён в следующих местах:
- функция
main - функция
panic_handler - безопасные методы трейтов
- безопасные функции по умолчанию в трейтах
Функции, помеченные target_feature, не встраиваются в контекст, который не поддерживает данные функции. Атрибут #[inline(always)] не может использоваться с атрибутом target_feature.
Доступные функции
Ниже приведён список доступных имён функций.
x86 или x86_64
Выполнение кода с неподдерживаемыми функциями является неопределённым поведением на этой платформе.
Следовательно, на этой платформе использование функций #[target_feature] следует
вышеуказанным ограничениям.
| Функция | Неявно включает | Описание |
|---|---|---|
adx | ADX — Многоточные расширения инструкций сложения с переносом | |
aes | sse2 | AES — Стандарт шифрования Advanced Encryption Standard |
avx | sse4.2 | AVX — Расширения Advanced Vector Extensions |
avx2 | avx | AVX2 — Расширения Advanced Vector Extensions 2 |
avx512bf16 | avx512bw | AVX512-BF16 — Расширения Advanced Vector Extensions 512-bit - Bfloat16 Extensions |
avx512bitalg | avx512bw | AVX512-BITALG — Расширения Advanced Vector Extensions 512-bit - Bit Algorithms |
avx512bw | avx512f | AVX512-BW — Расширения Advanced Vector Extensions 512-bit - Byte and Word Instructions |
avx512cd | avx512f | AVX512-CD — Расширения Advanced Vector Extensions 512-bit - Conflict Detection Instructions |
avx512dq | avx512f | AVX512-DQ — Расширения Advanced Vector Extensions 512-bit - Doubleword and Quadword Instructions |
avx512f | avx2, fma, f16c | AVX512-F — Расширения Advanced Vector Extensions 512-bit - Foundation |
avx512fp16 | avx512bw | AVX512-FP16 — Расширения Advanced Vector Extensions 512-bit - Float16 Extensions |
avx512ifma | avx512f | AVX512-IFMA — Расширения Advanced Vector Extensions 512-bit - Integer Fused Multiply Add |
avx512vbmi | avx512bw | AVX512-VBMI — Расширения Advanced Vector Extensions 512-bit - Vector Byte Manipulation Instructions |
avx512vbmi2 | avx512bw | AVX512-VBMI2 — Расширения Advanced Vector Extensions 512-bit - Vector Byte Manipulation Instructions 2 |
avx512vl | avx512f | AVX512-VL — Расширения Advanced Vector Extensions 512-bit - Vector Length Extensions |
avx512vnni | avx512f | AVX512-VNNI — Расширения Advanced Vector Extensions 512-bit - Vector Neural Network Instructions |
avx512vp2intersect | avx512f | AVX512-VP2INTERSECT — Расширения Advanced Vector Extensions 512-bit - Vector Pair Intersection to a Pair of Mask Registers |
avx512vpopcntdq | avx512f | AVX512-VPOPCNTDQ — Расширения Advanced Vector Extensions 512-bit - Vector Population Count Instruction |
avxifma | avx2 | AVX-IFMA — Расширения Advanced Vector Extensions - Integer Fused Multiply Add |
avxneconvert | avx2 | AVX-NE-CONVERT — Расширения Advanced Vector Extensions - No-Exception Floating-Point conversion Instructions |
avxvnni | avx2 | AVX-VNNI — Расширения Advanced Vector Extensions - Vector Neural Network Instructions |
avxvnniint16 | avx2 | AVX-VNNI-INT16 — Расширения Advanced Vector Extensions - Vector Neural Network Instructions with 16-bit Integers |
avxvnniint8 | avx2 | AVX-VNNI-INT8 — Расширения Advanced Vector Extensions - Vector Neural Network Instructions with 8-bit Integers |
bmi1 | BMI1 — Наборы инструкций манипуляции битами | |
bmi2 | BMI2 — Наборы инструкций манипуляции битами 2 | |
cmpxchg16b | cmpxchg16b — Сравнивает и обменивает 16 байт (128 бит) данных атомарно | |
f16c | avx | F16C — Инструкции преобразования 16-битных чисел с плавающей запятой |
fma | avx | FMA3 — Трёхоперандное fused multiply-add |
fxsr | fxsave и fxrstor — Сохранить и восстановить состояние x87 FPU, MMX Technology и SSE | |
gfni | sse2 | GFNI — Новые инструкции поля Галуа |
kl | sse2 | KEYLOCKER — Инструкции Intel Key Locker |
lzcnt | lzcnt — Подсчёт ведущих нулей | |
movbe | movbe — Перемещение данных после обмена байтов | |
pclmulqdq | sse2 | pclmulqdq — Упакованное умножение без переноса quadword |
popcnt | popcnt — Подсчёт битов, установленных в 1 | |
rdrand | rdrand — Чтение случайного числа | |
rdseed | rdseed — Чтение случайного сида | |
sha | sse2 | SHA — Алгоритм безопасного хеширования |
sha512 | avx2 | SHA512 — Алгоритм безопасного хеширования с дайджестом 512 бит |
sm3 | avx | SM3 — Алгоритм хеширования ShangMi 3 |
sm4 | avx2 | SM4 — Алгоритм шифрования ShangMi 4 |
sse | SSE — Расширения Streaming SIMD | |
sse2 | sse | SSE2 — Расширения Streaming SIMD 2 |
sse3 | sse2 | SSE3 — Расширения Streaming SIMD 3 |
sse4.1 | ssse3 | SSE4.1 — Расширения Streaming SIMD 4.1 |
sse4.2 | sse4.1 | SSE4.2 — Расширения Streaming SIMD 4.2 |
sse4a | sse3 | SSE4a — Расширения Streaming SIMD 4a |
ssse3 | sse3 | SSSE3 — Дополнительные расширения Streaming SIMD 3 |
tbm | TBM — Манипуляция trailing битами | |
vaes | avx2, aes | VAES — Векторные инструкции AES |
vpclmulqdq | avx, pclmulqdq | VPCLMULQDQ — Векторное умножение без переноса Quadwords |
widekl | kl | KEYLOCKER_WIDE — Инструкции Intel Wide Keylocker |
xsave | xsave — Сохранение расширенных состояний процессора | |
xsavec | xsavec — Сохранение расширенных состояний процессора с уплотнением | |
xsaveopt | xsaveopt — Оптимизированное сохранение расширенных состояний процессора | |
xsaves | xsaves — Сохранение расширенных состояний процессора supervisor |
aarch64
На этой платформе использование функций #[target_feature] следует
вышеуказанным ограничениям.
Дополнительная документация по этим функциям может быть найдена в ARM Architecture Reference Manual или elsewhere на developer.arm.com.
Note
Следующие пары функций должны быть помечены как включённые или отключённые вместе, если используются:
pacaиpacg, которые LLVM в настоящее время реализует как одну функцию.
| Функция | Неявно включает | Имя функции |
|---|---|---|
aes | neon | FEAT_AES & FEAT_PMULL — Расширения Advanced SIMD AES & PMULL instructions |
bf16 | FEAT_BF16 — Инструкции BFloat16 | |
bti | FEAT_BTI — Идентификация цели ветвления | |
crc | FEAT_CRC — Инструкции контрольной суммы CRC32 | |
dit | FEAT_DIT — Инструкции с независимым от данных временем | |
dotprod | neon | FEAT_DotProd — Расширения Advanced SIMD Int8 dot product instructions |
dpb | FEAT_DPB — Очистка кэша данных до точки сохранения | |
dpb2 | dpb | FEAT_DPB2 — Очистка кэша данных до точки глубокого сохранения |
f32mm | sve | FEAT_F32MM — Инструкция умножения матриц с плавающей запятой одинарной точности SVE |
f64mm | sve | FEAT_F64MM — Инструкция умножения матриц с плавающей запятой двойной точности SVE |
fcma | neon | FEAT_FCMA — Поддержка комплексных чисел с плавающей запятой |
fhm | fp16 | FEAT_FHM — Инструкции Half-precision FP FMLAL |
flagm | FEAT_FLAGM — Манипуляция условными флагами | |
fp16 | neon | FEAT_FP16 — Обработка данных с плавающей запятой половинной точности |
frintts | FEAT_FRINTTS — Вспомогательные инструкции преобразования плавающей запятой в int | |
i8mm | FEAT_I8MM — Умножение матриц Int8 | |
jsconv | neon | FEAT_JSCVT — Инструкция преобразования JavaScript |
lor | FEAT_LOR — Расширение ограниченных регионов упорядочения | |
lse | FEAT_LSE — Расширения больших систем | |
mte | FEAT_MTE & FEAT_MTE2 — Расширение тегирования памяти | |
neon | FEAT_AdvSimd & FEAT_FP — Расширения Floating Point и Advanced SIMD | |
paca | FEAT_PAUTH — Аутентификация указателей (аутентификация адреса) | |
pacg | FEAT_PAUTH — Аутентификация указателей (общая аутентификация) | |
pan | FEAT_PAN — Расширение Privileged Access-Never | |
pmuv3 | FEAT_PMUv3 — Расширения мониторов производительности (v3) | |
rand | FEAT_RNG — Генератор случайных чисел | |
ras | FEAT_RAS & FEAT_RASv1p1 — Расширение надёжности, доступности и обслуживаемости | |
rcpc | FEAT_LRCPC — Release consistent Processor Consistent | |
rcpc2 | rcpc | FEAT_LRCPC2 — RcPc с непосредственными смещениями |
rdm | neon | FEAT_RDM — Округление двойного умножения с накоплением |
sb | FEAT_SB — Барьер спекуляции | |
sha2 | neon | FEAT_SHA1 & FEAT_SHA256 — Расширения Advanced SIMD SHA instructions |
sha3 | sha2 | FEAT_SHA512 & FEAT_SHA3 — Расширения Advanced SIMD SHA instructions |
sm4 | neon | FEAT_SM3 & FEAT_SM4 — Расширения Advanced SIMD SM3/4 instructions |
spe | FEAT_SPE — Расширение статистического профилирования | |
ssbs | FEAT_SSBS & FEAT_SSBS2 — Speculative Store Bypass Safe | |
sve | neon | FEAT_SVE — Масштабируемое векторное расширение |
sve2 | sve | FEAT_SVE2 — Масштабируемое векторное расширение 2 |
sve2-aes | sve2, aes | FEAT_SVE_AES & FEAT_SVE_PMULL128 — Инструкции SVE AES |
sve2-bitperm | sve2 | FEAT_SVE2_BitPerm — SVE Bit Permute |
sve2-sha3 | sve2, sha3 | FEAT_SVE2_SHA3 — Инструкции SVE SHA3 |
sve2-sm4 | sve2, sm4 | FEAT_SVE2_SM4 — Инструкции SVE SM4 |
tme | FEAT_TME — Расширение транзакционной памяти | |
vh | FEAT_VHE — Расширения виртуализации хоста |
loongarch
На этой платформе использование функций #[target_feature] следует
вышеуказанным ограничениям.
| Функция | Неявно включает | Описание |
|---|---|---|
f | F — Инструкции чисел с плавающей запятой одинарной точности | |
d | f | D — Инструкции чисел с плавающей запятой двойной точности |
frecipe | FRECIPE — Инструкции аппроксимации обратной величины | |
lasx | lsx | LASX — 256-битные векторные инструкции |
lbt | LBT — Инструкции бинарной трансляции | |
lsx | d | LSX — 128-битные векторные инструкции |
lvz | LVZ — Инструкции виртуализации |
riscv32 или riscv64
На этой платформе использование функций #[target_feature] следует
вышеуказанным ограничениям.
Дополнительная документация по этим функциям может быть найдена в их соответствующих спецификациях. Многие спецификации описаны в RISC-V ISA Manual, version 20250508, или в другом руководстве, размещённом на RISC-V GitHub Account.
| Функция | Неявно включает | Описание |
|---|---|---|
a | A — Атомарные инструкции | |
c | C — Сжатые инструкции | |
m | M — Инструкции целочисленного умножения и деления | |
zba | Zba — Инструкции генерации адресов | |
zbb | Zbb — Базовая манипуляция битами | |
zbc | zbkc | Zbc — Умножение без переноса |
zbkb | Zbkb — Инструкции манипуляции битами для криптографии | |
zbkc | Zbkc — Умножение без переноса для криптографии | |
zbkx | Zbkx — Перестановки crossbar | |
zbs | Zbs — Инструкции работы с одним битом | |
zk | zkn, zkr, zks, zkt, zbkb, zbkc, zkbx | Zk — Скалярная криптография |
zkn | zknd, zkne, zknh, zbkb, zbkc, zkbx | Zkn — Расширение набора алгоритмов NIST |
zknd | Zknd — Набор NIST: Дешифрование AES | |
zkne | Zkne — Набор NIST: Шифрование AES | |
zknh | Zknh — Набор NIST: Инструкции хеш-функций | |
zkr | Zkr — Расширение источника энтропии | |
zks | zksed, zksh, zbkb, zbkc, zkbx | Zks — Набор алгоритмов ShangMi |
zksed | Zksed — Набор ShangMi: Инструкции блочного шифра SM4 | |
zksh | Zksh — Набор ShangMi: Инструкции хеш-функции SM3 | |
zkt | Zkt — Подмножество с независимой от данных задержкой выполнения |
wasm32 или wasm64
Безопасные функции #[target_feature] могут всегда использоваться в безопасных контекстах на платформах Wasm.
Невозможно вызвать неопределённое поведение через атрибут
#[target_feature], потому что попытка использовать инструкции,
не поддерживаемые движком Wasm, завершится ошибкой во время загрузки без риска быть
интерпретированной способом, отличным от ожидаемого компилятором.
| Функция | Неявно включает | Описание |
|---|---|---|
bulk-memory | Предложение операций с массовой памятью WebAssembly | |
extended-const | Предложение расширенных константных выражений WebAssembly | |
mutable-globals | Предложение изменяемых глобальных переменных WebAssembly | |
nontrapping-fptoint | Предложение нетrapping-преобразования float-to-int WebAssembly | |
relaxed-simd | simd128 | Предложение relaxed simd WebAssembly |
sign-ext | Предложение операторов расширения знака WebAssembly | |
simd128 | Предложение simd WebAssembly | |
multivalue | Предложение multivalue WebAssembly | |
reference-types | Предложение reference-types WebAssembly | |
tail-call | Предложение tail-call WebAssembly |
Дополнительная информация
См. опцию условной компиляции [target_feature] для выборочного
включения или отключения компиляции кода на основе настроек времени компиляции. Обратите внимание,
что эта опция не зависит от атрибута target_feature и
управляется только функциями, включёнными для всего крейта.
См. макросы is_x86_feature_detected или is_aarch64_feature_detected
в стандартной библиотеке для обнаружения функций во время выполнения на этих платформах.
Note
rustcимеет набор функций, включённых по умолчанию для каждой цели и CPU. CPU может быть выбран с помощью флага-C target-cpu. Отдельные функции могут быть включены или отключены для всего крейта с помощью флага-C target-feature.
Атрибут track_caller
Атрибут track_caller может применяться к любой функции с ABI "Rust"
за исключением точки входа fn main.
При применении к функциям и методам в объявлениях трейтов атрибут применяется ко всем реализациям. Если трейт предоставляет реализацию по умолчанию с атрибутом, то атрибут также применяется к переопределяющим реализациям.
При применении к функции в блоке extern атрибут также должен быть применён к любым связанным
реализациям, иначе результат — неопределённое поведение. При применении к функции, которая становится
доступной для блока extern, объявление в блоке extern также должно иметь атрибут,
иначе результат — неопределённое поведение.
Поведение
Применение атрибута к функции f позволяет коду внутри f получить подсказку о Location
“самого верхнего” отслеживаемого вызова, который привёл к вызову f. В момент наблюдения реализация
ведёт себя так, как если бы она поднималась по стеку от фрейма f, чтобы найти ближайший фрейм
без атрибута функции outer, и возвращает Location отслеживаемого вызова в outer.
#![allow(unused)] fn main() { #[track_caller] fn f() { println!("{}", std::panic::Location::caller()); } }
Note
coreпредоставляетcore::panic::Location::callerдля наблюдения за местоположениями вызывающих. Он оборачивает внутреннюю функциюcore::intrinsics::caller_location, реализованнуюrustc.
Note
Поскольку результирующий
Locationявляется подсказкой, реализация может остановить подъём по стеку раньше. См. Ограничения для важных предостережений.
Примеры
Когда f вызывается напрямую calls_f, код в f наблюдает место вызова внутри calls_f:
#![allow(unused)] fn main() { #[track_caller] fn f() { println!("{}", std::panic::Location::caller()); } fn calls_f() { f(); // <-- f() печатает это местоположение } }
Когда f вызывается другой атрибутированной функцией g, которая в свою очередь вызывается calls_g, код в
обоих f и g наблюдает место вызова g внутри calls_g:
#![allow(unused)] fn main() { #[track_caller] fn f() { println!("{}", std::panic::Location::caller()); } #[track_caller] fn g() { println!("{}", std::panic::Location::caller()); f(); } fn calls_g() { g(); // <-- g() печатает это местоположение дважды, один раз сама и один раз из f() } }
Когда g вызывается другой атрибутированной функцией h, которая в свою очередь вызывается calls_h, весь код
в f, g и h наблюдает место вызова h внутри calls_h:
#![allow(unused)] fn main() { #[track_caller] fn f() { println!("{}", std::panic::Location::caller()); } #[track_caller] fn g() { println!("{}", std::panic::Location::caller()); f(); } #[track_caller] fn h() { println!("{}", std::panic::Location::caller()); g(); } fn calls_h() { h(); // <-- печатает это местоположение трижды, один раз сама, один раз из g(), один раз из f() } }
И так далее.
Ограничения
Эта информация является подсказкой, и реализации не обязаны её сохранять.
В частности, приведение функции с #[track_caller] к указателю на функцию создаёт обёртку (shim), которая
для наблюдателей появляется так, как если бы она была вызвана в месте определения атрибутированной функции, теряя фактическую
информацию о вызывающем при виртуальных вызовах. Распространённым примером этого приведения является создание
объекта трейта, методы которого атрибутированы.
Note
Упомянутая выше обёртка для указателей на функции необходима, потому что
rustcреализуетtrack_callerв контексте кодогенерации, добавляя неявный параметр к ABI функции, но это было бы небезопасно для косвенного вызова, потому что параметр не является частью типа функции, и данный тип указателя на функцию может ссылаться или не ссылаться на функцию с атрибутом. Создание обёртки скрывает неявный параметр от вызывающих указатель на функцию, сохраняя безопасность.
Атрибут instruction_set
Атрибут instruction_set указывает набор инструкций, который функция будет использовать во время генерации кода. Это позволяет смешивать более одного набора инструкций в одной программе.
Example
#[instruction_set(arm::a32)] fn arm_code() {} #[instruction_set(arm::t32)] fn thumb_code() {}
Атрибут instruction_set использует синтаксис MetaListPaths для указания единственного пути, состоящего из имени семейства архитектуры и имени набора инструкций.
Атрибут instruction_set может применяться только к функциям с телами — замыканиям, async блокам, свободным функциям, ассоциированным функциям в неявной реализации или реализации трейта, и ассоциированным функциям в определении трейта, когда эти функции имеют определение по умолчанию.
Note
rustcигнорирует использование в других позициях, но выдает предупреждение. В будущем это может стать ошибкой.
Note
Хотя атрибут может применяться к замыканиям и async блокам, полезность этого ограничена, так как мы ещё не поддерживаем атрибуты на выражениях.
Атрибут instruction_set может использоваться только один раз на функции.
Атрибут instruction_set может использоваться только с целью, которая поддерживает данное значение.
Когда используется атрибут instruction_set, любая встроенная ассемблерная вставка в функции должна использовать указанный набор инструкций вместо целевого по умолчанию.
instruction_set на ARM
При нацеливании на архитектуры ARMv4T и ARMv5te поддерживаемые значения для instruction_set:
arm::a32— Генерировать функцию как код A32 “ARM”.arm::t32— Генерировать функцию как код T32 “Thumb”.
Если адрес функции берётся как указатель на функцию, младший бит адреса будет зависеть от выбранного набора инструкций:
- Для
arm::a32(“ARM”) он будет 0. - Для
arm::t32(“Thumb”) он будет 1.