# crustc: rustc 전체를 C로 변환

> Clean Markdown view of GeekNews topic #31088. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=31088](https://news.hada.io/topic?id=31088)
- GeekNews Markdown: [https://news.hada.io/topic/31088.md](https://news.hada.io/topic/31088.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-07-03T22:02:11+09:00
- Updated: 2026-07-03T22:02:11+09:00
- Original source: [github.com/FractalFir](https://github.com/FractalFir/crustc)
- Points: 1
- Comments: 1

## Topic Body

- `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.0**과 **Ubuntu 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` 도구체인이 아직 공개되지 않은 이유 중 하나는 **최적화 관련 버그**를 추적 중이기 때문임

## Comments



### Comment 61220

- Author: neo
- Created: 2026-07-03T22:02:12+09:00
- Points: 1

###### [Lobste.rs 의견들](https://lobste.rs/s/ryny2c/crustc_entirety_rustc_translated_c) 
- 주어진 컴파일러와 플랫폼이 무엇을 지원하는지 확인하는 **witness 프로그램**을 생성한다는 점이 흥미롭다  
  전통적인 C `configure` 빌드 체인이 대체로 이런 방식으로 동작한다는 게 꽤 이상하게 느껴지지만, 이 컴파일러, 혹은 트랜스파일러가 그 패턴을 따르는 건 납득됨  
  “14번째 시도: cilly”라니 대단한 집요함이고, 그런 끈기가 부럽다
- 비교하자면, Zig 컴파일러 전체를 C로 변환한 버전을 갖고 있는데, 이는 [소스에서 빌드하는 일반 절차](https://ziglang.org/news/goodbye-cpp/)의 일부임  
  규모는 **460만 줄**이라 이 프로젝트보다 거의 정확히 한 자릿수 작다. 생성된 C 코드는 대상별로 달라지지만, 컴파일러별로 달라지지는 않음
- 시스템 프로그래머는 아니지만, 이런 프로젝트가 Rust와 Zig 중 무엇을 쓸지에 영향을 줄 수 있을지 궁금함  
  Zig의 장점에는 다양한 **교차 컴파일 대상** 지원과 자체 호스팅 도구체인, LLVM 선택 의존성이 포함되는데, Rust를 희귀 플랫폼용 C로 컴파일할 수 있다는 약속은 Zig 쪽을 겨냥한 신호처럼도 보임
  - `crustc`를 쓰는 것만으로는 그렇지 않음. 변환된 컴파일러도 원래 컴파일러와 같은 **컴파일 대상**만 지원하기 때문임  
    다만 다른 Rust 프로젝트를 C로 변환해서 C만 지원하는 대상에서 실행하고 컴파일하는 것은 가능함  
    그래도 영향을 과대평가하면 안 됨. 아주 틈새 문제를 위한 약간 번거로운 해법에 가깝다. `rustc`는 이미 대상 지원이 넓고, `gcc` 백엔드를 통해 더 늘어날 예정임  
    Zig의 교차 컴파일 도구는 멋지지만, 특히 Zig나 Rust보다 까다로운 C 부분에서 편의성을 높이는 쪽에 가깝고, 더 많은 대상을 지원한다는 의미는 상대적으로 작음  
    결국 Zig와 Rust의 대상 지원은 이미 꽤 비슷해서 결정적 요인이 되긴 어렵고, 두 언어 사이에는 훨씬 중요한 차이가 많다
- 멋지긴 한데, 결국 **LLVM의 능력**에 제한되는 것 아닌가?
  - 왜 그래야 하는지 모르겠음. `crustc`는 Rust를 C로 바꾸는 도구체인인 `cilly`가 무엇을 할 수 있는지 보여주는 예시일 뿐임  
    전체 `cilly` 도구체인은 사용자의 Rust 코드를 **임의의 대상**용 C로 컴파일한다. 이 저장소는 가장 화려한 시연이라고 생각해서 컴파일러가 자기 자신을 컴파일하는 모습을 보여주는 것임
- mrustc(https://github.com/thepowersgang/mrustc)도 볼 만함. C++로 작성된 Rust 컴파일러로, C로 트랜스파일한 뒤 GCC에 넘기는 방식이라 `rustc`도 C로 변환할 수 있음
