Skip to content

Commit 2ad160b

Browse files
committed
Print spans where tags are created and invalidated
1 parent 65125df commit 2ad160b

File tree

4 files changed

+257
-40
lines changed

4 files changed

+257
-40
lines changed

src/diagnostics.rs

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ use log::trace;
77
use rustc_middle::ty;
88
use rustc_span::{source_map::DUMMY_SP, Span, SpanData, Symbol};
99

10-
use crate::stacked_borrows::{AccessKind, SbTag};
10+
use crate::stacked_borrows::{AccessKind, SbTag, TagHistory};
11+
use crate::helpers::HexRange;
1112
use crate::*;
1213

14+
1315
/// Details of premature program termination.
1416
pub enum TerminationInfo {
1517
Exit(i64),
@@ -19,6 +21,7 @@ pub enum TerminationInfo {
1921
msg: String,
2022
help: Option<String>,
2123
url: String,
24+
history: Option<TagHistory>,
2225
},
2326
Deadlock,
2427
MultipleSymbolDefinitions {
@@ -155,12 +158,38 @@ pub fn report_error<'tcx, 'mir>(
155158
(None, format!("pass the flag `-Zmiri-disable-isolation` to disable isolation;")),
156159
(None, format!("or pass `-Zmiri-isolation-error=warn` to configure Miri to return an error code from isolated operations (if supported for that operation) and continue with a warning")),
157160
],
158-
ExperimentalUb { url, help, .. } => {
161+
ExperimentalUb { url, help, history, .. } => {
159162
msg.extend(help.clone());
160-
vec![
163+
let mut helps = vec![
161164
(None, format!("this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental")),
162-
(None, format!("see {} for further information", url))
163-
]
165+
(None, format!("see {} for further information", url)),
166+
];
167+
match history {
168+
Some(TagHistory::Tagged {tag, created: (created_range, created_span), invalidated}) => {
169+
let msg = format!("{:?} was created due to a retag at offsets {}", tag, HexRange(*created_range));
170+
helps.push((Some(created_span.clone()), msg));
171+
if let Some((invalidated_range, invalidated_span)) = invalidated {
172+
let msg = format!("{:?} was later invalidated due to a retag at offsets {}", tag, HexRange(*invalidated_range));
173+
helps.push((Some(invalidated_span.clone()), msg));
174+
}
175+
}
176+
Some(TagHistory::Untagged{ recently_created, recently_invalidated, matching_created }) => {
177+
if let Some((range, span)) = recently_created {
178+
let msg = format!("tag was most recently created at offsets {}", HexRange(*range));
179+
helps.push((Some(span.clone()), msg));
180+
}
181+
if let Some((range, span)) = recently_invalidated {
182+
let msg = format!("tag was later invalidated at offsets {}", HexRange(*range));
183+
helps.push((Some(span.clone()), msg));
184+
}
185+
if let Some((range, span)) = matching_created {
186+
let msg = format!("this tag was also created here at offsets {}", HexRange(*range));
187+
helps.push((Some(span.clone()), msg));
188+
}
189+
}
190+
None => {}
191+
}
192+
helps
164193
}
165194
MultipleSymbolDefinitions { first, first_crate, second, second_crate, .. } =>
166195
vec![

src/eval.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,24 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
279279
Ok((ecx, ret_place))
280280
}
281281

282+
// This is potentially a performance hazard.
283+
// Factoring it into its own function lets us keep an eye on how much it shows up in a profile.
284+
fn set_current_span<'mir, 'tcx: 'mir>(ecx: &mut MiriEvalContext<'mir, 'tcx>) {
285+
let current_span = Machine::stack(&ecx)
286+
.into_iter()
287+
.rev()
288+
.find(|frame| {
289+
let info =
290+
FrameInfo { instance: frame.instance, span: frame.current_span(), lint_root: None };
291+
ecx.machine.is_local(&info)
292+
})
293+
.map(|frame| frame.current_span())
294+
.unwrap_or(rustc_span::DUMMY_SP);
295+
if let Some(sb) = ecx.memory.extra.stacked_borrows.as_mut() {
296+
sb.get_mut().current_span = current_span;
297+
}
298+
}
299+
282300
/// Evaluates the entry function specified by `entry_id`.
283301
/// Returns `Some(return_code)` if program executed completed.
284302
/// Returns `None` if an evaluation error occured.
@@ -306,6 +324,9 @@ pub fn eval_entry<'tcx>(
306324
let info = ecx.preprocess_diagnostics();
307325
match ecx.schedule()? {
308326
SchedulingAction::ExecuteStep => {
327+
if ecx.memory.extra.stacked_borrows.is_some() {
328+
set_current_span(&mut ecx);
329+
}
309330
assert!(ecx.step()?, "a terminated thread was scheduled for execution");
310331
}
311332
SchedulingAction::ExecuteTimeoutCallback => {

src/helpers.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,3 +794,12 @@ pub fn get_local_crates(tcx: &TyCtxt<'_>) -> Vec<CrateNum> {
794794
}
795795
local_crates
796796
}
797+
798+
/// Formats an AllocRange like [0x1..0x3], for use in diagnostics.
799+
pub struct HexRange(pub AllocRange);
800+
801+
impl std::fmt::Display for HexRange {
802+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
803+
write!(f, "[{:#x}..{:#x}]", self.0.start.bytes(), self.0.end().bytes())
804+
}
805+
}

0 commit comments

Comments
 (0)