The main purpose of this post is an introduction into how Rust code is compiled.
I found out about rustc by accident when I was trying something else (see post about stack smashing protection) but it turns out it's really cool.
Rustc is really simple at heart.
It takes Rust source code as input.
It does some magic stuff.
It outputs LLVM IR.
You can then take this LLVM IR as input into other tools such as llc which compiles it down into assembly.
So let's see how it works.
First we'll write some simple Rust code:
fn main() { println!("Hello world!") }
And now let's run rustc:
$ rustc -Z verbose=thin src/main.rs -o bin/main -O -C prefer-dynamic
running `rustc` binary
rustc main.rs --crate-name main --crate-type bin -C opt-level=2 -C metadata=8e7d5a9dabdb3896 -C extra-filename=-8e7d5a9dabdb3896 --out-dir /home/gigahorse/projects/rust-playground/bin --emit=dep-info,mir -C debuginfo=2 -C debug-assertions=on -C overflow-checks=on -C metadata=8e7d5a9dabdb3896 -C extra-filename=-8e7d5a9dabdb3896
error: aborting due to previous error
Ok so it looks like there was an error but there isn't any output so let's add more verbosity:
$ rustc -Z verbose=thin src/main.rs -o bin/main -O -C prefer-dynamic
running `rustc` binary
rustc main.rs --crate-name main --crate-type bin -C opt-level=2 -C metadata=8e7d5a9dabdb3896 -C extra-filename=-8e7d5a9dabdb3896 --out-dir /home/gigahorse/projects/rust-playground/bin --emit=dep-info,mir -C debuginfo=2 -C debug-assertions=on -C overflow-checks=on -C metadata=8e7d5a9dabdb3896 -C extra-filename=-8e7d5a9dabdb3896
Compiling main v0.1.0 (/home/gigahorse/projects/rust-playground/src)
> <anon> |
> <anon> |
> <anon> | = note: in <std macros></anon>:1:32, expanding macro `compile_error`
> <anon> | = note: #[deny(dead_code)] inferred #[deny(unused_macros)] | | | = note: #[deny(dead_code)] inferred #[deny(unused_variables)] | | | = note: #[deny(dead_code)] inferred #[deny(unused_mut)] | | = note: #[deny(dead_code)] inferred #[deny(unused_assignments)] | | = note: #[deny(dead_code)] inferred #[deny(unused_unsafe)] | | = note: #[deny(dead_code)] inferred #[deny(unused_features)] | | = note: #[deny(dead_code)] inferred #[deny(missing_docs)] | | = note: #[deny(dead_code)] inferred #[deny(missing_debug_implementations)] | | = note: #[deny(dead_code)] inferred #[deny(const_err)] |
> <anon> | = note: #[deny(dead_code)] inferred #[deny(unsafe_code)]
> <anon> |= help: consider adding an attribute `#[allow(unused_macros)]` or `#[allow(dead_code)]` here
> <anon> /home/gigahorse/.cargo/registry/src/github.com-1ecc6299db9ec823/unicode-xid-0.2._alpha