코드 생성 속성
코드 생성 속성 (Code generation attributes)
컴파일러가 생성하는 기계어 코드의 형태를 조정하고 싶을 때가 있어요. 예를 들어 이 함수는 꼭 인라인 시켜라, 아니면 절대 인라인 하지 마라 같은 요청 말이죠. 그런 지시를 내리는 데 쓰는 속성(attribute)들을 이 장에서 다룹니다.
출처: Rust Reference
본문
다음 속성들은 코드 생성(code generation)을 제어하는 데 사용돼요.
inline 속성
inline 속성은 속성이 붙은 함수의 코드 사본을 호출자에게 배치할지, 아니면 그 함수에 대한 호출을 생성할지를 제안합니다.
예시
#![allow(unused)]
fn main() {
#[inline]
pub fn example1() {}
#[inline(always)]
pub fn example2() {}
#[inline(never)]
pub fn example3() {}
}
참고:
rustc는 그럴 만하다고 판단되면 함수를 자동으로 인라인해요. 무엇을 인라인할지에 대한 잘못된 결정은 프로그램을 느려지게 할 수 있으므로, 이 속성은 조심해서 사용하세요.
문법
InlineAttribute →
inline ( always )
| inline ( never )
| inline
적용 가능한 위치
inline 속성은 본문(body)이 있는 함수 — 클로저, async 블록, 자유 함수, 고유 구현이나 트레이트 구현의 연관 함수, 그리고 트레이트 정의에서 기본 정의(default definition)가 있는 연관 함수 — 에만 적용될 수 있어요.
참고:
rustc는 다른 위치에서의 사용을 무시하지만 그에 대해 린트(lint)해요. 이는 미래에 오류가 될 수 있습니다.참고: 클로저와 async 블록에 적용할 수는 있지만, 아직 표현식 위의 속성을 지원하지 않으므로 그 유용성은 제한적이에요.
#![allow(unused)]
fn main() {
// 문장 위의 속성은 허용한다.
#[inline] || (); // OK
#[inline] async {}; // OK
}
#![allow(unused)]
fn main() {
// 표현식 위의 속성은 아직 허용하지 않는다.
let f = #[inline] || (); // ERROR
}
중복 사용
함수에 대한 inline의 첫 번째 사용만 효과가 있어요.
참고:
rustc는 첫 번째 사용 이후의 사용을 린트해요. 이는 미래에 오류가 될 수 있습니다.
모드 (Modes)
inline 속성은 다음 모드를 지원해요.
#[inline]— 인라인 확장을 수행하라고 제안#[inline(always)]— 인라인 확장을 항상 수행하라고 제안#[inline(never)]— 인라인 확장을 절대 수행하지 말라고 제안
참고: 모든 형태에서 이 속성은 **힌트(hint)**일 뿐이에요. 컴파일러는 이를 무시할 수 있습니다.
트레이트·async에서의 적용 범위
트레이트의 함수에 inline이 적용되면 기본 정의의 코드에만 적용돼요.
async 함수나 async 클로저에 적용되면 생성된 poll 함수의 코드에만 적용됩니다.
참고: 자세한 내용은 Rust issue #129347을 참고해요.
외부 내보내기와의 상호작용
함수가 no_mangle이나 export_name으로 외부에 내보내지면 inline 속성은 무시돼요.
cold 속성
cold 속성은 속성이 붙은 함수가 호출될 가능성이 낮다고 제안합니다. 이는 컴파일러가 더 나은 코드를 만드는 데 도움이 될 수 있어요.
예시
#![allow(unused)]
fn main() {
#[cold]
pub fn example() {}
}
문법
cold 속성은 MetaWord 문법을 사용해요.
적용 가능한 위치
cold 속성은 본문(body)이 있는 함수 — 클로저, async 블록, 자유 함수, 고유 구현이나 트레이트 구현의 연관 함수, 그리고 트레이트 정의에서 기본 정의가 있는 연관 함수 — 에만 적용될 수 있어요.
참고:
rustc는 다른 위치에서의 사용을 무시하지만 그에 대해 린트해요. 이는 미래에 오류가 될 수 있습니다.참고: 클로저와 async 블록에 적용할 수는 있지만, 아직 표현식 위의 속성을 지원하지 않으므로 그 유용성은 제한적이에요.
중복 사용
함수에 대한 cold의 첫 번째 사용만 효과가 있어요.
참고:
rustc는 첫 번째 사용 이후의 사용을 린트해요. 이는 미래에 오류가 될 수 있습니다.
트레이트에서의 적용 범위
트레이트의 함수에 cold가 적용되면 기본 정의의 코드에만 적용돼요.
naked 속성
naked 속성은 속성이 붙은 함수에 대해 함수 프롤로그(prologue)와 에필로그(epilogue)를 컴파일러가 생성하지 못하게 합니다. 이런 함수를 naked 함수라고 불러요.
예시
#![allow(unused)]
fn main() {
#[cfg(target_arch = "x86_64")] {
/// 주어진 숫자에 3을 더한다.
// SAFETY: 본문은 "sysv64" 호출 규약을 지키고,
// 시그니처를 유지하며, 끝까지 흘러내리지(fall through) 않는다.
#[unsafe(naked)]
pub extern "sysv64" fn add_n(number: u64) -> u64 {
core::arch::naked_asm!(
"add rdi, {}",
"mov rax, rdi",
"ret",
const 3,
)
}
}
}
문법
naked 속성은 MetaWord 문법을 사용해요.
적용 가능한 위치
naked 속성은 자유 함수, 고유 구현이나 트레이트 구현의 연관 함수, 그리고 트레이트 정의에서 기본 정의가 있는 연관 함수에만 적용될 수 있어요.
중복 사용
함수에 대한 naked의 첫 번째 사용만 효과가 있어요.
참고:
rustc는 첫 번째 사용 이후의 사용을 린트해요.
unsafe로 표시해야 하는 이유
naked 속성은 반드시 unsafe로 표시해야 해요. 본문이 함수의 호출 규약을 지키고, 시그니처를 유지하며, **반환하거나 발산(diverge)**해야 하기 때문입니다(즉 어셈블리 코드 끝을 지나서 흘러내리면 안 돼요).
본문 요구사항
함수 본문은 정확히 하나의 naked_asm! 매크로 호출로만 이루어져야 해요.
프롤로그·에필로그 없음
컴파일러는 naked 함수에 대해 프롤로그나 에필로그를 생성하지 않아요. naked_asm! 호출의 어셈블리 코드가 그 함수의 전체 본문을 구성합니다.
호출 스택 가정
진입 시 어셈블리 코드는 호출 스택과 레지스터 상태가 함수의 시그니처와 호출 규약에 따라 유효하다고 가정할 수 있어요.
코드 중복 금지
컴파일러는 다형(polymorphic) 함수를 모노모픽화(monomorphizing)할 때를 제외하고는 어셈블리 코드를 중복해서는 안 돼요.
참고: 이 보장은 심볼을 정의하는 naked 함수에게 중요해요.
미사용 변수 린트
naked 함수에서는 unused_variables 린트가 억제돼요.
사용할 수 없는 속성들
naked 함수에는 다음 속성을 적용할 수 없어요.
ABI 제한
naked 함수는 "Rust" ABI를 사용할 수 없어요.
no_builtins 속성
no_builtins 속성은 존재한다고 가정되는 라이브러리 함수 호출과 관련된 특정 코드 패턴의 최적화를 비활성화해요.
예시
#![allow(unused)]
#![no_builtins]
fn main() {
}
문법
no_builtins 속성은 MetaWord 문법을 사용해요.
적용 가능한 위치
no_builtins 속성은 크레이트 루트(crate root)에만 적용될 수 있어요.
중복 사용
no_builtins 속성의 첫 번째 사용만 효과가 있어요.
참고:
rustc는 첫 번째 사용 이후의 사용을 린트해요.
target_feature 속성
target_feature 속성은 함수에 적용해서, 특정 플랫폼 아키텍처 기능에 대해 그 함수의 코드 생성을 활성화할 수 있어요. MetaListNameValueStr 문법을 사용하며, 키는 enable 하나이고 그 값은 활성화할 기능 이름들을 쉼표로 구분한 문자열이에요.
#![allow(unused)]
fn main() {
#[cfg(target_feature = "avx2")]
#[target_feature(enable = "avx2")]
fn foo_avx2() {}
}
아키텍처별 기능
각 대상 아키텍처에는 활성화할 수 있는 기능 세트가 있어요. 크레이트가 컴파일되고 있지 않은 대상 아키텍처의 기능을 지정하는 것은 오류예요.
클로저 상속
target_feature 주석이 달린 함수 안에 정의된 클로저는 바깥 함수에서 이 속성을 상속해요.
타깃 UB
현재 코드가 실행되는 플랫폼에서 지원되지 않는 기능으로 컴파일된 함수를 호출하는 것은 정의되지 않은 동작(undefined behavior)이에요. 플랫폼이 명시적으로 이를 안전하다고 문서화한 경우는 예외입니다.
안전성 제한
아래의 플랫폼 규칙에서 달리 지정하지 않는 한, 다음 제한이 적용돼요.
- 안전한
#[target_feature]함수(및 속성을 상속한 클로저)는 호출자가 그 함수가 활성화한 모든target_feature를 활성화한 경우에만 안전하게 호출될 수 있어요. 이 제한은unsafe맥락에는 적용되지 않아요. - 안전한
#[target_feature]함수(및 속성을 상속한 클로저)는 모든target_feature를 활성화한 맥락에서만 안전한 함수 포인터로 강제 변환될 수 있어요. 이 제한은unsafe함수 포인터에는 적용되지 않아요.
암시적으로 활성화되는 기능도 이 규칙에 포함돼요. 예를 들어 sse2 함수는 sse로 표시된 함수를 호출할 수 있어요.
#![allow(unused)]
fn main() {
#[cfg(target_feature = "sse2")] {
#[target_feature(enable = "sse")]
fn foo_sse() {}
fn bar() {
// 여기서 `foo_sse`를 호출하는 것은 unsafe다.
// 대상 플랫폼에서 `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() {
// `sse2`가 `sse`를 암시하므로 여기서 `foo_sse` 호출은 안전하다.
foo_sse();
}
}
}
Fn 트레이트
#[target_feature] 속성이 있는 함수는 Fn 계열 트레이트를 절대 구현하지 않아요. 다만 바깥 함수에서 기능을 상속하는 클로저는 구현합니다.
적용 불가 위치
#[target_feature] 속성은 다음 위치엔 허용되지 않아요.
main함수panic_handler함수- 안전한 트레이트 메서드
- 트레이트의 안전한 기본 함수
인라인 제한
target_feature로 표시된 함수는 주어진 기능을 지원하지 않는 맥락으로는 인라인되지 않아요. #[inline(always)] 속성을 target_feature 속성과 함께 사용할 수 없습니다.
사용 가능한 기능들 (Available features)
다음은 사용 가능한 기능 이름들의 목록이에요.
이 목록에서 "(cfg only)"로 표시된 대상 기능 이름은 target_feature 속성이 아니라 target_feature 조건부 컴파일 옵션에서만 사용할 수 있어요.
x86 또는 x86_64
이 플랫폼에서 지원되지 않는 기능으로 코드를 실행하는 것은 정의되지 않은 동작이에요. 따라서 이 플랫폼에서 #[target_feature] 함수를 사용하는 것은 위의 제한을 따릅니다.
| 기능 | 암시적으로 활성화 | 설명 |
|---|---|---|
adx |
ADX — 다중 정밀도 가산-캐리(Multi-Precision Add-Carry) 명령어 확장 | |
aes |
sse2 |
AES — 고급 암호화 표준(Advanced Encryption Standard) |
avx |
sse4.2 |
AVX — 고급 벡터 확장(Advanced Vector Extensions) |
avx2 |
avx |
AVX2 — 고급 벡터 확장 2 |
avx512bf16 |
avx512bw |
AVX512-BF16 — 고급 벡터 확장 512비트 - Bfloat16 확장 |
avx512bitalg |
avx512bw |
AVX512-BITALG — 고급 벡터 확장 512비트 - 비트 알고리즘 |
avx512bw |
avx512f |
AVX512-BW — 고급 벡터 확장 512비트 - 바이트·워드 명령어 |
avx512cd |
avx512f |
AVX512-CD — 고급 벡터 확장 512비트 - 충돌 감지 명령어 |
avx512dq |
avx512f |
AVX512-DQ — 고급 벡터 확장 512비트 - 더블워드·쿼드워드 명령어 |
avx512f |
avx2, fma, f16c |
AVX512-F — 고급 벡터 확장 512비트 - 기반(Foundation) |
avx512fp16 |
avx512bw |
AVX512-FP16 — 고급 벡터 확장 512비트 - Float16 확장 |
avx512ifma |
avx512f |
AVX512-IFMA — 고급 벡터 확장 512비트 - 정수 융합 곱셈-가산 |
avx512vbmi |
avx512bw |
AVX512-VBMI — 고급 벡터 확장 512비트 - 벡터 바이트 조작 명령어 |
avx512vbmi2 |
avx512bw |
AVX512-VBMI2 — 고급 벡터 확장 512비트 - 벡터 바이트 조작 명령어 2 |
avx512vl |
avx512f |
AVX512-VL — 고급 벡터 확장 512비트 - 벡터 길이 확장 |
avx512vnni |
avx512f |
AVX512-VNNI — 고급 벡터 확장 512비트 - 벡터 신경망 명령어 |
avx512vp2intersect |
avx512f |
AVX512-VP2INTERSECT — 고급 벡터 확장 512비트 - 벡터 쌍 교차 |
avx512vpopcntdq |
avx512f |
AVX512-VPOPCNTDQ — 고급 벡터 확장 512비트 - 벡터 인구 수 세기 명령어 |
avxifma |
avx2 |
AVX-IFMA — 고급 벡터 확장 - 정수 융합 곱셈-가산 |
avxneconvert |
avx2 |
AVX-NE-CONVERT — 고급 벡터 확장 - 비예외(No-Exception) 부동소수점 변환 명령어 |
avxvnni |
avx2 |
AVX-VNNI — 고급 벡터 확장 - 벡터 신경망 명령어 |
avxvnniint16 |
avx2 |
AVX-VNNI-INT16 — 고급 벡터 확장 - 16비트 정수 벡터 신경망 명령어 |
avxvnniint8 |
avx2 |
AVX-VNNI-INT8 — 고급 벡터 확장 - 8비트 정수 벡터 신경망 명령어 |
bmi1 |
BMI1 — 비트 조작 명령어 세트 | |
bmi2 |
BMI2 — 비트 조작 명령어 세트 2 | |
cmpxchg16b |
cmpxchg16b — 16바이트(128비트) 데이터를 원자적으로 비교·교환 |
|
f16c |
avx |
F16C — 16비트 부동소수점 변환 명령어 |
fma |
avx |
FMA3 — 3-피연산자 융합 곱셈-가산 |
fxsr |
fxsave 및 fxrstor — x87 FPU, MMX 기술, SSE 상태 저장·복원 |
|
gfni |
sse2 |
GFNI — 갈로아 필드(Galois Field) 새 명령어 |
kl |
sse2 |
KEYLOCKER — 인텔 키 로커 명령어 |
lzcnt |
lzcnt — 선행 0 개수 세기 |
|
movbe |
movbe — 바이트를 바꾼 뒤 데이터 이동 |
|
pclmulqdq |
sse2 |
pclmulqdq — 캐리 없는(패킹된) 곱셈 쿼드워드 |
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 — 스트리밍 SIMD 확장 | |
sse2 |
sse |
SSE2 — 스트리밍 SIMD 확장 2 |
sse3 |
sse2 |
SSE3 — 스트리밍 SIMD 확장 3 |
sse4.1 |
ssse3 |
SSE4.1 — 스트리밍 SIMD 확장 4.1 |
sse4.2 |
sse4.1 |
SSE4.2 — 스트리밍 SIMD 확장 4.2 |
sse4a |
sse3 |
SSE4a — 스트리밍 SIMD 확장 4a |
ssse3 |
sse3 |
SSSE3 — 보조 스트리밍 SIMD 확장 3 |
tbm |
TBM — 후행 비트 조작 | |
vaes |
avx2, aes |
VAES — 벡터 AES 명령어 |
vpclmulqdq |
avx, pclmulqdq |
VPCLMULQDQ — 쿼드워드의 벡터 캐리 없는 곱셈 |
widekl |
kl |
KEYLOCKER_WIDE — 인텔 와이드 키로커 명령어 |
xsave |
xsave — 프로세서 확장 상태 저장 |
|
xsavec |
xsavec — 압축으로 프로세서 확장 상태 저장 |
|
xsaveopt |
xsaveopt — 최적화된 프로세서 확장 상태 저장 |
|
xsaves |
xsaves — 슈퍼바이저 프로세서 확장 상태 저장 |
aarch64
이 플랫폼에서 #[target_feature] 함수를 사용하는 것은 위의 제한을 따릅니다.
이 기능들에 대한 자세한 문서는 ARM 아키텍처 참조 매뉴얼 또는 developer.arm.com의 다른 곳에서 찾을 수 있어요.
참고: 다음 기능 쌍들은 사용한다면 함께 활성화하거나 함께 비활성화해야 해요.
paca와pacg— LLVM이 현재 이 둘을 하나의 기능으로 구현하기 때문이에요.
| 기능 | 암시적으로 활성화 | 기능 이름 |
|---|---|---|
aes |
neon |
FEAT_AES & FEAT_PMULL — 고급 SIMD AES & PMULL 명령어 |
bf16 |
FEAT_BF16 — BFloat16 명령어 | |
bti |
FEAT_BTI — 분기 대상 식별(Branch Target Identification) | |
crc |
FEAT_CRC — CRC32 체크섬 명령어 | |
dit |
FEAT_DIT — 데이터 독립 타이밍(Data Independent Timing) 명령어 | |
dotprod |
neon |
FEAT_DotProd — 고급 SIMD Int8 내적(dot product) 명령어 |
dpb |
FEAT_DPB — 지속 지점까지 데이터 캐시 정리 | |
dpb2 |
dpb |
FEAT_DPB2 — 깊은 지속 지점까지 데이터 캐시 정리 |
f32mm |
sve |
FEAT_F32MM — SVE 단정밀도 FP 행렬 곱셈 명령어 |
f64mm |
sve |
FEAT_F64MM — SVE 배정밀도 FP 행렬 곱셈 명령어 |
fcma |
neon |
FEAT_FCMA — 부동소수점 복소수 지원 |
fhm |
fp16 |
FEAT_FHM — 반정밀도 FP FMLAL 명령어 |
flagm |
FEAT_FLAGM — 조건 플래그 조작 | |
fp16 |
neon |
FEAT_FP16 — 반정밀도 FP 데이터 처리 |
frintts |
FEAT_FRINTTS — 부동소수점을 정수로 변환하는 도우미 명령어 | |
i8mm |
FEAT_I8MM — Int8 행렬 곱셈 | |
jsconv |
neon |
FEAT_JSCVT — JavaScript 변환 명령어 |
lor |
FEAT_LOR — 제한된 순서 지정 영역(Limited Ordering Regions) 확장 | |
lse |
FEAT_LSE — 대형 시스템 확장(Large System Extensions) | |
mte |
FEAT_MTE & FEAT_MTE2 — 메모리 태깅 확장(Memory Tagging Extension) | |
neon |
FEAT_AdvSimd & FEAT_FP — 부동소수점과 고급 SIMD 확장 | |
paca |
FEAT_PAUTH — 포인터 인증(주소 인증) | |
pacg |
FEAT_PAUTH — 포인터 인증(일반 인증) | |
pan |
FEAT_PAN — 특권 접근 금지(Privileged Access-Never) 확장 | |
pmuv3 |
FEAT_PMUv3 — 성능 모니터 확장(v3) | |
rand |
FEAT_RNG — 난수 생성기(Random Number Generator) | |
ras |
FEAT_RAS & FEAT_RASv1p1 — 신뢰성·가용성·서비스 가능성(Reliability, Availability and Serviceability) 확장 | |
rcpc |
FEAT_LRCPC — Release consistent Processor Consistent | |
rcpc2 |
rcpc |
FEAT_LRCPC2 — 즉시 오프셋이 있는 RcPc |
rdm |
neon |
FEAT_RDM — 반올림 이중 곱셈 누적(Rounding Double Multiply accumulate) |
sb |
FEAT_SB — 추측 장벽(Speculation Barrier) | |
sha2 |
neon |
FEAT_SHA1 & FEAT_SHA256 — 고급 SIMD SHA 명령어 |
sha3 |
sha2 |
FEAT_SHA512 & FEAT_SHA3 — 고급 SIMD SHA 명령어 |
sm4 |
neon |
FEAT_SM3 & FEAT_SM4 — 고급 SIMD SM3/4 명령어 |
spe |
FEAT_SPE — 통계 프로파일링 확장(Statistical Profiling Extension) | |
ssbs |
FEAT_SSBS & FEAT_SSBS2 — 추측 저장소 우회 안전(Speculative Store Bypass Safe) | |
sve |
neon |
FEAT_SVE — 확장 가능한 벡터 확장(Scalable Vector Extension) |
sve2 |
sve |
FEAT_SVE2 — 확장 가능한 벡터 확장 2 |
sve2-aes |
sve2, aes |
FEAT_SVE_AES & FEAT_SVE_PMULL128 — SVE AES 명령어 |
sve2-bitperm |
sve2 |
FEAT_SVE2_BitPerm — SVE 비트 순열 |
sve2-sha3 |
sve2, sha3 |
FEAT_SVE2_SHA3 — SVE SHA3 명령어 |
sve2-sm4 |
sve2, sm4 |
FEAT_SVE2_SM4 — SVE SM4 명령어 |
tme |
FEAT_TME — 트랜잭션 메모리 확장(Transactional Memory Extension) | |
vh |
FEAT_VHE — 가상화 호스트 확장(Virtualization Host Extensions) |
loongarch
이 플랫폼에서 #[target_feature] 함수를 사용하는 것은 위의 제한을 따릅니다.
| 기능 | 암시적으로 활성화 | 설명 |
|---|---|---|
f |
F — 단정밀도 부동소수점 명령어 | |
d |
f |
D — 배정밀도 부동소수점 명령어 |
frecipe |
FRECIPE — 역수 근사(reciprocal approximation) 명령어 | |
lasx |
lsx |
LASX — 256비트 벡터 명령어 |
lbt |
LBT — 바이너리 변환(binary translation) 명령어 | |
lsx |
d |
LSX — 128비트 벡터 명령어 |
lvz |
LVZ — 가상화 명령어 | |
div32 |
DIV32 — 부호 확장되지 않은 32비트 피연산자를 받는 나눗셈 명령어 | |
lam-bh |
LAM-BH — 바이트와 하프워드용 원자적 교환·가산 명령어 | |
lamcas |
LAMCAS — 바이트·하프워드·워드·더블워드용 원자적 비교-교환 명령어 | |
ld-seq-sa |
LD-SEQ-SA — 같은 주소에 대한 로드의 순차적 순서 지정 | |
scq |
SCQ — 조건부 저장 쿼드워드(store-conditional quadword) 명령어 |
riscv32 또는 riscv64
이 플랫폼에서 #[target_feature] 함수를 사용하는 것은 위의 제한을 따릅니다.
이 기능들에 대한 자세한 문서는 각각의 명세에서 찾을 수 있어요. 많은 명세가 RISC-V ISA 매뉴얼, 버전 20250508 또는 RISC-V GitHub 계정에서 호스팅되는 다른 매뉴얼에 설명되어 있어요.
| 기능 | 암시적으로 활성화 | 설명 |
|---|---|---|
a |
zaamo, zalrsc |
A — 원자적(Atomic) 명령어 |
b |
zba, zbc, zbs |
B — 비트 조작(Bit Manipulation) 명령어 |
c |
zca |
C — 압축(Compressed) 명령어 |
d |
f |
D — [(cfg only)] 배정밀도 부동소수점 |
e |
E — [(cfg only)] 16개 GPR을 갖는 임베디드 명령어 세트 | |
f |
zicsr |
F — [(cfg only)] 단정밀도 부동소수점 |
m |
M — 정수 곱셈·나눗셈 명령어 | |
za64rs |
za128rs |
Za64rs — 플랫폼 동작: ≤64바이트의 자연 정렬 예약 세트 |
za128rs |
Za128rs — 플랫폼 동작: ≤128바이트의 자연 정렬 예약 세트 | |
zaamo |
Zaamo — 원자적 메모리 연산(Atomic Memory Operation) 명령어 | |
zabha |
zaamo |
Zabha — 바이트·하프워드 원자적 메모리 연산 명령어 |
zacas |
zaamo |
Zacas — 원자적 비교-교환(CAS) 명령어 |
zalrsc |
Zalrsc — Load-Reserved/Store-Conditional 명령어 | |
zama16b |
Zama16b — 플랫폼 동작: 자연 정렬 16바이트 경계를 넘지 않는 메인 메모리 영역에 대한 정렬이 어긋난 로드·스토어·AMO는 원자적이다 | |
zawrs |
Zawrs — Wait-on-Reservation-Set 명령어 | |
zba |
Zba — 주소 생성(Address Generation) 명령어 | |
zbb |
Zbb — 기본 비트 조작 | |
zbc |
zbkc |
Zbc — 캐리 없는 곱셈(Carry-less multiplication) |
zbkb |
Zbkb — 암호화용 비트 조작 명령어 | |
zbkc |
Zbkc — 암호화용 캐리 없는 곱셈 | |
zbkx |
Zbkx — 크로스바 순열(Crossbar permutations) | |
zbs |
Zbs — 단일 비트(single-bit) 명령어 | |
zca |
Zca — 압축 명령어: 정수 부분 부분집합 | |
zcb |
zca |
Zcb — 간단한 코드 크기 절약 압축 명령어 |
zcmop |
zca |
Zcmop — 압축 May-Be-Operations |
zic64b |
Zic64b — 플랫폼 동작: 자연 정렬 64바이트 캐시 블록 | |
zicbom |
Zicbom — 캐시 블록 관리(Cache-Block Management) 명령어 | |
zicbop |
Zicbop — 캐시 블록 프리페치 힌트 명령어 | |
zicboz |
Zicboz — 캐시 블록 제로(Cache-Block Zero) 명령어 | |
ziccamoa |
Ziccamoa — 플랫폼 동작: 캐시 가능·일관성 있는 메인 메모리가 모든 기본 원자적 연산을 지원한다 | |
ziccif |
Ziccif — 플랫폼 동작: 캐시 가능·일관성 있는 메인 메모리가 명령어 인출을 지원하고, min(ILEN,XLEN)까지의 자연 정렬 2의 거듭제곱 크기 인출은 원자적이다 |
|
zicclsm |
Zicclsm — 플랫폼 동작: 캐시 가능·일관성 있는 메인 메모리가 정렬이 어긋난 로드/스토어 접근을 지원한다 | |
ziccrse |
Ziccrse — 플랫폼 동작: 캐시 가능·일관성 있는 메인 메모리가 LR/SC 시퀀스에서 결국 성공함을 보장한다 | |
zicntr |
zicsr |
Zicntr — 기본 카운터와 타이머 |
zicond |
Zicond — 정수 조건부 연산(Integer Conditional Operation) 명령어 | |
zicsr |
Zicsr — 제어·상태 레지스터(CSR) 명령어 | |
zifencei |
Zifencei — 명령어 인출 펜스(Instruction-Fetch Fence) 명령어 | |
zihintntl |
Zihintntl — 비시간적 지역성 힌트(Non-Temporal Locality Hint) 명령어 | |
zihintpause |
Zihintpause — 일시 중지 힌트(Pause Hint) 명령어 | |
zihpm |
zicsr |
Zihpm — 하드웨어 성능 카운터 |
zimop |
Zimop — May-Be-Operations | |
zk |
zkn, zkr, zks, zkt, zbkb, zbkc, zkbx |
Zk — 스칼라 암호화(Scalar Cryptography) |
zkn |
zknd, zkne, zknh, zbkb, zbkc, zkbx |
Zkn — NIST 알고리즘 제품군 확장 |
zknd |
Zknd — NIST 제품군: AES 복호화 | |
zkne |
Zkne — NIST 제품군: AES 암호화 | |
zknh |
Zknh — NIST 제품군: 해시 함수 명령어 | |
zkr |
Zkr — 엔트로피 소스 확장(Entropy Source Extension) | |
zks |
zksed, zksh, zbkb, zbkc, zkbx |
Zks — ShangMi 알고리즘 제품군 |
zksed |
Zksed — ShangMi 제품군: SM4 블록 암호 명령어 | |
zksh |
Zksh — ShangMi 제품군: SM3 해시 함수 명령어 | |
zkt |
Zkt — 데이터 독립 실행 지연 부분집합 | |
ztso |
Ztso — 총 저장 순서(Total Store Ordering) |
wasm32 또는 wasm64
안전한 #[target_feature] 함수는 Wasm 플랫폼에서 안전한 맥락에서 항상 사용될 수 있어요. #[target_feature] 속성을 통해 정의되지 않은 동작을 일으키는 것은 불가능합니다. Wasm 엔진이 지원하지 않는 명령어를 사용하려 시도하면, 컴파일러가 예상한 것과 다르게 해석될 위험 없이 로드 시점에 실패하기 때문이에요.
| 기능 | 암시적으로 활성화 | 설명 |
|---|---|---|
bulk-memory |
WebAssembly bulk memory operations 제안 | |
extended-const |
WebAssembly extended const expressions 제안 | |
mutable-globals |
WebAssembly mutable global 제안 | |
nontrapping-fptoint |
WebAssembly non-trapping float-to-int conversion 제안 | |
relaxed-simd |
simd128 |
WebAssembly relaxed simd 제안 |
sign-ext |
WebAssembly sign extension operators 제안 | |
simd128 |
WebAssembly simd 제안 | |
multivalue |
WebAssembly multivalue 제안 | |
reference-types |
WebAssembly reference-types 제안 | |
tail-call |
WebAssembly tail-call 제안 |
s390x
s390x 대상에서 #[target_feature] 속성이 있는 함수를 사용하는 것은 위의 제한을 따릅니다.
이 기능들에 대한 자세한 문서는 z/Architecture 원리 1장의 "Additions to z/Architecture" 섹션에서 찾을 수 있어요.
| 기능 | 암시적으로 활성화 | 설명 |
|---|---|---|
vector |
128비트 벡터 명령어 | |
vector-enhancements-1 |
vector |
vector enhancements 1 |
vector-enhancements-2 |
vector-enhancements-1 |
vector enhancements 2 |
vector-enhancements-3 |
vector-enhancements-2 |
vector enhancements 3 |
vector-packed-decimal |
vector |
vector packed-decimal |
vector-packed-decimal-enhancement |
vector-packed-decimal |
vector packed-decimal enhancement |
vector-packed-decimal-enhancement-2 |
vector-packed-decimal-enhancement-2 |
vector packed-decimal enhancement 2 |
vector-packed-decimal-enhancement-3 |
vector-packed-decimal-enhancement-3 |
vector packed-decimal enhancement 3 |
nnp-assist |
vector |
nnp assist |
miscellaneous-extensions-2 |
miscellaneous extensions 2 | |
miscellaneous-extensions-3 |
miscellaneous extensions 3 | |
miscellaneous-extensions-4 |
miscellaneous extensions 4 |
추가 정보 (Additional information)
target_feature 조건부 컴파일 옵션에 대해서는 해당 문서를 참고해, 컴파일 타임 설정에 기반해 코드 컴파일을 선택적으로 켜거나 끌 수 있어요. 참고로 이 옵션은 target_feature 속성의 영향을 받지 않고, 크레이트 전체에 대해 활성화된 기능에 의해서만 결정돼요.
기능이 활성화되었는지는 표준 라이브러리의 플랫폼별 매크로로 런타임에 확인할 수 있어요. 예를 들어 is_x86_feature_detected나 is_aarch64_feature_detected 같은 매크로요.
참고:
rustc는 각 대상과 CPU에 대해 기본 활성화된 기능 세트를 가져요. CPU는-C target-cpu플래그로 고를 수 있고, 개별 기능은-C target-feature플래그로 크레이트 전체에 대해 켜거나 끌 수 있어요.
track_caller 속성
track_caller 속성은 진입점 fn main을 제외한 "Rust" ABI를 가진 어떤 함수에도 적용할 수 있어요.
트레이트에서의 적용
트레이트 선언의 함수·메서드에 적용되면, 속성은 모든 구현에 적용돼요. 트레이트가 이 속성이 있는 기본 구현을 제공한다면, 오버라이딩 구현에도 속성이 적용됩니다.
extern 블록 관련
extern 블록의 함수에 적용되면, 링크된 구현에도 속성을 적용해야 해요. 그렇지 않으면 정의되지 않은 동작이 발생합니다. extern 블록에 제공되는 함수에 적용되면, extern 블록의 선언에도 속성이 있어야 해요. 그렇지 않으면 정의되지 않은 동작이 발생해요.
동작 (Behavior)
함수 f에 속성을 적용하면 f 내부의 코드가 f 호출로 이어진 "최상위" 추적된 호출의 Location에 대한 힌트를 얻을 수 있어요. 관찰 지점에서 구현은 마치 f의 프레임에서부터 스택을 위로 걸어 올라가 속성이 없는 함수 outer의 가장 가까운 프레임을 찾고, outer 안의 추적된 호출의 Location을 반환하는 것처럼 동작합니다.
#![allow(unused)]
fn main() {
#[track_caller]
fn f() {
println!("{}", std::panic::Location::caller());
}
}
참고:
core는 호출자 위치를 관찰하기 위한core::panic::Location::caller를 제공해요. 이는rustc가 구현한core::intrinsics::caller_location내장 함수를 감싼 것이에요.참고: 결과
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에 의해 호출되고, g가 calls_g에 호출된다면, f와 g 둘 다의 코드는 calls_g 안에서 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에 호출되고, h가 calls_h에 호출된다면, f, g, h의 모든 코드는 calls_h 안에서 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()에서
}
}
그리고 이러한 방식이 계속 이어져요.
제한사항 (Limitations)
이 정보는 힌트이며, 구현이 이를 보존할 의무는 없어요.
특히, #[track_caller]가 있는 함수를 함수 포인터로 강제 변환하면 shim이 만들어져, 관찰자에게는 속성 함수의 정의 지점에서 호출된 것처럼 보이고 가상 호출을 가로질러 실제 호출자 정보가 사라져요. 이 강제 변환의 흔한 예는 속성화된 메서드를 갖는 트레이트 객체를 만드는 것이에요.
참고: 함수 포인터용 shim이 필요한 이유는,
rustc가track_caller를 코드젠 맥락에서 함수 ABI에 암시적 매개변수를 덧붙이는 방식으로 구현하는데, 간접 호출에서는 그 매개변수가 함수의 타입 일부가 아니므로 건전하지 않기(unsoound) 때문이에요. 주어진 함수 포인터 타입이 속성 있는 함수를 가리킬 수도 있고 아닐 수도 있으니까요. shim을 만들면 함수 포인터 호출자에게서 암시적 매개변수를 숨겨 건전성을 유지합니다.
instruction_set 속성
instruction_set 속성은 **코드 생성 중 함수가 사용할 명령어 세트(instruction set)**를 지정해요. 이렇게 하면 하나의 프로그램 안에서 여러 명령어 세트를 섞어 쓸 수 있습니다.
예시
#[instruction_set(arm::a32)]
fn arm_code() {}
#[instruction_set(arm::t32)]
fn thumb_code() {}
문법
instruction_set 속성은 MetaListPaths 문법을 사용해, 아키텍처 패밀리 이름과 명령어 세트 이름으로 이루어진 단일 경로를 지정해요.
적용 가능한 위치
instruction_set 속성은 본문(body)이 있는 함수 — 클로저, async 블록, 자유 함수, 고유 구현이나 트레이트 구현의 연관 함수, 그리고 트레이트 정의에서 기본 정의가 있는 연관 함수 — 에만 적용될 수 있어요.
참고:
rustc는 다른 위치에서의 사용을 무시하지만 그에 대해 린트해요. 이는 미래에 오류가 될 수 있습니다.참고: 클로저와 async 블록에 적용할 수는 있지만, 아직 표현식 위의 속성을 지원하지 않으므로 그 유용성은 제한적이에요.
중복 사용
instruction_set 속성은 함수에 한 번만 사용할 수 있어요.
대상 제한
instruction_set 속성은 주어진 값을 지원하는 대상에서만 사용할 수 있어요.
인라인 어셈블리
instruction_set 속성을 사용하면, 함수의 인라인 어셈블리는 대상 기본값 대신 지정된 명령어 세트를 사용해야 해요.
ARM에서의 instruction_set
ARMv4T와 ARMv5te 아키텍처를 대상으로 할 때 instruction_set에 지원되는 값은 다음과 같아요.
arm::a32— 함수를 A32 "ARM" 코드로 생성arm::t32— 함수를 T32 "Thumb" 코드로 생성
함수의 주소를 함수 포인터로 취하면, 주소의 낮은 비트는 선택된 명령어 세트에 따라 달라져요.
arm::a32("ARM")의 경우 0arm::t32("Thumb")의 경우 1