No, you really shouldn’t target Rust unless you happen to be writing a language that is nearly semantically identical to Rust. Consider for instance how you’d bolt a non-standard calling convention (register pinning), like LLVM supports, onto Rust. You’re basically locked into the high-level semantics that Rust choose which are basically call/ret with it’s specific stack setup. LLVM is a much more malleable medium to target for languages of many different sorts because it makes much fewer assumptions, that’s why it’s such a great target.
This is extremely true, but also a specific case of a more general problem that people often seem to overlook: to compile language X to intermediate representation Y, Y must be able to efficiently implement all the concepts in X. LLVM IR keeps getting more features over time, in part to represent concepts that exist in certain source languages but cannot be efficiently (or at all) represented in LLVM IR without changes.
Languages don’t generally make good general-purpose IRs unless they’re designed for that (and get beaten on for years until they have the features people need). Sometimes people make new IRs for their own purposes because LLVM’s really isn’t a good mapping to what they need – but that new IR is likely only good for that purpose, because that’s what it was made to do. It’s not “better” than LLVM – just (usually) more specialized and different.
(The inverse is true too: LLVM IR has a lot of implicit assumptions, e.g. in its memory model, arithmetic system, and so on, that roughly match a C-like language model. And if you don’t want those…. it can be hard to work around them!)
This post conveniently ignores Rust’s most notable feature: lifetimes. Any language compiling to Rust would either inherit the same feature (so no other common language) or have unsafe sprinkled everywhere (kind of defeating the purpose). This is in addition to all the usual issues with One More IL: slower compilations, less obvious optimization misses, etc, etc.
or have unsafe sprinkled everywhere (kind of defeating the purpose)
While I generally agree with the sentiment that Rust is not a good LLVM IR replacement, people tend to believe that unsafe doesn’t have gain over C. unsafe Rust still has checks in place, for example, your are not allowed to arbitrarily cast between types of different sizes and such.
LLVM IR has the same requirement: you cannot bitcast between types of different sizes. If you want to convert between type sizes you typically have to use zext, sext, trunc, fpext, or fpround.
Instead of compiling to Rust, why not write a few macros instead?
It seems the author’s intent is to describe ways to develop new languages, not some approach to metaprogramming.
Programming languages and compilers are a sort of metaprogramming over assembly, no? :P
The other comments here have pointed out how by targeting Rust, the author is pegged to Rust’s semantics. It seems to me that they might as well fiddle with macros than create new languages on top.