From 3f53bcb7404d3a276e10f697e5f904057aceaed9 Mon Sep 17 00:00:00 2001 From: Andrew Brown Date: Fri, 14 Feb 2020 13:24:13 -0800 Subject: [PATCH] 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. --- cranelift/codegen/meta/src/gen_registers.rs | 8 +++++++- cranelift/codegen/src/isa/registers.rs | 15 +++++++++++++-- cranelift/codegen/src/isa/x86/unwind.rs | 10 +++++++--- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/cranelift/codegen/meta/src/gen_registers.rs b/cranelift/codegen/meta/src/gen_registers.rs index fbb61beb37..bd5ac95ae0 100644 --- a/cranelift/codegen/meta/src/gen_registers.rs +++ b/cranelift/codegen/meta/src/gen_registers.rs @@ -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, "subclasses: {:#x},", reg_class.subclass_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, "};"); diff --git a/cranelift/codegen/src/isa/registers.rs b/cranelift/codegen/src/isa/registers.rs index 6bb9e9cf4c..e67ae13453 100644 --- a/cranelift/codegen/src/isa/registers.rs +++ b/cranelift/codegen/src/isa/registers.rs @@ -180,7 +180,7 @@ impl RegClassData { /// Returns true if `other` is a subclass of this register class. /// A register class is considered to be a subclass of itself. pub fn has_subclass>(&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. @@ -196,7 +196,7 @@ impl RegClassData { /// Does this register class contain `regunit`? 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? @@ -207,6 +207,17 @@ impl RegClassData { .pinned_reg .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 { diff --git a/cranelift/codegen/src/isa/x86/unwind.rs b/cranelift/codegen/src/isa/x86/unwind.rs index 693693ab37..de653b89a6 100644 --- a/cranelift/codegen/src/isa/x86/unwind.rs +++ b/cranelift/codegen/src/isa/x86/unwind.rs @@ -1,6 +1,6 @@ //! Unwind information for x64 Windows. -use super::registers::RU; +use super::registers::{GPR, RU}; use crate::binemit::FrameUnwindSink; use crate::ir::{Function, InstructionData, Opcode}; use crate::isa::{CallConv, RegUnit, TargetIsa}; @@ -54,7 +54,8 @@ impl UnwindCode { write_u8(sink, *offset); write_u8( sink, - ((*reg as u8) << 4) | (UnwindOperation::PushNonvolatileRegister as u8), + ((GPR.index_of(*reg) as u8) << 4) + | (UnwindOperation::PushNonvolatileRegister as u8), ); } Self::StackAlloc { offset, size } => { @@ -262,7 +263,10 @@ impl UnwindInfo { write_u8(sink, node_count as u8); 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 { write_u8(sink, 0); }