crustc: conversión completa de rustc a C
(github.com/FractalFir)crustces una demo que convirtió todorustc 1.98.0-nightly (c712ea946 2026-06-16)en 46 millones de líneas de código C; al compilarlo conGCCymake, genera un compilador de Rust funcional- La herramienta base,
cilly, es un backend del compilador de Rust que compila Rust a C, y este repositorio está armado como la vitrina más llamativa de un compilador compilándose a sí mismo cillyconsulta, mediante programas witness, el layout de tipos, tamaños, alineación, codificación de caracteres, formato de enteros, etc. del compilador C y la plataforma de destino, para generar código C aceptable para un compilador C específico- El objetivo principal es hacer posible usar Rust en hardware antiguo o poco común que no cuenta con soporte de LLVM/GCC pero sí tiene un compilador C; también incluye transparencia de red para comunicarse con compiladores C remotos por TCP
- El C generado actualmente apunta a ARM64 Linux, la ISA de la workstation del autor; el toolchain completo de
cillytodavía no está listo para uso público y también se están rastreando bugs relacionados con optimización
Demo de rustc convertido a C
crustces un repositorio que convirtiórustc 1.98.0-nightly (c712ea946 2026-06-16)en 46 millones de líneas de código C- Este código C puede compilarse con
GCCymake, y el resultado de la compilación es un compilador de Rust funcional - El ejemplo de ejecución especifica la ruta de las bibliotecas LLVM y luego ejecuta
./rustc/rustc --version, que imprime la misma versiónrustc 1.98.0-nightly - El compilador de Rust generado puede compilar código y construir
core,allocystd - Además del código C, el código incluye algunos wrappers LLVM en C++
- Rust usa C++ para exponer algunas funcionalidades de LLVM
- Esos wrappers dependen de la versión de LLVM y son incómodos de compilar por separado, por lo que se entregan precompilados
El rol de cilly
crustces una demo/teaser decilly, un nuevo toolchain de compilación de Rust a C- El toolchain completo de
cillybusca compilar el código Rust del usuario a C para cualquier destino - Este repositorio está armado para mostrar a
cillycompilando el propio compilador cillyes una biblioteca Rust y un backend del compilador de Rust; es decir, compila Rust a C en forma de plugin- El autor dice que ha trabajado durante los últimos 3 años en compilar Rust a C y que, después de intentos públicos como
rustc_codegen_clry varios intentos privados,cillyes su intento número 14
Cómo genera código adaptado al compilador C
- Una característica principal de
cillyes que se adapta al compilador C - Puede generar programas witness que verifican qué soportan un compilador y una plataforma específicos
- Un ejemplo es
_Thread_local int KEYWORD_TLS_SUPPORTED;, que solo compila si ese compilador C soporta_Thread_local
- Un ejemplo es
cillyintenta generar código C que un compilador C específico pueda aceptar- El layout de tipos, tamaños, alineación, codificación de caracteres y formato de enteros son objeto de consulta
- Para la codificación de caracteres, verifica si es ASCII
- Para el formato de enteros, verifica si es two's complement
- Usa fallbacks cuando es posible
- Intenta evitar supuestos fuera de ANSI C y también incluye workarounds para comportamientos relacionados con estándares modernos de C, como strict aliasing
- En raras ocasiones puede necesitar supuestos razonables, como una conversión de ida y vuelta
(void*)(uintptr_t)(ptr)- Estos supuestos se documentan y, cuando es posible, se agregan asserts como
CHAR_BIT = 8
- Estos supuestos se documentan y, cuando es posible, se agregan asserts como
Código C por destino y restricciones de ABI
- El código C emitido por
cillyes específico por compilador- No se puede ejecutar tal cual en riscv32 el C de
cillygenerado para Arm64 - Sí se puede generar por separado C de
cillypara riscv32
- No se puede ejecutar tal cual en riscv32 el C de
- El C generado para
rustcen este repositorio apunta a ARM64 Linux debido a la ISA de la workstation del autor - El código generado por
cillyes, en general, compatible a nivel ABI con el código compilado porrustcnormal - En algunas plataformas,
rustcelige una ABI que no puede representarse en C, lo que dificulta la compatibilidad completa - En Arm64 hay restricciones por
sret, el puntero de retorno de estructuras- En la mayoría de las plataformas,
sretse pasa en el mismo registro que el primer argumento, lo que permite poner el puntero de salida como primer argumento - En Arm64, el puntero
sretse pasa en otro registro - El autor explica que el compilador C nativo debería elegir return-by-sret para estructuras pequeñas, pero no lo hace con estructuras pequeñas de menos de 16 bytes
- En la mayoría de las plataformas,
Soporte para destinos antiguos o poco comunes
- El objetivo principal de este proyecto es permitir usar Rust en hardware antiguo o poco común que no cuenta con soporte de LLVM/GCC pero sí soporta C
- Cuando un proyecto pasa de Rust a C, o cuando se crea una alternativa en Rust a un proyecto en C, la falta de soporte para esos destinos puede señalarse como una desventaja de Rust
cillyenvuelverustcy el compilador C, y convierte código Rust a C sobre la marcha- Desde el punto de vista del usuario, se parece a definir el compilador C que se usará para un destino específico
- La configuración de ejemplo usa el triple
sdcc_z180-unknown-noney los argumentos/usr/bin/sdcc,-mz180,--std-c89,-c
Transparencia de red y compiladores C remotos
cillytiene transparencia de red y puede comunicarse con compiladores C mediante TCP- Si hace falta, puede extenderse a métodos de comunicación más inusuales, como UART
- Este enfoque busca resolver la paradoja de bootstrap en plataformas sin cross-compiler de C
- Se puede compilar y ejecutar un pequeño servidor C en el OS de destino, ejecutar
rustcen una plataforma común como Linux, y hacer quecillyse comunique por la red - El autor compiló con éxito un pequeño programa Rust para una VM x86 de Plan 9 mientras ejecutaba
rustcen Arm64 Linux- La salida del entorno Plan 9 es
gnot osversion 2000 cputype 386 - El resultado de ejecutar
/tmp/hello_plan9esHello, world! - El resultado de
nmmuestra el símbolorust_begin_unwind
- La salida del entorno Plan 9 es
Función de generación de makefiles
cillypuede insertar opcionalmente un marcador dentro de los archivos objeto y guardar el IR en un directorio de caché- Luego puede leer ese marcador para separar funciones y globales según dónde están definidos
- Con esta información, genera un directorio con un makefile, lo que permite compilar Rust usando solo un compilador C y
make
Condiciones de compilación y ejecución
- El sistema usado para compilar la demo es ARM64 Linux basado en Ubuntu
- La cadena del kernel es
Linux spark-2773 6.17.0-1021-nvidia ... aarch64
- La cadena del kernel es
- La información del compilador C usado es GCC 13.3.0 y Ubuntu LLD 18.1.3
- Para compilar se necesitan las bibliotecas LLVM correctas; la forma más simple es instalar ese nightly con
rustup install nightly-2026-06-16 - El comando de compilación especifica con
LLVM_LIB_DIRla ruta delibLLVM.so.22.1-rust-1.98.0-nightlyy ejecutamake -j20 CFLAGSfunciona, pero algunas flags pueden hacer más lenta la compilación- No se recomienda optimizar
- La demo todavía está verde y la optimización puede causar problemas
- A esta escala, optimizar toma mucho tiempo
- Sin optimización, en la máquina del autor se compila en pocos minutos
- Las mediciones son
937.98s user,123.77s system,1352% cpu,1:18.48 total
- Las mediciones son
- Si se activa la optimización, la mayor parte del código avanza rápido, pero puede quedarse trabada en algunos archivos Rust grandes
Pruebas y problemas conocidos
- La prueba de compilación consiste en definir en
LD_LIBRARY_PATHlas bibliotecas LLVM del nightly y./rustc_driver, y ejecutar./rustc/rustc --version - Para compilar programas normales, hay que construir
std- Sin
std, aparece el errorerror[E0463]: can't find crate for std - Para construir la biblioteca estándar, hay que consultar
BUILDING_STD.md
- Sin
- Como bug conocido, por un problema extraño de normalización de rutas,
crustcpuede crashear cuando se ejecuta desde el directorio donde fue compilado, es decir, la raíz del repositorio - En otras ubicaciones funciona correctamente
Estado público de cilly
cillytodavía no está listo para uso público- El autor dice que planea publicarlo lo antes posible
- Entre las razones de la demora menciona el trabajo, la tesis universitaria y una lesión en la mano
- Una de las razones por las que el toolchain completo de
cillytodavía no se publicó es que se están rastreando bugs relacionados con optimización
1 comentarios
Opiniones en Lobste.rs
Se siente bastante extraño que las cadenas de build tradicionales de C con
configurefuncionen, en general, de esta manera, pero tiene sentido que este compilador, o transpiler, siga ese patrón.“14.º intento: cilly” muestra una perseverancia impresionante, y envidio esa tenacidad.
Su tamaño es de 4.6 millones de líneas, casi exactamente un orden de magnitud menor que este proyecto. El código C generado varía según el target, pero no según el compilador.
Entre las ventajas de Zig están el soporte para una amplia variedad de targets de compilación cruzada, una toolchain self-hosted y que LLVM sea una dependencia opcional; la promesa de poder compilar Rust a C para plataformas poco comunes también parece una señal dirigida hacia Zig.
crustc, no. Porque el compilador convertido admite los mismos targets de compilación que el compilador original.Sin embargo, sí es posible convertir otros proyectos Rust a C para ejecutarlos y compilarlos en targets que solo admiten C.
Aun así, no hay que sobreestimar su impacto. Es más bien una solución algo engorrosa para un problema muy de nicho.
rustcya tiene un soporte amplio de targets, y se ampliará más mediante el backend degcc.Las herramientas de compilación cruzada de Zig son geniales, pero sobre todo mejoran la comodidad, especialmente en la parte de C, que es más complicada que Zig o Rust; que admitan más targets es un punto relativamente menor.
Al final, el soporte de targets de Zig y Rust ya es bastante parecido, así que difícilmente será un factor decisivo, y hay muchas diferencias mucho más importantes entre ambos lenguajes.
crustces solo un ejemplo de lo que puede hacercilly, una toolchain que convierte Rust a C.La toolchain completa de
cillycompila el código Rust del usuario a C para targets arbitrarios. Creo que este repositorio es la demostración más vistosa, por eso muestra al compilador compilándose a sí mismo.rustca C.