crustc: rustc 전체를 C로 변환

7 hours ago 3
  • crustc는 rustc 1.98.0-nightly (c712ea946 2026-06-16) 전체를 4,600만 줄 C 코드로 변환한 데모이며, GCC와 make로 빌드하면 동작하는 Rust 컴파일러가 생성됨
  • 기반 도구인 cilly는 Rust를 C로 컴파일하는 Rust 컴파일러 백엔드이며, 이 저장소는 컴파일러가 자기 자신을 컴파일하는 가장 눈에 띄는 쇼케이스로 구성됨
  • cilly는 대상 C 컴파일러와 플랫폼의 타입 레이아웃, 크기, 정렬, 문자 인코딩, 정수 형식 등을 witness 프로그램으로 질의해, 특정 C 컴파일러가 받아들일 수 있는 C 코드를 생성함
  • 주요 목표는 LLVM/GCC 지원이 없지만 C 컴파일러는 있는 오래되거나 특이한 하드웨어에서 Rust 사용을 가능하게 하는 것이며, TCP로 원격 C 컴파일러와 통신하는 네트워크 투명성도 포함함
  • 현재 생성된 C는 작성자의 워크스테이션 ISA인 ARM64 Linux를 대상으로 하며, cilly 전체 도구체인은 아직 공개 사용 준비가 되지 않았고 최적화 관련 버그도 추적 중임

rustc를 C로 변환한 데모

  • crustc는 rustc 1.98.0-nightly (c712ea946 2026-06-16)을 4,600만 줄 C 코드로 변환한 저장소임
  • 이 C 코드는 GCC와 make로 빌드할 수 있으며, 빌드 결과는 동작하는 Rust 컴파일러가 됨
  • 실행 예시는 LLVM 라이브러리 경로를 지정한 뒤 ./rustc/rustc --version을 실행해 동일한 rustc 1.98.0-nightly 버전을 출력함
  • 생성된 Rust 컴파일러는 코드 컴파일, core, alloc, std 빌드가 가능함
  • 코드에는 C 코드 외에 일부 C++ LLVM 래퍼가 포함됨
    • Rust가 LLVM의 일부 기능을 노출하기 위해 C++를 사용함
    • 해당 래퍼는 LLVM 버전에 종속적이고 단독 빌드가 번거로워 미리 컴파일된 상태로 제공됨

cilly의 역할

  • crustc는 새 Rust-to-C 컴파일러 도구체인인 cilly의 데모/티저
  • 전체 cilly 도구체인은 사용자의 Rust 코드를 임의의 대상에 맞춰 C로 컴파일하는 것을 목표로 함
  • 이 저장소는 cilly가 컴파일러 자체를 컴파일하는 모습을 보여주기 위해 구성됨
  • cilly는 Rust 라이브러리이자 Rust 컴파일러 백엔드, 즉 플러그인 형태로 Rust를 C로 컴파일함
  • 작성자는 지난 3년간 Rust를 C로 컴파일하는 작업을 해왔고, rustc_codegen_clr 같은 공개 시도와 여러 비공개 시도 이후 cilly가 14번째 시도라고 밝힘

C 컴파일러에 맞춰 코드를 생성하는 방식

  • cilly의 주요 특징은 C 컴파일러에 적응한다는 점임
  • 특정 컴파일러와 플랫폼이 무엇을 지원하는지 확인하는 witness 프로그램을 생성할 수 있음
    • 예시는 _Thread_local int KEYWORD_TLS_SUPPORTED;이며, 해당 C 컴파일러가 _Thread_local을 지원할 때만 컴파일됨
  • cilly는 특정 C 컴파일러가 받아들일 수 있는 C 코드를 생성하려고 함
  • 타입 레이아웃, 크기, 정렬, 문자 인코딩, 정수 형식은 질의 대상임
    • 문자 인코딩은 ASCII 여부를 확인함
    • 정수 형식은 two's complement 여부를 확인함
  • 가능한 경우 폴백을 사용함
  • ANSI C 밖의 가정을 피하려고 하며, strict aliasing 같은 현대 C 표준 관련 동작에도 우회책을 둠
  • 드물게 (void*)(uintptr_t)(ptr) 왕복 변환 같은 합리적 가정이 필요할 수 있음
    • 이런 가정은 문서화하고, 가능하면 CHAR_BIT = 8 같은 assert를 추가함

대상별 C 코드와 ABI 제약

  • cilly의 출력 C 코드는 컴파일러별
    • Arm64용으로 생성한 cilly C를 riscv32에서 그대로 실행할 수는 없음
    • riscv32용 cilly C를 별도로 생성할 수는 있음
  • 이 저장소의 rustc 생성 C는 작성자 워크스테이션의 ISA 때문에 ARM64 Linux를 대상으로 함
  • cilly가 생성한 코드는 일반 rustc가 컴파일한 코드와 대체로 ABI 호환됨
  • 일부 플랫폼에서는 rustc가 C로 표현할 수 없는 ABI를 선택해 완전한 호환이 어려움
  • Arm64에서는 구조체 반환 포인터인 sret 때문에 제약이 있음
    • 대부분의 플랫폼에서는 sret이 첫 번째 인자와 같은 레지스터로 전달되어 첫 인자를 출력 포인터로 두는 방식이 가능함
    • Arm64에서는 sret 포인터가 다른 레지스터로 전달됨
    • 네이티브 C 컴파일러가 작은 구조체에 대해 return-by-sret을 선택해야 하지만, 16바이트 미만 작은 구조체에서는 그렇게 하지 않는다고 설명함

오래되거나 특이한 대상 지원

  • 이 프로젝트의 주요 목표는 LLVM/GCC 지원이 없지만 C는 지원하는 오래되거나 특이한 하드웨어에서 Rust를 사용할 수 있게 하는 것임
  • 어떤 프로젝트가 Rust에서 C로 이동하거나 C 프로젝트의 Rust 대안이 만들어질 때, 그런 대상 지원 부족은 Rust의 단점으로 제기될 수 있음
  • cilly는 rustc와 C 컴파일러를 감싸고 Rust 코드를 즉석에서 C로 변환함
  • 사용자 관점에서는 특정 대상에 사용할 C 컴파일러를 정의하는 방식에 가까움
  • 예시 설정은 sdcc_z180-unknown-none 트리플과 /usr/bin/sdcc, -mz180, --std-c89, -c 인자를 사용함

네트워크 투명성과 원격 C 컴파일러

  • cilly는 네트워크 투명성을 갖고 TCP를 통해 C 컴파일러와 통신할 수 있음
  • 필요하다면 UART 같은 더 특이한 통신 방식으로 확장될 수 있음
  • 이 방식은 C 크로스 컴파일러가 없는 플랫폼의 부트스트랩 역설을 해결하기 위한 방법임
  • 대상 OS에서 작은 C 서버를 빌드해 실행하고, Linux 같은 일반 플랫폼에서 rustc를 실행한 뒤 cilly가 네트워크로 통신하게 할 수 있음
  • 작성자는 Arm64 Linux에서 rustc를 실행하면서 x86 Plan 9 VM용 작은 Rust 프로그램을 성공적으로 컴파일함
    • Plan 9 환경 출력은 gnot osversion 2000 cputype 386임
    • /tmp/hello_plan9 실행 결과는 Hello, world!임
    • nm 결과에는 rust_begin_unwind 심볼이 표시됨

makefile 생성 기능

  • cilly는 선택적으로 오브젝트 파일 안에 마커를 삽입하고 IR을 캐시 디렉터리에 저장할 수 있음
  • 이후 해당 마커를 읽어 함수와 전역을 정의 위치별로 나눌 수 있음
  • 이 정보를 바탕으로 makefile이 들어 있는 디렉터리를 생성해, C 컴파일러와 make만으로 Rust를 빌드할 수 있게 함

빌드와 실행 조건

  • 데모 빌드에 사용된 시스템은 Ubuntu 기반 ARM64 Linux임
    • 커널 문자열은 Linux spark-2773 6.17.0-1021-nvidia ... aarch64임
  • 사용된 C 컴파일러 정보는 GCC 13.3.0Ubuntu LLD 18.1.3
  • 빌드하려면 올바른 LLVM 라이브러리가 필요하며, 가장 쉬운 방법은 rustup install nightly-2026-06-16으로 해당 nightly를 설치하는 것임
  • 빌드 명령은 LLVM_LIB_DIR로 libLLVM.so.22.1-rust-1.98.0-nightly 경로를 지정해 make -j20을 실행함
  • CFLAGS는 동작하지만 일부 플래그는 컴파일을 느리게 만들 수 있음
  • 최적화는 권장되지 않음
    • 데모가 아직 거칠고 최적화가 문제를 일으킬 수 있음
    • 이 규모에서는 최적화에 시간이 많이 걸림
  • 최적화 없이 작성자 머신에서는 몇 분 안에 빌드됨
    • 측정값은 937.98s user, 123.77s system, 1352% cpu, 1:18.48 total임
  • 최적화를 켜면 대부분의 코드는 빠르게 지나가지만 일부 큰 Rust 파일에서 막힐 수 있음

테스트와 알려진 문제

  • 빌드 테스트는 LD_LIBRARY_PATH에 nightly LLVM 라이브러리와 ./rustc_driver를 지정하고 ./rustc/rustc --version을 실행하는 방식임
  • 일반 프로그램을 빌드하려면 std를 빌드해야 함
    • std가 없으면 error[E0463]: can't find crate for std 오류가 발생함
    • 표준 라이브러리 빌드는 BUILDING_STD.md를 참고해야 함
  • 알려진 버그로, 이상한 경로 정규화 문제 때문에 crustc가 빌드된 디렉터리, 즉 저장소 루트에서 실행될 때 크래시할 수 있음
  • 다른 위치에서는 정상 동작함

cilly 공개 상태

  • cilly는 아직 공개 사용 준비가 되지 않았음
  • 작성자는 가능한 빨리 공개할 계획이라고 밝힘
  • 공개가 늦어지는 이유로 직장, 대학 논문, 손 부상을 들고 있음
  • 전체 cilly 도구체인이 아직 공개되지 않은 이유 중 하나는 최적화 관련 버그를 추적 중이기 때문임
Read Entire Article