Allocate a fresh ValueRegs.
(&mut self, ty: Type)
| 1714 | |
| 1715 | /// Allocate a fresh ValueRegs. |
| 1716 | pub fn alloc(&mut self, ty: Type) -> CodegenResult<ValueRegs<Reg>> { |
| 1717 | if self.deferred_error.is_some() { |
| 1718 | return Err(CodegenError::CodeTooLarge); |
| 1719 | } |
| 1720 | let v = self.vreg_types.len(); |
| 1721 | let (regclasses, tys) = I::rc_for_type(ty)?; |
| 1722 | |
| 1723 | // Check that new indices are in-bounds for regalloc2's |
| 1724 | // VReg/Operand representation. |
| 1725 | if v + regclasses.len() > VReg::MAX { |
| 1726 | return Err(CodegenError::CodeTooLarge); |
| 1727 | } |
| 1728 | |
| 1729 | // Check that new indices are in-bounds for our Reg |
| 1730 | // bit-packing on top of the RA2 types, which represents |
| 1731 | // spillslots as well. |
| 1732 | let check = |vreg: regalloc2::VReg| -> CodegenResult<Reg> { |
| 1733 | Reg::from_virtual_reg_checked(vreg).ok_or(CodegenError::CodeTooLarge) |
| 1734 | }; |
| 1735 | |
| 1736 | let regs: ValueRegs<Reg> = match regclasses { |
| 1737 | &[rc0] => ValueRegs::one(check(VReg::new(v, rc0))?), |
| 1738 | &[rc0, rc1] => ValueRegs::two(check(VReg::new(v, rc0))?, check(VReg::new(v + 1, rc1))?), |
| 1739 | // We can extend this if/when we support 32-bit targets; e.g., |
| 1740 | // an i128 on a 32-bit machine will need up to four machine regs |
| 1741 | // for a `Value`. |
| 1742 | _ => panic!("Value must reside in 1 or 2 registers"), |
| 1743 | }; |
| 1744 | for (®_ty, ®) in tys.iter().zip(regs.regs().iter()) { |
| 1745 | let vreg = reg.to_virtual_reg().unwrap(); |
| 1746 | debug_assert_eq!(self.vreg_types.len(), vreg.index()); |
| 1747 | self.vreg_types.push(reg_ty); |
| 1748 | } |
| 1749 | |
| 1750 | Ok(regs) |
| 1751 | } |
| 1752 | |
| 1753 | /// Allocate a fresh ValueRegs, deferring any out-of-vregs |
| 1754 | /// errors. This is useful in places where we cannot bubble a |