Skip to content

Commit abacaf2

Browse files
committed
u128 truncation and sign extension are not just interpreter related
1 parent e67c768 commit abacaf2

File tree

18 files changed

+73
-89
lines changed

18 files changed

+73
-89
lines changed

compiler/rustc_codegen_cranelift/src/base.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -585,10 +585,7 @@ fn codegen_stmt<'tcx>(
585585
.discriminant_for_variant(fx.tcx, *index)
586586
.unwrap();
587587
let discr = if discr.ty.is_signed() {
588-
rustc_middle::mir::interpret::sign_extend(
589-
discr.val,
590-
fx.layout_of(discr.ty).size,
591-
)
588+
fx.layout_of(discr.ty).size.sign_extend(discr.val)
592589
} else {
593590
discr.val
594591
};

compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ use rustc_hir::def::CtorKind;
2929
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
3030
use rustc_index::vec::{Idx, IndexVec};
3131
use rustc_middle::ich::NodeIdHashingMode;
32-
use rustc_middle::mir::interpret::truncate;
3332
use rustc_middle::mir::{self, Field, GeneratorLayout};
3433
use rustc_middle::ty::layout::{self, IntegerExt, PrimitiveExt, TyAndLayout};
3534
use rustc_middle::ty::subst::GenericArgKind;
@@ -1693,7 +1692,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
16931692
let value = (i.as_u32() as u128)
16941693
.wrapping_sub(niche_variants.start().as_u32() as u128)
16951694
.wrapping_add(niche_start);
1696-
let value = truncate(value, tag.value.size(cx));
1695+
let value = tag.value.size(cx).truncate(value);
16971696
// NOTE(eddyb) do *NOT* remove this assert, until
16981697
// we pass the full 128-bit value to LLVM, otherwise
16991698
// truncation will be silent and remain undetected.

compiler/rustc_lint/src/types.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use rustc_errors::Applicability;
66
use rustc_hir as hir;
77
use rustc_hir::{is_range_literal, ExprKind, Node};
88
use rustc_index::vec::Idx;
9-
use rustc_middle::mir::interpret::{sign_extend, truncate};
109
use rustc_middle::ty::layout::{IntegerExt, SizeSkeleton};
1110
use rustc_middle::ty::subst::SubstsRef;
1211
use rustc_middle::ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable};
@@ -218,11 +217,11 @@ fn report_bin_hex_error(
218217
cx.struct_span_lint(OVERFLOWING_LITERALS, expr.span, |lint| {
219218
let (t, actually) = match ty {
220219
attr::IntType::SignedInt(t) => {
221-
let actually = sign_extend(val, size) as i128;
220+
let actually = size.sign_extend(val) as i128;
222221
(t.name_str(), actually.to_string())
223222
}
224223
attr::IntType::UnsignedInt(t) => {
225-
let actually = truncate(val, size);
224+
let actually = size.truncate(val);
226225
(t.name_str(), actually.to_string())
227226
}
228227
};

compiler/rustc_middle/src/mir/interpret/mod.rs

+1-34
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ use rustc_hir::def_id::DefId;
110110
use rustc_macros::HashStable;
111111
use rustc_middle::ty::print::with_no_trimmed_paths;
112112
use rustc_serialize::{Decodable, Encodable};
113-
use rustc_target::abi::{Endian, Size};
113+
use rustc_target::abi::Endian;
114114

115115
use crate::mir;
116116
use crate::ty::codec::{TyDecoder, TyEncoder};
@@ -590,39 +590,6 @@ pub fn read_target_uint(endianness: Endian, mut source: &[u8]) -> Result<u128, i
590590
uint
591591
}
592592

593-
////////////////////////////////////////////////////////////////////////////////
594-
// Methods to facilitate working with signed integers stored in a u128
595-
////////////////////////////////////////////////////////////////////////////////
596-
597-
/// Truncates `value` to `size` bits and then sign-extend it to 128 bits
598-
/// (i.e., if it is negative, fill with 1's on the left).
599-
#[inline]
600-
pub fn sign_extend(value: u128, size: Size) -> u128 {
601-
let size = size.bits();
602-
if size == 0 {
603-
// Truncated until nothing is left.
604-
return 0;
605-
}
606-
// Sign-extend it.
607-
let shift = 128 - size;
608-
// Shift the unsigned value to the left, then shift back to the right as signed
609-
// (essentially fills with FF on the left).
610-
(((value << shift) as i128) >> shift) as u128
611-
}
612-
613-
/// Truncates `value` to `size` bits.
614-
#[inline]
615-
pub fn truncate(value: u128, size: Size) -> u128 {
616-
let size = size.bits();
617-
if size == 0 {
618-
// Truncated until nothing is left.
619-
return 0;
620-
}
621-
let shift = 128 - size;
622-
// Truncate (shift left to drop out leftover values, shift right to fill with zeroes).
623-
(value << shift) >> shift
624-
}
625-
626593
/// Computes the unsigned absolute value without wrapping or panicking.
627594
#[inline]
628595
pub fn uabs(value: i64) -> u64 {

compiler/rustc_middle/src/mir/interpret/value.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc_target::abi::{HasDataLayout, Size, TargetDataLayout};
1010

1111
use crate::ty::{ParamEnv, ScalarInt, Ty, TyCtxt};
1212

13-
use super::{sign_extend, AllocId, Allocation, InterpResult, Pointer, PointerArithmetic};
13+
use super::{AllocId, Allocation, InterpResult, Pointer, PointerArithmetic};
1414

1515
/// Represents the result of const evaluation via the `eval_to_allocation` query.
1616
#[derive(Clone, HashStable, TyEncodable, TyDecodable)]
@@ -448,7 +448,7 @@ impl<'tcx, Tag> Scalar<Tag> {
448448
fn to_signed_with_bit_width(self, bits: u64) -> InterpResult<'static, i128> {
449449
let sz = Size::from_bits(bits);
450450
let b = self.to_bits(sz)?;
451-
Ok(sign_extend(b, sz) as i128)
451+
Ok(sz.sign_extend(b) as i128)
452452
}
453453

454454
/// Converts the scalar to produce an `i8`. Fails if the scalar is a pointer.
@@ -479,7 +479,7 @@ impl<'tcx, Tag> Scalar<Tag> {
479479
pub fn to_machine_isize(self, cx: &impl HasDataLayout) -> InterpResult<'static, i64> {
480480
let sz = cx.data_layout().pointer_size;
481481
let b = self.to_bits(sz)?;
482-
let b = sign_extend(b, sz) as i128;
482+
let b = sz.sign_extend(b) as i128;
483483
Ok(i64::try_from(b).unwrap())
484484
}
485485

compiler/rustc_middle/src/ty/consts/int.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::mir::interpret::{sign_extend, truncate, InterpResult};
1+
use crate::mir::interpret::InterpResult;
22
use rustc_apfloat::ieee::{Double, Single};
33
use rustc_apfloat::Float;
44
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
@@ -75,7 +75,7 @@ impl std::fmt::Debug for ConstInt {
7575
Ok(())
7676
}
7777
} else {
78-
let max = truncate(u128::MAX, Size::from_bytes(size));
78+
let max = Size::from_bytes(size).truncate(u128::MAX);
7979
if raw == max {
8080
match (size, is_ptr_sized_integral) {
8181
(_, true) => write!(fmt, "usize::MAX"),
@@ -174,7 +174,7 @@ impl ScalarInt {
174174
// is a packed struct, that would create a possibly unaligned reference, which
175175
// is UB.
176176
debug_assert_eq!(
177-
truncate(self.data, self.size()),
177+
self.size().truncate(self.data),
178178
{ self.data },
179179
"Scalar value {:#x} exceeds size of {} bytes",
180180
{ self.data },
@@ -204,7 +204,7 @@ impl ScalarInt {
204204
#[inline]
205205
pub fn try_from_uint(i: impl Into<u128>, size: Size) -> Option<Self> {
206206
let data = i.into();
207-
if truncate(data, size) == data {
207+
if size.truncate(data) == data {
208208
Some(Self { data, size: size.bytes() as u8 })
209209
} else {
210210
None
@@ -215,8 +215,8 @@ impl ScalarInt {
215215
pub fn try_from_int(i: impl Into<i128>, size: Size) -> Option<Self> {
216216
let i = i.into();
217217
// `into` performed sign extension, we have to truncate
218-
let truncated = truncate(i as u128, size);
219-
if sign_extend(truncated, size) as i128 == i {
218+
let truncated = size.truncate(i as u128);
219+
if size.sign_extend(truncated) as i128 == i {
220220
Some(Self { data: truncated, size: size.bytes() as u8 })
221221
} else {
222222
None

compiler/rustc_middle/src/ty/util.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
33
use crate::ich::NodeIdHashingMode;
44
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
5-
use crate::mir::interpret::{sign_extend, truncate};
65
use crate::ty::fold::TypeFolder;
76
use crate::ty::layout::IntegerExt;
87
use crate::ty::query::TyCtxtAt;
@@ -38,7 +37,7 @@ impl<'tcx> fmt::Display for Discr<'tcx> {
3837
let size = ty::tls::with(|tcx| Integer::from_attr(&tcx, SignedInt(ity)).size());
3938
let x = self.val;
4039
// sign extend the raw representation to be an i128
41-
let x = sign_extend(x, size) as i128;
40+
let x = size.sign_extend(x) as i128;
4241
write!(fmt, "{}", x)
4342
}
4443
_ => write!(fmt, "{}", self.val),
@@ -47,7 +46,7 @@ impl<'tcx> fmt::Display for Discr<'tcx> {
4746
}
4847

4948
fn signed_min(size: Size) -> i128 {
50-
sign_extend(1_u128 << (size.bits() - 1), size) as i128
49+
size.sign_extend(1_u128 << (size.bits() - 1)) as i128
5150
}
5251

5352
fn signed_max(size: Size) -> i128 {
@@ -77,14 +76,14 @@ impl<'tcx> Discr<'tcx> {
7776
let (val, oflo) = if signed {
7877
let min = signed_min(size);
7978
let max = signed_max(size);
80-
let val = sign_extend(self.val, size) as i128;
79+
let val = size.sign_extend(self.val) as i128;
8180
assert!(n < (i128::MAX as u128));
8281
let n = n as i128;
8382
let oflo = val > max - n;
8483
let val = if oflo { min + (n - (max - val) - 1) } else { val + n };
8584
// zero the upper bits
8685
let val = val as u128;
87-
let val = truncate(val, size);
86+
let val = size.truncate(val);
8887
(val, oflo)
8988
} else {
9089
let max = unsigned_max(size);
@@ -650,7 +649,7 @@ impl<'tcx> ty::TyS<'tcx> {
650649
let val = match self.kind() {
651650
ty::Int(_) | ty::Uint(_) => {
652651
let (size, signed) = int_size_and_signed(tcx, self);
653-
let val = if signed { truncate(signed_min(size) as u128, size) } else { 0 };
652+
let val = if signed { size.truncate(signed_min(size) as u128) } else { 0 };
654653
Some(val)
655654
}
656655
ty::Char => Some(0),

compiler/rustc_mir/src/interpret/cast.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ use rustc_span::symbol::sym;
1313
use rustc_target::abi::{Integer, LayoutOf, Variants};
1414

1515
use super::{
16-
truncate, util::ensure_monomorphic_enough, FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy,
17-
PlaceTy,
16+
util::ensure_monomorphic_enough, FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy, PlaceTy,
1817
};
1918

2019
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> {
209208
RawPtr(_) => self.pointer_size(),
210209
_ => bug!(),
211210
};
212-
let v = truncate(v, size);
211+
let v = size.truncate(v);
213212
Scalar::from_uint(v, size)
214213
}
215214

compiler/rustc_mir/src/interpret/eval_context.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@ use rustc_index::vec::IndexVec;
99
use rustc_macros::HashStable;
1010
use rustc_middle::ich::StableHashingContext;
1111
use rustc_middle::mir;
12-
use rustc_middle::mir::interpret::{
13-
sign_extend, truncate, GlobalId, InterpResult, Pointer, Scalar,
14-
};
12+
use rustc_middle::mir::interpret::{GlobalId, InterpResult, Pointer, Scalar};
1513
use rustc_middle::ty::layout::{self, TyAndLayout};
1614
use rustc_middle::ty::{
1715
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> {
443441
#[inline(always)]
444442
pub fn sign_extend(&self, value: u128, ty: TyAndLayout<'_>) -> u128 {
445443
assert!(ty.abi.is_signed());
446-
sign_extend(value, ty.size)
444+
ty.size.sign_extend(value)
447445
}
448446

449447
#[inline(always)]
450448
pub fn truncate(&self, value: u128, ty: TyAndLayout<'_>) -> u128 {
451-
truncate(value, ty.size)
449+
ty.size.truncate(value)
452450
}
453451

454452
#[inline]

compiler/rustc_mir/src/interpret/place.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ use rustc_target::abi::{Abi, Align, FieldsShape, TagEncoding};
1414
use rustc_target::abi::{HasDataLayout, LayoutOf, Size, VariantIdx, Variants};
1515

1616
use super::{
17-
mir_assign_valid_types, truncate, AllocId, AllocMap, Allocation, AllocationExtra, ConstAlloc,
18-
ImmTy, Immediate, InterpCx, InterpResult, LocalValue, Machine, MemoryKind, OpTy, Operand,
19-
Pointer, PointerArithmetic, Scalar, ScalarMaybeUninit,
17+
mir_assign_valid_types, AllocId, AllocMap, Allocation, AllocationExtra, ConstAlloc, ImmTy,
18+
Immediate, InterpCx, InterpResult, LocalValue, Machine, MemoryKind, OpTy, Operand, Pointer,
19+
PointerArithmetic, Scalar, ScalarMaybeUninit,
2020
};
2121

2222
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
@@ -1073,7 +1073,7 @@ where
10731073
// their computation, but the in-memory tag is the smallest possible
10741074
// representation
10751075
let size = tag_layout.value.size(self);
1076-
let tag_val = truncate(discr_val, size);
1076+
let tag_val = size.truncate(discr_val);
10771077

10781078
let tag_dest = self.place_field(dest, tag_field)?;
10791079
self.write_scalar(Scalar::from_uint(tag_val, size), tag_dest)?;

compiler/rustc_mir/src/transform/const_prop.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,9 @@ use rustc_trait_selection::traits;
2929

3030
use crate::const_eval::ConstEvalErr;
3131
use crate::interpret::{
32-
self, compile_time_machine, truncate, AllocId, Allocation, ConstValue, CtfeValidationMode,
33-
Frame, ImmTy, Immediate, InterpCx, InterpResult, LocalState, LocalValue, MemPlace, Memory,
34-
MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, Pointer, Scalar, ScalarMaybeUninit,
35-
StackPopCleanup,
32+
self, compile_time_machine, AllocId, Allocation, ConstValue, CtfeValidationMode, Frame, ImmTy,
33+
Immediate, InterpCx, InterpResult, LocalState, LocalValue, MemPlace, Memory, MemoryKind, OpTy,
34+
Operand as InterpOperand, PlaceTy, Pointer, Scalar, ScalarMaybeUninit, StackPopCleanup,
3635
};
3736
use crate::transform::MirPass;
3837

@@ -746,7 +745,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
746745
}
747746
}
748747
BinOp::BitOr => {
749-
if arg_value == truncate(u128::MAX, const_arg.layout.size)
748+
if arg_value == const_arg.layout.size.truncate(u128::MAX)
750749
|| (const_arg.layout.ty.is_bool() && arg_value == 1)
751750
{
752751
this.ecx.write_immediate(*const_arg, dest)?;

compiler/rustc_mir_build/src/build/matches/simplify.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ use crate::build::Builder;
1717
use crate::thir::{self, *};
1818
use rustc_attr::{SignedInt, UnsignedInt};
1919
use rustc_hir::RangeEnd;
20-
use rustc_middle::mir::interpret::truncate;
2120
use rustc_middle::mir::Place;
2221
use rustc_middle::ty;
2322
use rustc_middle::ty::layout::IntegerExt;
@@ -161,13 +160,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
161160
}
162161
ty::Int(ity) => {
163162
let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
164-
let max = truncate(u128::MAX, size);
163+
let max = size.truncate(u128::MAX);
165164
let bias = 1u128 << (size.bits() - 1);
166165
(Some((0, max, size)), bias)
167166
}
168167
ty::Uint(uty) => {
169168
let size = Integer::from_attr(&tcx, UnsignedInt(uty)).size();
170-
let max = truncate(u128::MAX, size);
169+
let max = size.truncate(u128::MAX);
171170
(Some((0, max, size)), 0)
172171
}
173172
_ => (None, 0),

compiler/rustc_mir_build/src/thir/constant.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use rustc_ast as ast;
22
use rustc_middle::mir::interpret::{
3-
truncate, Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
3+
Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
44
};
55
use rustc_middle::ty::{self, ParamEnv, TyCtxt};
66
use rustc_span::symbol::Symbol;
@@ -16,7 +16,7 @@ crate fn lit_to_const<'tcx>(
1616
let param_ty = ParamEnv::reveal_all().and(ty);
1717
let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
1818
trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
19-
let result = truncate(n, width);
19+
let result = width.truncate(n);
2020
trace!("trunc result: {}", result);
2121
Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
2222
};

compiler/rustc_mir_build/src/thir/pattern/_match.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ use rustc_arena::TypedArena;
304304
use rustc_attr::{SignedInt, UnsignedInt};
305305
use rustc_hir::def_id::DefId;
306306
use rustc_hir::{HirId, RangeEnd};
307-
use rustc_middle::mir::interpret::{truncate, ConstValue};
307+
use rustc_middle::mir::interpret::ConstValue;
308308
use rustc_middle::mir::Field;
309309
use rustc_middle::ty::layout::IntegerExt;
310310
use rustc_middle::ty::{self, Const, Ty, TyCtxt};
@@ -1608,7 +1608,7 @@ fn all_constructors<'p, 'tcx>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Vec<Constructor<'tc
16081608
}
16091609
&ty::Uint(uty) => {
16101610
let size = Integer::from_attr(&cx.tcx, UnsignedInt(uty)).size();
1611-
let max = truncate(u128::MAX, size);
1611+
let max = size.truncate(u128::MAX);
16121612
vec![make_range(0, max)]
16131613
}
16141614
_ if cx.is_uninhabited(pcx.ty) => vec![],

compiler/rustc_mir_build/src/thir/pattern/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
1515
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
1616
use rustc_hir::RangeEnd;
1717
use rustc_index::vec::Idx;
18-
use rustc_middle::mir::interpret::{get_slice_bytes, sign_extend, ConstValue};
18+
use rustc_middle::mir::interpret::{get_slice_bytes, ConstValue};
1919
use rustc_middle::mir::interpret::{ErrorHandled, LitToConstError, LitToConstInput};
2020
use rustc_middle::mir::UserTypeProjection;
2121
use rustc_middle::mir::{BorrowKind, Field, Mutability};
@@ -1082,8 +1082,8 @@ crate fn compare_const_vals<'tcx>(
10821082
use rustc_attr::SignedInt;
10831083
use rustc_middle::ty::layout::IntegerExt;
10841084
let size = rustc_target::abi::Integer::from_attr(&tcx, SignedInt(ity)).size();
1085-
let a = sign_extend(a, size);
1086-
let b = sign_extend(b, size);
1085+
let a = size.sign_extend(a);
1086+
let b = size.sign_extend(b);
10871087
Some((a as i128).cmp(&(b as i128)))
10881088
}
10891089
_ => Some(a.cmp(&b)),

0 commit comments

Comments
 (0)