编译器如何理解你的代码

原理

Rust 编译器工作流程:

源码 (.rs)
  → Lexer/Parse → AST (abstract syntax tree)
  → HIR (high-level IR): 宏展开后、类型推导前的 IR
  → MIR (mid-level IR): 控制流图形式,borrow check、drop elaboration、优化
  → LLVM IR: SSA 形式的底层表示
  → 目标平台机器码

HIR 阶段:AST → 高层表示,保留 Rust 语义。用于类型推导和 trait 解析。

MIR 阶段(关键):将 HIR 降级为控制流图。这是 borrow checker、NLL(non-lexical lifetimes)分析、drop 插入、常量求值的舞台。MIR 是 Rust 安全保证的核心编译阶段。

LLVM IR 阶段:MIR → LLVM IR。LLVM 执行优化 pass(内联、循环展开、noalias 利用、SIMD 向量化等)。-C opt-level=3 控制优化力度。

rust-analyzer 使用 libsyntax2 提供 IDE 级别的实时分析(不完整编译,仅增量分析)。

Cargo 的增量编译:MIR 单元按函数粒度缓存,只重编译有变化的函数。Clean build vs incremental:增量编译在 10%~50% 的时间完成。


语法

查看 MIR

rustc --emit mir main.rs

查看 LLVM IR

rustc --emit llvm-ir main.rs

查看汇编

rustc --emit asm -C opt-level=3 main.rs

编译器标志速查

标志作用
-C opt-level=0..3/s/z优化级别
-C debuginfo=0..2调试信息
-C lto=fat/thin链接时优化
-C panic=abort/unwindpanic 行为
-C target-cpu=native目标 CPU 优化
-Z time-passes编译时间分析

lint 级别

#[deny(warnings)]
#[allow(unused_variables)]
#[warn(missing_docs)]

实践

AI 自检

  1. MIR 和 LLVM IR 的根本区别?为什么 borrow checker 在 MIR 层而非 LLVM IR 层?
  2. ThinLTO 和 full LTO 的区别?增量编译时 LTO 如何处理缓存?