Generalize debug-info support a bit. (#34)

* Generalize debug-info support a bit.

Previously, debug value-label support required each vreg to have a
disjoint sequence of instruction ranges, each with one label.

Unfortunately, it's entirely possible for multiple values at the program
level to map to one vreg at the IR level, leading to multiple labels.

This PR generalizes the debug-info generation support to allow for
arbitrary (label, range, vreg) tuples, as long as they are sorted by
vreg, with no other requirements. The lookup is a little more costly
when we generate the debuginfo, but in practice we shouldn't have more
than a *few* debug value labels per vreg, so in practice the constants
should be small.

* Typo fix from Amanieu

Co-authored-by: Amanieu d'Antras <amanieu@gmail.com>

Co-authored-by: Amanieu d'Antras <amanieu@gmail.com>
This commit is contained in:
Chris Fallin
2022-03-18 10:32:27 -07:00
committed by GitHub
parent 00dc692489
commit 4f1161d9e4
2 changed files with 15 additions and 57 deletions

View File

@@ -16,7 +16,6 @@ use super::{
Env, InsertMovePrio, InsertedMove, LiveRangeFlag, LiveRangeIndex, RedundantMoveEliminator,
VRegIndex, SLOT_NONE,
};
use crate::ion::data_structures::{BlockparamIn, BlockparamOut, CodeRange, PosWithPrio};
use crate::moves::ParallelMoves;
use crate::{
@@ -179,25 +178,6 @@ impl<'a, F: Function> Env<'a, F> {
}
let debug_labels = self.func.debug_value_labels();
#[cfg(debug_assertions)]
{
// Check the precondition that the debug-labels list is
// sorted, and that ranges are non-overlapping.
let mut last = None;
for tuple in debug_labels {
if let Some(last) = last {
// Precondition 1: sorted.
debug_assert!(last <= tuple);
// Precondition 2: ranges for a given vreg are
// non-overlapping. Note that `from`s are
// inclusive and `to`s are exclusive.
let &(last_vreg, _, last_to, _) = last;
let &(tuple_vreg, tuple_from, _, _) = tuple;
debug_assert!(last_vreg < tuple_vreg || last_to <= tuple_from);
}
last = Some(tuple);
}
}
let mut half_moves: Vec<HalfMove> = Vec::with_capacity(6 * self.func.num_insts());
let mut reuse_input_insts = Vec::with_capacity(self.func.num_insts() / 2);
@@ -522,58 +502,38 @@ impl<'a, F: Function> Env<'a, F> {
// giving the allocation location for each label.
if !debug_labels.is_empty() {
// Do a binary search to find the start of any
// relevant labels. Recall that we require
// debug-label requests to be sorted by vreg then
// by inst-range, with non-overlapping ranges, as
// preconditions (which we verified above).
// labels for this vreg. Recall that we require
// debug-label requests to be sorted by vreg as a
// precondition (which we verified above).
let start = debug_labels
.binary_search_by(|&(label_vreg, _label_from, label_to, _label)| {
.binary_search_by(|&(label_vreg, _label_from, _label_to, _label)| {
// Search for the point just before the first
// tuple that could be for `vreg` overlapping
// with `range`. Never return
// `Ordering::Equal`; `binary_search_by` in
// this case returns the index of the first
// entry that is greater as an `Err`.
label_vreg.vreg().cmp(&vreg.index()).then(
if range.from < ProgPoint::before(label_to) {
std::cmp::Ordering::Less
} else {
std::cmp::Ordering::Greater
},
)
if label_vreg.vreg() < vreg.index() {
std::cmp::Ordering::Less
} else {
std::cmp::Ordering::Greater
}
})
.unwrap_err();
for &(label_vreg, label_from, label_to, label) in &debug_labels[start..] {
let label_from = ProgPoint::before(label_from);
let label_to = ProgPoint::before(label_to);
if label_to <= range.from {
continue;
}
if label_from >= range.to {
break;
}
let label_range = CodeRange {
from: label_from,
to: label_to,
};
if label_vreg.vreg() != vreg.index() {
break;
}
if label_from == label_to {
if !range.overlaps(&label_range) {
continue;
}
debug_assert!(label_from < label_to);
#[cfg(debug_assertions)]
{
let label_range = CodeRange {
from: label_from,
to: label_to,
};
debug_assert!(
label_range.overlaps(&range),
"label_range = {:?} range = {:?}",
label_range,
range
);
}
let from = std::cmp::max(label_from, range.from);
let to = std::cmp::min(label_to, range.to);

View File

@@ -962,9 +962,7 @@ pub trait Function {
/// The instruction indices imply a program point just *before*
/// the instruction.
///
/// Preconditions: we require this slice to be sorted in
/// lexicographic order (i.e., first by vreg, then by instruction
/// index), and we require the ranges to be non-overlapping.
/// Precondition: we require this slice to be sorted by vreg.
fn debug_value_labels(&self) -> &[(VReg, Inst, Inst, u32)] {
&[]
}