Live data from Hacker News

A possible new back end for Rust

jason-williams.co.uk

161–170 of 224 posts

Re: A possible new back end for Rust

#161
post #40

Earlier quoted context omitted.

Why phrase it as "other than to prove it can be done" if you already know there are good answers? I think the following obviously do apply: 1) much easier for Rust community to contribute to the compiler from end-to-end. 2) lower coordination cost with LLVM giving complete, Rust-focussed control over code generation/optimisation. Think about e.g. fixing noalias. 3) lower maintenance cost for LLVM integration/fork. It…

Because I don't think the possible good answers apply. Sure it is harder to contribute to the backend, but does it matter? I've been doing c++ for years and never looked at the backend. I'll grant lower coordination costs. However I believe they are not outweighed by the advantages of the other llvm contributions. If they need to fork llvm that is a problem. Either merge it back in and be done (with some tests so wha…

Yes, it does matter, because LLVM is an incredibly complex piece of software. And when you work on a compiler, it turns out you'll have to work on the backend. When I worked on a compiler day-in-and-out, there were single files in LLVM that were bigger than our entire in-house compilation backend put together. Which do you think is more appealing to debug? When a bug in code generation causes compiled programs to segfault, it is not necessarily easy to debug if you aren't intimately familiar with the project, and this fact is compounded when you consider not everyone hacking your compiler is also a C++ programmer, knows LLVM's architecture, and so on. It is literally hundreds of thousands of lines of C++. The trigger test case is probably a massive generated IR program generated by some toolchain written in a completely foreign language, for a foreign language. Playing the game of "recover the blackbox from the crash site" is not always fun.

You can file bug reports, but not every part of the project is going to receive the same level of attention or care from core developers, and not everyone has the same priority. For example the Glasgow Haskell Compiler had to post-process LLVM generated assembly for years because we lacked the ability to attach data directly next to functions in an object file (i.e. at an offset directly preceding the function). Not doing this resulted in serious, meaningful performance drops. That was only fixed because GHC developers, not any other LLVM users, fixed it after finding the situation untenable after so long. But it required feature design, coordination, and care like anything else and did not happen immediately. On the other hand the post-processing stuff was a huge hack and broke in somewhat strange ways. We had other priorities. In the end GHC, LLVM, and LLVM users benefitted, but it was not exactly ideal or easy, necessarily.

On the other hand, "normal" code generation bugs like register misallocation or whatever, caused by extreme cases, were occasionally fixed by upstream developers, or patches were merged quickly. But absolutely none of this was as simple as you think. LLVM is largely a toolchain designed for a C compiler, and things like this show. Rust has similarly stressed LLVM in interesting ways. Good luck if your language has interesting aliasing semantics! (I gave up on trying to integrate LLVM plugins into our build system so that the code generator could better understand e.g. stack and heap registers never aliased. That would have resulted in better code, but I gave up because it turns out writing and distributing plugins for random LLVM versions your users want to use isn't fun or easy, which is a direct result of LLVM's fast-moving release policy -- and it is objectively better to generate worse code if it's more reliable to do so, without question.)

Finally, LLVM's compilation time issues are very real. Almost every project that uses LLVM in my experience ends up having to either A) just accept the fact LLVM will probably eat up a non-negligible amount of the compilation time, or B) you have to spend a lot of time tuning the pass sets and finding the right set of passes that work based on your design and architecture (e.g. earlier passes outside of LLVM, in your own IR, might make later passes not very worth it). This isn't exactly LLVM's fault, basically, but it's worth keeping in mind. Even for GHC, a language with heavy "frontend complexity", you might suspect type checking or whatever would dwarf stuff -- but the LLVM backend measurably increased build times on large projects.

> Either merge it back in and be done

It's weird how you think coordination costs aren't a big deal and then immediately say afterwords "just merge it back in and be done". Yeah, that's how it works, definitely. You just email the patch and it gets accepted, every time. Just "merge it back in". Going to go out on a limb and say you've never actually done this kind of work before? For the record, Rust has maintained various levels of LLVM patches for years at this point. They may or may not maintain various ones now, but I wouldn't be surprised if still they did. Ebbs and flows.

I'm not saying LLVM isn't a good project, or that it is not worth using. It's a great project! If you're writing a compiler, you should think about it seriously. If I was writing a statically typed language it'd be my first choice unless my needs were extreme or exotic. But if you think the people working on this Rust backend are somehow unaware of what they're dealing with, or what problems they deal with, I'm going to go out on a limb and suggest that: they actually do understand the problem domain much, much better than you.

Based on my own experience, I strongly suspect this backend will not only be profitable in terms of compilation time, which is a serious and meaningful metric for users, but will also be more easily understood and grokked by the core developers. And Cranelift itself will benefit, which will extend into other Rust projects.

Re: A possible new back end for Rust

#162
post #106
post #90

Earlier quoted context omitted.

Haskell, OCaml, SML, Idris also compile quite fast, with complex type systems. Their secret? Multiple backends with different kinds of optimizations. You don't need to compile for the ultimate release performance when in the middle of compile-debug-edit cycle.

From my (limited) experience, Haskell does not compile fast, especially if you’re doing something that needs lenses.

It surely does, because Haskell is not one compiler language, not only does it have multiple implementations, which I concede almost everyone only cares about GHC, there are interpreters and a REPL experience as well.

You don't need to compile your program in one go using GHC's LLVM backend, many times a GHCi session is more than enough.

Re: A possible new back end for Rust

#163
post #151

Earlier quoted context omitted.

Still not as good as emitting C code in most cases? C code gets optimized using either llvm or any other optimizer so it’s a more portable compile target.

When you emit C, you're limited by C, at least if you want to emit C as opposed to inline assembly wrapped in C. For example, it's harder to have a function return more than one value in C than it is in most architectures, you can't do things with processor flags (on architectures which have them), you're at the mercy of the C compiler's optimizer as to vectorization and loop unrolling, you can't always preserve sema…

> it's harder to have a function return more than one value in C than it is in most architectures

Biggest issue is the cultural aversion to returning structs and tagged unions.

Re: A possible new back end for Rust

#164
post #151

Earlier quoted context omitted.

Still not as good as emitting C code in most cases? C code gets optimized using either llvm or any other optimizer so it’s a more portable compile target.

When you emit C, you're limited by C, at least if you want to emit C as opposed to inline assembly wrapped in C. For example, it's harder to have a function return more than one value in C than it is in most architectures, you can't do things with processor flags (on architectures which have them), you're at the mercy of the C compiler's optimizer as to vectorization and loop unrolling, you can't always preserve sema…

I think we can all agree that LLVM IR is a more powerful compilation target than C. However, what Pizlo was saying is that generating C can be simpler than generating LLVM IR. A bunch of printfs can get you very far.

Re: A possible new back end for Rust

#165

This is really great. The world needs more diverse compiler tech. The llvm monoculture is constraining what kind of compiler research folks do to just the things that are practical to do in llvm. I particularly suspect that if something like Cranelift gets evolved more then it will eventually reach throughput parity with llvm, likely without actually implementing all of the optimizations that llvm has. It shouldn’t b…

We are also seeing MLIR emerging as a compiler framework and LLVM being a dialect of that. This is happening within the LLVM project itself. From this point, it may be easier to write compilers without bringing in all of LLVM with it.

Re: A possible new back end for Rust

#166
post #151

Earlier quoted context omitted.

Still not as good as emitting C code in most cases? C code gets optimized using either llvm or any other optimizer so it’s a more portable compile target.

When you emit C, you're limited by C, at least if you want to emit C as opposed to inline assembly wrapped in C. For example, it's harder to have a function return more than one value in C than it is in most architectures, you can't do things with processor flags (on architectures which have them), you're at the mercy of the C compiler's optimizer as to vectorization and loop unrolling, you can't always preserve sema…

LLVM while a very successful project isn't nothing new as idea.

IBM had several LLVM like projects during the 70's, and that is how their surviving IBM i and z/OS work anyway, with language environments that AOT at installation time.

Likewise there were projects like Amsterdam Compiler Kit among others during the early 80's.

Re: A possible new back end for Rust

#167
post #73

Earlier quoted context omitted.

Yes, it's a monoculture when the majority of all compiler work/research is happening on one compiler chain. (I feel like GCC is still competitive enough to keep up some competition, but Clang does have a lot of backing.) And yes, if we made a rust replacement and that somehow eclipsed all other compiler suites it would be a monoculture and be bad, but that's unlikely and creating an alternative to the most popular op…

So if we join forces and create a reusable compiler backend so not every compiler writer has to implement the same optimizers and code generators over and over again, then this is bad because it's a monoculture? How strange is that? To me, it sounds more like political propaganda from a few idealists who want to justify why - instead of participating in a joint project - they want to develop everything themselves fro…

> So if we join forces and create a reusable compiler backend so not every compiler writer has to implement the same optimizers and code generators over and over again, then this is bad because it's a monoculture? How strange is that?

Why is that strange? You now have a diverse set of frontends and a monoculture on the backend. A world with Chrome, Chromium, Edge, Brave, and the Yandex browser is still a browser engine monoculture.

Re: A possible new back end for Rust

#168

Earlier quoted context omitted.

C is a pretty lousy intermediate language: * It's missing several useful operators, such as classic bit manipulation (count trailing zero, byteswap), or even 8- and 16-bit arithmetic. Checked arithmetic is another useful one that's not present (or even really possible in C's ABI). * Signed integer overflow is UB. * Utterly no support for SIMD types. * Proper IEEE 754 floating-point control is kind of spotty, although…

Just out of curiosity, what would be a great intermediate language to transpile to (as of intermediate language)?

In practice I think it is hard to beat C in this regard. You can go pretty far if you are willing adapt to its quirks! And while C doesn't always allow for the best optimization (such as returning multiple values via registers), the workarounds often are still pretty fast.

On a more theoretical level there has been some research on what a better intermediate language would look like. One project I found interesting was Mu VM, which offers some niceties for compiling languages with a garbage collector.

https://microvm.github.io/

Re: A possible new back end for Rust

#169
post #151

Earlier quoted context omitted.

When you emit C, you're limited by C, at least if you want to emit C as opposed to inline assembly wrapped in C. For example, it's harder to have a function return more than one value in C than it is in most architectures, you can't do things with processor flags (on architectures which have them), you're at the mercy of the C compiler's optimizer as to vectorization and loop unrolling, you can't always preserve sema…

> it's harder to have a function return more than one value in C than it is in most architectures Biggest issue is the cultural aversion to returning structs and tagged unions.

And it's not even hard, just ugly. Which is much less of a problem for a compiler IR.

Re: A possible new back end for Rust

#170

Earlier quoted context omitted.

Llvm is absolutely not the least effort for generating machine code. In many settings, it takes a fraction of the effort of integrating llvm to create a template compiler that goes straight to machine code. In many other cases, your best bet is to have your compiler emit C and then feed that to a C compiler of your choice. It’s good to have divergence. Competition is good. Otherwise people stop trying new things.

Depends on your goals. Writing a front end, optimizer and backend quickly gets to more work. I can write a c++ compiler in a few months. It won't be good and to make it good would be many many years of work. If I write a llvm backend it might take a little longer (I doubt it), but I automatically get all the optimizations llvm has plus a good front end that doesn't have bugs in obscure corner cases. (not claiming llv…

> I can write a c++ compiler in a few months.

Not that it substantially distracts from your point, but I strongly doubt this. Or did you mean a heavily restricted subset of C++? A C++ front end alone is so complex to build that these guys make a living off of licensing their front end code: https://www.edg.com/

(Fun fact: Microsoft rebuilt IntelliSense for C++ on the EDG front end. Yes, that Microsoft with the MSVC compiler. See https://devblogs.microsoft.com/cppblog/rebuilding-intellisen... and https://old.reddit.com/r/cpp/comments/bdt8ep/does_msvc_still...)

Even without compatibility cruft, you're looking at multiple 100k LOC if their code base is anything to go by. That's man-years, not man-months...

Post reply on HN