Rust 인라인 어셈블리, 컴파일러 최적화와 안전성을 모두 잡는 방법?

by DD
2개월 전
조회수 12

Rust에서 인라인 어셈블리(Inline Assembly) 사용 시, 컴파일러 최적화 과정에서 예상치 못한 동작(Unexpected Behavior)이 발생할 수 있음

'스토리텔링(Storytelling)' 기법을 통해 인라인 어셈블리가 Rust의 추상 머신(Abstract Machine) 규칙을 준수하도록 설계

인라인 어셈블리 블록에 대응하는 Rust 코드를 작성하여 컴파일러가 안전하게 최적화(Safe Optimization)를 수행하도록 유도

FFI(Foreign Function Interface) 호출에도 동일한 원리가 적용되며, 코드의 안전성과 이식성을 높이는 데 기여

인라인 어셈블리(Inline Assembly)의 안전성 문제

인라인 어셈블리는 Rust 코드 내에서 어셈블리 코드를 직접 삽입하여 하드웨어에 접근할 수 있게 해준다. 하지만, 컴파일러의 최적화 과정에서 인라인 어셈블리 블록이 예상치 못한 동작(Unexpected Behavior)을 유발할 수 있다. 예를 들어, 공유 참조(Shared Reference)를 통해 접근하는 메모리에 인라인 어셈블리가 직접 값을 쓰는 경우, 컴파일러는 최적화를 통해 해당 코드를 제거할 수 있으며, 이는 정의되지 않은 동작(Undefined Behavior)으로 이어진다.

스토리텔링(Storytelling) 기법의 핵심 원리

스토리텔링 기법은 인라인 어셈블리 블록에 대응하는 Rust 코드를 작성하여 컴파일러가 안전하게 최적화를 수행하도록 돕는다. 즉, 인라인 어셈블리 블록이 수행하는 동작을 Rust 코드로 표현하고, 컴파일러는 해당 Rust 코드를 기반으로 최적화를 수행한다. 이 때, Rust 코드는 인라인 어셈블리 블록에 제공된 데이터(오퍼랜드, 전역 변수)만을 사용해야 하며, 추상 머신(Abstract Machine)의 모든 규칙을 준수해야 한다.

스토리텔링(Storytelling) 기법의 실제 적용 사례

스토리텔링 기법은 다양한 상황에서 활용될 수 있다. 예를 들어, 하드웨어의 새로운 연산을 사용하기 위해 인라인 어셈블리를 사용하는 경우, 해당 연산을 Rust 코드로 구현하여 스토리 코드를 작성할 수 있다. 또한, 페이지 테이블 조작과 같은 OS 커널(OS Kernel) 관련 작업에도 적용 가능하다. 이처럼, 스토리텔링 기법은 컴파일러 최적화(Compiler Optimization)안전성(Safety)을 모두 확보하는 데 기여한다.

비(非) 임시 저장(Non-Temporal) 저장소와 스토리텔링(Storytelling)

비(非) 임시 저장(Non-Temporal) 저장소는 캐시를 사용하지 않고 메모리에 직접 데이터를 쓰는 x86 아키텍처의 기능이다. 이 기능을 사용하면, Rust의 총 저장 순서(Total Store Order) 모델을 위반하여 데이터 경합(Data Race)이 발생할 수 있다. 스토리텔링 기법을 사용하면, 비(非) 임시 저장(Non-Temporal) 저장소를 사용하는 코드를 Rust 코드의 관점에서 설명하여, 컴파일러가 안전하게 코드를 최적화하도록 할 수 있다. 즉, 데이터 미저장 정책(Zero-Retention Policy)을 준수하도록 설계할 수 있다.

How to use storytelling to fit inline assembly into Rust