5 ms·
I don't follow, why would SSA need to be translated into an input language? LLVM used to have a C backend, yes, but that hasn't been maintained for a while now
by eddyb 11y ago
I don't follow, why would SSA need to be translated into an input language?
LLVM used to have a C backend, yes, but that hasn't been maintained for a while now.
- sklogic 11y ago> I don't follow, why would SSA need to be translated into an input language? Rust is a meta-language with very powerful macros in it. What is a macro? Macro, essentially, is a compiler. You can have some petty macros implementing tiny syntax sugar on top of your language, that's totally fine, but that's not their purpose. The real metaprogramming kicks in when you implement very high-level eDSLs on top of your macros. And for this sort of things, having a proper compilation pipeline is a must. Many eDSLs may end up being represented as an SSA. E.g., I'm doing this with a Packrat eDSL - it pays to represent its intermediate language as an SSA for doing some high level optimisations before spitting out the host language code.
- mafribe 11y agoThe compiler implementing the macros (a form of compile-time meta-programming) should be the same compiler as that for the rest of the language.
- sklogic 11y ago> should be the same compiler as that for the rest of the language Sorry, I do not understand what are you talking about. Of course it is the same host compiler. But, every macro itself is a small compiler. Sometimes, when your DSL is an elaborate, complex thing, the macro itself is a complicated, big compiler. With all the bells and whistles of a big compiler - multiple stages, multiple intermediate representations, all that stuff. And SSA is one of the most efficient intermediate representations ever, suitable for a huge number of semantic classes of DSLs. So, making it harder to generate your same host language code out of an intermediate, in-macro representation does not serve any reason, it's plainly conuterproductive.
- mafribe 11y agoBut, every macro itself is a small compiler. I'm not following you here. What does that mean? The macro gets expanded at compile-time into 'normal' source code, by the compiler.
- sklogic 11y ago> I'm not following you here. Any marginally non-trivial macro is a compiler, by definition. > The macro gets expanded at compile-time into 'normal' source code, by the compiler. Macro expands a DSL inside it into the underlying host meta-language code. In other words, it compiles this DSL into the host language. For example, a macro which defines a parser. Inside it is a BNF (or PEG), a very high level language. Macro must compile this language into Rust, and, since it is a very high level language, there are tons of optimisation opportunities that would be totally missed by the underlying Rust and LLVM because they lack this domain-specific knowledge. Your macro will compile this source DSL in multiple stages (well, because this is the only sane approach to compilation anyway, read about the Nanopass framework for more details). First it will operate on an AST level, do some analysis, error reporting, inlining, may annotate the detected left recursive nodes and binary expression nodes. Then you'd lower it down into the trivial Packrat building blocks - still a tree. But now you notice that there is a lot of redundant reads from the input stream, and if you flatten this tree into an SSA you can optimise them all away. Alas, after such an optimisation you'd have to promote it back to tree in order to generate Rust, because there is no `goto`. And this is only one trivial example. In my practice there were dozens such DSLs. For example, same story is with an optimising WAM-based embedded Prolog DSL, multiple querying DSLs, tree walking DSLs (which are essential for implementing macros efficiently).
- Havvy 11y agoA compiler takes a text from one language and translate it into text of another executable language.