Rust to C compiler – 95.9% test pass rate, odd platforms
263 comments
·April 12, 2025cbmuser
Aurornis
> to allow me to bootstrap Rust on alpha, hppa, m68k and sh4
Do you actually use all four of those platforms, or is this an arbitrary threshold for what you consider a complete set of platform support?
im_down_w_otp
They're still common (except for alpha) platforms in some market segment specific corners of embedded development. So, maybe for those purposes?
Though, the trend I'm seeing a lot of is greenfield projects just migrating their MCUs to ARM.
Aurornis
> Though, the trend I'm seeing a lot of is greenfield projects just migrating their MCUs to ARM.
That’s what I would expect, too.
The Venn diagram of projects using an old architecture like alpha but also wanting to adopt a new programming language is nearly two separate circles.
The parent comment even included HPPA (PA-RISC) which almost makes me think they’re into either retro computing or they have some arbitrary completionist goal of covering all platforms.
cbmuser
I am actively maintaining all of these within Debian.
Plus, there is a very vibrant community around the Motorola 68000 and SuperH CPUs thanks to the Amiga, Sega Dreamcast and many other classical computer systems and consoles.
shakna
"m68k-unknown-linux-gnu" was merged as a Tier-3 target for Rust, wasn't it? [0]
cbmuser
Yes, it was me that did the work on the Rust side. It doesn't work yet though as progress on the LLVM side is very slow.
hedgehog
Did they abandon that goal? Last I heard it was still under development.
cbmuser
Well, the promise was that rustc_codegen_gcc would reach its goals very quickly which is why several people dismissed projects such as gccrs.
But it turns out that rustc_codegen_gcc still hasn't delivered and it seems the project has fallen asleep.
FractalFir
I am not affiliated with `cg_gcc`, but I have contributed some tiny things here and there.
Currently, `cg_gcc` is within spitting distance of being able to bootstrap the compiler. There really are only 3(!) bugs that currently stop a stage 2 build.
I know for sure, because I found workarounds for them, and have a working stage 2 build. A stage 3 build requires a bit more RAM than I have, but, besides that, it is definitely possible.
Those 3 bugs are: 1. Lack of support for 128 bit SwitchInt terminators(Rust IR equivalent of switch). This is likely caused by an issue on the GCC side, since libgccjit rejects 128 bit labels provided by `cg_gcc`. 2. A semantic difference between Rust's `#[inline(always)]` and `__attribute__((always_inline)) `. In Rust `#[inline(always)]` is a hint and works on recursive functions, but the GCC equivalent is not a hint, but a gurante, and does not work on recursive function. 3. `cg_gcc` miscompiles the Rust compiler's interner code if level 3 optimzations are enabled. The Rust compiler interner is quite complex, and does a lot of fiddly unsafe things, so it is the most likely to break. The exact cause of this issue is hard to pin down, but it can be worked around(by setting a lower opt level).
If you work around those issues, `cg_gcc` is able to successfully build the Rust compiler, at least on `x86_64 Linux`. Going from that to other architectures will still take time, but it is not as far away as some might think.
cod1r
this fractalfir person is super talented. See them on the rust reddit all the time. I'm not knowledgeable on compilers at all but others seem to really like their work.
landr0id
I think they’re pretty young too. Hoping for a bright future ahead of them!
1vuio0pswjnm7
"Most components of std are about 95% working in .NET, and 80% working in C."
.NET
Core tests 1662 39 12 97.02%
C
Core tests 1419 294 82.83%
Missing from HN title: The "95%" pass rate only applies to .NET. For GCC/Clang it is only "80%".
FractalFir
Sorry, the README was out of date. Those numbers are from the beginning of the year, and now they are: | .NET Core tests | 1764 | 48 | 20 | 96.29% | | C Core tests | 1712 | 71 | 8 | 95.59% |
1vuio0pswjnm7
Has anyone tested this project on NetBSD.
https://github.com/dotnet/coreclr/pull/4504/files
Any reason why it would not work.
iaaan
Lots of interesting use cases for this. First one that comes to mind is better interop with other languages, like Python.
pornel
The interop is already great via PyO3, except when people want to build the Rust part from source, but are grumpy about having to install the Rust compiler.
This hack is a Rust compiler back-end. Backends get platform-specific instructions as an input, so non-trivial generated C code won't be portable. Users will need to either get pre-generated platform-specific source, or install the Rust compiler and this back-end to generate one themselves.
chrisrodrigue
They are grumpy about having to install the Rust compiler for a good reason. You can’t compile for Rust on Windows without using MSVC via Visual Studio Build Tools, which has a restrictive license.
steveklabnik
You can use the GNU ABI instead, if you don't want to use the Visual Studio Build Tools.
estebank
https://rust-lang.github.io/rustup/installation/windows.html
> When targeting the MSVC ABI, Rust additionally requires an installation of Visual Studio so rustc can use its linker and libraries.
> When targeting the GNU ABI, no additional software is strictly required for basic use. However, many library crates will not be able to compile until the full MSYS2 with MinGW has been installed.
...
> Since the MSVC ABI provides the best interoperation with other Windows software it is recommended for most purposes. The GNU toolchain is always available, even if you don’t use it by default.
xmodem
What does this gain you that you can't already do with `extern "c"` functions from rust?
nicce
’Extern c’ still uses Rust. You want to skip Rust and call C from other languages directly.
dcow
Rust doesn't have a runtime so it looks just like C in compiled form. c-bindgen even spits out a c header. I’m not sure what skipping C practically means even if you can argue there’s a philosophical skip happening.
hypeatei
Not GP, but what is the point of touching Rust at all then?
null
dilawar
Is it LLVM IR --> C? Or Rust AST to C?
dilawar
Found the answer in the project readme.
> My representation of .NETs IR maps nicely to C, which means that I was able to add support for compiling Rust to C in 2-3K LOC. Almost all of the codebase is reused, with the C and .NET specific code only present in the very last stage of compilation
nickpsecurity
Which might also allow one to use tools that work on .NET bytecode. They include verification, optimization, debugging, and other transpilers. You might also get a grant or job offer from MS Research. :)
epage
It is a rustc backend, ie an alternative to llvm, gcc, or the cranelift backends.
It started as a .NET backend but they found that their approach could easily support C code generation as well so they added that. They do this by turning what rustc gives them into their own IR.
jedisct1
Nim to C compiler, 100% test pass rate.
Krutonium
But does it carry the Rusty guarantees?
GolDDranks
If the transpilation itself is bug-free, why not? For static guarantees, provided we transpile Rust code that already compiles on a normal Rust compiler, the guarantees are already checked and there, and the dynamic ones such as bounds checking can be implemented runtime in C with no problems.
chii
this assumes the rusty guarantees are transitive. There's no reason to believe it isn't, but it'd be nice to see some sort of proof, or at least an argument for it.
josephg
Should be. The rust borrow checker has no runtime component. It checks the code as-is before (or during) compilation.
Arguably it’s not the compiled binary that’s “safe”. It’s the code.
fpoling
Rust does not generate machine code itself. It uses LLVM to do that and there is no proof that the transformations done by that continue to keep the borrow checker guarantees. One just assumes with sufficient testing all bugs will be discovered.
Then the machine code generated by LLVM is not run directly by modern CPUs and is translated into internal representation first. And the future CPUs will behave like JIT-compilers with even more complex transformations.
The intermediate C code generated by this project just adds yet another transformation not fundamentally different from any of the above.
ryao
Rust does not guarantee that all bounds checks can be proven correct at compile time, so it relies on runtime bounds checks. If this does not implement the same bounds checks, then probably not.
cryptonector
Why wouldn't it?
pornel
It could fail if the generated C code triggered Undefined Behavior.
For example, signed overflow is UB in C, but defined in Rust. Generated code can't simply use the + operator.
C has type-based alias analysis that makes some type casts illegal. Rust handles alias analysis through borrowing, so it's more forgiving about type casts.
Rust has an UnsafeCell wrapper type for hacks that break the safe memory model and would be UB otherwise. C doesn't have such thing, so only uses of UnsafeCell that are already allowed by C are safe.
FractalFir
I have workarounds for all "simple" cases of UB in C(this is partially what the talk is about). The test code is running with `-fsantize=undefined`, and triggers no UB checks.
There are also escape hatches for strict aliasing in the C standard - mainly using memcpy for all memory operations.
cryptonector
> It could fail if the generated C code triggered Undefined Behavior.
> For example, signed overflow is UB in C, but defined in Rust. Generated code can't simply use the + operator.
Obviously, yes, but it could generate overflow checks.
bregma
Wait until you find out how unsafe software written in the machine language that Rust usually transpiles to is.
claudiojulio
Very cool. C to Rust would be fantastic.
Aurornis
> C to Rust would be fantastic.
This would have to go into one big unsafe block for any nontrivial program. C doesn’t convey all of the explicit things you need to know about the code to make it even compile in Rust.
CryZe
I once implemented a WASM to Rust compiler that due to WASM's safety compiles to fully safe Rust. So I was able to compile C -> WASM -> Rust and ended up with fully safe code. Though of course, just like in WASM, the C code is still able to corrupt its own linear memory, just can't escape the "sandbox". Firefox has employed a similar strategy: https://hacks.mozilla.org/2020/02/securing-firefox-with-weba...
sitkack
I'd love to check that out. Did it unroll a wasm interpreter into wasm_op function calls?
JonChesterfield
If your translator is correct, the rust front end enforces the semantics of rust then C implements them. It's as safe as any other implementation.
If that feels uncomfortable, consider that x64 machine code has no approximation to rust safety checks, and you trust rust binaries running on x64.
"Correct" is doing some heavy lifting here but generally people seem willing to believe that their toolchain is bug free.
pests
They are discussing C to Rust, not the topic of the post. Rust would need to guess the semantics of the original C.
g-mork
Mark Russinovich recently gave a talk at a UK Rust conference that mentioned Microsoft's internal attempts at large scale C->Rust translation, https://www.youtube.com/watch?v=1VgptLwP588
pjmlp
Note the AI part of the tooling.
jeroenhd
Tools like those exist. The problem with them is that they use unsafe blocks a lot, and the code usually isn't very idiomatic. Translating global variable state machines into more idiomatic Rust state machines based on things like named enums, for instance, would be very difficult.
With the help of powerful enough AI we might be able to get a tool like this, but as AI still very much sucks at actually doing what it's supposed to do, I don't think we're quite ready yet. I imagine you'd also need enough memory to keep the entire C and Rust code base inside of your context window, which would quickly require very expensive hardware once your code grows beyond a certain threshold. If you don't, you end up like many code assisting LLMs, generating code independently that's incompatible with itself.
Still, if you're looking to take a C project and extend it in Rust, or perhaps slowly rewrite it piece by piece, https://c2rust.com/ is ready for action.
ndndjdnd
What benefit would you envision from this?
trentearl
There is DARPA program called TRACTOR to pursue this:
https://www.darpa.mil/news/2024/memory-safety-vulnerabilitie...
IshKebab
1. It means you don't need C code & a C compiler in your project any more, which simplifies infrastructure. E.g. cross compiling is easier without any C.
2. You can do LTO between Rust and the C->Rust code so in theory you could get a smaller & faster executable.
3. In most cases it is the first step to a gradual rewrite in idiomatic Rust.
alexpadula
Rust to C? Why would someone do that. Just write C.. if you can figure rust out you surely can figure C out and be proficient.
AS04
Because of the niceties of Rust, combined with the widespread compatibility and architecture support of gcc / C compilers in general?
Rust is a modern language, with package management, streamlined integrated build/testing tools, much less cruft, and lots of high-level features and syntax that people actually like. C is neat but complex codebases benefit from modern languages that help in building robust abstractions while still maintaining the speed of C. Not to mention, of course, the borrow checker and memory safety.
AlotOfReading
So you can get the benefits of Rust on platforms that rustc doesn't support. Seems pretty straightforward.
wolrah
It seems like there's a healthy dose of "because it can be done" in play here, but also because there are a lot of platforms that are not supported by Rust where a Rust-to-C converter that generated standard-enough code could be used to bridge the gap.
null
alexpadula
I will read further into the project just off the bat I don’t get the point. Good luck it looks quite extensive :)
jokoon
At first I read it as C to rust compiler.
What is the point of compiling rust to C?
drdeca
I think there are probably C compilers for more platforms than there are rust compilers. So, if you want to compile your rust project on some obscure platform that doesn’t have a rust compiler for it yet, you could compile to C and then compile the resulting C code for that platform?
Just a guess.
Someone
This project doesn’t have that as a goal. In fact, it doesn’t even have “Rust to C compiler” as a goal. https://github.com/FractalFir/rustc_codegen_clr:
“ The project aims to provide a way to easily use Rust libraries in .NET. It comes with a Rust/.NET interop layer, which allows you to easily interact with .NET code from Rust
[…]
While .NET is the main focus of my work, this project can also be used to compile Rust to C, by setting the C_MODE enviroment flag to 1.
This may seem like a strange and unrelated feature, but the project was written in such a way that this is not only possible, but relatively easy.”
It also doesn’t mention for which version of C it produces code. That may or may not hinder attempts to use this to run rust on obscure platforms.
FractalFir
The README is slightly out of date, sorry. Supporting old platforms is one of the goals.
Truth be told, the support for C was at first added as a proff-of-concept that a Rust to C compiler is possible. But it worked surprisingly well, so I just decided to roll with it, and see where it takes me.
My policy in regards to C version is: I want to be as close to ANSI C as possible. So, I avoid modern C features as much as I can. I don't know if full compatibility is achievable, but I certainly hope so. Only time will tell.
Some simpler pieces of Rust work just fine with ANSI C compilers, but more complex code breaks(eg. due to unsupported intrinsics). If I will be able to solve that(+ some potential soundness issues) then I'll be able to use ANSI C.
arka2147483647
The article mentions ANSI-C at places. So seems like the old c standard is targeted.
tetha
This is a fairly common technique in compiler construction and programming language research: Don't try to emit some machine code, instead emit C or an IR for clang or GCC. And suddenly your little research language (not that rust is one) is executable on many, many platforms, can rely on optimizations the compilers can do, has potential access to debug handling, ..
kvemkon
Vala [1] is, perhaps, the most prominent example of practically used programming language with such compiler.
[1] https://en.wikipedia.org/wiki/Vala_(programming_language)
widforss
Regarding the other way, I guess a lot of (practically) legal C wouldn't compile to Rust at all due to the language's restrictions and C's laxness, while I think all Rust could be translated to C.
p0w3n3d
Exactly. Btw rust toolchain is quite complicated while a code that was tanspiled to C might be as well compiled to e.g. 6052
arghwhat
Using C compiler infrastructure, taking Rust where rustc/llvm does not go. Proprietary platforms with proprietary compilers for example.
teo_zero
> What is the point of compiling rust to C?
To address platforms that don't support Rust. TFA mentions NonStop, whatever it is.
vbitz
Fault-Tolerant mainframe type systems.
nickpsecurity
They are amazing machines designed for fault tolerance (99.999% reliability). The Wikipedia article below has design details for how many generations were made. HP bought them.
https://en.m.wikipedia.org/wiki/Tandem_Computers
I think it would be useful in open-source, fault tolerance to copy one of their designs with SiFive's RISC-V cores. They could use a 20 year old approach to dodge patent issues. Despite its age, the design would probably be competitive, maybe better, than FOSS clusters on modern hardware in fault tolerance.
One might also combine the architecture with one of the strong-consistency DR'S, like FoundationDB or CochroachDB, with modifications to take advantage of its custom hardware. At the local site, the result would be easy scaling of a system whose nodes appeared to never fail. The administrator still has to do regular maintenance, though, as the system reports component failures which it works around.
steveklabnik
Not only does NonStop not support Rust, but apparently they failed to port gcc to it, even. So compiling Rust straight to C itself is pretty much the only option there.
oulipo
I guess it's to target platforms (like some microcontrollers) which don't yet have a native Rust compiler, but often do have a C compiler?
jeroenhd
To use rust in places where you can only use C. I imagine there are quite a few obscure microcontrollers that would benefit greatly from this pipeline.
Hell, you might finally be able to get Rust into the Linux kernel. Just don't tell them the code was originally written in Rust to calm their nerves.
vblanco
Game consoles generally only offer clang as a possibility for compiler. If you can compile rust to C, then you can finally use rust for videogames that need to run everywhere.
koakuma-chan
Is Steam Deck a monopoly yet? I feel like if your game compiles to Linux, you can target pretty much every market out there.
dcow
I don’t think I’ve ever heard those two terms “video game” and “run everywhere” in the same sentence. Bravo.
null
snvzz
Excellent.
Now we can quickly re-rustify projects by converting them to C.
I am still waiting for any of the alternative Rust front- or backends to allow me to bootstrap Rust on alpha, hppa, m68k and sh4 which are still lacking Rust support.
Originally, the rustc_codegen_gcc project made this promise but never fulfilled it.