crustc: rustc vollständig nach C übersetzt
(github.com/FractalFir)crustcist eine Demo, die den gesamtenrustc 1.98.0-nightly (c712ea946 2026-06-16)in 46 Millionen Zeilen C-Code übersetzt; mitGCCundmakegebaut entsteht daraus ein funktionsfähiger Rust-Compiler- Das zugrunde liegende Tool
cillyist ein Rust-Compiler-Backend, das Rust nach C kompiliert; dieses Repository ist als besonders auffälliges Showcase dafür aufgebaut, dass der Compiler sich selbst kompiliert cillyfragt über Witness-Programme Typ-Layouts, Größen, Ausrichtung, Zeichenkodierung, Integer-Formate usw. des Ziel-C-Compilers und der Plattform ab, um C-Code zu erzeugen, den ein bestimmter C-Compiler akzeptieren kann- Das Hauptziel ist, Rust auf alter oder ungewöhnlicher Hardware nutzbar zu machen, für die es keine LLVM-/GCC-Unterstützung, aber einen C-Compiler gibt; dazu gehört auch Netzwerktransparenz für die Kommunikation mit einem entfernten C-Compiler per TCP
- Der derzeit erzeugte C-Code zielt auf die Workstation-ISA des Autors, ARM64 Linux; die komplette
cilly-Toolchain ist noch nicht für die öffentliche Nutzung bereit, und Optimierungsfehler werden noch untersucht
Demo: rustc nach C übersetzt
crustcist ein Repository, dasrustc 1.98.0-nightly (c712ea946 2026-06-16)in 46 Millionen Zeilen C-Code übersetzt- Dieser C-Code kann mit
GCCundmakegebaut werden; das Ergebnis ist ein funktionsfähiger Rust-Compiler - Ein Ausführungsbeispiel setzt zunächst den Pfad zur LLVM-Bibliothek und führt dann
./rustc/rustc --versionaus, was dieselbe Versionrustc 1.98.0-nightlyausgibt - Der erzeugte Rust-Compiler kann Code kompilieren sowie
core,allocundstdbauen - Neben C-Code enthält der Code auch einige C++-LLVM-Wrapper
- Rust nutzt C++, um einige LLVM-Funktionen verfügbar zu machen
- Diese Wrapper sind von der LLVM-Version abhängig und einzeln umständlich zu bauen, daher werden sie vorkompiliert bereitgestellt
Die Rolle von cilly
crustcist eine Demo/ein Teaser für die neue Rust-to-C-Compiler-Toolchaincilly- Die vollständige
cilly-Toolchain soll Rust-Code von Nutzern für beliebige Ziele nach C kompilieren - Dieses Repository ist dafür aufgebaut, zu zeigen, wie
cillyden Compiler selbst kompiliert cillyist eine Rust-Bibliothek und ein Rust-Compiler-Backend, kompiliert Rust also als eine Art Plugin nach C- Der Autor sagt, er arbeite seit drei Jahren daran, Rust nach C zu kompilieren; nach öffentlichen Versuchen wie
rustc_codegen_clrund mehreren nicht öffentlichen Versuchen seicillyder 14. Versuch
Wie Code passend zum C-Compiler erzeugt wird
- Ein zentrales Merkmal von
cillyist, dass es sich an den C-Compiler anpasst - Es kann Witness-Programme erzeugen, die prüfen, was ein bestimmter Compiler und eine Plattform unterstützen
- Ein Beispiel ist
_Thread_local int KEYWORD_TLS_SUPPORTED;; es kompiliert nur, wenn der jeweilige C-Compiler_Thread_localunterstützt
- Ein Beispiel ist
cillyversucht, C-Code zu erzeugen, den ein bestimmter C-Compiler akzeptieren kann- Typ-Layouts, Größen, Ausrichtung, Zeichenkodierung und Integer-Formate werden abgefragt
- Bei der Zeichenkodierung wird geprüft, ob sie ASCII ist
- Bei Integer-Formaten wird geprüft, ob sie Two's Complement verwenden
- Wenn möglich, werden Fallbacks verwendet
- Annahmen außerhalb von ANSI C sollen vermieden werden; auch für Verhalten moderner C-Standards wie strict aliasing gibt es Workarounds
- In seltenen Fällen können vernünftige Annahmen nötig sein, etwa eine Roundtrip-Konvertierung wie
(void*)(uintptr_t)(ptr)- Solche Annahmen werden dokumentiert, und wenn möglich werden Asserts wie
CHAR_BIT = 8hinzugefügt
- Solche Annahmen werden dokumentiert, und wenn möglich werden Asserts wie
Zielabhängiger C-Code und ABI-Einschränkungen
- Der von
cillyausgegebene C-Code ist compiler-spezifisch- Für Arm64 erzeugter
cilly-C-Code kann nicht unverändert auf riscv32 ausgeführt werden - Für riscv32 kann jedoch separat
cilly-C-Code erzeugt werden
- Für Arm64 erzeugter
- Der in diesem Repository erzeugte C-Code für
rustczielt wegen der ISA der Workstation des Autors auf ARM64 Linux - Von
cillyerzeugter Code ist im Allgemeinen ABI-kompatibel mit Code, der von normalemrustckompiliert wurde - Auf manchen Plattformen wählt
rustcjedoch ABIs, die sich in C nicht ausdrücken lassen, sodass vollständige Kompatibilität schwierig ist - Auf Arm64 gibt es Einschränkungen wegen
sret, dem Rückgabepointer für Strukturen- Auf den meisten Plattformen wird
sretim selben Register wie das erste Argument übergeben, sodass der erste Parameter als Ausgabe-Pointer genutzt werden kann - Auf Arm64 wird der
sret-Pointer in einem anderen Register übergeben - Laut Beschreibung müsste der native C-Compiler bei kleinen Strukturen return-by-sret wählen, tut dies bei kleinen Strukturen unter 16 Byte aber nicht
- Auf den meisten Plattformen wird
Unterstützung für alte oder ungewöhnliche Ziele
- Das Hauptziel dieses Projekts ist, Rust auf alter oder ungewöhnlicher Hardware nutzbar zu machen, die keine LLVM-/GCC-Unterstützung hat, aber C unterstützt
- Wenn ein Projekt von Rust nach C wechselt oder eine Rust-Alternative zu einem C-Projekt entsteht, kann fehlende Unterstützung für solche Ziele als Nachteil von Rust angeführt werden
cillyumhülltrustcund den C-Compiler und wandelt Rust-Code on the fly nach C um- Aus Nutzersicht entspricht das in etwa dem Definieren eines C-Compilers für ein bestimmtes Ziel
- Eine Beispielkonfiguration nutzt das Triple
sdcc_z180-unknown-nonesowie/usr/bin/sdcc,-mz180,--std-c89und das Argument-c
Netzwerktransparenz und entfernte C-Compiler
cillybietet Netzwerktransparenz und kann über TCP mit einem C-Compiler kommunizieren- Falls nötig, ließe sich das auf ungewöhnlichere Kommunikationswege wie UART erweitern
- Dieser Ansatz soll das Bootstrap-Paradox für Plattformen lösen, für die es keinen C-Cross-Compiler gibt
- Man kann auf dem Ziel-OS einen kleinen C-Server bauen und ausführen, auf einer üblichen Plattform wie Linux
rustcstarten undcillyüber das Netzwerk kommunizieren lassen - Der Autor hat erfolgreich auf Arm64 Linux
rustcausgeführt und ein kleines Rust-Programm für eine x86-Plan-9-VM kompiliert- Die Ausgabe der Plan-9-Umgebung lautet
gnot osversion 2000 cputype 386 - Das Ergebnis von
/tmp/hello_plan9istHello, world! - Das Ergebnis von
nmzeigt das Symbolrust_begin_unwind
- Die Ausgabe der Plan-9-Umgebung lautet
Makefile-Erzeugung
cillykann optional Marker in Objektdateien einfügen und IR in einem Cache-Verzeichnis speichern- Später kann es diese Marker lesen und Funktionen sowie Globals nach Definitionsort aufteilen
- Auf Basis dieser Informationen erzeugt es ein Verzeichnis mit Makefile, sodass Rust nur mit einem C-Compiler und
makegebaut werden kann
Build- und Ausführungsbedingungen
- Das für den Demo-Build verwendete System ist ein Ubuntu-basiertes ARM64 Linux
- Der Kernel-String lautet
Linux spark-2773 6.17.0-1021-nvidia ... aarch64
- Der Kernel-String lautet
- Als C-Compiler wurden GCC 13.3.0 und Ubuntu LLD 18.1.3 verwendet
- Zum Bauen wird die passende LLVM-Bibliothek benötigt; am einfachsten ist es, die entsprechende Nightly-Version mit
rustup install nightly-2026-06-16zu installieren - Der Build-Befehl setzt mit
LLVM_LIB_DIRden Pfad zulibLLVM.so.22.1-rust-1.98.0-nightlyund führtmake -j20aus CFLAGSfunktioniert, einige Flags können die Kompilierung jedoch verlangsamen- Optimierung wird nicht empfohlen
- Die Demo ist noch roh, und Optimierung kann Probleme verursachen
- In dieser Größenordnung dauert Optimierung sehr lange
- Ohne Optimierung wird auf der Maschine des Autors innerhalb weniger Minuten gebaut
- Die Messwerte sind
937.98s user,123.77s system,1352% cpu,1:18.48 total
- Die Messwerte sind
- Mit eingeschalteter Optimierung läuft der Großteil des Codes schnell durch, kann aber bei einigen großen Rust-Dateien hängen bleiben
Tests und bekannte Probleme
- Der Build-Test besteht darin, in
LD_LIBRARY_PATHdie nightly-LLVM-Bibliothek und./rustc_driveranzugeben und./rustc/rustc --versionauszuführen - Um normale Programme zu bauen, muss
stdgebaut werden- Ohne
stdtritt der Fehlererror[E0463]: can't find crate for stdauf - Für den Build der Standardbibliothek soll
BUILDING_STD.mdherangezogen werden
- Ohne
- Ein bekannter Bug ist, dass
crustcwegen eines merkwürdigen Problems bei der Pfadnormalisierung abstürzen kann, wenn es aus dem Verzeichnis ausgeführt wird, in dem es gebaut wurde, also aus dem Repository-Root - Von anderen Orten aus funktioniert es normal
Veröffentlichungsstatus von cilly
cillyist noch nicht für die öffentliche Nutzung bereit- Der Autor erklärt, er plane eine Veröffentlichung so bald wie möglich
- Als Gründe für die Verzögerung nennt er Arbeit, eine Hochschularbeit und eine Handverletzung
- Einer der Gründe, warum die vollständige
cilly-Toolchain noch nicht veröffentlicht wurde, ist, dass noch Optimierungsfehler untersucht werden
1 Kommentare
Kommentare auf Lobste.rs
Dass die traditionelle C-
configure-Build-Chain im Großen und Ganzen so funktioniert, wirkt ziemlich seltsam, aber dass dieser Compiler bzw. Transpiler diesem Muster folgt, ist nachvollziehbar.„14. Versuch: cilly“ – das ist beeindruckende Beharrlichkeit, und um solche Ausdauer kann man neidisch werden.
Mit 4,6 Millionen Zeilen ist sie fast genau um eine Größenordnung kleiner als dieses Projekt. Der erzeugte C-Code unterscheidet sich je nach Ziel, aber nicht je nach Compiler.
Zu den Stärken von Zig gehören die Unterstützung vieler Cross-Compilation-Ziele, eine selbst gehostete Toolchain und eine optionale Abhängigkeit von LLVM; das Versprechen, Rust für seltene Plattformen nach C kompilieren zu können, wirkt auch wie ein Signal in Richtung Zig.
crustcist das nicht der Fall. Denn der übersetzte Compiler unterstützt nur dieselben Compilation-Ziele wie der ursprüngliche Compiler.Es ist allerdings möglich, andere Rust-Projekte nach C zu übersetzen und sie auf Zielen auszuführen und zu kompilieren, die nur C unterstützen.
Trotzdem sollte man den Effekt nicht überschätzen. Es ist eher eine etwas umständliche Lösung für ein sehr spezielles Problem.
rustcunterstützt bereits viele Ziele, und über dasgcc-Backend sollen es noch mehr werden.Zigs Cross-Compilation-Werkzeuge sind beeindruckend, erhöhen aber vor allem den Komfort – insbesondere bei C, das heikler ist als Zig oder Rust –, und bedeuten nur in geringerem Maße, dass mehr Ziele unterstützt werden.
Letztlich ist die Zielunterstützung von Zig und Rust bereits ziemlich ähnlich und dürfte kaum der entscheidende Faktor sein; zwischen den beiden Sprachen gibt es weit wichtigere Unterschiede.
crustcist nur ein Beispiel dafür, wascilly, eine Toolchain zur Übersetzung von Rust nach C, leisten kann.Die gesamte
cilly-Toolchain kompiliert den Rust-Code des Nutzers zu C für beliebige Ziele. Dieses Repository zeigt den Compiler, der sich selbst kompiliert, weil das wohl die spektakulärste Demonstration ist.rustcnach C übersetzt werden.