From d57e07626703658ae8a8bea2b8604f30cf115b68 Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Mon, 29 Sep 2025 20:41:20 +0200 Subject: [PATCH] better gaming --- .../2025-10-10-how-rust-compiles/index.html | 93 +++++++++++----- slides/speaker-notes.md | 101 ++++++++++++++++++ 2 files changed, 165 insertions(+), 29 deletions(-) create mode 100644 slides/speaker-notes.md diff --git a/slides/2025-10-10-how-rust-compiles/index.html b/slides/2025-10-10-how-rust-compiles/index.html index bc9bdff..4112d0f 100644 --- a/slides/2025-10-10-how-rust-compiles/index.html +++ b/slides/2025-10-10-how-rust-compiles/index.html @@ -25,7 +25,8 @@
-

how rust compiles

+

how Rust compiles

+

i promise it's actually doing something useful while you wait

@@ -34,7 +35,7 @@ @@ -58,7 +59,7 @@

cargo vs rustc


-                    $ cargo build
+                    $ cargo build -v
                 
cargo
@@ -70,11 +71,11 @@
-

so you want to compile a crate

+

what does rustc like, do?

+

a quick overview of the compilation phases

-

so you want to compile a crate

-

source code:

+

it all starts at the source


               #[no_mangle]
               pub fn add(a: u8, b: u8) -> u8 {
@@ -82,6 +83,38 @@
               }
             
+
+

the frontend and the backend

+
+
+              %%{init: {'theme': 'dark', 'themeVariables': { 'darkMode': true, 'fontSize': '25px' }}}%%
+              flowchart LR
+                subgraph compiler
+                  frontend --> backend
+                end
+                source --> frontend
+                backend --> binary
+            
+
+
+
+

lex, parse, resolve, typecheck, all these fancy things

+
+
+              %%{init: {'theme': 'dark', 'themeVariables': { 'darkMode': true, 'fontSize': '25px' }}}%%
+              flowchart TB
+                function --> return
+                function --> params
+                params --> a_def[a]
+                params --> b_def[b]
+                function --> body
+                body --> cl["method call"]
+                cl --> a_use[a]
+                cl --> wrapping_add
+                cl --> b_use[b]
+            
+
+

so you want to compile a crate

MIR

@@ -114,6 +147,20 @@ ```
+
+ +
+
+ +

codegen units


@@ -129,7 +176,7 @@ fn main() {}
                   mainll["main (LLVM IR)"]
                 end
 
-                mycgu1 --> mycgu1.rcgu.o
+                mycgu1 --> |LLVM| mycgu1.rcgu.o
 
                 mainmir --> mainll
 
@@ -311,18 +358,6 @@ fn main() { math::add() }
             
-
- -
@@ -542,11 +577,11 @@ fn main() { math::add() }
diff --git a/slides/speaker-notes.md b/slides/speaker-notes.md new file mode 100644 index 0000000..619a68a --- /dev/null +++ b/slides/speaker-notes.md @@ -0,0 +1,101 @@ +# how rust compiles + +- welcome to my talk about how rust compiles + - we'll take a look at rusts compilation model +- before we get started + - example of confusing behavior arising from the model +- me +- behind cargo build + - we use cargo + - one cargo many rustc per crate + - use -v +- what does rustc do +- source example + - add function that adds +- frontend and backend +- frontend in a single slide + - parse into AST + - resolve, typecheck +- MIR + - intermediate representation + - CFG + - borrow checker +- LLVM IR + - LLVM backend + - clang, swift, julia + - IR to assembly + - optimizes +- Assembly + - machine code +- it's not that simple +- backend orchestration + - how, what, and when invoking LLVM +- codegen unit + - LLVM module/object file + - group of functions + - linked together +- more codegen units + - three functions into two codegen units + - functions grouped into codegen units is complicated +- codegen units cross crate + - a great add function + - add into cgu in math crate + - object file into rlibs +- generics + - mono +- instantiating generics + - MIR to LLVM IR +- generics cross crate + - math crate only MIR + - instantiated in our own crate + - read MIR from rlib +- inlining + - a function call + - inefficient call + - maybe just turn it into 5 +- inlining + - very good + - everywhere, or very slow +- cross crate inlining catch + - access to the body +- #[inline] + - why? +- #[inline] + - like a generic function + - instantiated downstream +- #[inline] + - non-generic + - automatically for small + - not for others + - cross-crate-inline-threshold=always + - dont always use it because its slow + - dont forget about it + - benchmark +- if you dont want to worry about this as an application +- LTO + - no cross-crate-inline-threshold + - LTO + - applies optimizations once for everything at the end + - breaks crate boundaries + - slow +- fat LTO + - LLVM IR instead of machine code in libs + - combines all LLVM IR + - this CGU is huge, not parallel + - see everything + - not all optimizations for larger programs +- thin LTO + - confusing name + - try both + - LLVM IR for libs + - for generics, just in instantiating crate + - combine for summary + - summary of function (size and where to find it) + - many different units in parallel + - look at the summary for inlining +- linker plugin LTO + - fat LTO or thin LTO + - not by rustc, but by the linker + - across languages + - LLVM IR from Rust, LLVM IR from clang + - annoying to set up \ No newline at end of file