mirror of
https://github.com/Noratrieb/website.git
synced 2026-01-14 17:05:02 +01:00
Compare commits
No commits in common. "97b2f2c4be398f2420e2badd0f81085ec29a9a47" and "bcfaf55513aa25340c74356031bdc1c5070d4587" have entirely different histories.
97b2f2c4be
...
bcfaf55513
2 changed files with 29 additions and 200 deletions
|
|
@ -25,8 +25,7 @@
|
|||
<div class="reveal">
|
||||
<div class="slides">
|
||||
<section>
|
||||
<h2>how Rust compiles</h2>
|
||||
<h4>i promise it's actually doing something useful while you wait</h4>
|
||||
<h2>how rust compiles</h2>
|
||||
</section>
|
||||
<section style="height: 100%">
|
||||
<div style="display: flex; align-items: flex-start; height: 100%">
|
||||
|
|
@ -35,7 +34,7 @@
|
|||
<iframe
|
||||
height="600"
|
||||
width="800"
|
||||
src="https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=7ac62650fd0b942ae5952b0027e0c1ce"
|
||||
src="https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=aa4567f7a97dd255dc4f314ae2b5d63c"
|
||||
referrerpolicy="no-referrer"
|
||||
></iframe>
|
||||
</details>
|
||||
|
|
@ -59,7 +58,7 @@
|
|||
<p>cargo vs rustc</p>
|
||||
<div style="display: grid; grid-template-columns: 2fr 1fr 2fr">
|
||||
<pre><code data-trim>
|
||||
$ cargo build -v
|
||||
$ cargo build
|
||||
</code></pre>
|
||||
<div style="display: flex; align-items: center">cargo</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: flex-start">
|
||||
|
|
@ -71,11 +70,11 @@
|
|||
</div>
|
||||
</section>
|
||||
<section>
|
||||
<h2>what does rustc like, do?</h2>
|
||||
<h4>a quick overview of the compilation phases</h4>
|
||||
<h2>so you want to compile a crate</h2>
|
||||
</section>
|
||||
<section>
|
||||
<h2>it all starts at the source</h2>
|
||||
<h2>so you want to compile a crate</h2>
|
||||
<p>source code:</p>
|
||||
<pre><code data-trim>
|
||||
#[no_mangle]
|
||||
pub fn add(a: u8, b: u8) -> u8 {
|
||||
|
|
@ -83,38 +82,6 @@
|
|||
}
|
||||
</code></pre>
|
||||
</section>
|
||||
<section>
|
||||
<h2>the frontend and the backend</h2>
|
||||
<div class="mermaid">
|
||||
<pre>
|
||||
%%{init: {'theme': 'dark', 'themeVariables': { 'darkMode': true, 'fontSize': '25px' }}}%%
|
||||
flowchart LR
|
||||
subgraph compiler
|
||||
frontend --> backend
|
||||
end
|
||||
source --> frontend
|
||||
backend --> binary
|
||||
</pre>
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
<h2>lex, parse, resolve, typecheck, all these fancy things</h2>
|
||||
<div class="mermaid">
|
||||
<pre>
|
||||
%%{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]
|
||||
</pre>
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
<h2>so you want to compile a crate</h2>
|
||||
<p>MIR</p>
|
||||
|
|
@ -147,20 +114,6 @@
|
|||
```
|
||||
</textarea>
|
||||
</section>
|
||||
<section data-markdown>
|
||||
<textarea data-template>
|
||||
## but compiling a ton of crates can't be that simple!
|
||||
|
||||
- yes
|
||||
</textarea>
|
||||
</section>
|
||||
<section data-markdown>
|
||||
<textarea data-template>
|
||||
## backend orchestration
|
||||
|
||||
- the how, what, and when of invoking LLVM
|
||||
</textarea>
|
||||
</section>
|
||||
<section>
|
||||
<h2>codegen units</h2>
|
||||
<pre><code>
|
||||
|
|
@ -176,7 +129,7 @@ fn main() {}
|
|||
mainll["main (LLVM IR)"]
|
||||
end
|
||||
|
||||
mycgu1 --> |LLVM| mycgu1.rcgu.o
|
||||
mycgu1 --> mycgu1.rcgu.o
|
||||
|
||||
mainmir --> mainll
|
||||
|
||||
|
|
@ -358,6 +311,18 @@ fn main() { math::add() }
|
|||
</pre>
|
||||
</div>
|
||||
</section>
|
||||
<section data-markdown>
|
||||
<textarea data-template>
|
||||
## instantiation modes
|
||||
|
||||
the two ways to instantiate MIR:
|
||||
|
||||
- in the definition crate (Globally Shared)
|
||||
- in the using crate (Local Copy)
|
||||
- generic functions
|
||||
- `#[inline]` functions
|
||||
</textarea>
|
||||
</section>
|
||||
<section data-markdown>
|
||||
<textarea data-template>
|
||||
## inlining
|
||||
|
|
@ -376,7 +341,7 @@ fn main() { math::add() }
|
|||
</section>
|
||||
<section data-markdown>
|
||||
<textarea data-template>
|
||||
## let's inline it
|
||||
## inlining
|
||||
|
||||
```rust
|
||||
fn add(a: u8, b: u8) -> u8 {
|
||||
|
|
@ -399,13 +364,13 @@ fn main() { math::add() }
|
|||
## cross-crate inlining
|
||||
|
||||
```rust
|
||||
pub fn add(a: u8, b: u8) -> u8 {
|
||||
fn add(a: u8, b: u8) -> u8 {
|
||||
a + b
|
||||
}
|
||||
```
|
||||
```rust
|
||||
fn main() {
|
||||
let x = math::add(1, 4); // what is the body?...
|
||||
let x = add(1, 4); // what is the body?...
|
||||
println!("{x}");
|
||||
}
|
||||
```
|
||||
|
|
@ -417,13 +382,13 @@ fn main() { math::add() }
|
|||
|
||||
```rust
|
||||
#[inline]
|
||||
pub fn add(a: u8, b: u8) -> u8 {
|
||||
fn add(a: u8, b: u8) -> u8 {
|
||||
a + b
|
||||
}
|
||||
```
|
||||
```rust
|
||||
fn main() {
|
||||
let x = math::add(1, 4); // 💡 it's a + b
|
||||
let x = add(1, 4); // 💡 it's a + b
|
||||
println!("{x}");
|
||||
}
|
||||
```
|
||||
|
|
@ -433,13 +398,13 @@ fn main() { math::add() }
|
|||
<div style="display: flex; flex-direction: row; gap: 16px">
|
||||
<pre><code data-trim class="language-rust">
|
||||
#[inline]
|
||||
pub fn add(a: u8, b: u8) -> u8 {
|
||||
fn add(a: u8, b: u8) -> u8 {
|
||||
a + b
|
||||
}
|
||||
</code></pre>
|
||||
<pre><code data-trim class="language-rust">
|
||||
fn main() {
|
||||
let x = math::add(1, 4);
|
||||
let x = add(1, 4);
|
||||
println!("{x}");
|
||||
}
|
||||
</code></pre>
|
||||
|
|
@ -476,7 +441,7 @@ fn main() { math::add() }
|
|||
## `#[inline]`
|
||||
- `#[inline]` enables cross-crate inlining of non-generic functions
|
||||
- for very small functions, this happens automatically
|
||||
- for other functions, it doesn't, because it would be slow (try with `-Zcross-crate-inline-threshold=always`)
|
||||
- for other functions, it doesn't, because it would be slow
|
||||
- don't over-apply it in a library, but also don't forget about it
|
||||
- benchmark!
|
||||
</textarea>
|
||||
|
|
@ -577,46 +542,11 @@ fn main() { math::add() }
|
|||
<textarea data-template>
|
||||
## linker-plugin-lto
|
||||
|
||||
- fat LTO style and thin LTO style
|
||||
- "original" LTO
|
||||
- like fat LTO
|
||||
- the merging is not done by rustc but by the linker
|
||||
- works across languages (Rust (rustc) + C (clang))
|
||||
- great for FFI
|
||||
- annoying to set up
|
||||
</textarea>
|
||||
</section>
|
||||
<section data-markdown>
|
||||
<textarea data-template>
|
||||
## inlining across codegen units in the same crate
|
||||
|
||||
- ThinLTO across different codegen units by default
|
||||
</textarea>
|
||||
</section>
|
||||
<section data-markdown>
|
||||
<textarea data-template>
|
||||
## `Cargo.toml` config
|
||||
|
||||
```toml
|
||||
[profile.release]
|
||||
lto = "thin"
|
||||
codegen-units = 1
|
||||
```
|
||||
</textarea>
|
||||
</section>
|
||||
<section data-markdown>
|
||||
<textarea data-template>
|
||||
## and why did `#[inline]` make the error go away?
|
||||
|
||||
```rust
|
||||
pub fn error() {
|
||||
// vvvvvvvvvvv post-mono error!
|
||||
let _x: [u8; usize::MAX] = [0; usize::MAX];
|
||||
}
|
||||
```
|
||||
</textarea>
|
||||
</section>
|
||||
<section data-markdown>
|
||||
<textarea data-template>
|
||||
## happy compiling
|
||||
</textarea>
|
||||
</section>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,101 +0,0 @@
|
|||
# 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
|
||||
- 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
|
||||
- todo
|
||||
- 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue