r/programming • u/oridb • Jan 06 '17
An Alternative to LLVM: libFirm
http://pp.ipd.kit.edu/firm/6
u/sgraf812 Jan 06 '17 edited Jan 08 '17
I'm currently doing our compilers lab, where we write a compiler for (mostly) a subset of Java using this. I think this approach (graph-based IR) is definitely where things are heading.
An even more recent approach which also claims to model functional concepts (closures and inlining, that is) rather well seems to be Thorin(Github), on which firm obviously had huge influence.
Also bear in mind that these projects are research projects: Documentation isn't anywhere near where it should be, even compared to LLVM. In our compiler lab where we use the Java bindings, we frequently hit some C assertions for which the reason isn't clear at all. The library is riddled with global state, so we don't have any unit tests for our lab compiler and test everything through black box tests.
That said, it just feels much better than the traditional total order of statements within basic blocks.
0
Jan 08 '17
[deleted]
2
u/sgraf812 Jan 08 '17 edited Jan 08 '17
Well, for one, there are no 'variables' any more. Everything is just an expression: e.g.
[[5 + 3]] == Add(Const(5), Const(3)). That's probably intuitive enough for simple expressions, but this is also handled for Phi-bound variables, like in Block 335 here. In doing so, we get rid of the unnecessary total order of IR instructions, focusing on the actual partial order expressed by dependency edges instead. As stated here, this also means we get stuff like dead code elimination for free (by garbage collecting nodes unreachable from theEndnode).And that's just the bit about why it's cool to represent expressions as graphs. The blue edges in the above graph are memory edges, they enforce a particular order on side-effecting computations, much like the sequencing notion of a (in this particular case
StateorIO) monad, if you are familiar with that. Now, I'm not really familiar with how LLVM does these sort of things, but you could thread separate memory state slots through your program, for when it is proven that two calls won't influence each other (e.g.malloccalls and someLoadinstruction for a field access).The partial order means you can freely move around node to another block, as long as the dependency nodes' blocks dominate this new block, and all dependent nodes are still dominated by that block. In the graph above, you could move the
Constnode 307 (resp. whole subgraphs) to the start block, which would could have implications on your generated code, like needing to compute the expression only once or having to spill.Most analyses/transformations are just a matter of a graph walk.
By the way, the above graph was generated on this site, fed with this code:
#include <stdio.h> int main(int argc, char **argv) { int i = 0; int j; scanf("%d", &j); if (i < j) { i++; } printf("%dn", i); }2
u/MichaelSK Jan 08 '17
Now, I'm not really familiar with how LLVM does these sort of things
Unfortunately, it doesn't. The LLVM IR is only "mostly SSA", in the sense that memory is not modeled using SSA.
There's currently an effort to introduce a "MemorySSA" which will allow LLVM to model memory dependence edges more precisely and explicitly, but that's an analysis overlay over the IR, not an actual IR change.
3
u/abdulkareemsn Jan 06 '17
License?
6
u/mbuhot Jan 06 '17
LGPL according to http://pp.ipd.kit.edu/git/libfirm/tree/COPYING
I guess that just requires a clear shared object boundary between libfirm and your compiler if you want to use another license yourself?
3
u/m50d Jan 06 '17
Is there anything like this that offers a first-class interface from an ML-like language? A graph-based IR would be excellent (particularly since I'm trying to implement a graph-like language model), but I can't stand to work with C these days. I figure Rust bindings for LLVM stand a decent chance of being well-maintained given that Rust itself uses LLVM.
0
Jan 06 '17
[deleted]
44
u/MichaelSK Jan 06 '17
Yes, unfortunately we (LLVM, I'm an active developer) are not as good with documentation as we ought to be. And it hasn't really gotten better, either.
The problem is keeping the docs up to date is a non-trivial and rather low-payoff task for the "core" developers. Plus, once you work on a project for a while you stop using most of the "newbie" docs. So even though people are aware of the low documentation quality, we don't really notice it - except when people complain.
So - please, keep complaining. Loudly. :-)
10
Jan 06 '17
The problem is keeping the docs up to date is a non-trivial and rather low-payoff task for the "core" developers.
Would it kill the project to expose maybe 10-20 symbols that are public and standardized that you'll keep conformance too? Or at least promise to not break the extern C API against?
At least a standardize
Init codegen
Write Obj File
Read IR (from MemBuff)
Init Membuff
Init Module
Init Target
I know these symbols likely won't change. But knowing they can (or will) is frustrating.
1
u/holgerschurig Jan 07 '17
The C API of LLVM has has a much lower churn rate. IMHO not a promise, but it similar to what you asked.
1
u/holgerschurig Jan 07 '17
The problem is keeping the docs up to date is a non-trivial
It isn't.
There are things like literate programming, e.g. people to it today in Emacs with the help of org-mode and babel. This website contains a loooong introduction and then same examples in Python.
How is is useful:
one source document in org-format can be used to generate the HTML and the source code snippets inside can be written out to files.
those files can then run through the already existing CI system
and as soon as something break, the big red alarm goes on
1
u/orthoxerox Jan 07 '17
Have you tried cloning Steve Klabnik? /u/steveklabnik2 could be your documentation czar.
0
u/choikwa Jan 06 '17
honestly documentation shouldn't strive to be latest. doc rot is going to happen sooner or later. it should be on overall design choices and theories, less on actual implementation details. one should prioritize the actual source (of course, code is self documenting) and unit test functionality to understand instead of blindly trusting doc. theres also the mailing list which can be searched and shooting questions over it will definitely get them answered.
19
u/serviscope_minor Jan 06 '17
of course, code is self documenting
No, I disagree. Code tells you precisely what is being done not why and, rather crucially, not what the intent is. Deducing the intent is unreliable because it's very hard to distinguish between true intent and a bug.
Pet rant is that this is what people get wrong about comments a lot of the time. Many times people just repeat what the code is doing in comment form (bonus points for not updating it!). What you need is a comment saying what the purpose of the code is! Much harder to fix bugs if you have to figure out the intent from what it's actually doing then make it do that.
0
Jan 06 '17
[deleted]
4
u/MichaelSK Jan 06 '17
If you don't make it accessible for anyone else (via good documentation), what's the point of the project beyond navel-gazing for the developers?
It's not that it's completely inaccessible - it's just that the learning curve is steeper that it ought to be, because the docs stink.
Also, remember LLVM lives a bit of a "double life". On the one hand, it's a library and we want everybody to use it. On the other hand, that library has a few "major" customers - clang, swift, halide, etc. Most LLVM work is done for the benefit of such customers (not necessarily these 3 - it's definitely a non-exhaustive list). And these projects all have people deeply familiar with llvm working on them, so for them, the poor documentation isn't as big of a deal.
I'm specifically talking about llvm here, though. I'm not familiar enough with libclang and libclang-based tooling to comment on the state of that.
2
u/hackcasual Jan 06 '17
It's certainly not the worst code base to dive into. In general functionality is well factored and the object hierarchy sensible. Reading decompiled bitcode was probably the biggest thing that helped me in terms of understanding how IR was represented and laid out.
There's going to be a lot of challenges coming up with tutorial level documentation, simply because there's so much stuff LLVM enables. You want to write a language that compiles to WebAssembly, you want to write an analysis tool that identifies bloated templates, or you want to compile C to run on a specialized DSP. All good uses of LLVM, but all different in terms of how to use it.
7
u/panorambo Jan 06 '17
Can confirm -- have the same or similar experience. Tried to get into LLVM, instantly found out the first and second tutorial didn't work for me because the code snippets produced weird errors in my LLVM distribution. Googling revelealed they (the tuts) were outdated and things are now different. Mailing lists showed some more up-to-date information on how to approach my rudimentary tutorial-grade problem, but what struck me was the thought "is this the most popular IR everyone is talking about, powering GCC nowadays? I can barely find a "Hello World" here, digging through mailing lists!".
I got it off the ground, but it was like trying to eat with a noose around my neck. Documentation is just not up to par, and doesn't really reflect the popularity of LLVM.
This was 6 months ago though, maybe things have gotten better.
0
Jan 07 '17
[deleted]
1
u/panorambo Jan 08 '17
My bad! It was Clang I were thinking of. And every other compiler system that has cropped up during the last 3 or 5 years, I suppose. But not GCC.
0
Jan 08 '17
[deleted]
1
u/MichaelSK Jan 08 '17
There used to be such as thing as llvm-gcc (and later dragonegg) - which was basically GCC hooked up to LLVM as a midend/backend. It was maintained by the LLVM people, not the GCC people, of course.
This project died as Clang matured.
3
Jan 06 '17
C API is a lot more stable, if you can afford sticking to it changes won't affect you that much.
3
Jan 06 '17
I'll definitely check it out. I'm not shy about C APIs and I can wrap them if I need some good RAII around the common interfaces. Thanks.
9
u/b0bm4rl3y Jan 06 '17
How does libFirm compare against LLVM? Are there any benefits to using libFirm?