Skip to content

Commit b9ef2e8

Browse files
committed
fix progress report being deduplicated
1 parent da45adc commit b9ef2e8

File tree

2 files changed

+55
-31
lines changed

2 files changed

+55
-31
lines changed

src/diagnostics.rs

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ pub enum NonHaltingDiagnostic {
7070
CreatedAlloc(AllocId, Size, Align, MemoryKind<MiriMemoryKind>),
7171
FreedAlloc(AllocId),
7272
RejectedIsolatedOp(String),
73-
ProgressReport,
73+
ProgressReport {
74+
block_count: u64, // how many basic blocks have been run so far
75+
},
7476
Int2Ptr {
7577
details: bool,
7678
},
@@ -261,6 +263,7 @@ pub fn report_error<'tcx, 'mir>(
261263
DiagLevel::Error,
262264
&if let Some(title) = title { format!("{}: {}", title, msg[0]) } else { msg[0].clone() },
263265
msg,
266+
vec![],
264267
helps,
265268
&stacktrace,
266269
);
@@ -307,6 +310,7 @@ fn report_msg<'mir, 'tcx>(
307310
diag_level: DiagLevel,
308311
title: &str,
309312
span_msg: Vec<String>,
313+
notes: Vec<(Option<SpanData>, String)>,
310314
helps: Vec<(Option<SpanData>, String)>,
311315
stacktrace: &[FrameInfo<'tcx>],
312316
) {
@@ -331,15 +335,22 @@ fn report_msg<'mir, 'tcx>(
331335
err.note("(no span available)");
332336
}
333337

334-
// Show help messages.
335-
if !helps.is_empty() {
336-
for (span_data, help) in helps {
337-
if let Some(span_data) = span_data {
338-
err.span_help(span_data.span(), &help);
339-
} else {
340-
err.help(&help);
341-
}
338+
// Show note and help messages.
339+
for (span_data, note) in &notes {
340+
if let Some(span_data) = span_data {
341+
err.span_note(span_data.span(), note);
342+
} else {
343+
err.note(note);
342344
}
345+
}
346+
for (span_data, help) in &helps {
347+
if let Some(span_data) = span_data {
348+
err.span_help(span_data.span(), help);
349+
} else {
350+
err.help(help);
351+
}
352+
}
353+
if notes.len() + helps.len() > 0 {
343354
// Add visual separator before backtrace.
344355
err.note("backtrace:");
345356
}
@@ -436,6 +447,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
436447
// Show diagnostics.
437448
for e in diagnostics.drain(..) {
438449
use NonHaltingDiagnostic::*;
450+
451+
let (title, diag_level) = match e {
452+
RejectedIsolatedOp(_) =>
453+
("operation rejected by isolation", DiagLevel::Warning),
454+
Int2Ptr { .. } => ("integer-to-pointer cast", DiagLevel::Warning),
455+
CreatedPointerTag(..)
456+
| PoppedPointerTag(..)
457+
| CreatedCallId(..)
458+
| CreatedAlloc(..)
459+
| FreedAlloc(..)
460+
| ProgressReport { .. }
461+
| WeakMemoryOutdatedLoad =>
462+
("tracking was triggered", DiagLevel::Note),
463+
};
464+
439465
let msg = match e {
440466
CreatedPointerTag(tag, None) =>
441467
format!("created tag {tag:?}"),
@@ -465,26 +491,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
465491
format!("freed allocation with id {id}"),
466492
RejectedIsolatedOp(ref op) =>
467493
format!("{op} was made to return an error due to isolation"),
468-
ProgressReport =>
494+
ProgressReport { .. } =>
469495
format!("progress report: current operation being executed is here"),
470496
Int2Ptr { .. } =>
471497
format!("integer-to-pointer cast"),
472498
WeakMemoryOutdatedLoad =>
473499
format!("weak memory emulation: outdated value returned from load"),
474500
};
475501

476-
let (title, diag_level) = match e {
477-
RejectedIsolatedOp(_) =>
478-
("operation rejected by isolation", DiagLevel::Warning),
479-
Int2Ptr { .. } => ("integer-to-pointer cast", DiagLevel::Warning),
480-
CreatedPointerTag(..)
481-
| PoppedPointerTag(..)
482-
| CreatedCallId(..)
483-
| CreatedAlloc(..)
484-
| FreedAlloc(..)
485-
| ProgressReport
486-
| WeakMemoryOutdatedLoad =>
487-
("tracking was triggered", DiagLevel::Note),
502+
let notes = match e {
503+
ProgressReport { block_count } => {
504+
// It is important that each progress report is slightly different, since
505+
// identical diagnostics are being deduplicated.
506+
vec![
507+
(None, format!("so far, {block_count} basic blocks have been executed")),
508+
]
509+
}
510+
_ => vec![],
488511
};
489512

490513
let helps = match e {
@@ -500,7 +523,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
500523
_ => vec![],
501524
};
502525

503-
report_msg(this, diag_level, title, vec![msg], helps, &stacktrace);
526+
report_msg(this, diag_level, title, vec![msg], notes, helps, &stacktrace);
504527
}
505528
});
506529
}
@@ -519,6 +542,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
519542
"the place in the program where the ICE was triggered",
520543
vec![],
521544
vec![],
545+
vec![],
522546
&stacktrace,
523547
);
524548
}

src/machine.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -374,8 +374,8 @@ pub struct Evaluator<'mir, 'tcx> {
374374

375375
/// If `Some`, we will report the current stack every N basic blocks.
376376
pub(crate) report_progress: Option<u32>,
377-
/// The number of blocks that passed since the last progress report.
378-
pub(crate) since_progress_report: u32,
377+
// The total number of blocks that have been executed.
378+
pub(crate) basic_block_count: u64,
379379

380380
/// Handle of the optional shared object file for external functions.
381381
pub external_so_lib: Option<(libloading::Library, std::path::PathBuf)>,
@@ -433,7 +433,7 @@ impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
433433
weak_memory: config.weak_memory_emulation,
434434
preemption_rate: config.preemption_rate,
435435
report_progress: config.report_progress,
436-
since_progress_report: 0,
436+
basic_block_count: 0,
437437
external_so_lib: config.external_so_file.as_ref().map(|lib_file_path| {
438438
// Check if host target == the session target.
439439
if env!("TARGET") != target_triple {
@@ -992,14 +992,14 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
992992
}
993993

994994
fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
995+
ecx.machine.basic_block_count += 1u64; // a u64 that is only incremented by 1 will "never" overflow
995996
// Possibly report our progress.
996997
if let Some(report_progress) = ecx.machine.report_progress {
997-
if ecx.machine.since_progress_report >= report_progress {
998-
register_diagnostic(NonHaltingDiagnostic::ProgressReport);
999-
ecx.machine.since_progress_report = 0;
998+
if ecx.machine.basic_block_count % u64::from(report_progress) == 0 {
999+
register_diagnostic(NonHaltingDiagnostic::ProgressReport {
1000+
block_count: ecx.machine.basic_block_count,
1001+
});
10001002
}
1001-
// Cannot overflow, since it is strictly less than `report_progress`.
1002-
ecx.machine.since_progress_report += 1;
10031003
}
10041004
// These are our preemption points.
10051005
ecx.maybe_preempt_active_thread();

0 commit comments

Comments
 (0)