| use crate::mir::interpret::truncate; |
| use rustc_target::abi::Size; |
| |
| #[derive(Copy, Clone)] |
| /// A type for representing any integer. Only used for printing. |
| // FIXME: Use this for the integer-tree representation needed for type level ints and |
| // const generics? |
| pub struct ConstInt { |
| /// Number of bytes of the integer. Only 1, 2, 4, 8, 16 are legal values. |
| size: u8, |
| /// Whether the value is of a signed integer type. |
| signed: bool, |
| /// Whether the value is a `usize` or `isize` type. |
| is_ptr_sized_integral: bool, |
| /// Raw memory of the integer. All bytes beyond the `size` are unused and must be zero. |
| raw: u128, |
| } |
| |
| impl ConstInt { |
| pub fn new(raw: u128, size: Size, signed: bool, is_ptr_sized_integral: bool) -> Self { |
| assert!(raw <= truncate(u128::MAX, size)); |
| Self { raw, size: size.bytes() as u8, signed, is_ptr_sized_integral } |
| } |
| } |
| |
| impl std::fmt::Debug for ConstInt { |
| fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| let Self { size, signed, raw, is_ptr_sized_integral } = *self; |
| if signed { |
| let bit_size = size * 8; |
| let min = 1u128 << (bit_size - 1); |
| let max = min - 1; |
| if raw == min { |
| match (size, is_ptr_sized_integral) { |
| (_, true) => write!(fmt, "isize::MIN"), |
| (1, _) => write!(fmt, "i8::MIN"), |
| (2, _) => write!(fmt, "i16::MIN"), |
| (4, _) => write!(fmt, "i32::MIN"), |
| (8, _) => write!(fmt, "i64::MIN"), |
| (16, _) => write!(fmt, "i128::MIN"), |
| _ => bug!("ConstInt 0x{:x} with size = {} and signed = {}", raw, size, signed), |
| } |
| } else if raw == max { |
| match (size, is_ptr_sized_integral) { |
| (_, true) => write!(fmt, "isize::MAX"), |
| (1, _) => write!(fmt, "i8::MAX"), |
| (2, _) => write!(fmt, "i16::MAX"), |
| (4, _) => write!(fmt, "i32::MAX"), |
| (8, _) => write!(fmt, "i64::MAX"), |
| (16, _) => write!(fmt, "i128::MAX"), |
| _ => bug!("ConstInt 0x{:x} with size = {} and signed = {}", raw, size, signed), |
| } |
| } else { |
| match size { |
| 1 => write!(fmt, "{}", raw as i8)?, |
| 2 => write!(fmt, "{}", raw as i16)?, |
| 4 => write!(fmt, "{}", raw as i32)?, |
| 8 => write!(fmt, "{}", raw as i64)?, |
| 16 => write!(fmt, "{}", raw as i128)?, |
| _ => bug!("ConstInt 0x{:x} with size = {} and signed = {}", raw, size, signed), |
| } |
| if fmt.alternate() { |
| match (size, is_ptr_sized_integral) { |
| (_, true) => write!(fmt, "_isize")?, |
| (1, _) => write!(fmt, "_i8")?, |
| (2, _) => write!(fmt, "_i16")?, |
| (4, _) => write!(fmt, "_i32")?, |
| (8, _) => write!(fmt, "_i64")?, |
| (16, _) => write!(fmt, "_i128")?, |
| _ => bug!(), |
| } |
| } |
| Ok(()) |
| } |
| } else { |
| let max = truncate(u128::MAX, Size::from_bytes(size)); |
| if raw == max { |
| match (size, is_ptr_sized_integral) { |
| (_, true) => write!(fmt, "usize::MAX"), |
| (1, _) => write!(fmt, "u8::MAX"), |
| (2, _) => write!(fmt, "u16::MAX"), |
| (4, _) => write!(fmt, "u32::MAX"), |
| (8, _) => write!(fmt, "u64::MAX"), |
| (16, _) => write!(fmt, "u128::MAX"), |
| _ => bug!("ConstInt 0x{:x} with size = {} and signed = {}", raw, size, signed), |
| } |
| } else { |
| match size { |
| 1 => write!(fmt, "{}", raw as u8)?, |
| 2 => write!(fmt, "{}", raw as u16)?, |
| 4 => write!(fmt, "{}", raw as u32)?, |
| 8 => write!(fmt, "{}", raw as u64)?, |
| 16 => write!(fmt, "{}", raw as u128)?, |
| _ => bug!("ConstInt 0x{:x} with size = {} and signed = {}", raw, size, signed), |
| } |
| if fmt.alternate() { |
| match (size, is_ptr_sized_integral) { |
| (_, true) => write!(fmt, "_usize")?, |
| (1, _) => write!(fmt, "_u8")?, |
| (2, _) => write!(fmt, "_u16")?, |
| (4, _) => write!(fmt, "_u32")?, |
| (8, _) => write!(fmt, "_u64")?, |
| (16, _) => write!(fmt, "_u128")?, |
| _ => bug!(), |
| } |
| } |
| Ok(()) |
| } |
| } |
| } |
| } |