diff --git a/src/ion/data_structures.rs b/src/ion/data_structures.rs index 848ab2a3..208be91d 100644 --- a/src/ion/data_structures.rs +++ b/src/ion/data_structures.rs @@ -179,13 +179,13 @@ impl LiveRange { pub struct Use { pub operand: Operand, pub pos: ProgPoint, - pub slot: u8, + pub slot: u16, pub weight: u16, } impl Use { #[inline(always)] - pub fn new(operand: Operand, pos: ProgPoint, slot: u8) -> Self { + pub fn new(operand: Operand, pos: ProgPoint, slot: u16) -> Self { Self { operand, pos, @@ -315,8 +315,8 @@ pub struct PRegData { #[derive(Clone, Debug)] pub struct MultiFixedRegFixup { pub pos: ProgPoint, - pub from_slot: u8, - pub to_slot: u8, + pub from_slot: u16, + pub to_slot: u16, pub level: FixedRegFixupLevel, pub to_preg: PRegIndex, pub vreg: VRegIndex, diff --git a/src/ion/liveranges.rs b/src/ion/liveranges.rs index c518262b..55818280 100644 --- a/src/ion/liveranges.rs +++ b/src/ion/liveranges.rs @@ -24,6 +24,7 @@ use crate::{ Allocation, Block, Function, Inst, InstPosition, Operand, OperandConstraint, OperandKind, OperandPos, PReg, ProgPoint, RegAllocError, VReg, VecExt, }; +use core::convert::TryFrom; use smallvec::{smallvec, SmallVec}; /// A spill weight computed for a certain Use. @@ -94,6 +95,10 @@ impl core::ops::Add for SpillWeight { } } +fn slot_idx(i: usize) -> Result { + u16::try_from(i).map_err(|_| RegAllocError::TooManyOperands) +} + impl<'a, F: Function> Env<'a, F> { pub fn create_pregs_and_vregs(&mut self) { // Create PRegs from the env. @@ -362,7 +367,7 @@ impl<'a, F: Function> Env<'a, F> { Ok(()) } - pub fn build_liveranges(&mut self) { + pub fn build_liveranges(&mut self) -> Result<(), RegAllocError> { // Create Uses and Defs referring to VRegs, and place the Uses // in LiveRanges. // @@ -533,8 +538,8 @@ impl<'a, F: Function> Env<'a, F> { let pos = ProgPoint::before(inst); self.multi_fixed_reg_fixups.push(MultiFixedRegFixup { pos, - from_slot: i as u8, - to_slot: i as u8, + from_slot: slot_idx(i)?, + to_slot: slot_idx(i)?, to_preg: PRegIndex::new(preg.index()), vreg: VRegIndex::new(operand.vreg().vreg()), level: FixedRegFixupLevel::Initial, @@ -638,7 +643,10 @@ impl<'a, F: Function> Env<'a, F> { live.set(operand.vreg().vreg(), true); } // Create the use in the LiveRange. - self.insert_use_into_liverange(lr, Use::new(operand, pos, i as u8)); + self.insert_use_into_liverange( + lr, + Use::new(operand, pos, slot_idx(i)?), + ); // If def (not mod), this reg is now dead, // scanning backward; make it so. if operand.kind() == OperandKind::Def { @@ -681,7 +689,10 @@ impl<'a, F: Function> Env<'a, F> { trace!("Use of {:?} at {:?} -> {:?}", operand, pos, lr,); - self.insert_use_into_liverange(lr, Use::new(operand, pos, i as u8)); + self.insert_use_into_liverange( + lr, + Use::new(operand, pos, slot_idx(i)?), + ); // Add to live-set. live.set(operand.vreg().vreg(), true); @@ -756,6 +767,8 @@ impl<'a, F: Function> Env<'a, F> { self.output.stats.blockparam_outs_count = self.blockparam_outs.len(); self.ctx.scratch_vreg_ranges = vreg_ranges; self.ctx.scratch_operand_rewrites = operand_rewrites; + + Ok(()) } pub fn fixup_multi_fixed_vregs(&mut self) { diff --git a/src/ion/mod.rs b/src/ion/mod.rs index 51751d5e..99181191 100644 --- a/src/ion/mod.rs +++ b/src/ion/mod.rs @@ -83,7 +83,7 @@ impl<'a, F: Function> Env<'a, F> { pub(crate) fn init(&mut self) -> Result<(), RegAllocError> { self.create_pregs_and_vregs(); self.compute_liveness()?; - self.build_liveranges(); + self.build_liveranges()?; self.fixup_multi_fixed_vregs(); self.merge_vreg_bundles(); self.queue_bundles(); diff --git a/src/lib.rs b/src/lib.rs index f3bc744e..a672583f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1577,6 +1577,9 @@ pub enum RegAllocError { /// Too many pinned VRegs + Reg-constrained Operands are live at /// once, making allocation impossible. TooManyLiveRegs, + /// Too many operands on a single instruction (beyond limit of + /// 2^16 - 1). + TooManyOperands, } impl core::fmt::Display for RegAllocError {