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

View File

@@ -19,7 +19,7 @@ use crate::index::ContainerComparator;
use crate::indexset::IndexSet; use crate::indexset::IndexSet;
use crate::{ use crate::{
define_index, Allocation, Block, Edit, Function, Inst, MachineEnv, Operand, PReg, ProgPoint, define_index, Allocation, Block, Edit, Function, Inst, MachineEnv, Operand, PReg, ProgPoint,
RegClass, SpillSlot, VReg, RegClass, VReg,
}; };
use smallvec::SmallVec; use smallvec::SmallVec;
use std::cmp::Ordering; use std::cmp::Ordering;
@@ -336,7 +336,7 @@ pub struct Env<'a, F: Function> {
pub allocs: Vec<Allocation>, pub allocs: Vec<Allocation>,
pub inst_alloc_offsets: Vec<u32>, pub inst_alloc_offsets: Vec<u32>,
pub num_spillslots: u32, pub num_spillslots: u32,
pub safepoint_slots: Vec<(ProgPoint, SpillSlot)>, pub safepoint_slots: Vec<(ProgPoint, Allocation)>,
pub allocated_bundle_count: usize, 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]); log::trace!(" -> covers safepoint {:?}", safepoints[safepoint_idx]);
let slot = alloc self.safepoint_slots
.as_stack() .push((safepoints[safepoint_idx], alloc));
.expect("Reference-typed value not in spillslot at safepoint");
self.safepoint_slots.push((safepoints[safepoint_idx], slot));
safepoint_idx += 1; safepoint_idx += 1;
} }
} }

View File

@@ -1180,8 +1180,11 @@ pub struct Output {
/// Allocation offset in `allocs` for each instruction. /// Allocation offset in `allocs` for each instruction.
pub inst_alloc_offsets: Vec<u32>, pub inst_alloc_offsets: Vec<u32>,
/// Safepoint records: at a given program point, a reference-typed value lives in the given SpillSlot. /// Safepoint records: at a given program point, a reference-typed value
pub safepoint_slots: Vec<(ProgPoint, SpillSlot)>, /// 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 /// Debug info: a labeled value (as applied to vregs by
/// `Function::debug_value_labels()` on the input side) is located /// `Function::debug_value_labels()` on the input side) is located