It's a bit dated (covers DAGISel rather than GlobalISel) but it gives a thorough introduction.
2. LLVM Developer Meeting tutorials
These are really good although you'll have to put them in order yourself. They will be out of date, a little. LLVM is a moving target. Also, you don't have to go through every tutorial. For example, MLIR is not for me.
3. LLVM documentation
I spent less time reading this than going through the Developer Meeting tutorials. I generally use it as a reference.
4. Discord, LLVM email list, git blame, LLVM Weekly
... because you will have questions.
5. MyFirstTypoFix (in the docs)
... when it comes time to submit a patch.
6. Mips backend
If you're doing a backend, you will need a place to start. The LLVM documentation points you to the horribly out of date SPARC backend. Don't even touch that. AArch64 and x86 are very full featured and thus very complex (100 kloc+). Don't use those either. RISC-V is ok but concerns itself mostly with supporting new RISC-V features rather than keeping up to date with LLVM compiler services. Don't use that either although definitely work through Alex Bradbury's RISC-V backend tutorials. Read the Mips backend. It is actively maintained. It has good GlobalISel support almost on par with the flagship AArch64 and x86 backends.
BTW, Chris Lattner is a super nice guy.
and don't forget IRC!
Are these all in one place or scattered about?
clang -emit-llvm -S sample.cpp
The article mentions Clang's AST, which can also be emitted: clang -Xclang -ast-dump -fsyntax-only sample.cpp
And for checking compiler outputs across lots of languages and implementations, there's always Matt Godbolt's Compiler Explorer: https://godbolt.orgAny pointers to similar courses much appreciated!
[1] cs.au.dk/~amoeller/spa
(For MIR overview, I recommend reading the Redhat blogposts mentioned in README rather than the README itself)
If I implement a language for learning purposes, I will implement it first in QBE and then MIR and then LLVM, and publish a retrospective analysis + comparison + thoughts.I think that would make really interesting reading!
How do you distribute your frontend with LLVM?
Let's say that I have lexer, parser and emitter written in e.g Haskell (random example)
I emit LLVM IR and then I use LLVM to generate something other
but the problem is, that I need to have LLVM binaries and I'd rather avoid telling people that want to contribute to my OSS project to install LLVM because it's painful process as hell
So I thought about just adding "binaries" folder to my repo and put executables there, but the problem is that they're huge as hell! and also when you're on linux, then you don't need windows' binaries
Another problem is that LLVM installer doesnt include all LLVM components that I need (llc and wasm-ld), so I gotta compile it and tell cmake (iirc) to generate those
I thought about creating 2nd repo where there'd be all binaries compiles for all platforms: mac, linux, windows and after cloning my_repo1, then instruction would point to download specific binaries
How you people do it?
In fact, you never have to call any binaries specifically; just do it through code and everything should link at compile-time and become one big binary.
For example, all of the code in clang to do this is located in https://github.com/llvm/llvm-project/blob/main/clang/lib/Cod...
When using these JLL packages from Julia, it will automatically download and load in dependencies, but if you're using it from some other system, you'll probably need to manually check out the `Project.toml` file and see what other JLL packages are listed as dependencies. As an example, `LLVM_full_jll` requires `Zlib_jll` [3], since we build with support for compressed ELF sections. As you may have guessed, you can get `Zlib_jll` from [4], and it thankfully does not have any transitive dependencies.
In the Julia world, we're typically concerned with dynamic linking, (we `dlopen()` and `dlsym()` our way into all our binary dependencies) so this may not meet all your needs, but I figured I'd give it a shout out as it is one of the easier ways to get some binaries; just `curl -L $url | tar -zxv` and you're done. Some larger packages like GTK need to have environment variables set to get them to work from strange locations like the user's home directory. We set those in Julia code when the package is loaded [5], so if you try to use a dependency like one of those, you're on your own to set whatever environment variables/configuration options are needed in order to make something work at an unusual location on disk. Luckily, LLVM (at least the way we use it, via `libLLVM.so`) doesn't require any such shenanigans.
[0] https://github.com/JuliaBinaryWrappers/ [1] https://github.com/JuliaBinaryWrappers/libLLVM_jll.jl/releas... [2] https://github.com/JuliaBinaryWrappers/LLVM_full_jll.jl/rele... [3] https://github.com/JuliaBinaryWrappers/LLVM_full_jll.jl/blob... [4] https://github.com/JuliaBinaryWrappers/Zlib_jll.jl/releases [5] https://github.com/JuliaGraphics/Gtk.jl/blob/0ff744723c32c3f...
I know code is only supposed to be JIT’ed and then executed by the runtime (that’s why PackageCompiler exists), but still I’d like to know more about how it works..
Like, if i write a simple pure function in Julia and call code_llvm on it… How “standalone” is the llvm code (if that is even a thing)? When does GC get called? How exactly does the generated code depend on the runtime?
Is there any good explanation of this?