fold/docs/internal/rustc-analysis-api-research.md
trvon 04642c46af
docs: rustc internals research for HIR/MIR analysis in fold-rust
- rustc_driver Callbacks, TyCtxt, HIR ExprKind, MIR BasicBlock/Rvalue
- TyKind type system: bit-width queries via LayoutS
- Borrow checker: BorrowKind, loan scopes, BorrowTracker usage
2026-05-28 20:09:14 -04:00

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)