1 puntos por GN⁺ 3 시간 전 | 1 comentarios | Compartir por WhatsApp
  • crustc es una demo que convirtió todo rustc 1.98.0-nightly (c712ea946 2026-06-16) en 46 millones de líneas de código C; al compilarlo con GCC y make, 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
  • cilly consulta, 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 cilly todaví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

  • crustc es 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 GCC y make, 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ón rustc 1.98.0-nightly
  • El compilador de Rust generado puede compilar código y construir core, alloc y std
  • 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

  • crustc es una demo/teaser de cilly, un nuevo toolchain de compilación de Rust a C
  • El toolchain completo de cilly busca compilar el código Rust del usuario a C para cualquier destino
  • Este repositorio está armado para mostrar a cilly compilando el propio compilador
  • cilly es 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_clr y varios intentos privados, cilly es su intento número 14

Cómo genera código adaptado al compilador C

  • Una característica principal de cilly es 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
  • cilly intenta 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

Código C por destino y restricciones de ABI

  • El código C emitido por cilly es específico por compilador
    • No se puede ejecutar tal cual en riscv32 el C de cilly generado para Arm64
    • Sí se puede generar por separado C de cilly para riscv32
  • El C generado para rustc en este repositorio apunta a ARM64 Linux debido a la ISA de la workstation del autor
  • El código generado por cilly es, en general, compatible a nivel ABI con el código compilado por rustc normal
  • En algunas plataformas, rustc elige 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, sret se pasa en el mismo registro que el primer argumento, lo que permite poner el puntero de salida como primer argumento
    • En Arm64, el puntero sret se 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

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
  • cilly envuelve rustc y 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-none y los argumentos /usr/bin/sdcc, -mz180, --std-c89, -c

Transparencia de red y compiladores C remotos

  • cilly tiene 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 rustc en una plataforma común como Linux, y hacer que cilly se comunique por la red
  • El autor compiló con éxito un pequeño programa Rust para una VM x86 de Plan 9 mientras ejecutaba rustc en Arm64 Linux
    • La salida del entorno Plan 9 es gnot osversion 2000 cputype 386
    • El resultado de ejecutar /tmp/hello_plan9 es Hello, world!
    • El resultado de nm muestra el símbolo rust_begin_unwind

Función de generación de makefiles

  • cilly puede 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 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_DIR la ruta de libLLVM.so.22.1-rust-1.98.0-nightly y ejecuta make -j20
  • CFLAGS funciona, 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
  • 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_PATH las bibliotecas LLVM del nightly y ./rustc_driver, y ejecutar ./rustc/rustc --version
  • Para compilar programas normales, hay que construir std
    • Sin std, aparece el error error[E0463]: can't find crate for std
    • Para construir la biblioteca estándar, hay que consultar BUILDING_STD.md
  • Como bug conocido, por un problema extraño de normalización de rutas, crustc puede 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

  • cilly todaví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 cilly todavía no se publicó es que se están rastreando bugs relacionados con optimización

1 comentarios

 
GN⁺ 3 시간 전
Opiniones en Lobste.rs
  • Es interesante que genere un programa testigo para comprobar qué admite un compilador y una plataforma dados.
    Se siente bastante extraño que las cadenas de build tradicionales de C con configure funcionen, 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.
  • Como comparación, Zig tiene una versión de todo el compilador Zig convertida a C, que forma parte del procedimiento normal para compilar desde el código fuente.
    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.
  • No soy programador de sistemas, pero me pregunto si un proyecto así podría influir en la decisión de usar Rust o Zig.
    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.
    • Solo con usar 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. rustc ya tiene un soporte amplio de targets, y se ampliará más mediante el backend de gcc.
      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.
  • Está genial, pero ¿no queda limitado al final por las capacidades de LLVM?
    • No veo por qué tendría que ser así. crustc es solo un ejemplo de lo que puede hacer cilly, una toolchain que convierte Rust a C.
      La toolchain completa de cilly compila 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.
  • También vale la pena mirar mrustc(https://github.com/thepowersgang/mrustc). Es un compilador de Rust escrito en C++ que transpila a C y luego se lo pasa a GCC, así que también puede convertir rustc a C.