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}