Return safepoint_slots as Allocations instead of SpillSlots

This enables us to support reftype vregs in register locations in the
future.
This commit is contained in:
Amanieu d'Antras
2021-09-16 14:02:26 +01:00
parent a527a6d25a
commit a516e6d6f3
4 changed files with 26 additions and 28 deletions

View File

@@ -78,7 +78,7 @@
use crate::{
Allocation, AllocationKind, Block, Edit, Function, Inst, InstPosition, Operand,
OperandConstraint, OperandKind, OperandPos, Output, PReg, ProgPoint, SpillSlot, VReg,
OperandConstraint, OperandKind, OperandPos, Output, PReg, ProgPoint, RegClass, VReg,
};
use std::collections::{HashMap, HashSet, VecDeque};
@@ -143,11 +143,11 @@ pub enum CheckerError {
},
ConflictedValueInStackmap {
inst: Inst,
slot: SpillSlot,
alloc: Allocation,
},
NonRefValueInStackmap {
inst: Inst,
slot: SpillSlot,
alloc: Allocation,
vreg: VReg,
},
}
@@ -332,9 +332,8 @@ impl CheckerState {
self.check_val(inst, *op, *alloc, val, allocs)?;
}
}
&CheckerInst::Safepoint { inst, ref slots } => {
for &slot in slots {
let alloc = Allocation::stack(slot);
&CheckerInst::Safepoint { inst, ref allocs } => {
for &alloc in allocs {
let val = self
.allocations
.get(&alloc)
@@ -343,17 +342,17 @@ impl CheckerState {
log::trace!(
"checker: checkinst {:?}: safepoint slot {}, checker value {:?}",
checkinst,
slot,
alloc,
val
);
match val {
CheckerValue::Unknown => {}
CheckerValue::Conflicted => {
return Err(CheckerError::ConflictedValueInStackmap { inst, slot });
return Err(CheckerError::ConflictedValueInStackmap { inst, alloc });
}
CheckerValue::Reg(vreg, false) => {
return Err(CheckerError::NonRefValueInStackmap { inst, slot, vreg });
return Err(CheckerError::NonRefValueInStackmap { inst, alloc, vreg });
}
CheckerValue::Reg(_, true) => {}
}
@@ -405,12 +404,10 @@ impl CheckerState {
self.allocations
.insert(alloc, CheckerValue::Reg(vreg, reftyped));
}
&CheckerInst::Safepoint { ref slots, .. } => {
&CheckerInst::Safepoint { ref allocs, .. } => {
for (alloc, value) in &mut self.allocations {
if let CheckerValue::Reg(_, true) = *value {
if alloc.is_reg() {
*value = CheckerValue::Conflicted;
} else if alloc.is_stack() && !slots.contains(&alloc.as_stack().unwrap()) {
if !allocs.contains(&alloc) {
*value = CheckerValue::Conflicted;
}
}
@@ -483,9 +480,9 @@ pub(crate) enum CheckerInst {
/// of a value is logically transferred to a new vreg.
DefAlloc { alloc: Allocation, vreg: VReg },
/// A safepoint, with the given SpillSlots specified as containing
/// A safepoint, with the given Allocations specified as containing
/// reftyped values. All other reftyped values become invalid.
Safepoint { inst: Inst, slots: Vec<SpillSlot> },
Safepoint { inst: Inst, allocs: Vec<Allocation> },
}
#[derive(Debug)]
@@ -529,7 +526,7 @@ impl<'a, F: Function> Checker<'a, F> {
pub fn prepare(&mut self, out: &Output) {
log::trace!("checker: out = {:?}", out);
// Preprocess safepoint stack-maps into per-inst vecs.
let mut safepoint_slots: HashMap<Inst, Vec<SpillSlot>> = HashMap::new();
let mut safepoint_slots: HashMap<Inst, Vec<Allocation>> = HashMap::new();
for &(progpoint, slot) in &out.safepoint_slots {
safepoint_slots
.entry(progpoint.inst())
@@ -551,9 +548,9 @@ impl<'a, F: Function> Checker<'a, F> {
// If this is a safepoint, then check the spillslots at this point.
if self.f.requires_refs_on_stack(inst) {
let slots = safepoint_slots.remove(&inst).unwrap_or_else(|| vec![]);
let allocs = safepoint_slots.remove(&inst).unwrap_or_else(|| vec![]);
let checkinst = CheckerInst::Safepoint { inst, slots };
let checkinst = CheckerInst::Safepoint { inst, allocs };
self.bb_insts.get_mut(&block).unwrap().push(checkinst);
}
@@ -727,9 +724,9 @@ impl<'a, F: Function> Checker<'a, F> {
&CheckerInst::DefAlloc { alloc, vreg } => {
log::trace!(" defalloc: {}:{}", vreg, alloc);
}
&CheckerInst::Safepoint { ref slots, .. } => {
&CheckerInst::Safepoint { ref allocs, .. } => {
let mut slotargs = vec![];
for &slot in slots {
for &slot in allocs {
slotargs.push(format!("{}", slot));
}
log::trace!(" safepoint: {}", slotargs.join(", "));

View File

@@ -19,7 +19,7 @@ use crate::index::ContainerComparator;
use crate::indexset::IndexSet;
use crate::{
define_index, Allocation, Block, Edit, Function, Inst, MachineEnv, Operand, PReg, ProgPoint,
RegClass, SpillSlot, VReg,
RegClass, VReg,
};
use smallvec::SmallVec;
use std::cmp::Ordering;
@@ -336,7 +336,7 @@ pub struct Env<'a, F: Function> {
pub allocs: Vec<Allocation>,
pub inst_alloc_offsets: Vec<u32>,
pub num_spillslots: u32,
pub safepoint_slots: Vec<(ProgPoint, SpillSlot)>,
pub safepoint_slots: Vec<(ProgPoint, Allocation)>,
pub allocated_bundle_count: usize,

View File

@@ -58,10 +58,8 @@ impl<'a, F: Function> Env<'a, F> {
}
log::trace!(" -> covers safepoint {:?}", safepoints[safepoint_idx]);
let slot = alloc
.as_stack()
.expect("Reference-typed value not in spillslot at safepoint");
self.safepoint_slots.push((safepoints[safepoint_idx], slot));
self.safepoint_slots
.push((safepoints[safepoint_idx], alloc));
safepoint_idx += 1;
}
}

View File

@@ -1180,8 +1180,11 @@ pub struct Output {
/// Allocation offset in `allocs` for each instruction.
pub inst_alloc_offsets: Vec<u32>,
/// Safepoint records: at a given program point, a reference-typed value lives in the given SpillSlot.
pub safepoint_slots: Vec<(ProgPoint, SpillSlot)>,
/// Safepoint records: at a given program point, a reference-typed value
/// lives in the given Allocation. Currently these are guaranteed to be
/// stack slots, but in the future an option may be added to allow
/// reftype value to be kept in registers at safepoints.
pub safepoint_slots: Vec<(ProgPoint, Allocation)>,
/// Debug info: a labeled value (as applied to vregs by
/// `Function::debug_value_labels()` on the input side) is located