Remove dependency on hard-coded ordering of x86 register banks

With this change, register banks can now be re-ordered and other components (e.g. unwinding, regalloc) will no longer break. The previous behavior assumed that GPR registers always started at `RegUnit` 0.
This commit is contained in:
Andrew Brown
2020-02-14 13:24:13 -08:00
parent 518c7526d2
commit 3f53bcb740
3 changed files with 27 additions and 6 deletions

View File

@@ -57,7 +57,13 @@ fn gen_regclass(isa: &TargetIsa, reg_class: &RegClass, fmt: &mut Formatter) {
fmtln!(fmt, "first: {},", reg_bank.first_unit + reg_class.start); fmtln!(fmt, "first: {},", reg_bank.first_unit + reg_class.start);
fmtln!(fmt, "subclasses: {:#x},", reg_class.subclass_mask()); fmtln!(fmt, "subclasses: {:#x},", reg_class.subclass_mask());
fmtln!(fmt, "mask: [{}],", mask); fmtln!(fmt, "mask: [{}],", mask);
fmtln!(fmt, "pinned_reg: {:?},", reg_bank.pinned_reg); fmtln!(
fmt,
"pinned_reg: {:?},",
reg_bank
.pinned_reg
.map(|index| index + reg_bank.first_unit as u16 + reg_class.start as u16)
);
fmtln!(fmt, "info: &INFO,"); fmtln!(fmt, "info: &INFO,");
}); });
fmtln!(fmt, "};"); fmtln!(fmt, "};");

View File

@@ -180,7 +180,7 @@ impl RegClassData {
/// Returns true if `other` is a subclass of this register class. /// Returns true if `other` is a subclass of this register class.
/// A register class is considered to be a subclass of itself. /// A register class is considered to be a subclass of itself.
pub fn has_subclass<RCI: Into<RegClassIndex>>(&self, other: RCI) -> bool { pub fn has_subclass<RCI: Into<RegClassIndex>>(&self, other: RCI) -> bool {
self.subclasses & (1 << other.into().0) != 0 self.subclasses & (1 << other.into().0) as u32 != 0
} }
/// Get the top-level register class containing this class. /// Get the top-level register class containing this class.
@@ -196,7 +196,7 @@ impl RegClassData {
/// Does this register class contain `regunit`? /// Does this register class contain `regunit`?
pub fn contains(&self, regunit: RegUnit) -> bool { pub fn contains(&self, regunit: RegUnit) -> bool {
self.mask[(regunit / 32) as usize] & (1u32 << (regunit % 32)) != 0 self.mask[(regunit / 32) as usize] & (1u32 << (regunit % 32) as u32) != 0
} }
/// If the pinned register is used, is the given regunit the pinned register of this class? /// If the pinned register is used, is the given regunit the pinned register of this class?
@@ -207,6 +207,17 @@ impl RegClassData {
.pinned_reg .pinned_reg
.map_or(false, |pinned_reg| pinned_reg == regunit) .map_or(false, |pinned_reg| pinned_reg == regunit)
} }
/// Calculate the index of the register inside the class.
pub fn index_of(&self, regunit: RegUnit) -> u16 {
assert!(
self.contains(regunit),
"the {} register class does not contain {}",
self.name,
regunit
);
regunit - self.first
}
} }
impl fmt::Display for RegClassData { impl fmt::Display for RegClassData {

View File

@@ -1,6 +1,6 @@
//! Unwind information for x64 Windows. //! Unwind information for x64 Windows.
use super::registers::RU; use super::registers::{GPR, RU};
use crate::binemit::FrameUnwindSink; use crate::binemit::FrameUnwindSink;
use crate::ir::{Function, InstructionData, Opcode}; use crate::ir::{Function, InstructionData, Opcode};
use crate::isa::{CallConv, RegUnit, TargetIsa}; use crate::isa::{CallConv, RegUnit, TargetIsa};
@@ -54,7 +54,8 @@ impl UnwindCode {
write_u8(sink, *offset); write_u8(sink, *offset);
write_u8( write_u8(
sink, sink,
((*reg as u8) << 4) | (UnwindOperation::PushNonvolatileRegister as u8), ((GPR.index_of(*reg) as u8) << 4)
| (UnwindOperation::PushNonvolatileRegister as u8),
); );
} }
Self::StackAlloc { offset, size } => { Self::StackAlloc { offset, size } => {
@@ -262,7 +263,10 @@ impl UnwindInfo {
write_u8(sink, node_count as u8); write_u8(sink, node_count as u8);
if let Some(reg) = self.frame_register { if let Some(reg) = self.frame_register {
write_u8(sink, (self.frame_register_offset << 4) | reg as u8); write_u8(
sink,
(self.frame_register_offset << 4) | GPR.index_of(reg) as u8,
);
} else { } else {
write_u8(sink, 0); write_u8(sink, 0);
} }