8 ms·
Rust to C compiler – 95.9% test pass rate, odd platforms
- claudiojulio 2y agoVery cool. C to Rust would be fantastic.
- ndndjdnd 2y agoWhat benefit would you envision from this?
- trentearl 2y agoThere is DARPA program called TRACTOR to pursue this: https://www.darpa.mil/news/2024/memory-safety-vulnerabilities https://www.darpa.mil/news/2024/memory-safety-vulnerabilitie...
- IshKebab 2y ago1. 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.
- Aurornis 2y ago> 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.
- JonChesterfield 2y agoIf 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 2y agoThey are discussing C to Rust, not the topic of the post. Rust would need to guess the semantics of the original C.
- CryZe 2y agoI 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-webassembly/ https://hacks.mozilla.org/2020/02/securing-firefox-with-weba...
- sitkack 2y agoI'd love to check that out. Did it unroll a wasm interpreter into wasm_op function calls?
- CryZe 2y agoThere's no interpreter, I just map each instruction to equivalent Rust code. Linear memory is accessed through a trait. The compiler is here: https://github.com/CryZe/wasm-to-rust https://github.com/CryZe/wasm-to-rust I have an example of a GameBoy emulator compiled from AssemblyScript to WASM to Rust here: https://github.com/CryZe/wasmboy-rs/blob/master/src/wasm.rs https://github.com/CryZe/wasmboy-rs/blob/master/src/wasm.rs
- sitkack 2y agoThat is super cool! Have you run into any limitations? Have you tried running in loop, wasm->rust->wasm->rust ? This is not-unlike unrolling an interpreter. There was a lua2c project that did something similar.
- fabrice_d 2y agoSee https://github.com/immunant/c2rust https://github.com/immunant/c2rust
- g-mork 2y agoMark 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 https://www.youtube.com/watch?v=1VgptLwP588
- pjmlp 2y agoNote the AI part of the tooling.
- jeroenhd 2y agoTools 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/ https://c2rust.com/ is ready for action.
- Krutonium 2y agoBut does it carry the Rusty guarantees?
- cryptonector 2y agoWhy wouldn't it?
- pornel 2y agoIt 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 2y agoI 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.
- bregma 2y agoWait until you find out how unsafe software written in the machine language that Rust usually transpiles to is.
- adwn 2y agoThat's not the same, and not what pornel is talking about. The x86 ADD instruction has a well-defined behavior on overflow, and i32 + i32 in Rust will usually be translated to an ADD instruction, same as int + int in C. But a C compiler is allowed to assume that a signed addition operation will never overflow (the dreaded Undefined Behavior), while a Rust compiler must not make that assumption. This means that i32 + i32 must not be translated to int + int. For example, a C compiler is allowed to optimize the expression a+1<a to false (if a is signed), but a Rust compiler isn't allowed to do this.
- db48x 2y agoI'm not convinced that it’s worth spending any time supporting most proprietary systems. Maybe not even Windows, but especially the really expensive ones.
- o11c 2y agoYou shouldn't spend your own effort; you should make it clear that you're open to users of such systems contributing. That's how GCC became so dominant - there were people already using all sorts of Unixen and they wanted a compiler, so they made it work.
- weinzierl 2y agoThat is absolutely true but exotic platforms are also fun to investigate and you can learn a lot. So I'd say you shouldn't spend your own effort if you don't want to but I am glad fractalfir did and I am looking forward to the his RustWeekNL presentation.
- eru 2y agoOf course, accepting contributions comes with some effort, too.
- lmm 2y ago> You shouldn't spend your own effort; you should make it clear that you're open to users of such systems contributing. In practice you can't really draw a line between those two things. I don't know the end result, but I remember a discussion of how implementing parts of Git in Rust would be a problem because NonStop, a currently supported platform, has no Rust support. Of course the sane response would be "screw NonStop then", but having accepted contributions to make NonStop a supported platform that isn't an easy path to take.
- AlienRobot 2y agoFunny, because the average person is convinced it's not worth spending any time supporting Linux!
- EasyMark 2y ago
- iaaan 2y agoLots of interesting use cases for this. First one that comes to mind is better interop with other languages, like Python.
- xmodem 2y agoWhat does this gain you that you can't already do with `extern "c"` functions from rust?
- nicce 2y ago’Extern c’ still uses Rust. You want to skip Rust and call C from other languages directly.
- hypeatei 2y agoNot GP, but what is the point of touching Rust at all then?
- nicce 2y agoTo generate safer C?
- koakuma-chan 2y agoCompiling Rust to C doesn’t simplify interoperability. Either way you’ll be calling C functions. I assume compiling Rust to C is useful if you’re targeting some esoteric platform that Rust compiler doesn’t support.
- nickpsecurity 2y agoI'd like to write Rust, receive its safety benefits (esp borrow checker), compiler to equivalent C, and then use C's tooling on the result. Why use C's tooling? In verification, C has piles of static analyzers, dynamic analyzers, test generators (eg KLEE), code generators (eg for parsing), a prover (Frama-C), and a certified compiler. If using a subset of these, C code can be made more secure than Rust code with more effort. There's also many tools for debugging and maintenance made for C. I can also obfuscate by swapping out processor ISA's because C supports all of them. On the business end, they may be cheaper with lower watts. I also have more skilled people I can hire or contract to do any of the above. One source estimated 7 million C/C++ developers worldwide. There's also a ton of books, online articles, and example code for anything we need. Rust is very strong in that last area for a new language but C/C++ will maintain an advantage, esp for low-level programming. These are the reasons I'd use Rust if I wanted C or C++ for deployment. Likewise, I wish there was still a top-notch C++ to C compiler to get the same benefits I described with C's tooling.
- snvzz 2y agoExcellent. Now we can quickly re-rustify projects by converting them to C.
- dilawar 2y agoIs it LLVM IR --> C? Or Rust AST to C?
- dilawar 2y agoFound 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 2y agoWhich 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 2y agoIt 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.
- OutOfHere 2y agoHow is this not dangerous? How can one be assured that all of the compile-time safety features of the Rust compiler are still in effect? Handwaving does not help.
- HeliumHydride 2y agoIt's as safe as LLVM IR is safe, assuming you trust the LLVM IR -> C translation step.
- grandempire 2y agoBecause they happen at compile time?
- cv5005 2y agoHow does the rust compiler assure that when compiling to machine code? Machine code is less safe than C after all.
- lmm 2y agoMachine code is generally much safer than C - e.g. it usually lacks undefined behaviour. If you're unsure about how a given piece of machine code behaves, it's usually sufficient to test it empirically.
- cv5005 2y agoNot any different from C - a given C compiler + platform will behave completetly deterministically and you can test the output and see what it does, regardless of UB or not.
- lmm 2y ago> a given C compiler + platform will behave completetly deterministically and you can test the output and see what it does, regardless of UB or not. Sure[1], but that doesn't mean it's safe to publish that C code - the next version of that same compiler on that same platform might do something very different. With machine code (especially x86, with its very friendly memory model) that's unlikely. (There are cases like unused instructions becoming used in never revisions of a processor - but you wouldn't be using those unused instructions in the first place. Whereas it's extremely common to have C code that looks like it's doing something useful, and is doing that useful thing when compiled with a particular compiler, but is nevertheless undefined behaviour that will do something different in a future version) [1] Build nondeterminism does exist, but it's not my main concern
- flomo 2y agoOf course, everyone votes up the headlines, but this link seems like premature WIP. Hopefully this will get posted for real after the presentation.
- ay 2y agoI clicked through to the project at https://github.com/FractalFir/rustc_codegen_clr https://github.com/FractalFir/rustc_codegen_clr - from a quick glance at it, with 1.8k stars and 17 contributors, it deserves a better treatment than a passive—aggressive dismissal like this as a top comment. It is a very impressive piece of work.
- flomo 2y agoRight, and that probably should have been the link rather than some in-process thoughts about popcount or w/e. Sorry for not figuring it out and clicking around effectively.
- FractalFir 2y agoThe linked article was mostly meant for people already lossely familiar with the project, but it seems it escaped its intended audience. I do have a whole bunch of articles about the project on my website, going trough the entire journey of the project, from its start as a Rust to .NET compiler, to the current state. https://fractalfir.github.io/generated_html/home.html https://fractalfir.github.io/generated_html/home.html I should have probably linked the previous articles in this one - I'll add that to my website. I'll also look into adding some more context to the articles next time. Thanks for the feedback :)
- cod1r 2y agothis 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 2y agoI think they’re pretty young too. Hoping for a bright future ahead of them!
- jokoon 2y agoAt first I read it as C to rust compiler. What is the point of compiling rust to C?
- arghwhat 2y agoUsing C compiler infrastructure, taking Rust where rustc/llvm does not go. Proprietary platforms with proprietary compilers for example.
- drdeca 2y agoI 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.
- p0w3n3d 2y agoExactly. Btw rust toolchain is quite complicated while a code that was tanspiled to C might be as well compiled to e.g. 6052
- tetha 2y agoThis 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 2y agoVala [1] is, perhaps, the most prominent example of practically used programming language with such compiler. [1] https://en.wikipedia.org/wiki/Vala_(programming_language) https://en.wikipedia.org/wiki/Vala_(programming_language)
- widforss 2y ago
- pixelfarmer 2y agoIf I see something like "At least on Linux, long and long long are both 64 bits in size." my skin starts to crawl. Not only that, but GCC defines __builtin_popcount() with unsigned int / long / long long, respective, i.e. even in the text it should be mentioned correctly (unless a different compiler uses signed types there ... ugh). The call is done with unsigned, using uint64_t as a type-cast, but using a fixed __builtin_popcountl() which translates to unsigned long. There are systems where this will fail, i.e. the only safe bet to use here is __builtin_popcountll() as this will cover at least 64 bit wide arguments. Also, if a * b overflows within the result type, it is an undefined behavior according to the C standard, so this overflow check is at least not properly portable, either, and the shown code for that is actually buggy because the last A1 has to be A0. No idea why all that gets me so grumpy today ...
- dlahoda 2y agothank for PR. very fast turn around.
- FractalFir 2y agoCorrect me if I am wrong C, unsigned overflow is well-defined - at least the GCC manual says so, but I'll have to check the standard. https://www.gnu.org/software/c-intro-and-ref/manual/html_node/Unsigned-Overflow.html https://www.gnu.org/software/c-intro-and-ref/manual/html_nod... Since signed multiplication is bitwise-equivalent to unsigned multiplication, I use unsigned multiplication to emulate UB-free signed multiplication. The signed variant of this overflow check is a bit harder to read because of that, but it still works just fine. bool i128_mul_ovf_check(__int128 A0 ,__int128 A1 ){ bb0: if((A1) != (0)) goto bb1; return false; bb1: return (((__int128)((__uint128_t)(A0) * (__uint128_t)(A1))) / (A1)) == (A1); } As for using `__builtin_popcountll` instead - you are right, my mistake. Thanks for pointing that out :). I did not use the word "unsigned" before long long for the sake of readability - I know that repeating a word so many times can make it harder to parse for some folk. The project itself uses the correct types in the code, I was just kind of loose with the language in the article itself. My bad, I'll fix that and be a bit more accurate. Once again, thanks for the feedback!
- 2y ago
- zwnow 2y agoWhy would I use a tool that doesn't pass all tests?
- 01HNNWZ0MV43FF 2y agoTo not write C
- haswell 2y agoThe post is an update on the status of an ongoing project. > This is an update on the progress I have made on my Rust to C compiler. > There still are about 65 tests that need fixing, but they all seem to have pretty similar causes. So, fixing them should not be too difficult.
- cbmuser 2y agoI 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.
- Aurornis 2y ago> 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 2y agoThey'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 2y ago> 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.
- CursedSilicon 2y agoHi, retro computing person here. I've had a similar debate with Rust evangelists in past Something the Rust community doesn't understand is when they shout "REWRITE IT IN RUST!" at a certain point that's simply not possible Those mainframes your Bank runs? I'm sure they'd love to see all that "awful" FORTRAN or C or whatever other language rewritten in Rust. But if Rust as a platform doesn't support the architecture? Well then that's a non-starter Worse still, Rust seems to basically leave anything that isn't i686/x86_64 or ARM64 as "Tier 2" or worse This specific line in Tier 2 would send most project managers running for the hills "Tier 2 target-specific code is not closely scrutinized by Rust team(s) when modifications are made. Bugs are possible in all code, but the level of quality control for these targets is likely to be lower" Lower level of quality control when you're trying to upgrade or refactor a legacy code base? And the target is a nuclear power plant? Or an air traffic control system? Or a bank? The usual response from the Rust evangelists is "well then they should sponsor it to run better!" but the economics simply don't stack up. Why hire 50 Rust programmers to whip rust-m68k into shape when you can just hire 10 senior C programmers for 20% of the cost? EDIT: Architecture, not language. I need my morning coffee
- deleted 2y ago[deleted]
- curtisszmania 2y ago[dead]
- jedisct1 2y agoNim to C compiler, 100% test pass rate.
- alexpadula 2y agoRust 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.
- alexpadula 2y agoI will read further into the project just off the bat I don’t get the point. Good luck it looks quite extensive :)
- AS04 2y agoBecause 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.
- wolrah 2y agoIt 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.
- AlotOfReading 2y agoSo you can get the benefits of Rust on platforms that rustc doesn't support. Seems pretty straightforward.
- deleted 2y ago[deleted]
- nullpoint420 2y agoWould it be possible for Rust to output LLVM IR? Would that make it easier to port if they have a LLVM frontend?
- guipsp 2y agoThis comment is strange, given that LLVM is rust's most mature backend
- woodruffw 2y agoI think the GP means emit LLVM IR directly. And the answer to that is yes; you can pass a flag to rustc that will emit the IR[1]. [1]: https://stackoverflow.com/questions/39004513/how-to-emit-llvm-ir-from-cargo https://stackoverflow.com/questions/39004513/how-to-emit-llv...
- nullpoint420 2y agoThis is what I meant, thank you.
- deleted 2y ago[deleted]
- 1vuio0pswjnm7 2y ago"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 2y agoSorry, 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 2y agoHas anyone tested this project on NetBSD. https://github.com/dotnet/coreclr/pull/4504/files https://github.com/dotnet/coreclr/pull/4504/files Any reason why it would not work.