【Rust】20-Rust 编译器架构与 MIR/LLVM 优化管线
Rust 编译器架构与 MIR/LLVM 优化管线研究目标建立 rustc 从源码到机器码的整体模型。理解 HIR、MIR、LLVM IR 分别解决什么问题。知道编译器优化与所有权检查之间的关系。rustc 的总体流程Rust 编译大致可以分为这些阶段source - tokens - AST - HIR - type checking - MIR - borrow checking - MIR optimizations - LLVM IR - machine code - linking真实流程更细包括宏展开、名称解析、trait 求解、单态化、增量编译、代码生成单元等。但这个模型足以帮助理解 Rust 为什么能同时提供高级抽象和底层性能。词法分析、解析与 AST编译器首先把源代码变成 token再解析成 AST。AST 保留了较多源代码语法结构。宏展开也发生在早期阶段。Rust 宏可以生成新的 token这些 token 继续参与解析、名称解析和类型检查。如果宏生成的代码有类型错误错误信息常常会涉及展开后的代码。过程宏质量很大程度取决于是否能提供准确 span 和可读错误。HIRHIR 是 high-level intermediate representation高层中间表示。它比 AST 更接近编译器后续分析需要的结构去掉一些纯语法糖并完成名称解析等工作。HIR 阶段适合做类型检查。trait 解析和方法查找。lint 分析。生成更低层的 MIR。Rust 的很多用户可见错误如类型不匹配、方法不存在、trait bound 不满足会在 HIR 附近的分析中产生。类型检查与 trait 求解Rust 类型系统需要处理泛型参数。trait bound。关联类型。自动引用和解引用。生命周期约束。impl Trait 和 dyn Trait。示例fnprintT:std::fmt::Display(value:T){println!({value});}编译器必须证明传入类型满足Display。如果存在多个 impl、关联类型约束或复杂 where 子句trait 求解会成为编译复杂度的重要来源。MIR 是什么MIR 是 mid-level intermediate representation。它比 HIR 更接近控制流图简化了 Rust 语法结构适合做借用检查和优化。源代码fnadd_one(value:i32)-i32{value1}MIR 会把代码表示成基本块、局部变量、赋值、跳转和返回。它让编译器更容易分析“某个值在哪里被移动”“某个引用在哪里最后使用”“控制流是否经过某个释放点”。借用检查在 MIR 上执行现代 Rust 借用检查基于 MIR。原因是 MIR 明确表达控制流和使用点适合非词法生命周期分析。借用检查需要知道哪些位置被借用。借用在哪里活跃。哪些路径发生移动。哪些地方可能 Drop。返回引用和输入引用之间有什么区域关系。这也是为什么 Rust 能接受很多旧式词法生命周期会拒绝的程序。MIR 提供了更精确的控制流基础。Drop ElaborationRust 的自动析构也会在中间表示中展开。编译器需要在正确路径插入 drop并确保部分移动、panic 路径、提前返回等场景下资源被正确释放。fnexample(){letaString::from(a);letbString::from(b);println!({a}{b});}编译器要确保b和a在离开作用域时按正确顺序释放。如果中间发生 panic也要遵守栈展开期间的析构规则。MIR 优化在进入 LLVM 前rustc 会做一些 MIR 级优化例如常量传播。简化控制流。消除不必要临时变量。内联某些函数。优化匹配和分支。MIR 优化知道 Rust 语言语义因此可以在比 LLVM 更高层的位置做一些更合适的变换。单态化泛型代码在代码生成前会单态化。编译器为实际使用的类型生成具体实例。fnidT(value:T)-T{value}调用id::i32和id::String会产生不同实例。单态化之后LLVM 看到的是具体类型代码可以继续做底层优化。单态化是 Rust 性能的重要来源也是编译时间和二进制体积的重要来源。LLVM 后端LLVM IR 是更底层的中间表示。LLVM 负责许多目标平台相关和机器级优化指令选择。寄存器分配。循环优化。向量化。链接时优化。目标平台代码生成。Rust 借助 LLVM 获得成熟后端和多平台支持。也因此某些性能问题需要同时理解 Rust 前端生成了什么 IR以及 LLVM 后端如何优化。增量编译与查询系统rustc 内部采用查询系统组织编译任务。很多结果可以缓存增量编译会尽量复用未变化部分。这对大型项目很重要改一个函数不应重编译整个世界。crate 边界会影响并行和缓存效果。泛型和宏可能扩大重新编译范围。工程上合理拆分 crate、控制公共泛型 API、减少大规模宏生成都能改善编译体验。查看编译器中间结果一些命令可以帮助研究rustc--emitmir src/main.rs rustc--emitllvm-ir src/main.rscargorustc ----emitllvm-irNightly 编译器还支持更多-Z选项例如打印 MIR、查看优化阶段等。这些工具适合研究不建议作为普通项目构建流程依赖。常见误解Rust 的内存安全检查不是 LLVM 做的主要在 rustc 前端和 MIR 阶段完成。LLVM 优化不理解完整 Rust 所有权模型它看到的是更低层 IR。MIR 不只是优化工具也是借用检查的重要基础。编译慢往往不是单一原因泛型、宏、trait 求解、crate 图都会影响。继续研究rustc-dev-guideoverview、HIR、MIR、borrow check、monomorphization、codegen。Rust Referenceconditional compilation、linkage、ABI。Cargo Bookprofiles、incremental compilation、workspaces。工具cargo expand、cargo llvm-lines、cargo bloat、rustc -Znightly 选项。后记2026年6月11日15点32分于上海。