Skip to content

Commit da34b31

Browse files
Add move metadata into source info
Add a new MIR pass which changes the source filename for statements with move operands to include information about the types being moved.
1 parent 43a2166 commit da34b31

File tree

2 files changed

+131
-0
lines changed

2 files changed

+131
-0
lines changed
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
//! This module provides a pass that modifies spans for statements with move operands,
2+
//! adding information about moved types and their sizes to the filename.
3+
4+
use rustc_middle::mir::{Body, Operand, Rvalue, StatementKind};
5+
use rustc_middle::ty::{Ty, TyCtxt, TypingEnv};
6+
use rustc_span::{FileName, Span};
7+
use tracing::debug;
8+
9+
pub(super) struct AddMoveMetadata;
10+
11+
impl<'tcx> crate::MirPass<'tcx> for AddMoveMetadata {
12+
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
13+
for basic_block in body.basic_blocks.as_mut() {
14+
for statement in basic_block.statements.iter_mut() {
15+
if let StatementKind::Assign(box (place, rvalue)) = &statement.kind {
16+
if rvalue_has_move(rvalue) {
17+
let moved_types =
18+
get_moved_types_from_rvalue(rvalue, &body.local_decls, tcx);
19+
let mut moved_types_with_sizes: Vec<_> = moved_types
20+
.iter()
21+
.map(|ty| {
22+
let size = tcx
23+
.layout_of(TypingEnv::fully_monomorphized().as_query_input(*ty))
24+
.map(|layout| layout.size.bytes())
25+
.unwrap_or(0);
26+
(*ty, size)
27+
})
28+
.collect();
29+
moved_types_with_sizes.sort_by(|a, b| b.1.cmp(&a.1));
30+
let old_span = statement.source_info.span;
31+
statement.source_info.span = modify_span_filename(
32+
statement.source_info.span,
33+
&moved_types_with_sizes,
34+
tcx,
35+
);
36+
for (ty, size) in &moved_types_with_sizes {
37+
debug!("Moved type: {} (size: {} bytes)", ty, size);
38+
}
39+
debug!(
40+
"Changed span from {:?} to {:?}, place: {:?}, rvalue: {:?}",
41+
old_span, statement.source_info.span, place, rvalue
42+
);
43+
}
44+
}
45+
}
46+
}
47+
}
48+
49+
fn is_required(&self) -> bool {
50+
true
51+
}
52+
}
53+
54+
fn rvalue_has_move(rvalue: &Rvalue<'_>) -> bool {
55+
match rvalue {
56+
Rvalue::Use(operand)
57+
| Rvalue::Repeat(operand, _)
58+
| Rvalue::Cast(_, operand, _)
59+
| Rvalue::UnaryOp(_, operand) => matches!(operand, Operand::Move(_)),
60+
Rvalue::BinaryOp(_, box (left, right)) => {
61+
matches!(left, Operand::Move(_)) || matches!(right, Operand::Move(_))
62+
}
63+
Rvalue::Aggregate(_, operands) => operands.iter().any(|op| matches!(op, Operand::Move(_))),
64+
_ => false,
65+
}
66+
}
67+
68+
fn get_moved_types_from_rvalue<'tcx>(
69+
rvalue: &Rvalue<'tcx>,
70+
local_decls: &rustc_middle::mir::LocalDecls<'tcx>,
71+
tcx: TyCtxt<'tcx>,
72+
) -> Vec<Ty<'tcx>> {
73+
let mut types = Vec::new();
74+
match rvalue {
75+
Rvalue::Use(Operand::Move(place))
76+
| Rvalue::Repeat(Operand::Move(place), _)
77+
| Rvalue::Cast(_, Operand::Move(place), _)
78+
| Rvalue::UnaryOp(_, Operand::Move(place)) => {
79+
types.push(place.ty(local_decls, tcx).ty);
80+
}
81+
Rvalue::BinaryOp(_, box (left, right)) => {
82+
if let Operand::Move(place) = left {
83+
types.push(place.ty(local_decls, tcx).ty);
84+
}
85+
if let Operand::Move(place) = right {
86+
types.push(place.ty(local_decls, tcx).ty);
87+
}
88+
}
89+
Rvalue::Aggregate(_, operands) => {
90+
for operand in operands {
91+
if let Operand::Move(place) = operand {
92+
types.push(place.ty(local_decls, tcx).ty);
93+
}
94+
}
95+
}
96+
_ => {}
97+
}
98+
types
99+
}
100+
101+
fn modify_span_filename<'tcx>(
102+
span: Span,
103+
moved_types_with_sizes: &[(Ty<'tcx>, u64)],
104+
tcx: TyCtxt<'tcx>,
105+
) -> Span {
106+
let source_map = tcx.sess.source_map();
107+
let source_file = source_map.lookup_source_file(span.lo());
108+
let filename = source_file.name.prefer_local().to_string();
109+
let types_str = moved_types_with_sizes
110+
.iter()
111+
.map(|(ty, size)| format!("{}({} bytes)", ty, size))
112+
.collect::<Vec<_>>()
113+
.join(", ");
114+
let new_filename = format!("{} Moved:[{}] Line:", filename, types_str);
115+
116+
let src = source_file.src.as_ref().map(|s| s.as_str()).unwrap_or("").to_string();
117+
let new_source_file = source_map.new_source_file(
118+
FileName::Real(rustc_span::RealFileName::LocalPath(std::path::PathBuf::from(new_filename))),
119+
src,
120+
);
121+
122+
let offset = span.lo() - source_file.start_pos;
123+
Span::new(
124+
new_source_file.start_pos + offset,
125+
new_source_file.start_pos + offset + (span.hi() - span.lo()),
126+
span.ctxt(),
127+
span.parent(),
128+
)
129+
}

compiler/rustc_mir_transform/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ declare_passes! {
123123
mod check_packed_ref : CheckPackedRef;
124124
// This pass is public to allow external drivers to perform MIR cleanup
125125
pub mod cleanup_post_borrowck : CleanupPostBorrowck;
126+
mod add_move_metadata : AddMoveMetadata;
126127

127128
mod copy_prop : CopyProp;
128129
mod coroutine : StateTransform;
@@ -578,6 +579,7 @@ pub fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'
578579
fn run_analysis_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
579580
let passes: &[&dyn MirPass<'tcx>] = &[
580581
&impossible_predicates::ImpossiblePredicates,
582+
&add_move_metadata::AddMoveMetadata,
581583
&cleanup_post_borrowck::CleanupPostBorrowck,
582584
&remove_noop_landing_pads::RemoveNoopLandingPads,
583585
&simplify::SimplifyCfg::PostAnalysis,

0 commit comments

Comments
 (0)