u128
truncation and sign extension are not just interpreter related
This commit is contained in:
parent
e67c768110
commit
abacaf2aef
18 changed files with 73 additions and 89 deletions
|
@ -585,10 +585,7 @@ fn codegen_stmt<'tcx>(
|
||||||
.discriminant_for_variant(fx.tcx, *index)
|
.discriminant_for_variant(fx.tcx, *index)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let discr = if discr.ty.is_signed() {
|
let discr = if discr.ty.is_signed() {
|
||||||
rustc_middle::mir::interpret::sign_extend(
|
fx.layout_of(discr.ty).size.sign_extend(discr.val)
|
||||||
discr.val,
|
|
||||||
fx.layout_of(discr.ty).size,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
discr.val
|
discr.val
|
||||||
};
|
};
|
||||||
|
|
|
@ -29,7 +29,6 @@ use rustc_hir::def::CtorKind;
|
||||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||||
use rustc_index::vec::{Idx, IndexVec};
|
use rustc_index::vec::{Idx, IndexVec};
|
||||||
use rustc_middle::ich::NodeIdHashingMode;
|
use rustc_middle::ich::NodeIdHashingMode;
|
||||||
use rustc_middle::mir::interpret::truncate;
|
|
||||||
use rustc_middle::mir::{self, Field, GeneratorLayout};
|
use rustc_middle::mir::{self, Field, GeneratorLayout};
|
||||||
use rustc_middle::ty::layout::{self, IntegerExt, PrimitiveExt, TyAndLayout};
|
use rustc_middle::ty::layout::{self, IntegerExt, PrimitiveExt, TyAndLayout};
|
||||||
use rustc_middle::ty::subst::GenericArgKind;
|
use rustc_middle::ty::subst::GenericArgKind;
|
||||||
|
@ -1693,7 +1692,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||||
let value = (i.as_u32() as u128)
|
let value = (i.as_u32() as u128)
|
||||||
.wrapping_sub(niche_variants.start().as_u32() as u128)
|
.wrapping_sub(niche_variants.start().as_u32() as u128)
|
||||||
.wrapping_add(niche_start);
|
.wrapping_add(niche_start);
|
||||||
let value = truncate(value, tag.value.size(cx));
|
let value = tag.value.size(cx).truncate(value);
|
||||||
// NOTE(eddyb) do *NOT* remove this assert, until
|
// NOTE(eddyb) do *NOT* remove this assert, until
|
||||||
// we pass the full 128-bit value to LLVM, otherwise
|
// we pass the full 128-bit value to LLVM, otherwise
|
||||||
// truncation will be silent and remain undetected.
|
// truncation will be silent and remain undetected.
|
||||||
|
|
|
@ -6,7 +6,6 @@ use rustc_errors::Applicability;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::{is_range_literal, ExprKind, Node};
|
use rustc_hir::{is_range_literal, ExprKind, Node};
|
||||||
use rustc_index::vec::Idx;
|
use rustc_index::vec::Idx;
|
||||||
use rustc_middle::mir::interpret::{sign_extend, truncate};
|
|
||||||
use rustc_middle::ty::layout::{IntegerExt, SizeSkeleton};
|
use rustc_middle::ty::layout::{IntegerExt, SizeSkeleton};
|
||||||
use rustc_middle::ty::subst::SubstsRef;
|
use rustc_middle::ty::subst::SubstsRef;
|
||||||
use rustc_middle::ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable};
|
use rustc_middle::ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable};
|
||||||
|
@ -218,11 +217,11 @@ fn report_bin_hex_error(
|
||||||
cx.struct_span_lint(OVERFLOWING_LITERALS, expr.span, |lint| {
|
cx.struct_span_lint(OVERFLOWING_LITERALS, expr.span, |lint| {
|
||||||
let (t, actually) = match ty {
|
let (t, actually) = match ty {
|
||||||
attr::IntType::SignedInt(t) => {
|
attr::IntType::SignedInt(t) => {
|
||||||
let actually = sign_extend(val, size) as i128;
|
let actually = size.sign_extend(val) as i128;
|
||||||
(t.name_str(), actually.to_string())
|
(t.name_str(), actually.to_string())
|
||||||
}
|
}
|
||||||
attr::IntType::UnsignedInt(t) => {
|
attr::IntType::UnsignedInt(t) => {
|
||||||
let actually = truncate(val, size);
|
let actually = size.truncate(val);
|
||||||
(t.name_str(), actually.to_string())
|
(t.name_str(), actually.to_string())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -110,7 +110,7 @@ use rustc_hir::def_id::DefId;
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||||
use rustc_serialize::{Decodable, Encodable};
|
use rustc_serialize::{Decodable, Encodable};
|
||||||
use rustc_target::abi::{Endian, Size};
|
use rustc_target::abi::Endian;
|
||||||
|
|
||||||
use crate::mir;
|
use crate::mir;
|
||||||
use crate::ty::codec::{TyDecoder, TyEncoder};
|
use crate::ty::codec::{TyDecoder, TyEncoder};
|
||||||
|
@ -590,39 +590,6 @@ pub fn read_target_uint(endianness: Endian, mut source: &[u8]) -> Result<u128, i
|
||||||
uint
|
uint
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Methods to facilitate working with signed integers stored in a u128
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/// Truncates `value` to `size` bits and then sign-extend it to 128 bits
|
|
||||||
/// (i.e., if it is negative, fill with 1's on the left).
|
|
||||||
#[inline]
|
|
||||||
pub fn sign_extend(value: u128, size: Size) -> u128 {
|
|
||||||
let size = size.bits();
|
|
||||||
if size == 0 {
|
|
||||||
// Truncated until nothing is left.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
// Sign-extend it.
|
|
||||||
let shift = 128 - size;
|
|
||||||
// Shift the unsigned value to the left, then shift back to the right as signed
|
|
||||||
// (essentially fills with FF on the left).
|
|
||||||
(((value << shift) as i128) >> shift) as u128
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Truncates `value` to `size` bits.
|
|
||||||
#[inline]
|
|
||||||
pub fn truncate(value: u128, size: Size) -> u128 {
|
|
||||||
let size = size.bits();
|
|
||||||
if size == 0 {
|
|
||||||
// Truncated until nothing is left.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
let shift = 128 - size;
|
|
||||||
// Truncate (shift left to drop out leftover values, shift right to fill with zeroes).
|
|
||||||
(value << shift) >> shift
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Computes the unsigned absolute value without wrapping or panicking.
|
/// Computes the unsigned absolute value without wrapping or panicking.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn uabs(value: i64) -> u64 {
|
pub fn uabs(value: i64) -> u64 {
|
||||||
|
|
|
@ -10,7 +10,7 @@ use rustc_target::abi::{HasDataLayout, Size, TargetDataLayout};
|
||||||
|
|
||||||
use crate::ty::{ParamEnv, ScalarInt, Ty, TyCtxt};
|
use crate::ty::{ParamEnv, ScalarInt, Ty, TyCtxt};
|
||||||
|
|
||||||
use super::{sign_extend, AllocId, Allocation, InterpResult, Pointer, PointerArithmetic};
|
use super::{AllocId, Allocation, InterpResult, Pointer, PointerArithmetic};
|
||||||
|
|
||||||
/// Represents the result of const evaluation via the `eval_to_allocation` query.
|
/// Represents the result of const evaluation via the `eval_to_allocation` query.
|
||||||
#[derive(Clone, HashStable, TyEncodable, TyDecodable)]
|
#[derive(Clone, HashStable, TyEncodable, TyDecodable)]
|
||||||
|
@ -448,7 +448,7 @@ impl<'tcx, Tag> Scalar<Tag> {
|
||||||
fn to_signed_with_bit_width(self, bits: u64) -> InterpResult<'static, i128> {
|
fn to_signed_with_bit_width(self, bits: u64) -> InterpResult<'static, i128> {
|
||||||
let sz = Size::from_bits(bits);
|
let sz = Size::from_bits(bits);
|
||||||
let b = self.to_bits(sz)?;
|
let b = self.to_bits(sz)?;
|
||||||
Ok(sign_extend(b, sz) as i128)
|
Ok(sz.sign_extend(b) as i128)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts the scalar to produce an `i8`. Fails if the scalar is a pointer.
|
/// Converts the scalar to produce an `i8`. Fails if the scalar is a pointer.
|
||||||
|
@ -479,7 +479,7 @@ impl<'tcx, Tag> Scalar<Tag> {
|
||||||
pub fn to_machine_isize(self, cx: &impl HasDataLayout) -> InterpResult<'static, i64> {
|
pub fn to_machine_isize(self, cx: &impl HasDataLayout) -> InterpResult<'static, i64> {
|
||||||
let sz = cx.data_layout().pointer_size;
|
let sz = cx.data_layout().pointer_size;
|
||||||
let b = self.to_bits(sz)?;
|
let b = self.to_bits(sz)?;
|
||||||
let b = sign_extend(b, sz) as i128;
|
let b = sz.sign_extend(b) as i128;
|
||||||
Ok(i64::try_from(b).unwrap())
|
Ok(i64::try_from(b).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::mir::interpret::{sign_extend, truncate, InterpResult};
|
use crate::mir::interpret::InterpResult;
|
||||||
use rustc_apfloat::ieee::{Double, Single};
|
use rustc_apfloat::ieee::{Double, Single};
|
||||||
use rustc_apfloat::Float;
|
use rustc_apfloat::Float;
|
||||||
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
||||||
|
@ -75,7 +75,7 @@ impl std::fmt::Debug for ConstInt {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let max = truncate(u128::MAX, Size::from_bytes(size));
|
let max = Size::from_bytes(size).truncate(u128::MAX);
|
||||||
if raw == max {
|
if raw == max {
|
||||||
match (size, is_ptr_sized_integral) {
|
match (size, is_ptr_sized_integral) {
|
||||||
(_, true) => write!(fmt, "usize::MAX"),
|
(_, true) => write!(fmt, "usize::MAX"),
|
||||||
|
@ -174,7 +174,7 @@ impl ScalarInt {
|
||||||
// is a packed struct, that would create a possibly unaligned reference, which
|
// is a packed struct, that would create a possibly unaligned reference, which
|
||||||
// is UB.
|
// is UB.
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(
|
||||||
truncate(self.data, self.size()),
|
self.size().truncate(self.data),
|
||||||
{ self.data },
|
{ self.data },
|
||||||
"Scalar value {:#x} exceeds size of {} bytes",
|
"Scalar value {:#x} exceeds size of {} bytes",
|
||||||
{ self.data },
|
{ self.data },
|
||||||
|
@ -204,7 +204,7 @@ impl ScalarInt {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_from_uint(i: impl Into<u128>, size: Size) -> Option<Self> {
|
pub fn try_from_uint(i: impl Into<u128>, size: Size) -> Option<Self> {
|
||||||
let data = i.into();
|
let data = i.into();
|
||||||
if truncate(data, size) == data {
|
if size.truncate(data) == data {
|
||||||
Some(Self { data, size: size.bytes() as u8 })
|
Some(Self { data, size: size.bytes() as u8 })
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -215,8 +215,8 @@ impl ScalarInt {
|
||||||
pub fn try_from_int(i: impl Into<i128>, size: Size) -> Option<Self> {
|
pub fn try_from_int(i: impl Into<i128>, size: Size) -> Option<Self> {
|
||||||
let i = i.into();
|
let i = i.into();
|
||||||
// `into` performed sign extension, we have to truncate
|
// `into` performed sign extension, we have to truncate
|
||||||
let truncated = truncate(i as u128, size);
|
let truncated = size.truncate(i as u128);
|
||||||
if sign_extend(truncated, size) as i128 == i {
|
if size.sign_extend(truncated) as i128 == i {
|
||||||
Some(Self { data: truncated, size: size.bytes() as u8 })
|
Some(Self { data: truncated, size: size.bytes() as u8 })
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
use crate::ich::NodeIdHashingMode;
|
use crate::ich::NodeIdHashingMode;
|
||||||
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||||
use crate::mir::interpret::{sign_extend, truncate};
|
|
||||||
use crate::ty::fold::TypeFolder;
|
use crate::ty::fold::TypeFolder;
|
||||||
use crate::ty::layout::IntegerExt;
|
use crate::ty::layout::IntegerExt;
|
||||||
use crate::ty::query::TyCtxtAt;
|
use crate::ty::query::TyCtxtAt;
|
||||||
|
@ -38,7 +37,7 @@ impl<'tcx> fmt::Display for Discr<'tcx> {
|
||||||
let size = ty::tls::with(|tcx| Integer::from_attr(&tcx, SignedInt(ity)).size());
|
let size = ty::tls::with(|tcx| Integer::from_attr(&tcx, SignedInt(ity)).size());
|
||||||
let x = self.val;
|
let x = self.val;
|
||||||
// sign extend the raw representation to be an i128
|
// sign extend the raw representation to be an i128
|
||||||
let x = sign_extend(x, size) as i128;
|
let x = size.sign_extend(x) as i128;
|
||||||
write!(fmt, "{}", x)
|
write!(fmt, "{}", x)
|
||||||
}
|
}
|
||||||
_ => write!(fmt, "{}", self.val),
|
_ => write!(fmt, "{}", self.val),
|
||||||
|
@ -47,7 +46,7 @@ impl<'tcx> fmt::Display for Discr<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signed_min(size: Size) -> i128 {
|
fn signed_min(size: Size) -> i128 {
|
||||||
sign_extend(1_u128 << (size.bits() - 1), size) as i128
|
size.sign_extend(1_u128 << (size.bits() - 1)) as i128
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signed_max(size: Size) -> i128 {
|
fn signed_max(size: Size) -> i128 {
|
||||||
|
@ -77,14 +76,14 @@ impl<'tcx> Discr<'tcx> {
|
||||||
let (val, oflo) = if signed {
|
let (val, oflo) = if signed {
|
||||||
let min = signed_min(size);
|
let min = signed_min(size);
|
||||||
let max = signed_max(size);
|
let max = signed_max(size);
|
||||||
let val = sign_extend(self.val, size) as i128;
|
let val = size.sign_extend(self.val) as i128;
|
||||||
assert!(n < (i128::MAX as u128));
|
assert!(n < (i128::MAX as u128));
|
||||||
let n = n as i128;
|
let n = n as i128;
|
||||||
let oflo = val > max - n;
|
let oflo = val > max - n;
|
||||||
let val = if oflo { min + (n - (max - val) - 1) } else { val + n };
|
let val = if oflo { min + (n - (max - val) - 1) } else { val + n };
|
||||||
// zero the upper bits
|
// zero the upper bits
|
||||||
let val = val as u128;
|
let val = val as u128;
|
||||||
let val = truncate(val, size);
|
let val = size.truncate(val);
|
||||||
(val, oflo)
|
(val, oflo)
|
||||||
} else {
|
} else {
|
||||||
let max = unsigned_max(size);
|
let max = unsigned_max(size);
|
||||||
|
@ -650,7 +649,7 @@ impl<'tcx> ty::TyS<'tcx> {
|
||||||
let val = match self.kind() {
|
let val = match self.kind() {
|
||||||
ty::Int(_) | ty::Uint(_) => {
|
ty::Int(_) | ty::Uint(_) => {
|
||||||
let (size, signed) = int_size_and_signed(tcx, self);
|
let (size, signed) = int_size_and_signed(tcx, self);
|
||||||
let val = if signed { truncate(signed_min(size) as u128, size) } else { 0 };
|
let val = if signed { size.truncate(signed_min(size) as u128) } else { 0 };
|
||||||
Some(val)
|
Some(val)
|
||||||
}
|
}
|
||||||
ty::Char => Some(0),
|
ty::Char => Some(0),
|
||||||
|
|
|
@ -13,8 +13,7 @@ use rustc_span::symbol::sym;
|
||||||
use rustc_target::abi::{Integer, LayoutOf, Variants};
|
use rustc_target::abi::{Integer, LayoutOf, Variants};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
truncate, util::ensure_monomorphic_enough, FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy,
|
util::ensure_monomorphic_enough, FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy, PlaceTy,
|
||||||
PlaceTy,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
|
@ -209,7 +208,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
RawPtr(_) => self.pointer_size(),
|
RawPtr(_) => self.pointer_size(),
|
||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
};
|
};
|
||||||
let v = truncate(v, size);
|
let v = size.truncate(v);
|
||||||
Scalar::from_uint(v, size)
|
Scalar::from_uint(v, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,7 @@ use rustc_index::vec::IndexVec;
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
use rustc_middle::ich::StableHashingContext;
|
use rustc_middle::ich::StableHashingContext;
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_middle::mir::interpret::{
|
use rustc_middle::mir::interpret::{GlobalId, InterpResult, Pointer, Scalar};
|
||||||
sign_extend, truncate, GlobalId, InterpResult, Pointer, Scalar,
|
|
||||||
};
|
|
||||||
use rustc_middle::ty::layout::{self, TyAndLayout};
|
use rustc_middle::ty::layout::{self, TyAndLayout};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
|
self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
|
||||||
|
@ -443,12 +441,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn sign_extend(&self, value: u128, ty: TyAndLayout<'_>) -> u128 {
|
pub fn sign_extend(&self, value: u128, ty: TyAndLayout<'_>) -> u128 {
|
||||||
assert!(ty.abi.is_signed());
|
assert!(ty.abi.is_signed());
|
||||||
sign_extend(value, ty.size)
|
ty.size.sign_extend(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn truncate(&self, value: u128, ty: TyAndLayout<'_>) -> u128 {
|
pub fn truncate(&self, value: u128, ty: TyAndLayout<'_>) -> u128 {
|
||||||
truncate(value, ty.size)
|
ty.size.truncate(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -14,9 +14,9 @@ use rustc_target::abi::{Abi, Align, FieldsShape, TagEncoding};
|
||||||
use rustc_target::abi::{HasDataLayout, LayoutOf, Size, VariantIdx, Variants};
|
use rustc_target::abi::{HasDataLayout, LayoutOf, Size, VariantIdx, Variants};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
mir_assign_valid_types, truncate, AllocId, AllocMap, Allocation, AllocationExtra, ConstAlloc,
|
mir_assign_valid_types, AllocId, AllocMap, Allocation, AllocationExtra, ConstAlloc, ImmTy,
|
||||||
ImmTy, Immediate, InterpCx, InterpResult, LocalValue, Machine, MemoryKind, OpTy, Operand,
|
Immediate, InterpCx, InterpResult, LocalValue, Machine, MemoryKind, OpTy, Operand, Pointer,
|
||||||
Pointer, PointerArithmetic, Scalar, ScalarMaybeUninit,
|
PointerArithmetic, Scalar, ScalarMaybeUninit,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
|
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
|
||||||
|
@ -1073,7 +1073,7 @@ where
|
||||||
// their computation, but the in-memory tag is the smallest possible
|
// their computation, but the in-memory tag is the smallest possible
|
||||||
// representation
|
// representation
|
||||||
let size = tag_layout.value.size(self);
|
let size = tag_layout.value.size(self);
|
||||||
let tag_val = truncate(discr_val, size);
|
let tag_val = size.truncate(discr_val);
|
||||||
|
|
||||||
let tag_dest = self.place_field(dest, tag_field)?;
|
let tag_dest = self.place_field(dest, tag_field)?;
|
||||||
self.write_scalar(Scalar::from_uint(tag_val, size), tag_dest)?;
|
self.write_scalar(Scalar::from_uint(tag_val, size), tag_dest)?;
|
||||||
|
|
|
@ -29,10 +29,9 @@ use rustc_trait_selection::traits;
|
||||||
|
|
||||||
use crate::const_eval::ConstEvalErr;
|
use crate::const_eval::ConstEvalErr;
|
||||||
use crate::interpret::{
|
use crate::interpret::{
|
||||||
self, compile_time_machine, truncate, AllocId, Allocation, ConstValue, CtfeValidationMode,
|
self, compile_time_machine, AllocId, Allocation, ConstValue, CtfeValidationMode, Frame, ImmTy,
|
||||||
Frame, ImmTy, Immediate, InterpCx, InterpResult, LocalState, LocalValue, MemPlace, Memory,
|
Immediate, InterpCx, InterpResult, LocalState, LocalValue, MemPlace, Memory, MemoryKind, OpTy,
|
||||||
MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, Pointer, Scalar, ScalarMaybeUninit,
|
Operand as InterpOperand, PlaceTy, Pointer, Scalar, ScalarMaybeUninit, StackPopCleanup,
|
||||||
StackPopCleanup,
|
|
||||||
};
|
};
|
||||||
use crate::transform::MirPass;
|
use crate::transform::MirPass;
|
||||||
|
|
||||||
|
@ -746,7 +745,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BinOp::BitOr => {
|
BinOp::BitOr => {
|
||||||
if arg_value == truncate(u128::MAX, const_arg.layout.size)
|
if arg_value == const_arg.layout.size.truncate(u128::MAX)
|
||||||
|| (const_arg.layout.ty.is_bool() && arg_value == 1)
|
|| (const_arg.layout.ty.is_bool() && arg_value == 1)
|
||||||
{
|
{
|
||||||
this.ecx.write_immediate(*const_arg, dest)?;
|
this.ecx.write_immediate(*const_arg, dest)?;
|
||||||
|
|
|
@ -17,7 +17,6 @@ use crate::build::Builder;
|
||||||
use crate::thir::{self, *};
|
use crate::thir::{self, *};
|
||||||
use rustc_attr::{SignedInt, UnsignedInt};
|
use rustc_attr::{SignedInt, UnsignedInt};
|
||||||
use rustc_hir::RangeEnd;
|
use rustc_hir::RangeEnd;
|
||||||
use rustc_middle::mir::interpret::truncate;
|
|
||||||
use rustc_middle::mir::Place;
|
use rustc_middle::mir::Place;
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_middle::ty::layout::IntegerExt;
|
use rustc_middle::ty::layout::IntegerExt;
|
||||||
|
@ -161,13 +160,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
ty::Int(ity) => {
|
ty::Int(ity) => {
|
||||||
let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
|
let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
|
||||||
let max = truncate(u128::MAX, size);
|
let max = size.truncate(u128::MAX);
|
||||||
let bias = 1u128 << (size.bits() - 1);
|
let bias = 1u128 << (size.bits() - 1);
|
||||||
(Some((0, max, size)), bias)
|
(Some((0, max, size)), bias)
|
||||||
}
|
}
|
||||||
ty::Uint(uty) => {
|
ty::Uint(uty) => {
|
||||||
let size = Integer::from_attr(&tcx, UnsignedInt(uty)).size();
|
let size = Integer::from_attr(&tcx, UnsignedInt(uty)).size();
|
||||||
let max = truncate(u128::MAX, size);
|
let max = size.truncate(u128::MAX);
|
||||||
(Some((0, max, size)), 0)
|
(Some((0, max, size)), 0)
|
||||||
}
|
}
|
||||||
_ => (None, 0),
|
_ => (None, 0),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_middle::mir::interpret::{
|
use rustc_middle::mir::interpret::{
|
||||||
truncate, Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
|
Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::{self, ParamEnv, TyCtxt};
|
use rustc_middle::ty::{self, ParamEnv, TyCtxt};
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
|
@ -16,7 +16,7 @@ crate fn lit_to_const<'tcx>(
|
||||||
let param_ty = ParamEnv::reveal_all().and(ty);
|
let param_ty = ParamEnv::reveal_all().and(ty);
|
||||||
let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
|
let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
|
||||||
trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
|
trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
|
||||||
let result = truncate(n, width);
|
let result = width.truncate(n);
|
||||||
trace!("trunc result: {}", result);
|
trace!("trunc result: {}", result);
|
||||||
Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
|
Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
|
||||||
};
|
};
|
||||||
|
|
|
@ -304,7 +304,7 @@ use rustc_arena::TypedArena;
|
||||||
use rustc_attr::{SignedInt, UnsignedInt};
|
use rustc_attr::{SignedInt, UnsignedInt};
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::{HirId, RangeEnd};
|
use rustc_hir::{HirId, RangeEnd};
|
||||||
use rustc_middle::mir::interpret::{truncate, ConstValue};
|
use rustc_middle::mir::interpret::ConstValue;
|
||||||
use rustc_middle::mir::Field;
|
use rustc_middle::mir::Field;
|
||||||
use rustc_middle::ty::layout::IntegerExt;
|
use rustc_middle::ty::layout::IntegerExt;
|
||||||
use rustc_middle::ty::{self, Const, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Const, Ty, TyCtxt};
|
||||||
|
@ -1608,7 +1608,7 @@ fn all_constructors<'p, 'tcx>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Vec<Constructor<'tc
|
||||||
}
|
}
|
||||||
&ty::Uint(uty) => {
|
&ty::Uint(uty) => {
|
||||||
let size = Integer::from_attr(&cx.tcx, UnsignedInt(uty)).size();
|
let size = Integer::from_attr(&cx.tcx, UnsignedInt(uty)).size();
|
||||||
let max = truncate(u128::MAX, size);
|
let max = size.truncate(u128::MAX);
|
||||||
vec![make_range(0, max)]
|
vec![make_range(0, max)]
|
||||||
}
|
}
|
||||||
_ if cx.is_uninhabited(pcx.ty) => vec![],
|
_ if cx.is_uninhabited(pcx.ty) => vec![],
|
||||||
|
|
|
@ -15,7 +15,7 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
|
||||||
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
|
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
|
||||||
use rustc_hir::RangeEnd;
|
use rustc_hir::RangeEnd;
|
||||||
use rustc_index::vec::Idx;
|
use rustc_index::vec::Idx;
|
||||||
use rustc_middle::mir::interpret::{get_slice_bytes, sign_extend, ConstValue};
|
use rustc_middle::mir::interpret::{get_slice_bytes, ConstValue};
|
||||||
use rustc_middle::mir::interpret::{ErrorHandled, LitToConstError, LitToConstInput};
|
use rustc_middle::mir::interpret::{ErrorHandled, LitToConstError, LitToConstInput};
|
||||||
use rustc_middle::mir::UserTypeProjection;
|
use rustc_middle::mir::UserTypeProjection;
|
||||||
use rustc_middle::mir::{BorrowKind, Field, Mutability};
|
use rustc_middle::mir::{BorrowKind, Field, Mutability};
|
||||||
|
@ -1082,8 +1082,8 @@ crate fn compare_const_vals<'tcx>(
|
||||||
use rustc_attr::SignedInt;
|
use rustc_attr::SignedInt;
|
||||||
use rustc_middle::ty::layout::IntegerExt;
|
use rustc_middle::ty::layout::IntegerExt;
|
||||||
let size = rustc_target::abi::Integer::from_attr(&tcx, SignedInt(ity)).size();
|
let size = rustc_target::abi::Integer::from_attr(&tcx, SignedInt(ity)).size();
|
||||||
let a = sign_extend(a, size);
|
let a = size.sign_extend(a);
|
||||||
let b = sign_extend(b, size);
|
let b = size.sign_extend(b);
|
||||||
Some((a as i128).cmp(&(b as i128)))
|
Some((a as i128).cmp(&(b as i128)))
|
||||||
}
|
}
|
||||||
_ => Some(a.cmp(&b)),
|
_ => Some(a.cmp(&b)),
|
||||||
|
|
|
@ -4,7 +4,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::{CrateNum, DefId};
|
use rustc_hir::def_id::{CrateNum, DefId};
|
||||||
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
|
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
|
||||||
use rustc_middle::mir::interpret::sign_extend;
|
|
||||||
use rustc_middle::ty::print::{Print, Printer};
|
use rustc_middle::ty::print::{Print, Printer};
|
||||||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
|
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
|
||||||
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable};
|
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable};
|
||||||
|
@ -527,7 +526,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
|
||||||
let param_env = ty::ParamEnv::reveal_all();
|
let param_env = ty::ParamEnv::reveal_all();
|
||||||
ct.try_eval_bits(self.tcx, param_env, ct.ty).and_then(|b| {
|
ct.try_eval_bits(self.tcx, param_env, ct.ty).and_then(|b| {
|
||||||
let sz = self.tcx.layout_of(param_env.and(ct.ty)).ok()?.size;
|
let sz = self.tcx.layout_of(param_env.and(ct.ty)).ok()?.size;
|
||||||
let val = sign_extend(b, sz) as i128;
|
let val = sz.sign_extend(b) as i128;
|
||||||
if val < 0 {
|
if val < 0 {
|
||||||
neg = true;
|
neg = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -306,6 +306,35 @@ impl Size {
|
||||||
let bytes = self.bytes().checked_mul(count)?;
|
let bytes = self.bytes().checked_mul(count)?;
|
||||||
if bytes < dl.obj_size_bound() { Some(Size::from_bytes(bytes)) } else { None }
|
if bytes < dl.obj_size_bound() { Some(Size::from_bytes(bytes)) } else { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Truncates `value` to `self` bits and then sign-extend it to 128 bits
|
||||||
|
/// (i.e., if it is negative, fill with 1's on the left).
|
||||||
|
#[inline]
|
||||||
|
pub fn sign_extend(self, value: u128) -> u128 {
|
||||||
|
let size = self.bits();
|
||||||
|
if size == 0 {
|
||||||
|
// Truncated until nothing is left.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// Sign-extend it.
|
||||||
|
let shift = 128 - size;
|
||||||
|
// Shift the unsigned value to the left, then shift back to the right as signed
|
||||||
|
// (essentially fills with FF on the left).
|
||||||
|
(((value << shift) as i128) >> shift) as u128
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Truncates `value` to `self` bits.
|
||||||
|
#[inline]
|
||||||
|
pub fn truncate(self, value: u128) -> u128 {
|
||||||
|
let size = self.bits();
|
||||||
|
if size == 0 {
|
||||||
|
// Truncated until nothing is left.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
let shift = 128 - size;
|
||||||
|
// Truncate (shift left to drop out leftover values, shift right to fill with zeroes).
|
||||||
|
(value << shift) >> shift
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Panicking addition, subtraction and multiplication for convenience.
|
// Panicking addition, subtraction and multiplication for convenience.
|
||||||
|
|
|
@ -14,7 +14,7 @@ use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||||
use rustc_middle::mir::interpret::{sign_extend, ConstValue};
|
use rustc_middle::mir::interpret::ConstValue;
|
||||||
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
|
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
|
||||||
use rustc_middle::ty::{self, DefIdTree, Ty};
|
use rustc_middle::ty::{self, DefIdTree, Ty};
|
||||||
use rustc_span::symbol::{kw, sym, Symbol};
|
use rustc_span::symbol::{kw, sym, Symbol};
|
||||||
|
@ -506,7 +506,7 @@ fn print_const_with_custom_print_scalar(cx: &DocContext<'_>, ct: &'tcx ty::Const
|
||||||
let ty = cx.tcx.lift(ct.ty).unwrap();
|
let ty = cx.tcx.lift(ct.ty).unwrap();
|
||||||
let size = cx.tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
|
let size = cx.tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
|
||||||
let data = int.assert_bits(size);
|
let data = int.assert_bits(size);
|
||||||
let sign_extended_data = sign_extend(data, size) as i128;
|
let sign_extended_data = size.sign_extend(data) as i128;
|
||||||
|
|
||||||
format!(
|
format!(
|
||||||
"{}{}",
|
"{}{}",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue