}
}
- /// Do not call this method! Use either `assert_bits` or `force_bits`.
+ /// This method is intentionally private!
+ /// It is just a helper for other methods in this file.
#[inline]
- pub fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> {
+ fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> {
match self {
Scalar::Raw { data, size } => {
assert_eq!(target_size.bytes(), size as u64);
pub fn assert_ptr(self) -> Pointer<Tag> {
match self {
Scalar::Ptr(p) => p,
- Scalar::Raw { .. } => bug!("expected a Pointer but got Raw bits")
+ Scalar::Raw { .. } => bug!("expected a Pointer but got Raw bits"),
}
}
}
}
- /// Do not call this method! Use either `assert_bits` or `force_bits`.
- #[inline(always)]
- pub fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> {
- self.not_undef()?.to_bits(target_size)
- }
-
#[inline(always)]
pub fn to_bool(self) -> InterpResult<'tcx, bool> {
self.not_undef()?.to_bool()
impl<Tag: Copy> std::fmt::Display for ImmTy<'tcx, Tag> {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &self.imm {
- Immediate::Scalar(ScalarMaybeUndef::Scalar(s)) => match s.to_bits(self.layout.size) {
- Ok(s) => {
- match self.layout.ty.kind {
- ty::Int(_) => {
- return write!(
- fmt,
- "{}",
- super::sign_extend(s, self.layout.size) as i128,
- );
- }
- ty::Uint(_) => return write!(fmt, "{}", s),
- ty::Bool if s == 0 => return fmt.write_str("false"),
- ty::Bool if s == 1 => return fmt.write_str("true"),
- ty::Char => {
- if let Some(c) = u32::try_from(s).ok().and_then(std::char::from_u32) {
- return write!(fmt, "{}", c);
- }
+ // We cannot use `to_bits_or_ptr` as we do not have a `tcx`.
+ // So we use `is_bits` and circumvent a bunch of sanity checking -- but
+ // this is anyway only for printing.
+ Immediate::Scalar(ScalarMaybeUndef::Scalar(s)) if s.is_ptr() => {
+ fmt.write_str("{pointer}")
+ }
+ Immediate::Scalar(ScalarMaybeUndef::Scalar(s)) => {
+ let s = s.assert_bits(self.layout.size);
+ match self.layout.ty.kind {
+ ty::Int(_) => {
+ return write!(fmt, "{}", super::sign_extend(s, self.layout.size) as i128,);
+ }
+ ty::Uint(_) => return write!(fmt, "{}", s),
+ ty::Bool if s == 0 => return fmt.write_str("false"),
+ ty::Bool if s == 1 => return fmt.write_str("true"),
+ ty::Char => {
+ if let Some(c) = u32::try_from(s).ok().and_then(std::char::from_u32) {
+ return write!(fmt, "{}", c);
}
- ty::Float(ast::FloatTy::F32) => {
- if let Ok(u) = u32::try_from(s) {
- return write!(fmt, "{}", f32::from_bits(u));
- }
+ }
+ ty::Float(ast::FloatTy::F32) => {
+ if let Ok(u) = u32::try_from(s) {
+ return write!(fmt, "{}", f32::from_bits(u));
}
- ty::Float(ast::FloatTy::F64) => {
- if let Ok(u) = u64::try_from(s) {
- return write!(fmt, "{}", f64::from_bits(u));
- }
+ }
+ ty::Float(ast::FloatTy::F64) => {
+ if let Ok(u) = u64::try_from(s) {
+ return write!(fmt, "{}", f64::from_bits(u));
}
- _ => {}
}
- write!(fmt, "{:x}", s)
+ _ => {}
}
- Err(_) => fmt.write_str("{pointer}"),
- },
+ write!(fmt, "{:x}", s)
+ }
Immediate::Scalar(ScalarMaybeUndef::Undef) => fmt.write_str("{undef}"),
Immediate::ScalarPair(..) => fmt.write_str("{wide pointer or tuple}"),
}
pub fn from_int(i: impl Into<i128>, layout: TyLayout<'tcx>) -> Self {
Self::from_scalar(Scalar::from_int(i, layout.size), layout)
}
-
- #[inline]
- pub fn to_bits(self) -> InterpResult<'tcx, u128> {
- self.to_scalar()?.to_bits(self.layout.size)
- }
}
// Use the existing layout if given (but sanity check in debug mode),
ty::Float(_) | ty::Int(_) | ty::Uint(_) => {
// NOTE: Keep this in sync with the array optimization for int/float
// types below!
- let size = value.layout.size;
let value = value.to_scalar_or_undef();
if self.ref_tracking_for_consts.is_some() {
// Integers/floats in CTFE: Must be scalar bits, pointers are dangerous
- try_validation!(
- value.to_bits(size),
- value,
- self.path,
- "initialized plain (non-pointer) bytes"
- );
+ let is_bits = value.not_undef().map_or(false, |v| v.is_bits());
+ if !is_bits {
+ throw_validation_failure!(
+ value,
+ self.path,
+ "initialized plain (non-pointer) bytes"
+ )
+ }
} else {
// At run-time, for now, we accept *anything* for these types, including
// undef. We should fix that, but let's start low.