rustc_mir_transform/
add_moves_for_packed_drops.rs
1use rustc_middle::mir::*;
2use rustc_middle::ty::{self, TyCtxt};
3use tracing::debug;
4
5use crate::patch::MirPatch;
6use crate::util;
7
8pub(super) struct AddMovesForPackedDrops;
39
40impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops {
41 fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
42 debug!("add_moves_for_packed_drops({:?} @ {:?})", body.source, body.span);
43 let mut patch = MirPatch::new(body);
44 let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id());
47
48 for (bb, data) in body.basic_blocks.iter_enumerated() {
49 let loc = Location { block: bb, statement_index: data.statements.len() };
50 let terminator = data.terminator();
51
52 match terminator.kind {
53 TerminatorKind::Drop { place, .. }
54 if util::is_disaligned(tcx, body, typing_env, place) =>
55 {
56 add_move_for_packed_drop(
57 tcx,
58 body,
59 &mut patch,
60 terminator,
61 loc,
62 data.is_cleanup,
63 );
64 }
65 _ => {}
66 }
67 }
68
69 patch.apply(body);
70 }
71
72 fn is_required(&self) -> bool {
73 true
74 }
75}
76
77fn add_move_for_packed_drop<'tcx>(
78 tcx: TyCtxt<'tcx>,
79 body: &Body<'tcx>,
80 patch: &mut MirPatch<'tcx>,
81 terminator: &Terminator<'tcx>,
82 loc: Location,
83 is_cleanup: bool,
84) {
85 debug!("add_move_for_packed_drop({:?} @ {:?})", terminator, loc);
86 let TerminatorKind::Drop { ref place, target, unwind, replace } = terminator.kind else {
87 unreachable!();
88 };
89
90 let source_info = terminator.source_info;
91 let ty = place.ty(body, tcx).ty;
92 let temp = patch.new_temp(ty, source_info.span);
93
94 let storage_dead_block = patch.new_block(BasicBlockData {
95 statements: vec![Statement { source_info, kind: StatementKind::StorageDead(temp) }],
96 terminator: Some(Terminator { source_info, kind: TerminatorKind::Goto { target } }),
97 is_cleanup,
98 });
99
100 patch.add_statement(loc, StatementKind::StorageLive(temp));
101 patch.add_assign(loc, Place::from(temp), Rvalue::Use(Operand::Move(*place)));
102 patch.patch_terminator(
103 loc.block,
104 TerminatorKind::Drop {
105 place: Place::from(temp),
106 target: storage_dead_block,
107 unwind,
108 replace,
109 },
110 );
111}