- rustc_driver Callbacks, TyCtxt, HIR ExprKind, MIR BasicBlock/Rvalue - TyKind type system: bit-width queries via LayoutS - Borrow checker: BorrowKind, loan scopes, BorrowTracker usage
100 lines
3.9 KiB
Markdown
100 lines
3.9 KiB
Markdown
# Rustc Internals for HIR/MIR Analysis in fold-rust
|
|
|
|
> Generated 2026-05-28. Research on rustc APIs available for fold-rust scanning.
|
|
|
|
## rustc_driver + rustc_interface
|
|
|
|
fold-rust uses `rustc_driver::Callbacks` to intercept compilation:
|
|
|
|
```rust
|
|
struct FoldCallbacks;
|
|
impl Callbacks for FoldCallbacks {
|
|
fn after_analysis<'tcx>(&mut self, _compiler: &Compiler,
|
|
queries: &'tcx Queries<'tcx>) -> Compilation {
|
|
queries.global_ctxt().unwrap().enter(|tcx| {
|
|
// tcx: TyCtxt<'tcx> — access to all compiler state
|
|
for def_id in tcx.hir().body_owners() {
|
|
emit_function(tcx, sm, def_id);
|
|
}
|
|
});
|
|
Compilation::Continue
|
|
}
|
|
}
|
|
```
|
|
|
|
Key APIs:
|
|
- `TyCtxt<'tcx>` — central query context: types, HIR, MIR, borrow checker
|
|
- `tcx.hir()` — access HIR (High-level IR)
|
|
- `tcx.optimized_mir(def_id)` — access MIR after optimizations
|
|
- `tcx.typeck(def_id)` — type-checking results
|
|
|
|
## HIR (High-level IR)
|
|
|
|
`rustc_hir::Expr` with `ExprKind` variants:
|
|
|
|
| ExprKind | Security relevance |
|
|
|----------|-------------------|
|
|
| `Unary(UnOp::Deref, sub)` | Raw pointer deref — null-deref detection |
|
|
| `MethodCall(segment, receiver, args)` | Method dispatch — taint tracking |
|
|
| `Call(callee, args)` | Function call — interprocedural boundary |
|
|
| `Binary(op, lhs, rhs)` | Arithmetic — overflow detection |
|
|
| `Index(base, index)` | Array access — OOB detection |
|
|
| `If(cond, then, else_opt)` | Branch — path predicate forking |
|
|
| `AddrOf(..)` | Address-of — pointer tracking |
|
|
| `Cast(expr, ty)` | Type cast — truncation detection |
|
|
|
|
fold-rust's `DerefHunter` visitor walks HIR and matches these patterns.
|
|
|
|
## MIR (Mid-level IR)
|
|
|
|
`rustc_middle::mir::Body` with `BasicBlock`s:
|
|
|
|
- `StatementKind::Assign(box (place, rvalue))` — variable assignment
|
|
- `StatementKind::StorageLive(local)` — variable comes into scope
|
|
- `StatementKind::StorageDead(local)` — variable goes out of scope
|
|
- `TerminatorKind::Call { func, args, destination, .. }` — function call
|
|
- `TerminatorKind::SwitchInt { discr, targets }` — enum/switch dispatch
|
|
- `TerminatorKind::Return` — function exit
|
|
- `TerminatorKind::Goto { target }` — unconditional branch
|
|
|
|
`Rvalue` variants:
|
|
- `Use(operand)` — copy/move
|
|
- `Ref(region, kind, place)` — borrow
|
|
- `BinaryOp(op, box (lhs, rhs))` — arithmetic
|
|
- `CheckedBinaryOp(op, box (lhs, rhs))` — checked arithmetic
|
|
- `Cast(kind, operand, ty)` — type cast
|
|
- `RawPtr(..)` — raw pointer creation
|
|
- `Discriminant(place)` — enum discriminant
|
|
|
|
## Type System
|
|
|
|
`TyKind` variants accessible via `tcx.type_of(def_id)`:
|
|
- `TyKind::Int(IntTy)` — signed integers (i8, i16, i32, i64, i128, isize)
|
|
- `TyKind::Uint(UintTy)` — unsigned integers (u8, u16, u32, u64, u128, usize)
|
|
- `TyKind::Bool`, `TyKind::Char`, `TyKind::Float(FloatTy)`
|
|
- `TyKind::Ref(region, ty, mutability)` — references
|
|
- `TyKind::RawPtr(TypeAndMut { ty, mutbl })` — raw pointers
|
|
- `TyKind::Adt(def, substs)` — structs, enums, unions
|
|
- `TyKind::Array(ty, len)` — fixed-size arrays
|
|
- `TyKind::Slice(ty)` — dynamically-sized slices
|
|
- `TyKind::FnDef(def_id, substs)` — function types
|
|
|
|
Bit-width queries:
|
|
- `tcx.layout_of(param_env.and(ty))` → `LayoutS` with `size`, `align`, `abi`
|
|
- `layout.size.bits()` → bit-width (for encoding)
|
|
|
|
## Borrow Checker
|
|
|
|
`rustc_borrowck::consumers::BodyWithBorrowckFacts` provides:
|
|
- `BorrowKind`: `Shared`, `Unique`, `Mut`
|
|
- Loan scopes: which regions a borrow covers
|
|
- Move tracking: which locals are moved
|
|
|
|
fold-rust's `mir_analysis::BorrowTracker` uses this to determine which pointers are borrow-backed (safe) vs raw-pointer (potentially unsafe).
|
|
|
|
## Recommendations for fold
|
|
|
|
1. Use MIR `BasicBlock` structure for control flow in the Z3 encoder (task 120)
|
|
2. Thread `TyKind` signedness through observer hooks (done: `93439bf`)
|
|
3. Leverage `LayoutS::size` for precise bit-widths in symbolic encoding
|
|
4. Use borrow checker facts for null-deref suppression (BorrowTracker, wired in task 102)
|