From 732bc7515adbb7e068a913080f31a23c342d9918 Mon Sep 17 00:00:00 2001 From: Jonas Kruckenberg Date: Mon, 13 Jan 2025 09:40:01 +0100 Subject: [PATCH 1/5] refactor: use `&'static [PReg]` instead of `Vec` --- src/checker.rs | 2 +- src/fastalloc/mod.rs | 6 +++--- src/fastalloc/tests.rs | 16 +++++++++------- src/ion/liveranges.rs | 2 +- src/lib.rs | 16 +++++++++++----- 5 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/checker.rs b/src/checker.rs index d67dc2da..8650cdd8 100644 --- a/src/checker.rs +++ b/src/checker.rs @@ -722,7 +722,7 @@ impl<'a, F: Function> Checker<'a, F> { bb_in.insert(f.entry_block(), CheckerState::default()); let mut stack_pregs = PRegSet::empty(); - for &preg in &machine_env.fixed_stack_slots { + for &preg in machine_env.fixed_stack_slots { stack_pregs.add(preg); } diff --git a/src/fastalloc/mod.rs b/src/fastalloc/mod.rs index c8d41f6c..8cad52c6 100644 --- a/src/fastalloc/mod.rs +++ b/src/fastalloc/mod.rs @@ -245,9 +245,9 @@ impl<'a, F: Function> Env<'a, F> { fn new(func: &'a F, env: &'a MachineEnv) -> Self { use alloc::vec; let mut regs = [ - env.preferred_regs_by_class[RegClass::Int as usize].clone(), - env.preferred_regs_by_class[RegClass::Float as usize].clone(), - env.preferred_regs_by_class[RegClass::Vector as usize].clone(), + Vec::from(env.preferred_regs_by_class[RegClass::Int as usize]), + Vec::from(env.preferred_regs_by_class[RegClass::Float as usize]), + Vec::from(env.preferred_regs_by_class[RegClass::Vector as usize]), ]; regs[0].extend( env.non_preferred_regs_by_class[RegClass::Int as usize] diff --git a/src/fastalloc/tests.rs b/src/fastalloc/tests.rs index 41be3771..c815991e 100644 --- a/src/fastalloc/tests.rs +++ b/src/fastalloc/tests.rs @@ -143,15 +143,17 @@ impl RealFunction { fn mach_env(no_of_regs: usize) -> MachineEnv { MachineEnv { preferred_regs_by_class: [ - (0..no_of_regs) - .map(|no| PReg::new(no, RegClass::Int)) - .collect(), - vec![], - vec![], + Vec::leak( + (0..no_of_regs) + .map(|no| PReg::new(no, RegClass::Int)) + .collect(), + ), + &[], + &[], ], - non_preferred_regs_by_class: [vec![], vec![], vec![]], + non_preferred_regs_by_class: [&[], &[], &[]], scratch_by_class: [None, None, None], - fixed_stack_slots: vec![], + fixed_stack_slots: &[], } } diff --git a/src/ion/liveranges.rs b/src/ion/liveranges.rs index c518262b..44719d85 100644 --- a/src/ion/liveranges.rs +++ b/src/ion/liveranges.rs @@ -104,7 +104,7 @@ impl<'a, F: Function> Env<'a, F> { is_stack: false, }, ); - for &preg in &self.env.fixed_stack_slots { + for &preg in self.env.fixed_stack_slots { self.pregs[preg.index()].is_stack = true; } for class in 0..self.preferred_victim_by_class.len() { diff --git a/src/lib.rs b/src/lib.rs index 539466a8..bd15101b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -338,13 +338,13 @@ impl From<&MachineEnv> for PRegSet { fn from(env: &MachineEnv) -> Self { let mut res = Self::default(); - for class in env.preferred_regs_by_class.iter() { + for class in env.preferred_regs_by_class { for preg in class { res.add(*preg) } } - for class in env.non_preferred_regs_by_class.iter() { + for class in env.non_preferred_regs_by_class { for preg in class { res.add(*preg) } @@ -1434,6 +1434,12 @@ impl<'a> Iterator for OutputIter<'a> { /// are available to allocate and what register may be used as a /// scratch register for each class, and some other miscellaneous info /// as well. +/// +/// Note that `MachineEnv` is designed to be a global configuration struct that programs +/// will have very few of and generally want to keep around for their entire lifetime. +/// In order to make static initialization easier the registers lists are static slices instead +/// of `Vec`s. If your use case depends on dynamically creating the registers lists, consider +/// `[Vec::leak`]. #[derive(Clone, Debug)] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub struct MachineEnv { @@ -1442,7 +1448,7 @@ pub struct MachineEnv { /// /// If an explicit scratch register is provided in `scratch_by_class` then /// it must not appear in this list. - pub preferred_regs_by_class: [Vec; 3], + pub preferred_regs_by_class: [&'static [PReg]; 3], /// Non-preferred physical registers for each class. These are the /// registers that will be allocated if a preferred register is @@ -1451,7 +1457,7 @@ pub struct MachineEnv { /// /// If an explicit scratch register is provided in `scratch_by_class` then /// it must not appear in this list. - pub non_preferred_regs_by_class: [Vec; 3], + pub non_preferred_regs_by_class: [&'static [PReg]; 3], /// Optional dedicated scratch register per class. This is needed to perform /// moves between registers when cyclic move patterns occur. The @@ -1476,7 +1482,7 @@ pub struct MachineEnv { /// /// `PReg`s in this list cannot be used as an allocatable or scratch /// register. - pub fixed_stack_slots: Vec, + pub fixed_stack_slots: &'static [PReg], } /// The output of the register allocator. From 0d5975998ece049ce60f297efe1d4881f108d276 Mon Sep 17 00:00:00 2001 From: Jonas Kruckenberg Date: Mon, 13 Jan 2025 10:13:27 +0100 Subject: [PATCH 2/5] add `SerializableMachineEnv` --- src/serialize.rs | 54 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/src/serialize.rs b/src/serialize.rs index e98d8831..94318d6c 100644 --- a/src/serialize.rs +++ b/src/serialize.rs @@ -3,7 +3,7 @@ use core::fmt; use alloc::{format, string::ToString, vec::Vec}; use serde::{Deserialize, Serialize}; -use crate::{Block, Function, Inst, InstRange, MachineEnv, Operand, PRegSet, RegClass, VReg}; +use crate::{Block, Function, Inst, InstRange, MachineEnv, Operand, PReg, PRegSet, RegClass, VReg}; #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] enum InstOpcode { @@ -37,7 +37,7 @@ struct InstData { /// was created with. #[derive(Serialize, Deserialize)] pub struct SerializableFunction { - machine_env: MachineEnv, + machine_env: SerializableMachineEnv, entry_block: Block, insts: Vec, blocks: Vec, @@ -57,7 +57,7 @@ impl SerializableFunction { /// `MachineEnv`. pub fn new(func: &impl Function, machine_env: MachineEnv) -> Self { Self { - machine_env, + machine_env: SerializableMachineEnv::new(machine_env), entry_block: func.entry_block(), insts: (0..func.num_insts()) .map(|i| { @@ -123,8 +123,8 @@ impl SerializableFunction { } /// Returns the `MachineEnv` associated with this function. - pub fn machine_env(&self) -> &MachineEnv { - &self.machine_env + pub fn machine_env(&self) -> MachineEnv { + self.machine_env.machine_env() } } @@ -291,3 +291,47 @@ impl fmt::Debug for SerializableFunction { Ok(()) } } + +#[derive(Serialize, Deserialize)] +pub struct SerializableMachineEnv { + preferred_regs_by_class: [Vec; 3], + non_preferred_regs_by_class: [Vec; 3], + scratch_by_class: [Option; 3], + fixed_stack_slots: Vec, +} + +impl SerializableMachineEnv { + pub fn new(machine_env: MachineEnv) -> Self { + Self { + preferred_regs_by_class: [ + machine_env.preferred_regs_by_class[0].to_vec(), + machine_env.preferred_regs_by_class[1].to_vec(), + machine_env.preferred_regs_by_class[2].to_vec(), + ], + non_preferred_regs_by_class: [ + machine_env.non_preferred_regs_by_class[0].to_vec(), + machine_env.non_preferred_regs_by_class[1].to_vec(), + machine_env.non_preferred_regs_by_class[2].to_vec(), + ], + scratch_by_class: machine_env.scratch_by_class, + fixed_stack_slots: machine_env.fixed_stack_slots.to_vec(), + } + } + + pub fn machine_env(&self) -> MachineEnv { + MachineEnv { + preferred_regs_by_class: [ + &self.preferred_regs_by_class[0], + &self.preferred_regs_by_class[1], + &self.preferred_regs_by_class[2], + ], + non_preferred_regs_by_class: [ + &self.non_preferred_regs_by_class[0], + &self.non_preferred_regs_by_class[1], + &self.non_preferred_regs_by_class[2], + ], + scratch_by_class: self.scratch_by_class, + fixed_stack_slots: &self.fixed_stack_slots, + } + } +} From 5e0d8941c9d8838ce438d1b886336b1bd6afc79e Mon Sep 17 00:00:00 2001 From: Jonas Kruckenberg Date: Mon, 13 Jan 2025 10:35:32 +0100 Subject: [PATCH 3/5] `MachineEnv` generic lifetime --- src/checker.rs | 14 +++++++------- src/fastalloc/tests.rs | 2 +- src/fuzzing/func.rs | 30 ++++++++++++++++-------------- src/ion/data_structures.rs | 10 +++++----- src/ion/dump.rs | 2 +- src/ion/liveranges.rs | 2 +- src/ion/merge.rs | 2 +- src/ion/mod.rs | 4 ++-- src/ion/moves.rs | 6 +++--- src/ion/process.rs | 2 +- src/ion/reg_traversal.rs | 10 +++++----- src/ion/requirement.rs | 2 +- src/ion/spill.rs | 2 +- src/lib.rs | 11 +++++------ 14 files changed, 50 insertions(+), 49 deletions(-) diff --git a/src/checker.rs b/src/checker.rs index 8650cdd8..72d9499b 100644 --- a/src/checker.rs +++ b/src/checker.rs @@ -430,7 +430,7 @@ impl CheckerState { alloc: Allocation, val: &CheckerValue, allocs: &[Allocation], - checker: &Checker<'a, F>, + checker: &Checker<'a, '_, F>, ) -> Result<(), CheckerError> { if alloc == Allocation::none() { return Err(CheckerError::MissingAllocation { inst, op }); @@ -465,7 +465,7 @@ impl CheckerState { &self, pos: InstPosition, checkinst: &CheckerInst, - checker: &Checker<'a, F>, + checker: &Checker<'a, '_, F>, ) -> Result<(), CheckerError> { let default_val = Default::default(); match checkinst { @@ -627,7 +627,7 @@ impl CheckerState { op: Operand, alloc: Allocation, allocs: &[Allocation], - checker: &Checker<'a, F>, + checker: &Checker<'a, '_, F>, ) -> Result<(), CheckerError> { match op.constraint() { OperandConstraint::Any => {} @@ -691,21 +691,21 @@ pub(crate) enum CheckerInst { } #[derive(Debug)] -pub struct Checker<'a, F: Function> { +pub struct Checker<'a, 'r, F: Function> { f: &'a F, bb_in: FxHashMap, bb_insts: FxHashMap>, edge_insts: FxHashMap<(Block, Block), Vec>, - machine_env: &'a MachineEnv, + machine_env: &'a MachineEnv<'r>, stack_pregs: PRegSet, } -impl<'a, F: Function> Checker<'a, F> { +impl<'a, 'r, F: Function> Checker<'a, 'r, F> { /// Create a new checker for the given function, initializing CFG /// info immediately. The client should call the `add_*()` /// methods to add abstract instructions to each BB before /// invoking `run()` to check for errors. - pub fn new(f: &'a F, machine_env: &'a MachineEnv) -> Checker<'a, F> { + pub fn new(f: &'a F, machine_env: &'a MachineEnv<'r>) -> Checker<'a, 'r, F> { let mut bb_in = FxHashMap::default(); let mut bb_insts = FxHashMap::default(); let mut edge_insts = FxHashMap::default(); diff --git a/src/fastalloc/tests.rs b/src/fastalloc/tests.rs index c815991e..552cb36b 100644 --- a/src/fastalloc/tests.rs +++ b/src/fastalloc/tests.rs @@ -140,7 +140,7 @@ impl RealFunction { } } -fn mach_env(no_of_regs: usize) -> MachineEnv { +fn mach_env(no_of_regs: usize) -> MachineEnv<'static> { MachineEnv { preferred_regs_by_class: [ Vec::leak( diff --git a/src/fuzzing/func.rs b/src/fuzzing/func.rs index 69ce7262..bab9df9a 100644 --- a/src/fuzzing/func.rs +++ b/src/fuzzing/func.rs @@ -624,30 +624,32 @@ impl core::fmt::Debug for Func { } } -pub fn machine_env() -> MachineEnv { - fn regs(r: core::ops::Range, c: RegClass) -> Vec { - r.map(|i| PReg::new(i, c)).collect() +pub fn machine_env() -> MachineEnv<'static> { + fn regs(r: core::ops::Range, c: RegClass) -> &'static [PReg] { + Vec::leak(r.map(|i| PReg::new(i, c)).collect()) } - let preferred_regs_by_class: [Vec; 3] = [ + let preferred_regs_by_class: [&'static [PReg]; 3] = [ regs(0..24, RegClass::Int), regs(0..24, RegClass::Float), regs(0..24, RegClass::Vector), ]; - let non_preferred_regs_by_class: [Vec; 3] = [ + let non_preferred_regs_by_class: [&'static [PReg]; 3] = [ regs(24..32, RegClass::Int), regs(24..32, RegClass::Float), regs(24..32, RegClass::Vector), ]; let scratch_by_class: [Option; 3] = [None, None, None]; - let fixed_stack_slots = (32..63) - .flat_map(|i| { - [ - PReg::new(i, RegClass::Int), - PReg::new(i, RegClass::Float), - PReg::new(i, RegClass::Vector), - ] - }) - .collect(); + let fixed_stack_slots = Vec::leak( + (32..63) + .flat_map(|i| { + [ + PReg::new(i, RegClass::Int), + PReg::new(i, RegClass::Float), + PReg::new(i, RegClass::Vector), + ] + }) + .collect(), + ); // Register 63 is reserved for use as a fixed non-allocatable register. MachineEnv { preferred_regs_by_class, diff --git a/src/ion/data_structures.rs b/src/ion/data_structures.rs index 848ab2a3..dc31837b 100644 --- a/src/ion/data_structures.rs +++ b/src/ion/data_structures.rs @@ -497,13 +497,13 @@ impl Ctx { } } -pub struct Env<'a, F: Function> { +pub struct Env<'a, 'r, F: Function> { pub func: &'a F, - pub env: &'a MachineEnv, + pub env: &'a MachineEnv<'r>, pub ctx: &'a mut Ctx, } -impl<'a, F: Function> Deref for Env<'a, F> { +impl<'a, F: Function> Deref for Env<'a, '_, F> { type Target = Ctx; fn deref(&self) -> &Self::Target { @@ -511,13 +511,13 @@ impl<'a, F: Function> Deref for Env<'a, F> { } } -impl<'a, F: Function> DerefMut for Env<'a, F> { +impl<'a, F: Function> DerefMut for Env<'a, '_, F> { fn deref_mut(&mut self) -> &mut Self::Target { self.ctx } } -impl<'a, F: Function> Env<'a, F> { +impl<'a, F: Function> Env<'a, '_, F> { /// Get the VReg (with bundled RegClass) from a vreg index. #[inline] pub fn vreg(&self, index: VRegIndex) -> VReg { diff --git a/src/ion/dump.rs b/src/ion/dump.rs index abcaaf32..e8e77147 100644 --- a/src/ion/dump.rs +++ b/src/ion/dump.rs @@ -7,7 +7,7 @@ use alloc::{string::String, vec::Vec}; use super::Env; use crate::{Block, Function, ProgPoint}; -impl<'a, F: Function> Env<'a, F> { +impl<'a, F: Function> Env<'a, '_, F> { pub fn dump_state(&self) { trace!("Bundles:"); for (i, b) in self.bundles.iter().enumerate() { diff --git a/src/ion/liveranges.rs b/src/ion/liveranges.rs index 44719d85..fe03235e 100644 --- a/src/ion/liveranges.rs +++ b/src/ion/liveranges.rs @@ -94,7 +94,7 @@ impl core::ops::Add for SpillWeight { } } -impl<'a, F: Function> Env<'a, F> { +impl<'a, F: Function> Env<'a, '_, F> { pub fn create_pregs_and_vregs(&mut self) { // Create PRegs from the env. self.pregs.resize( diff --git a/src/ion/merge.rs b/src/ion/merge.rs index f503acf1..c31de95e 100644 --- a/src/ion/merge.rs +++ b/src/ion/merge.rs @@ -22,7 +22,7 @@ use crate::{ }; use alloc::format; -impl<'a, F: Function> Env<'a, F> { +impl<'a, F: Function> Env<'a, '_, F> { pub fn merge_bundles(&mut self, from: LiveBundleIndex, to: LiveBundleIndex) -> bool { if from == to { // Merge bundle into self -- trivial merge. diff --git a/src/ion/mod.rs b/src/ion/mod.rs index 0de5f87a..9fd47f44 100644 --- a/src/ion/mod.rs +++ b/src/ion/mod.rs @@ -35,8 +35,8 @@ pub(crate) mod dump; pub(crate) mod moves; pub(crate) mod spill; -impl<'a, F: Function> Env<'a, F> { - pub(crate) fn new(func: &'a F, env: &'a MachineEnv, ctx: &'a mut Ctx) -> Self { +impl<'a, 'r, F: Function> Env<'a, 'r, F> { + pub(crate) fn new(func: &'a F, env: &'a MachineEnv<'r>, ctx: &'a mut Ctx) -> Self { let ninstrs = func.num_insts(); let nblocks = func.num_blocks(); diff --git a/src/ion/moves.rs b/src/ion/moves.rs index 22685e53..ab0dc784 100644 --- a/src/ion/moves.rs +++ b/src/ion/moves.rs @@ -33,7 +33,7 @@ use alloc::vec::Vec; use hashbrown::hash_map::Entry; use smallvec::{smallvec, SmallVec}; -impl<'a, F: Function> Env<'a, F> { +impl<'a, F: Function> Env<'a, '_, F> { pub fn is_start_of_block(&self, pos: ProgPoint) -> bool { let block = self.ctx.cfginfo.insn_block[pos.inst().index()]; pos == self.ctx.cfginfo.block_entry[block.index()] @@ -171,7 +171,7 @@ impl<'a, F: Function> Env<'a, F> { // and moves go at start of `to`. #[inline(always)] fn choose_move_location<'a, F: Function>( - env: &Env<'a, F>, + env: &Env<'a, '_, F>, from: Block, to: Block, ) -> (ProgPoint, InsertMovePrio) { @@ -787,7 +787,7 @@ impl<'a, F: Function> Env<'a, F> { let mut redundant_moves = RedundantMoveEliminator::default(); fn redundant_move_process_side_effects<'a, F: Function>( - this: &Env<'a, F>, + this: &Env<'a, '_, F>, redundant_moves: &mut RedundantMoveEliminator, from: ProgPoint, to: ProgPoint, diff --git a/src/ion/process.rs b/src/ion/process.rs index f3b91532..0fd9ed74 100644 --- a/src/ion/process.rs +++ b/src/ion/process.rs @@ -36,7 +36,7 @@ pub enum AllocRegResult<'a> { ConflictHighCost, } -impl<'a, F: Function> Env<'a, F> { +impl<'a, F: Function> Env<'a, '_, F> { pub fn process_bundles(&mut self) -> Result<(), RegAllocError> { while let Some((bundle, reg_hint)) = self.ctx.allocation_queue.pop() { self.ctx.output.stats.process_bundle_count += 1; diff --git a/src/ion/reg_traversal.rs b/src/ion/reg_traversal.rs index 729fd33e..224f276f 100644 --- a/src/ion/reg_traversal.rs +++ b/src/ion/reg_traversal.rs @@ -14,8 +14,8 @@ use crate::{MachineEnv, PReg, RegClass}; /// usage, these consist of caller-save and callee-save registers /// respectively, to minimize clobber-saves; but they need not.) -pub struct RegTraversalIter<'a> { - env: &'a MachineEnv, +pub struct RegTraversalIter<'a, 'r> { + env: &'a MachineEnv<'r>, class: usize, hints: [Option; 2], hint_idx: usize, @@ -27,9 +27,9 @@ pub struct RegTraversalIter<'a> { fixed: Option, } -impl<'a> RegTraversalIter<'a> { +impl<'a, 'r> RegTraversalIter<'a, 'r> { pub fn new( - env: &'a MachineEnv, + env: &'a MachineEnv<'r>, class: RegClass, hint_reg: PReg, hint2_reg: PReg, @@ -78,7 +78,7 @@ impl<'a> RegTraversalIter<'a> { } } -impl<'a> core::iter::Iterator for RegTraversalIter<'a> { +impl<'a> core::iter::Iterator for RegTraversalIter<'a, '_> { type Item = PReg; fn next(&mut self) -> Option { diff --git a/src/ion/requirement.rs b/src/ion/requirement.rs index 5e9af2a3..94abc985 100644 --- a/src/ion/requirement.rs +++ b/src/ion/requirement.rs @@ -98,7 +98,7 @@ impl Requirement { } } -impl<'a, F: Function> Env<'a, F> { +impl<'a, F: Function> Env<'a, '_, F> { #[inline(always)] pub fn requirement_from_operand(&self, op: Operand) -> Requirement { match op.constraint() { diff --git a/src/ion/spill.rs b/src/ion/spill.rs index c40efc80..4dfdf95c 100644 --- a/src/ion/spill.rs +++ b/src/ion/spill.rs @@ -18,7 +18,7 @@ use super::{ }; use crate::{Allocation, Function, SpillSlot}; -impl<'a, F: Function> Env<'a, F> { +impl<'a, F: Function> Env<'a, '_, F> { pub fn try_allocating_regs_for_spilled_bundles(&mut self) { trace!("allocating regs for spilled bundles"); let mut scratch = core::mem::take(&mut self.ctx.scratch_conflicts); diff --git a/src/lib.rs b/src/lib.rs index bd15101b..9c47fa72 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -334,7 +334,7 @@ impl Iterator for PRegSetIter { } } -impl From<&MachineEnv> for PRegSet { +impl From<&MachineEnv<'_>> for PRegSet { fn from(env: &MachineEnv) -> Self { let mut res = Self::default(); @@ -1441,14 +1441,13 @@ impl<'a> Iterator for OutputIter<'a> { /// of `Vec`s. If your use case depends on dynamically creating the registers lists, consider /// `[Vec::leak`]. #[derive(Clone, Debug)] -#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -pub struct MachineEnv { +pub struct MachineEnv<'a> { /// Preferred physical registers for each class. These are the /// registers that will be allocated first, if free. /// /// If an explicit scratch register is provided in `scratch_by_class` then /// it must not appear in this list. - pub preferred_regs_by_class: [&'static [PReg]; 3], + pub preferred_regs_by_class: [&'a [PReg]; 3], /// Non-preferred physical registers for each class. These are the /// registers that will be allocated if a preferred register is @@ -1457,7 +1456,7 @@ pub struct MachineEnv { /// /// If an explicit scratch register is provided in `scratch_by_class` then /// it must not appear in this list. - pub non_preferred_regs_by_class: [&'static [PReg]; 3], + pub non_preferred_regs_by_class: [&'a [PReg]; 3], /// Optional dedicated scratch register per class. This is needed to perform /// moves between registers when cyclic move patterns occur. The @@ -1482,7 +1481,7 @@ pub struct MachineEnv { /// /// `PReg`s in this list cannot be used as an allocatable or scratch /// register. - pub fixed_stack_slots: &'static [PReg], + pub fixed_stack_slots: &'a [PReg], } /// The output of the register allocator. From fbeebc33a620667e2bb2a2990d8b338089596089 Mon Sep 17 00:00:00 2001 From: Jonas Kruckenberg Date: Mon, 13 Jan 2025 10:35:52 +0100 Subject: [PATCH 4/5] Update src/lib.rs Co-authored-by: bjorn3 <17426603+bjorn3@users.noreply.github.com> --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 9c47fa72..50629154 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1439,7 +1439,7 @@ impl<'a> Iterator for OutputIter<'a> { /// will have very few of and generally want to keep around for their entire lifetime. /// In order to make static initialization easier the registers lists are static slices instead /// of `Vec`s. If your use case depends on dynamically creating the registers lists, consider -/// `[Vec::leak`]. +/// [`Vec::leak`]. #[derive(Clone, Debug)] pub struct MachineEnv<'a> { /// Preferred physical registers for each class. These are the From 305811667665047d750521973be4b3b7a6a7d312 Mon Sep 17 00:00:00 2001 From: Jonas Kruckenberg Date: Mon, 13 Jan 2025 11:25:47 +0100 Subject: [PATCH 5/5] fix tests --- regalloc2-tool/src/main.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/regalloc2-tool/src/main.rs b/regalloc2-tool/src/main.rs index b5a21842..9504b4ec 100644 --- a/regalloc2-tool/src/main.rs +++ b/regalloc2-tool/src/main.rs @@ -52,7 +52,7 @@ fn main() { validate_ssa: true, algorithm: args.algorithm.into(), }; - let output = match regalloc2::run(&function, function.machine_env(), &options) { + let output = match regalloc2::run(&function, &function.machine_env(), &options) { Ok(output) => output, Err(e) => { panic!("Register allocation failed: {e:#?}"); @@ -63,7 +63,8 @@ fn main() { print_output(&function, &output); } - let mut checker = Checker::new(&function, function.machine_env()); + let machine_env = function.machine_env(); + let mut checker = Checker::new(&function, &machine_env); checker.prepare(&output); if let Err(e) = checker.run() { panic!("Regsiter allocation checker failed: {e:#?}");