- rustc_driver Callbacks, TyCtxt, HIR ExprKind, MIR BasicBlock/Rvalue - TyKind type system: bit-width queries via LayoutS - Borrow checker: BorrowKind, loan scopes, BorrowTracker usage
3.9 KiB
3.9 KiB
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:
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 checkertcx.hir()— access HIR (High-level IR)tcx.optimized_mir(def_id)— access MIR after optimizationstcx.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 BasicBlocks:
StatementKind::Assign(box (place, rvalue))— variable assignmentStatementKind::StorageLive(local)— variable comes into scopeStatementKind::StorageDead(local)— variable goes out of scopeTerminatorKind::Call { func, args, destination, .. }— function callTerminatorKind::SwitchInt { discr, targets }— enum/switch dispatchTerminatorKind::Return— function exitTerminatorKind::Goto { target }— unconditional branch
Rvalue variants:
Use(operand)— copy/moveRef(region, kind, place)— borrowBinaryOp(op, box (lhs, rhs))— arithmeticCheckedBinaryOp(op, box (lhs, rhs))— checked arithmeticCast(kind, operand, ty)— type castRawPtr(..)— raw pointer creationDiscriminant(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)— referencesTyKind::RawPtr(TypeAndMut { ty, mutbl })— raw pointersTyKind::Adt(def, substs)— structs, enums, unionsTyKind::Array(ty, len)— fixed-size arraysTyKind::Slice(ty)— dynamically-sized slicesTyKind::FnDef(def_id, substs)— function types
Bit-width queries:
tcx.layout_of(param_env.and(ty))→LayoutSwithsize,align,abilayout.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
- Use MIR
BasicBlockstructure for control flow in the Z3 encoder (task 120) - Thread
TyKindsignedness through observer hooks (done:93439bf) - Leverage
LayoutS::sizefor precise bit-widths in symbolic encoding - Use borrow checker facts for null-deref suppression (BorrowTracker, wired in task 102)