Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactorings in preparation for const value trees #77227

Merged
merged 26 commits into from
Nov 4, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
362123d
Split the "raw integer bytes" part out of `Scalar`
oli-obk Sep 26, 2020
eac3099
Encode `ScalarInt::bytes` as `u128` instead of `[u8; 16]` to see if t…
oli-obk Oct 1, 2020
ed7a4ad
32 bit platforms don't have 64 bit pointers
oli-obk Oct 1, 2020
02131f4
Use packed struct instead of manually packing into an array
oli-obk Oct 29, 2020
c478574
Explain the use of blocks around `self.data` accesses
oli-obk Oct 29, 2020
3a79708
Fix cranelift build
oli-obk Oct 29, 2020
df4d717
s/Scalar::Raw/Scalar::Int
oli-obk Nov 1, 2020
e5258e6
Remove outdated FIXME
oli-obk Nov 1, 2020
1eb300e
Unaligned reads are UB in Rust irrelevant on which platform we are
oli-obk Nov 1, 2020
3ef9dfd
Update comment
oli-obk Nov 1, 2020
b8751c1
No need for a `zst` constructor method when we can have a constant
oli-obk Nov 1, 2020
8282d52
Replace `Scalar::zst` with a `Scalar::ZST` constant
oli-obk Nov 1, 2020
d1074ed
catch conversion errors during `ptr_sized_op`
oli-obk Nov 1, 2020
0347ca7
Explain why we forward to self-printing during self-printing
oli-obk Nov 1, 2020
f03b18b
Add `is_null` helper
oli-obk Nov 1, 2020
500af76
Add helper for getting an `int` out of a `Scalar`
oli-obk Nov 1, 2020
dad0036
Do not raise interp errors from the scalar int module
oli-obk Nov 1, 2020
98b70c9
Simplify `assert_bits` impl
oli-obk Nov 1, 2020
cb1cf6a
Update compiler/rustc_middle/src/ty/consts/int.rs
oli-obk Nov 2, 2020
e67c768
Move ZST constant to the top of the impl block
oli-obk Nov 2, 2020
abacaf2
`u128` truncation and sign extension are not just interpreter related
oli-obk Nov 4, 2020
2e53625
Document an `unwrap`
oli-obk Nov 4, 2020
97bfff1
Make `ScalarInt` entirely independent of MIR interpretation
oli-obk Nov 4, 2020
6e6c8a8
`u64::try_from` will now fail if `ScalarInt` isn't exactly 64 bits, t…
oli-obk Nov 4, 2020
5f087f0
Update compiler/rustc_target/src/abi/mod.rs
oli-obk Nov 4, 2020
332750f
Update compiler/rustc_target/src/abi/mod.rs
oli-obk Nov 4, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions compiler/rustc_codegen_cranelift/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -585,10 +585,7 @@ fn codegen_stmt<'tcx>(
.discriminant_for_variant(fx.tcx, *index)
.unwrap();
let discr = if discr.ty.is_signed() {
rustc_middle::mir::interpret::sign_extend(
discr.val,
fx.layout_of(discr.ty).size,
)
fx.layout_of(discr.ty).size.sign_extend(discr.val)
} else {
discr.val
};
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/value_and_place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ impl<'tcx> CValue<'tcx> {
fx
.bcx
.ins()
.iconst(clif_ty, u64::try_from(const_val).expect("uint") as i64)
.iconst(clif_ty, const_val.to_bits(layout.size).unwrap() as i64)
}
ty::Float(FloatTy::F32) => {
fx.bcx.ins().f32const(Ieee32::with_bits(u32::try_from(const_val).unwrap()))
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ use rustc_hir::def::CtorKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::ich::NodeIdHashingMode;
use rustc_middle::mir::interpret::truncate;
use rustc_middle::mir::{self, Field, GeneratorLayout};
use rustc_middle::ty::layout::{self, IntegerExt, PrimitiveExt, TyAndLayout};
use rustc_middle::ty::subst::GenericArgKind;
Expand Down Expand Up @@ -1693,7 +1692,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
let value = (i.as_u32() as u128)
.wrapping_sub(niche_variants.start().as_u32() as u128)
.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
// we pass the full 128-bit value to LLVM, otherwise
// truncation will be silent and remain undetected.
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::{is_range_literal, ExprKind, Node};
use rustc_index::vec::Idx;
use rustc_middle::mir::interpret::{sign_extend, truncate};
use rustc_middle::ty::layout::{IntegerExt, SizeSkeleton};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable};
Expand Down Expand Up @@ -218,11 +217,11 @@ fn report_bin_hex_error(
cx.struct_span_lint(OVERFLOWING_LITERALS, expr.span, |lint| {
let (t, actually) = match ty {
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())
}
attr::IntType::UnsignedInt(t) => {
let actually = truncate(val, size);
let actually = size.truncate(val);
(t.name_str(), actually.to_string())
}
};
Expand Down
35 changes: 1 addition & 34 deletions compiler/rustc_middle/src/mir/interpret/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_serialize::{Decodable, Encodable};
use rustc_target::abi::{Endian, Size};
use rustc_target::abi::Endian;

use crate::mir;
use crate::ty::codec::{TyDecoder, TyEncoder};
Expand Down Expand Up @@ -590,39 +590,6 @@ pub fn read_target_uint(endianness: Endian, mut source: &[u8]) -> Result<u128, i
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.
#[inline]
pub fn uabs(value: i64) -> u64 {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_middle/src/mir/interpret/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use rustc_target::abi::{HasDataLayout, Size, TargetDataLayout};

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.
#[derive(Clone, HashStable, TyEncodable, TyDecodable)]
Expand Down Expand Up @@ -448,7 +448,7 @@ impl<'tcx, Tag> Scalar<Tag> {
fn to_signed_with_bit_width(self, bits: u64) -> InterpResult<'static, i128> {
let sz = Size::from_bits(bits);
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.
Expand Down Expand Up @@ -479,7 +479,7 @@ impl<'tcx, Tag> Scalar<Tag> {
pub fn to_machine_isize(self, cx: &impl HasDataLayout) -> InterpResult<'static, i64> {
let sz = cx.data_layout().pointer_size;
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())
}

Expand Down
22 changes: 12 additions & 10 deletions compiler/rustc_middle/src/ty/consts/int.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::mir::interpret::{sign_extend, truncate, InterpResult};
use rustc_apfloat::ieee::{Double, Single};
use rustc_apfloat::Float;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
Expand Down Expand Up @@ -75,7 +74,7 @@ impl std::fmt::Debug for ConstInt {
Ok(())
}
} else {
let max = truncate(u128::MAX, Size::from_bytes(size));
let max = Size::from_bytes(size).truncate(u128::MAX);
if raw == max {
match (size, is_ptr_sized_integral) {
(_, true) => write!(fmt, "usize::MAX"),
Expand Down Expand Up @@ -174,7 +173,7 @@ impl ScalarInt {
// is a packed struct, that would create a possibly unaligned reference, which
// is UB.
debug_assert_eq!(
truncate(self.data, self.size()),
self.size().truncate(self.data),
{ self.data },
"Scalar value {:#x} exceeds size of {} bytes",
{ self.data },
Expand All @@ -192,19 +191,19 @@ impl ScalarInt {
self.data == 0
}

pub(crate) fn ptr_sized_op<'tcx>(
pub(crate) fn ptr_sized_op<E>(
self,
dl: &TargetDataLayout,
f_int: impl FnOnce(u64) -> InterpResult<'tcx, u64>,
) -> InterpResult<'tcx, Self> {
f_int: impl FnOnce(u64) -> Result<u64, E>,
) -> Result<Self, E> {
assert_eq!(u64::from(self.size), dl.pointer_size.bytes());
Ok(Self::try_from_uint(f_int(u64::try_from(self.data).unwrap())?, self.size()).unwrap())
}

#[inline]
pub fn try_from_uint(i: impl Into<u128>, size: Size) -> Option<Self> {
let data = i.into();
if truncate(data, size) == data {
if size.truncate(data) == data {
Some(Self { data, size: size.bytes() as u8 })
} else {
None
Expand All @@ -215,8 +214,8 @@ impl ScalarInt {
pub fn try_from_int(i: impl Into<i128>, size: Size) -> Option<Self> {
let i = i.into();
// `into` performed sign extension, we have to truncate
let truncated = truncate(i as u128, size);
if sign_extend(truncated, size) as i128 == i {
let truncated = size.truncate(i as u128);
if size.sign_extend(truncated) as i128 == i {
Some(Self { data: truncated, size: size.bytes() as u8 })
} else {
None
Expand Down Expand Up @@ -265,7 +264,10 @@ macro_rules! try_from {
type Error = Size;
#[inline]
fn try_from(int: ScalarInt) -> Result<Self, Size> {
int.to_bits(Size::from_bytes(std::mem::size_of::<$ty>())).map(|u| u.try_into().unwrap())
// The `unwrap` cannot fail because to_bits (if it succeeds)
// is guaranteed to return a value that fits into the size.
int.to_bits(Size::from_bytes(std::mem::size_of::<$ty>()))
.map(|u| u.try_into().unwrap())
}
}
)*
Expand Down
11 changes: 5 additions & 6 deletions compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

use crate::ich::NodeIdHashingMode;
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::mir::interpret::{sign_extend, truncate};
use crate::ty::fold::TypeFolder;
use crate::ty::layout::IntegerExt;
use crate::ty::query::TyCtxtAt;
Expand Down Expand Up @@ -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 x = self.val;
// 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, "{}", self.val),
Expand All @@ -47,7 +46,7 @@ impl<'tcx> fmt::Display for Discr<'tcx> {
}

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 {
Expand Down Expand Up @@ -77,14 +76,14 @@ impl<'tcx> Discr<'tcx> {
let (val, oflo) = if signed {
let min = signed_min(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));
let n = n as i128;
let oflo = val > max - n;
let val = if oflo { min + (n - (max - val) - 1) } else { val + n };
// zero the upper bits
let val = val as u128;
let val = truncate(val, size);
let val = size.truncate(val);
(val, oflo)
} else {
let max = unsigned_max(size);
Expand Down Expand Up @@ -650,7 +649,7 @@ impl<'tcx> ty::TyS<'tcx> {
let val = match self.kind() {
ty::Int(_) | ty::Uint(_) => {
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)
}
ty::Char => Some(0),
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_mir/src/interpret/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ use rustc_span::symbol::sym;
use rustc_target::abi::{Integer, LayoutOf, Variants};

use super::{
truncate, util::ensure_monomorphic_enough, FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy,
PlaceTy,
util::ensure_monomorphic_enough, FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy, PlaceTy,
};

impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Expand Down Expand Up @@ -209,7 +208,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
RawPtr(_) => self.pointer_size(),
_ => bug!(),
};
let v = truncate(v, size);
let v = size.truncate(v);
Scalar::from_uint(v, size)
}

Expand Down
8 changes: 3 additions & 5 deletions compiler/rustc_mir/src/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ use rustc_index::vec::IndexVec;
use rustc_macros::HashStable;
use rustc_middle::ich::StableHashingContext;
use rustc_middle::mir;
use rustc_middle::mir::interpret::{
sign_extend, truncate, GlobalId, InterpResult, Pointer, Scalar,
};
use rustc_middle::mir::interpret::{GlobalId, InterpResult, Pointer, Scalar};
use rustc_middle::ty::layout::{self, TyAndLayout};
use rustc_middle::ty::{
self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
Expand Down Expand Up @@ -443,12 +441,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
#[inline(always)]
pub fn sign_extend(&self, value: u128, ty: TyAndLayout<'_>) -> u128 {
assert!(ty.abi.is_signed());
sign_extend(value, ty.size)
ty.size.sign_extend(value)
}

#[inline(always)]
pub fn truncate(&self, value: u128, ty: TyAndLayout<'_>) -> u128 {
truncate(value, ty.size)
ty.size.truncate(value)
}

#[inline]
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_mir/src/interpret/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ use rustc_target::abi::{Abi, Align, FieldsShape, TagEncoding};
use rustc_target::abi::{HasDataLayout, LayoutOf, Size, VariantIdx, Variants};

use super::{
mir_assign_valid_types, truncate, AllocId, AllocMap, Allocation, AllocationExtra, ConstAlloc,
ImmTy, Immediate, InterpCx, InterpResult, LocalValue, Machine, MemoryKind, OpTy, Operand,
Pointer, PointerArithmetic, Scalar, ScalarMaybeUninit,
mir_assign_valid_types, AllocId, AllocMap, Allocation, AllocationExtra, ConstAlloc, ImmTy,
Immediate, InterpCx, InterpResult, LocalValue, Machine, MemoryKind, OpTy, Operand, Pointer,
PointerArithmetic, Scalar, ScalarMaybeUninit,
};

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
Expand Down Expand Up @@ -1073,7 +1073,7 @@ where
// their computation, but the in-memory tag is the smallest possible
// representation
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)?;
self.write_scalar(Scalar::from_uint(tag_val, size), tag_dest)?;
Expand Down
9 changes: 4 additions & 5 deletions compiler/rustc_mir/src/transform/const_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,9 @@ use rustc_trait_selection::traits;

use crate::const_eval::ConstEvalErr;
use crate::interpret::{
self, compile_time_machine, truncate, AllocId, Allocation, ConstValue, CtfeValidationMode,
Frame, ImmTy, Immediate, InterpCx, InterpResult, LocalState, LocalValue, MemPlace, Memory,
MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, Pointer, Scalar, ScalarMaybeUninit,
StackPopCleanup,
self, compile_time_machine, AllocId, Allocation, ConstValue, CtfeValidationMode, Frame, ImmTy,
Immediate, InterpCx, InterpResult, LocalState, LocalValue, MemPlace, Memory, MemoryKind, OpTy,
Operand as InterpOperand, PlaceTy, Pointer, Scalar, ScalarMaybeUninit, StackPopCleanup,
};
use crate::transform::MirPass;

Expand Down Expand Up @@ -746,7 +745,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
}
}
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)
{
this.ecx.write_immediate(*const_arg, dest)?;
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_mir_build/src/build/matches/simplify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use crate::build::Builder;
use crate::thir::{self, *};
use rustc_attr::{SignedInt, UnsignedInt};
use rustc_hir::RangeEnd;
use rustc_middle::mir::interpret::truncate;
use rustc_middle::mir::Place;
use rustc_middle::ty;
use rustc_middle::ty::layout::IntegerExt;
Expand Down Expand Up @@ -161,13 +160,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
ty::Int(ity) => {
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);
(Some((0, max, size)), bias)
}
ty::Uint(uty) => {
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)
}
_ => (None, 0),
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_mir_build/src/thir/constant.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rustc_ast as ast;
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_span::symbol::Symbol;
Expand All @@ -16,7 +16,7 @@ crate fn lit_to_const<'tcx>(
let param_ty = ParamEnv::reveal_all().and(ty);
let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
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);
Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
};
Expand Down
Loading