summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_middle/src/mir/interpret/value.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_middle/src/mir/interpret/value.rs')
-rw-r--r--compiler/rustc_middle/src/mir/interpret/value.rs134
1 files changed, 20 insertions, 114 deletions
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index 5345a6588..0d548f886 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -9,102 +9,9 @@ use rustc_apfloat::{
use rustc_macros::HashStable;
use rustc_target::abi::{HasDataLayout, Size};
-use crate::ty::{ParamEnv, ScalarInt, Ty, TyCtxt};
+use crate::ty::ScalarInt;
-use super::{
- AllocId, AllocRange, ConstAllocation, InterpResult, Pointer, PointerArithmetic, Provenance,
- ScalarSizeMismatch,
-};
-
-/// Represents the result of const evaluation via the `eval_to_allocation` query.
-#[derive(Copy, Clone, HashStable, TyEncodable, TyDecodable, Debug, Hash, Eq, PartialEq)]
-pub struct ConstAlloc<'tcx> {
- /// The value lives here, at offset 0, and that allocation definitely is an `AllocKind::Memory`
- /// (so you can use `AllocMap::unwrap_memory`).
- pub alloc_id: AllocId,
- pub ty: Ty<'tcx>,
-}
-
-/// Represents a constant value in Rust. `Scalar` and `Slice` are optimizations for
-/// array length computations, enum discriminants and the pattern matching logic.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Hash)]
-#[derive(HashStable, Lift)]
-pub enum ConstValue<'tcx> {
- /// Used only for types with `layout::abi::Scalar` ABI.
- ///
- /// Not using the enum `Value` to encode that this must not be `Uninit`.
- Scalar(Scalar),
-
- /// Only used for ZSTs.
- ZeroSized,
-
- /// Used only for `&[u8]` and `&str`
- Slice { data: ConstAllocation<'tcx>, start: usize, end: usize },
-
- /// A value not represented/representable by `Scalar` or `Slice`
- ByRef {
- /// The backing memory of the value, may contain more memory than needed for just the value
- /// in order to share `ConstAllocation`s between values
- alloc: ConstAllocation<'tcx>,
- /// Offset into `alloc`
- offset: Size,
- },
-}
-
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-static_assert_size!(ConstValue<'_>, 32);
-
-impl<'tcx> ConstValue<'tcx> {
- #[inline]
- pub fn try_to_scalar(&self) -> Option<Scalar<AllocId>> {
- match *self {
- ConstValue::ByRef { .. } | ConstValue::Slice { .. } | ConstValue::ZeroSized => None,
- ConstValue::Scalar(val) => Some(val),
- }
- }
-
- pub fn try_to_scalar_int(&self) -> Option<ScalarInt> {
- self.try_to_scalar()?.try_to_int().ok()
- }
-
- pub fn try_to_bits(&self, size: Size) -> Option<u128> {
- self.try_to_scalar_int()?.to_bits(size).ok()
- }
-
- pub fn try_to_bool(&self) -> Option<bool> {
- self.try_to_scalar_int()?.try_into().ok()
- }
-
- pub fn try_to_target_usize(&self, tcx: TyCtxt<'tcx>) -> Option<u64> {
- self.try_to_scalar_int()?.try_to_target_usize(tcx).ok()
- }
-
- pub fn try_to_bits_for_ty(
- &self,
- tcx: TyCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
- ty: Ty<'tcx>,
- ) -> Option<u128> {
- let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
- self.try_to_bits(size)
- }
-
- pub fn from_bool(b: bool) -> Self {
- ConstValue::Scalar(Scalar::from_bool(b))
- }
-
- pub fn from_u64(i: u64) -> Self {
- ConstValue::Scalar(Scalar::from_u64(i))
- }
-
- pub fn from_u128(i: u128) -> Self {
- ConstValue::Scalar(Scalar::from_u128(i))
- }
-
- pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self {
- ConstValue::Scalar(Scalar::from_target_usize(i, cx))
- }
-}
+use super::{AllocId, InterpResult, Pointer, PointerArithmetic, Provenance, ScalarSizeMismatch};
/// A `Scalar` represents an immediate, primitive value existing outside of a
/// `memory::Allocation`. It is in many ways like a small chunk of an `Allocation`, up to 16 bytes in
@@ -267,6 +174,16 @@ impl<Prov> Scalar<Prov> {
}
#[inline]
+ pub fn from_i8(i: i8) -> Self {
+ Self::from_int(i, Size::from_bits(8))
+ }
+
+ #[inline]
+ pub fn from_i16(i: i16) -> Self {
+ Self::from_int(i, Size::from_bits(16))
+ }
+
+ #[inline]
pub fn from_i32(i: i32) -> Self {
Self::from_int(i, Size::from_bits(32))
}
@@ -494,29 +411,18 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
}
#[inline]
- pub fn to_f32(self) -> InterpResult<'tcx, Single> {
- // Going through `u32` to check size and truncation.
- Ok(Single::from_bits(self.to_u32()?.into()))
+ pub fn to_float<F: Float>(self) -> InterpResult<'tcx, F> {
+ // Going through `to_uint` to check size and truncation.
+ Ok(F::from_bits(self.to_uint(Size::from_bits(F::BITS))?))
}
#[inline]
- pub fn to_f64(self) -> InterpResult<'tcx, Double> {
- // Going through `u64` to check size and truncation.
- Ok(Double::from_bits(self.to_u64()?.into()))
+ pub fn to_f32(self) -> InterpResult<'tcx, Single> {
+ self.to_float()
}
-}
-/// Gets the bytes of a constant slice value.
-pub fn get_slice_bytes<'tcx>(cx: &impl HasDataLayout, val: ConstValue<'tcx>) -> &'tcx [u8] {
- if let ConstValue::Slice { data, start, end } = val {
- let len = end - start;
- data.inner()
- .get_bytes_strip_provenance(
- cx,
- AllocRange { start: Size::from_bytes(start), size: Size::from_bytes(len) },
- )
- .unwrap_or_else(|err| bug!("const slice is invalid: {:?}", err))
- } else {
- bug!("expected const slice, but found another const value");
+ #[inline]
+ pub fn to_f64(self) -> InterpResult<'tcx, Double> {
+ self.to_float()
}
}