Skip to content

Commit

Permalink
Auto merge of rust-lang#77227 - oli-obk:const_val_🌳_prelude, r=RalfJung
Browse files Browse the repository at this point in the history
Refactorings in preparation for const value trees

cc rust-lang#72396

This PR changes the `Scalar::Bits { data: u128, size: u8 }` variant to `Scalar::Bits(ScalarInt)` where `ScalarInt` contains the same information, but is `repr(packed)`. The reason for using a packed struct is to allow enum variant packing to keep the original size of `Scalar` instead of adding another word to its size due to padding.
Other than that the PR just gets rid of all the inspection of the internal fields of `Scalar::Bits` which were frankly scary. These fields have invariants that we need to uphold and we can't do that without making the fields private.

r? `@ghost`
  • Loading branch information
bors committed Nov 4, 2020
2 parents 601c13c + 332750f commit 75f1db1
Show file tree
Hide file tree
Showing 36 changed files with 472 additions and 292 deletions.
8 changes: 3 additions & 5 deletions compiler/rustc_codegen_cranelift/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ fn codegen_stmt<'tcx>(
UnOp::Neg => match layout.ty.kind() {
ty::Int(IntTy::I128) => {
// FIXME remove this case once ineg.i128 works
let zero = CValue::const_val(fx, layout, 0);
let zero = CValue::const_val(fx, layout, ty::ScalarInt::null(layout.size));
crate::num::codegen_int_binop(fx, BinOp::Sub, zero, operand)
}
ty::Int(_) => CValue::by_val(fx.bcx.ins().ineg(val), layout),
Expand Down Expand Up @@ -585,13 +585,11 @@ 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
};
let discr = discr.into();

let discr = CValue::const_val(fx, fx.layout_of(to_ty), discr);
lval.write_cvalue(fx, discr);
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_codegen_cranelift/src/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,8 @@ pub(crate) fn codegen_const_value<'tcx>(
}

match x {
Scalar::Raw { data, size } => {
assert_eq!(u64::from(size), layout.size.bytes());
CValue::const_val(fx, layout, data)
Scalar::Int(int) => {
CValue::const_val(fx, layout, int)
}
Scalar::Ptr(ptr) => {
let alloc_kind = fx.tcx.get_global_alloc(ptr.alloc_id);
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_codegen_cranelift/src/discriminant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ pub(crate) fn codegen_set_discriminant<'tcx>(
.ty
.discriminant_for_variant(fx.tcx, variant_index)
.unwrap()
.val;
.val
.into();
let discr = CValue::const_val(fx, ptr.layout(), to);
ptr.write_cvalue(fx, discr);
}
Expand All @@ -49,7 +50,7 @@ pub(crate) fn codegen_set_discriminant<'tcx>(
let niche = place.place_field(fx, mir::Field::new(tag_field));
let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();
let niche_value = u128::from(niche_value).wrapping_add(niche_start);
let niche_llval = CValue::const_val(fx, niche.layout(), niche_value);
let niche_llval = CValue::const_val(fx, niche.layout(), niche_value.into());
niche.write_cvalue(fx, niche_llval);
}
}
Expand Down Expand Up @@ -77,7 +78,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
.ty
.discriminant_for_variant(fx.tcx, *index)
.map_or(u128::from(index.as_u32()), |discr| discr.val);
return CValue::const_val(fx, dest_layout, discr_val);
return CValue::const_val(fx, dest_layout, discr_val.into());
}
Variants::Multiple {
tag,
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1064,7 +1064,8 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(

fx.bcx.ins().call_indirect(f_sig, f, &[data]);

let ret_val = CValue::const_val(fx, ret.layout(), 0);
let layout = ret.layout();
let ret_val = CValue::const_val(fx, layout, ty::ScalarInt::null(layout.size));
ret.write_cvalue(fx, ret_val);
};

Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_codegen_cranelift/src/value_and_place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,22 +231,24 @@ impl<'tcx> CValue<'tcx> {
pub(crate) fn const_val(
fx: &mut FunctionCx<'_, 'tcx, impl Module>,
layout: TyAndLayout<'tcx>,
const_val: u128,
const_val: ty::ScalarInt,
) -> CValue<'tcx> {
assert_eq!(const_val.size(), layout.size);
use cranelift_codegen::ir::immediates::{Ieee32, Ieee64};

let clif_ty = fx.clif_type(layout.ty).unwrap();

if let ty::Bool = layout.ty.kind() {
assert!(
const_val == 0 || const_val == 1,
const_val == ty::ScalarInt::FALSE || const_val == ty::ScalarInt::TRUE,
"Invalid bool 0x{:032X}",
const_val
);
}

let val = match layout.ty.kind() {
ty::Uint(UintTy::U128) | ty::Int(IntTy::I128) => {
let const_val = const_val.to_bits(layout.size).unwrap();
let lsb = fx.bcx.ins().iconst(types::I64, const_val as u64 as i64);
let msb = fx
.bcx
Expand All @@ -259,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
8 changes: 4 additions & 4 deletions compiler/rustc_codegen_llvm/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::*;
use rustc_middle::bug;
use rustc_middle::mir::interpret::{Allocation, GlobalAlloc, Scalar};
use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::ty::{layout::TyAndLayout, ScalarInt};
use rustc_span::symbol::Symbol;
use rustc_target::abi::{self, AddressSpace, HasDataLayout, LayoutOf, Pointer, Size};

Expand Down Expand Up @@ -230,12 +230,12 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
fn scalar_to_backend(&self, cv: Scalar, layout: &abi::Scalar, llty: &'ll Type) -> &'ll Value {
let bitsize = if layout.is_bool() { 1 } else { layout.value.size(self).bits() };
match cv {
Scalar::Raw { size: 0, .. } => {
Scalar::Int(ScalarInt::ZST) => {
assert_eq!(0, layout.value.size(self).bytes());
self.const_undef(self.type_ix(0))
}
Scalar::Raw { data, size } => {
assert_eq!(size as u64, layout.value.size(self).bytes());
Scalar::Int(int) => {
let data = int.assert_bits(layout.value.size(self));
let llval = self.const_uint_big(self.type_ix(bitsize), data);
if layout.value == Pointer {
unsafe { llvm::LLVMConstIntToPtr(llval, llty) }
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
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(array_windows)]
#![feature(assoc_char_funcs)]
#![feature(backtrace)]
#![feature(bool_to_option)]
#![feature(box_patterns)]
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
Loading

0 comments on commit 75f1db1

Please sign in to comment.