rustc_mir_transform/
strip_debuginfo.rs

1use rustc_middle::mir::*;
2use rustc_middle::ty::TyCtxt;
3use rustc_mir_dataflow::debuginfo::debuginfo_locals;
4use rustc_session::config::MirStripDebugInfo;
5
6/// Conditionally remove some of the VarDebugInfo in MIR.
7///
8/// In particular, stripping non-parameter debug info for tiny, primitive-like
9/// methods in core saves work later, and nobody ever wanted to use it anyway.
10pub(super) struct StripDebugInfo;
11
12impl<'tcx> crate::MirPass<'tcx> for StripDebugInfo {
13    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
14        sess.opts.unstable_opts.mir_strip_debuginfo != MirStripDebugInfo::None
15    }
16
17    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
18        match tcx.sess.opts.unstable_opts.mir_strip_debuginfo {
19            MirStripDebugInfo::None => return,
20            MirStripDebugInfo::AllLocals => {}
21            MirStripDebugInfo::LocalsInTinyFunctions
22                if let TerminatorKind::Return { .. } =
23                    body.basic_blocks[START_BLOCK].terminator().kind => {}
24            MirStripDebugInfo::LocalsInTinyFunctions => return,
25        }
26
27        body.var_debug_info.retain(|vdi| {
28            matches!(
29                vdi.value,
30                VarDebugInfoContents::Place(place)
31                    if place.local.as_usize() <= body.arg_count && place.local != RETURN_PLACE,
32            )
33        });
34
35        let debuginfo_locals = debuginfo_locals(body);
36        for data in body.basic_blocks.as_mut_preserves_cfg() {
37            for stmt in data.statements.iter_mut() {
38                stmt.debuginfos.retain(|debuginfo| match debuginfo {
39                    StmtDebugInfo::AssignRef(local, _) | StmtDebugInfo::InvalidAssign(local) => {
40                        debuginfo_locals.contains(*local)
41                    }
42                });
43            }
44            data.after_last_stmt_debuginfos.retain(|debuginfo| match debuginfo {
45                StmtDebugInfo::AssignRef(local, _) | StmtDebugInfo::InvalidAssign(local) => {
46                    debuginfo_locals.contains(*local)
47                }
48            });
49        }
50    }
51
52    fn is_required(&self) -> bool {
53        true
54    }
55}