코드 생성 속성

코드 생성 속성 (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] 속성은 다음 위치엔 허용되지 않아요.

인라인 제한

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 fxsavefxrstor — 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의 다른 곳에서 찾을 수 있어요.

참고: 다음 기능 쌍들은 사용한다면 함께 활성화하거나 함께 비활성화해야 해요.

  • pacapacg — 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_detectedis_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힌트이므로, 구현은 스택 위로의 걸음을 일찍 멈출 수 있어요. 제한사항의 중요한 주의사항을 참고하세요.

예시들

fcalls_f에 직접 호출된다면, f의 코드는 calls_f 안에서 자신의 호출 지점을 관찰해요.

#![allow(unused)]
fn main() {
#[track_caller]
fn f() {
    println!("{}", std::panic::Location::caller());
}
fn calls_f() {
    f(); // <-- f()는 이 위치를 출력한다
}
}

f가 또 다른 속성 함수 g에 의해 호출되고, gcalls_g에 호출된다면, fg 둘 다의 코드는 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에 호출되고, hcalls_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이 필요한 이유는, rustctrack_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

ARMv4TARMv5te 아키텍처를 대상으로 할 때 instruction_set에 지원되는 값은 다음과 같아요.

  • arm::a32 — 함수를 A32 "ARM" 코드로 생성
  • arm::t32 — 함수를 T32 "Thumb" 코드로 생성

함수의 주소를 함수 포인터로 취하면, 주소의 낮은 비트는 선택된 명령어 세트에 따라 달라져요.

  • arm::a32("ARM")의 경우 0
  • arm::t32("Thumb")의 경우 1

더 알아보기