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:
@@ -16,7 +16,6 @@ use super::{
|
|||||||
Env, InsertMovePrio, InsertedMove, LiveRangeFlag, LiveRangeIndex, RedundantMoveEliminator,
|
Env, InsertMovePrio, InsertedMove, LiveRangeFlag, LiveRangeIndex, RedundantMoveEliminator,
|
||||||
VRegIndex, SLOT_NONE,
|
VRegIndex, SLOT_NONE,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::ion::data_structures::{BlockparamIn, BlockparamOut, CodeRange, PosWithPrio};
|
use crate::ion::data_structures::{BlockparamIn, BlockparamOut, CodeRange, PosWithPrio};
|
||||||
use crate::moves::ParallelMoves;
|
use crate::moves::ParallelMoves;
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -179,25 +178,6 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let debug_labels = self.func.debug_value_labels();
|
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 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);
|
let mut reuse_input_insts = Vec::with_capacity(self.func.num_insts() / 2);
|
||||||
@@ -522,57 +502,37 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
// giving the allocation location for each label.
|
// giving the allocation location for each label.
|
||||||
if !debug_labels.is_empty() {
|
if !debug_labels.is_empty() {
|
||||||
// Do a binary search to find the start of any
|
// Do a binary search to find the start of any
|
||||||
// relevant labels. Recall that we require
|
// labels for this vreg. Recall that we require
|
||||||
// debug-label requests to be sorted by vreg then
|
// debug-label requests to be sorted by vreg as a
|
||||||
// by inst-range, with non-overlapping ranges, as
|
// precondition (which we verified above).
|
||||||
// preconditions (which we verified above).
|
|
||||||
let start = debug_labels
|
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
|
// Search for the point just before the first
|
||||||
// tuple that could be for `vreg` overlapping
|
// tuple that could be for `vreg` overlapping
|
||||||
// with `range`. Never return
|
// with `range`. Never return
|
||||||
// `Ordering::Equal`; `binary_search_by` in
|
// `Ordering::Equal`; `binary_search_by` in
|
||||||
// this case returns the index of the first
|
// this case returns the index of the first
|
||||||
// entry that is greater as an `Err`.
|
// entry that is greater as an `Err`.
|
||||||
label_vreg.vreg().cmp(&vreg.index()).then(
|
if label_vreg.vreg() < vreg.index() {
|
||||||
if range.from < ProgPoint::before(label_to) {
|
|
||||||
std::cmp::Ordering::Less
|
std::cmp::Ordering::Less
|
||||||
} else {
|
} else {
|
||||||
std::cmp::Ordering::Greater
|
std::cmp::Ordering::Greater
|
||||||
},
|
}
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.unwrap_err();
|
.unwrap_err();
|
||||||
|
|
||||||
for &(label_vreg, label_from, label_to, label) in &debug_labels[start..] {
|
for &(label_vreg, label_from, label_to, label) in &debug_labels[start..] {
|
||||||
let label_from = ProgPoint::before(label_from);
|
let label_from = ProgPoint::before(label_from);
|
||||||
let label_to = ProgPoint::before(label_to);
|
let label_to = ProgPoint::before(label_to);
|
||||||
if label_to <= range.from {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if label_from >= range.to {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if label_vreg.vreg() != vreg.index() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if label_from == label_to {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
debug_assert!(label_from < label_to);
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
{
|
|
||||||
let label_range = CodeRange {
|
let label_range = CodeRange {
|
||||||
from: label_from,
|
from: label_from,
|
||||||
to: label_to,
|
to: label_to,
|
||||||
};
|
};
|
||||||
debug_assert!(
|
if label_vreg.vreg() != vreg.index() {
|
||||||
label_range.overlaps(&range),
|
break;
|
||||||
"label_range = {:?} range = {:?}",
|
}
|
||||||
label_range,
|
if !range.overlaps(&label_range) {
|
||||||
range
|
continue;
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let from = std::cmp::max(label_from, range.from);
|
let from = std::cmp::max(label_from, range.from);
|
||||||
|
|||||||
@@ -962,9 +962,7 @@ pub trait Function {
|
|||||||
/// The instruction indices imply a program point just *before*
|
/// The instruction indices imply a program point just *before*
|
||||||
/// the instruction.
|
/// the instruction.
|
||||||
///
|
///
|
||||||
/// Preconditions: we require this slice to be sorted in
|
/// Precondition: we require this slice to be sorted by vreg.
|
||||||
/// lexicographic order (i.e., first by vreg, then by instruction
|
|
||||||
/// index), and we require the ranges to be non-overlapping.
|
|
||||||
fn debug_value_labels(&self) -> &[(VReg, Inst, Inst, u32)] {
|
fn debug_value_labels(&self) -> &[(VReg, Inst, Inst, u32)] {
|
||||||
&[]
|
&[]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user