Add convenience conversion methods for ScalarInt

This commit is contained in:
Oli Scherer 2021-02-23 14:11:29 +00:00
parent 858216cabf
commit 09f7f91532
3 changed files with 53 additions and 10 deletions

View File

@ -1,4 +1,4 @@
use std::convert::TryFrom; use std::convert::{TryFrom, TryInto};
use std::fmt; use std::fmt;
use rustc_apfloat::{ use rustc_apfloat::{
@ -56,20 +56,20 @@ pub fn try_to_scalar(&self) -> Option<Scalar> {
} }
} }
pub fn try_to_scalar_int(&self) -> Option<ScalarInt> {
self.try_to_scalar()?.to_int().ok()
}
pub fn try_to_bits(&self, size: Size) -> Option<u128> { pub fn try_to_bits(&self, size: Size) -> Option<u128> {
self.try_to_scalar()?.to_bits(size).ok() self.try_to_scalar_int()?.to_bits(size).ok()
} }
pub fn try_to_bool(&self) -> Option<bool> { pub fn try_to_bool(&self) -> Option<bool> {
match self.try_to_bits(Size::from_bytes(1))? { self.try_to_scalar_int()?.try_into().ok()
0 => Some(false),
1 => Some(true),
_ => None,
}
} }
pub fn try_to_machine_usize(&self, tcx: TyCtxt<'tcx>) -> Option<u64> { pub fn try_to_machine_usize(&self, tcx: TyCtxt<'tcx>) -> Option<u64> {
Some(self.try_to_bits(tcx.data_layout.pointer_size)? as u64) self.try_to_scalar_int()?.try_to_machine_usize(tcx).ok()
} }
pub fn try_to_bits_for_ty( pub fn try_to_bits_for_ty(
@ -505,6 +505,21 @@ fn from(ptr: Pointer<Tag>) -> Self {
} }
} }
impl TryFrom<Scalar> for ScalarInt {
type Error = super::InterpErrorInfo<'static>;
#[inline]
fn try_from(scalar: Scalar) -> InterpResult<'static, Self> {
scalar.to_int()
}
}
impl<Tag> From<ScalarInt> for Scalar<Tag> {
#[inline(always)]
fn from(ptr: ScalarInt) -> Self {
Scalar::Int(ptr)
}
}
#[derive(Clone, Copy, Eq, PartialEq, TyEncodable, TyDecodable, HashStable, Hash)] #[derive(Clone, Copy, Eq, PartialEq, TyEncodable, TyDecodable, HashStable, Hash)]
pub enum ScalarMaybeUninit<Tag = ()> { pub enum ScalarMaybeUninit<Tag = ()> {
Scalar(Scalar<Tag>), Scalar(Scalar<Tag>),

View File

@ -5,6 +5,8 @@
use std::convert::{TryFrom, TryInto}; use std::convert::{TryFrom, TryInto};
use std::fmt; use std::fmt;
use crate::ty::TyCtxt;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
/// A type for representing any integer. Only used for printing. /// A type for representing any integer. Only used for printing.
pub struct ConstInt { pub struct ConstInt {
@ -239,6 +241,11 @@ pub fn to_bits(self, target_size: Size) -> Result<u128, Size> {
Err(self.size()) Err(self.size())
} }
} }
#[inline]
pub fn try_to_machine_usize(&self, tcx: TyCtxt<'tcx>) -> Result<u64, Size> {
Ok(self.to_bits(tcx.data_layout.pointer_size)? as u64)
}
} }
macro_rules! from { macro_rules! from {
@ -277,6 +284,18 @@ fn try_from(int: ScalarInt) -> Result<Self, Size> {
from!(u8, u16, u32, u64, u128, bool); from!(u8, u16, u32, u64, u128, bool);
try_from!(u8, u16, u32, u64, u128); try_from!(u8, u16, u32, u64, u128);
impl TryFrom<ScalarInt> for bool {
type Error = Size;
#[inline]
fn try_from(int: ScalarInt) -> Result<Self, Size> {
int.to_bits(Size::from_bytes(1)).and_then(|u| match u {
0 => Ok(false),
1 => Ok(true),
_ => Err(Size::from_bytes(1)),
})
}
}
impl From<char> for ScalarInt { impl From<char> for ScalarInt {
#[inline] #[inline]
fn from(c: char) -> Self { fn from(c: char) -> Self {

View File

@ -1,3 +1,5 @@
use std::convert::TryInto;
use crate::mir::interpret::ConstValue; use crate::mir::interpret::ConstValue;
use crate::mir::interpret::Scalar; use crate::mir::interpret::Scalar;
use crate::mir::Promoted; use crate::mir::Promoted;
@ -9,6 +11,8 @@
use rustc_macros::HashStable; use rustc_macros::HashStable;
use rustc_target::abi::Size; use rustc_target::abi::Size;
use super::ScalarInt;
/// Represents a constant in Rust. /// Represents a constant in Rust.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)] #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)]
#[derive(HashStable)] #[derive(HashStable)]
@ -51,14 +55,19 @@ pub fn try_to_scalar(self) -> Option<Scalar> {
self.try_to_value()?.try_to_scalar() self.try_to_value()?.try_to_scalar()
} }
#[inline]
pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
self.try_to_value()?.try_to_scalar()?.to_int().ok()
}
#[inline] #[inline]
pub fn try_to_bits(self, size: Size) -> Option<u128> { pub fn try_to_bits(self, size: Size) -> Option<u128> {
self.try_to_value()?.try_to_bits(size) self.try_to_scalar_int()?.to_bits(size).ok()
} }
#[inline] #[inline]
pub fn try_to_bool(self) -> Option<bool> { pub fn try_to_bool(self) -> Option<bool> {
self.try_to_value()?.try_to_bool() self.try_to_scalar_int()?.try_into().ok()
} }
#[inline] #[inline]