1
Fork 0

s/eval_usize/eval_target_usize/ for clarity

This commit is contained in:
Oli Scherer 2023-02-14 08:51:19 +00:00
parent c3c6d73b04
commit 936bf29d4c
48 changed files with 347 additions and 259 deletions

View file

@ -1782,7 +1782,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// than 1. // than 1.
// If the length is larger than 1, the repeat expression will need to copy the // If the length is larger than 1, the repeat expression will need to copy the
// element, so we require the `Copy` trait. // element, so we require the `Copy` trait.
if len.try_eval_usize(tcx, self.param_env).map_or(true, |len| len > 1) { if len.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
match operand { match operand {
Operand::Copy(..) | Operand::Constant(..) => { Operand::Copy(..) | Operand::Constant(..) => {
// These are always okay: direct use of a const, or a value that can evidently be copied. // These are always okay: direct use of a const, or a value that can evidently be copied.

View file

@ -857,7 +857,7 @@ fn codegen_stmt<'tcx>(
fn codegen_array_len<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, place: CPlace<'tcx>) -> Value { fn codegen_array_len<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, place: CPlace<'tcx>) -> Value {
match *place.layout().ty.kind() { match *place.layout().ty.kind() {
ty::Array(_elem_ty, len) => { ty::Array(_elem_ty, len) => {
let len = fx.monomorphize(len).eval_usize(fx.tcx, ParamEnv::reveal_all()) as i64; let len = fx.monomorphize(len).eval_target_usize(fx.tcx, ParamEnv::reveal_all()) as i64;
fx.bcx.ins().iconst(fx.pointer_type, len) fx.bcx.ins().iconst(fx.pointer_type, len)
} }
ty::Slice(_elem_ty) => { ty::Slice(_elem_ty) => {

View file

@ -141,7 +141,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
let idx_ty = fx.monomorphize(idx.ty(fx.mir, fx.tcx)); let idx_ty = fx.monomorphize(idx.ty(fx.mir, fx.tcx));
match idx_ty.kind() { match idx_ty.kind() {
ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => len ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => len
.try_eval_usize(fx.tcx, ty::ParamEnv::reveal_all()) .try_eval_target_usize(fx.tcx, ty::ParamEnv::reveal_all())
.unwrap_or_else(|| { .unwrap_or_else(|| {
span_bug!(span, "could not evaluate shuffle index array length") span_bug!(span, "could not evaluate shuffle index array length")
}) })
@ -735,7 +735,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => {} ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => {}
ty::Array(elem, len) ty::Array(elem, len)
if matches!(elem.kind(), ty::Uint(ty::UintTy::U8)) if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
&& len.try_eval_usize(fx.tcx, ty::ParamEnv::reveal_all()) && len.try_eval_target_usize(fx.tcx, ty::ParamEnv::reveal_all())
== Some(expected_bytes) => {} == Some(expected_bytes) => {}
_ => { _ => {
fx.tcx.sess.span_fatal( fx.tcx.sess.span_fatal(

View file

@ -24,7 +24,7 @@ pub(crate) fn unsized_info<'tcx>(
(&ty::Array(_, len), &ty::Slice(_)) => fx (&ty::Array(_, len), &ty::Slice(_)) => fx
.bcx .bcx
.ins() .ins()
.iconst(fx.pointer_type, len.eval_usize(fx.tcx, ParamEnv::reveal_all()) as i64), .iconst(fx.pointer_type, len.eval_target_usize(fx.tcx, ParamEnv::reveal_all()) as i64),
( (
&ty::Dynamic(ref data_a, _, src_dyn_kind), &ty::Dynamic(ref data_a, _, src_dyn_kind),
&ty::Dynamic(ref data_b, _, target_dyn_kind), &ty::Dynamic(ref data_b, _, target_dyn_kind),

View file

@ -564,8 +564,8 @@ impl<'tcx> CPlace<'tcx> {
CPlaceInner::Var(_local, var) => { CPlaceInner::Var(_local, var) => {
if let ty::Array(element, len) = dst_layout.ty.kind() { if let ty::Array(element, len) = dst_layout.ty.kind() {
// Can only happen for vector types // Can only happen for vector types
let len = let len = u32::try_from(len.eval_target_usize(fx.tcx, ParamEnv::reveal_all()))
u32::try_from(len.eval_usize(fx.tcx, ParamEnv::reveal_all())).unwrap(); .unwrap();
let vector_ty = fx.clif_type(*element).unwrap().by(len).unwrap(); let vector_ty = fx.clif_type(*element).unwrap().by(len).unwrap();
let data = match from.0 { let data = match from.0 {

View file

@ -1,6 +1,6 @@
use std::cmp::Ordering; use std::cmp::Ordering;
use gccjit::{BinaryOp, RValue, Type, ToRValue}; use gccjit::{BinaryOp, RValue, ToRValue, Type};
use rustc_codegen_ssa::base::compare_simd_types; use rustc_codegen_ssa::base::compare_simd_types;
use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::common::TypeKind;
use rustc_codegen_ssa::mir::operand::OperandRef; use rustc_codegen_ssa::mir::operand::OperandRef;
@ -10,52 +10,57 @@ use rustc_hir as hir;
use rustc_middle::span_bug; use rustc_middle::span_bug;
use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::layout::HasTyCtxt;
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
use rustc_span::{Span, Symbol, sym}; use rustc_span::{sym, Span, Symbol};
use rustc_target::abi::Align; use rustc_target::abi::Align;
use crate::builder::Builder; use crate::builder::Builder;
use crate::errors::{ use crate::errors::{
InvalidMonomorphizationInvalidFloatVector, InvalidMonomorphizationExpectedSignedUnsigned, InvalidMonomorphizationExpectedSimd,
InvalidMonomorphizationNotFloat, InvalidMonomorphizationInsertedType, InvalidMonomorphizationInvalidBitmask,
InvalidMonomorphizationUnrecognized, InvalidMonomorphizationInvalidFloatVector, InvalidMonomorphizationMaskType,
InvalidMonomorphizationExpectedSignedUnsigned, InvalidMonomorphizationMismatchedLengths, InvalidMonomorphizationNotFloat,
InvalidMonomorphizationUnsupportedElement, InvalidMonomorphizationReturnElement, InvalidMonomorphizationReturnIntegerType,
InvalidMonomorphizationInvalidBitmask, InvalidMonomorphizationReturnLength, InvalidMonomorphizationReturnLengthInputType,
InvalidMonomorphizationSimdShuffle, InvalidMonomorphizationReturnType, InvalidMonomorphizationSimdShuffle,
InvalidMonomorphizationExpectedSimd, InvalidMonomorphizationUnrecognized, InvalidMonomorphizationUnsupportedCast,
InvalidMonomorphizationMaskType, InvalidMonomorphizationUnsupportedElement, InvalidMonomorphizationUnsupportedOperation,
InvalidMonomorphizationReturnLength,
InvalidMonomorphizationReturnLengthInputType,
InvalidMonomorphizationReturnElement,
InvalidMonomorphizationReturnType,
InvalidMonomorphizationInsertedType,
InvalidMonomorphizationReturnIntegerType,
InvalidMonomorphizationMismatchedLengths,
InvalidMonomorphizationUnsupportedCast,
InvalidMonomorphizationUnsupportedOperation
}; };
use crate::intrinsic; use crate::intrinsic;
pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, name: Symbol, callee_ty: Ty<'tcx>, args: &[OperandRef<'tcx, RValue<'gcc>>], ret_ty: Ty<'tcx>, llret_ty: Type<'gcc>, span: Span) -> Result<RValue<'gcc>, ()> { pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
bx: &mut Builder<'a, 'gcc, 'tcx>,
name: Symbol,
callee_ty: Ty<'tcx>,
args: &[OperandRef<'tcx, RValue<'gcc>>],
ret_ty: Ty<'tcx>,
llret_ty: Type<'gcc>,
span: Span,
) -> Result<RValue<'gcc>, ()> {
// macros for error handling: // macros for error handling:
macro_rules! return_error { macro_rules! return_error {
($err:expr) => { ($err:expr) => {{
{ bx.sess().emit_err($err);
bx.sess().emit_err($err); return Err(());
return Err(()); }};
}
}
} }
macro_rules! require { macro_rules! require {
($cond:expr, $err:expr) => { ($cond:expr, $err:expr) => {
if !$cond { if !$cond {
return_error!($err); return_error!($err);
} }
} };
} }
macro_rules! require_simd { macro_rules! require_simd {
($ty: expr, $position: expr) => { ($ty: expr, $position: expr) => {
require!($ty.is_simd(), InvalidMonomorphizationExpectedSimd { span, name, position: $position, found_ty: $ty }) require!(
$ty.is_simd(),
InvalidMonomorphizationExpectedSimd {
span,
name,
position: $position,
found_ty: $ty
}
)
}; };
} }
@ -77,7 +82,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(), ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(),
ty::Array(elem, len) ty::Array(elem, len)
if matches!(elem.kind(), ty::Uint(ty::UintTy::U8)) if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
&& len.try_eval_usize(bx.tcx, ty::ParamEnv::reveal_all()) && len.try_eval_target_usize(bx.tcx, ty::ParamEnv::reveal_all())
== Some(expected_bytes) => == Some(expected_bytes) =>
{ {
let place = PlaceRef::alloca(bx, args[0].layout); let place = PlaceRef::alloca(bx, args[0].layout);
@ -86,9 +91,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let ptr = bx.pointercast(place.llval, bx.cx.type_ptr_to(int_ty)); let ptr = bx.pointercast(place.llval, bx.cx.type_ptr_to(int_ty));
bx.load(int_ty, ptr, Align::ONE) bx.load(int_ty, ptr, Align::ONE)
} }
_ => return_error!( _ => return_error!(InvalidMonomorphizationInvalidBitmask {
InvalidMonomorphizationInvalidBitmask { span, name, ty: mask_ty, expected_int_bits, expected_bytes } span,
), name,
ty: mask_ty,
expected_int_bits,
expected_bytes
}),
}; };
let arg1 = args[1].immediate(); let arg1 = args[1].immediate();
@ -129,11 +138,18 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
require!( require!(
in_len == out_len, in_len == out_len,
InvalidMonomorphizationReturnLengthInputType { span, name, in_len, in_ty, ret_ty, out_len } InvalidMonomorphizationReturnLengthInputType {
span,
name,
in_len,
in_ty,
ret_ty,
out_len
}
); );
require!( require!(
bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer, bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer,
InvalidMonomorphizationReturnIntegerType {span, name, ret_ty, out_ty} InvalidMonomorphizationReturnIntegerType { span, name, ret_ty, out_ty }
); );
return Ok(compare_simd_types( return Ok(compare_simd_types(
@ -147,26 +163,26 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
} }
if let Some(stripped) = name.as_str().strip_prefix("simd_shuffle") { if let Some(stripped) = name.as_str().strip_prefix("simd_shuffle") {
let n: u64 = let n: u64 = if stripped.is_empty() {
if stripped.is_empty() { // Make sure this is actually an array, since typeck only checks the length-suffixed
// Make sure this is actually an array, since typeck only checks the length-suffixed // version of this intrinsic.
// version of this intrinsic. match args[2].layout.ty.kind() {
match args[2].layout.ty.kind() { ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => {
ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(
len.try_eval_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(|| { || span_bug!(span, "could not evaluate shuffle index array length"),
span_bug!(span, "could not evaluate shuffle index array length") )
})
}
_ => return_error!(
InvalidMonomorphizationSimdShuffle { span, name, ty: args[2].layout.ty }
),
} }
_ => return_error!(InvalidMonomorphizationSimdShuffle {
span,
name,
ty: args[2].layout.ty
}),
} }
else { } else {
stripped.parse().unwrap_or_else(|_| { stripped.parse().unwrap_or_else(|_| {
span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?") span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?")
}) })
}; };
require_simd!(ret_ty, "return"); require_simd!(ret_ty, "return");
@ -182,14 +198,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let vector = args[2].immediate(); let vector = args[2].immediate();
return Ok(bx.shuffle_vector( return Ok(bx.shuffle_vector(args[0].immediate(), args[1].immediate(), vector));
args[0].immediate(),
args[1].immediate(),
vector,
));
} }
#[cfg(feature="master")] #[cfg(feature = "master")]
if name == sym::simd_insert { if name == sym::simd_insert {
require!( require!(
in_elem == arg_tys[2], in_elem == arg_tys[2],
@ -205,44 +217,44 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
// not be an l-value. So, call a builtin to set the element. // not be an l-value. So, call a builtin to set the element.
// TODO(antoyo): perhaps we could create a new vector or maybe there's a GIMPLE instruction for that? // TODO(antoyo): perhaps we could create a new vector or maybe there's a GIMPLE instruction for that?
// TODO(antoyo): don't use target specific builtins here. // TODO(antoyo): don't use target specific builtins here.
let func_name = let func_name = match in_len {
match in_len { 2 => {
2 => { if element_type == bx.i64_type {
if element_type == bx.i64_type { "__builtin_ia32_vec_set_v2di"
"__builtin_ia32_vec_set_v2di" } else {
} unimplemented!();
else { }
unimplemented!(); }
} 4 => {
}, if element_type == bx.i32_type {
4 => { "__builtin_ia32_vec_set_v4si"
if element_type == bx.i32_type { } else {
"__builtin_ia32_vec_set_v4si" unimplemented!();
} }
else { }
unimplemented!(); 8 => {
} if element_type == bx.i16_type {
}, "__builtin_ia32_vec_set_v8hi"
8 => { } else {
if element_type == bx.i16_type { unimplemented!();
"__builtin_ia32_vec_set_v8hi" }
} }
else { _ => unimplemented!("Len: {}", in_len),
unimplemented!(); };
}
},
_ => unimplemented!("Len: {}", in_len),
};
let builtin = bx.context.get_target_builtin_function(func_name); let builtin = bx.context.get_target_builtin_function(func_name);
let param1_type = builtin.get_param(0).to_rvalue().get_type(); let param1_type = builtin.get_param(0).to_rvalue().get_type();
// TODO(antoyo): perhaps use __builtin_convertvector for vector casting. // TODO(antoyo): perhaps use __builtin_convertvector for vector casting.
let vector = bx.cx.bitcast_if_needed(vector, param1_type); let vector = bx.cx.bitcast_if_needed(vector, param1_type);
let result = bx.context.new_call(None, builtin, &[vector, value, bx.context.new_cast(None, index, bx.int_type)]); let result = bx.context.new_call(
None,
builtin,
&[vector, value, bx.context.new_cast(None, index, bx.int_type)],
);
// TODO(antoyo): perhaps use __builtin_convertvector for vector casting. // TODO(antoyo): perhaps use __builtin_convertvector for vector casting.
return Ok(bx.context.new_bitcast(None, result, vector.get_type())); return Ok(bx.context.new_bitcast(None, result, vector.get_type()));
} }
#[cfg(feature="master")] #[cfg(feature = "master")]
if name == sym::simd_extract { if name == sym::simd_extract {
require!( require!(
ret_ty == in_elem, ret_ty == in_elem,
@ -273,7 +285,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
require!( require!(
in_len == out_len, in_len == out_len,
InvalidMonomorphizationReturnLengthInputType { span, name, in_len, in_ty, ret_ty, out_len } InvalidMonomorphizationReturnLengthInputType {
span,
name,
in_len,
in_ty,
ret_ty,
out_len
}
); );
// casting cares about nominal type, not just structural type // casting cares about nominal type, not just structural type
if in_elem == out_elem { if in_elem == out_elem {
@ -322,19 +341,27 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let cast_vec_element = |index| { let cast_vec_element = |index| {
let index = bx.context.new_rvalue_from_int(bx.int_type, index); let index = bx.context.new_rvalue_from_int(bx.int_type, index);
bx.context.new_cast(None, bx.context.new_array_access(None, array, index).to_rvalue(), out_type) bx.context.new_cast(
None,
bx.context.new_array_access(None, array, index).to_rvalue(),
out_type,
)
}; };
bx.context.new_rvalue_from_vector(None, vector_type, &[ bx.context.new_rvalue_from_vector(
cast_vec_element(0), None,
cast_vec_element(1), vector_type,
cast_vec_element(2), &[
cast_vec_element(3), cast_vec_element(0),
cast_vec_element(4), cast_vec_element(1),
cast_vec_element(5), cast_vec_element(2),
cast_vec_element(6), cast_vec_element(3),
cast_vec_element(7), cast_vec_element(4),
]) cast_vec_element(5),
cast_vec_element(6),
cast_vec_element(7),
],
)
}; };
match (in_style, out_style) { match (in_style, out_style) {
@ -385,9 +412,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
} }
_ => { /* Unsupported. Fallthrough. */ } _ => { /* Unsupported. Fallthrough. */ }
} }
return_error!( return_error!(InvalidMonomorphizationUnsupportedCast {
InvalidMonomorphizationUnsupportedCast { span, name, in_ty, in_elem, ret_ty, out_elem } span,
); name,
in_ty,
in_elem,
ret_ty,
out_elem
});
} }
macro_rules! arith_binary { macro_rules! arith_binary {
@ -414,54 +446,60 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
args: &[OperandRef<'tcx, RValue<'gcc>>], args: &[OperandRef<'tcx, RValue<'gcc>>],
) -> Result<RValue<'gcc>, ()> { ) -> Result<RValue<'gcc>, ()> {
macro_rules! return_error { macro_rules! return_error {
($err:expr) => { ($err:expr) => {{
{ bx.sess().emit_err($err);
bx.sess().emit_err($err); return Err(());
return Err(()); }};
}
}
} }
let (elem_ty_str, elem_ty) = let (elem_ty_str, elem_ty) = if let ty::Float(f) = in_elem.kind() {
if let ty::Float(f) = in_elem.kind() { let elem_ty = bx.cx.type_float_from_ty(*f);
let elem_ty = bx.cx.type_float_from_ty(*f); match f.bit_width() {
match f.bit_width() { 32 => ("f32", elem_ty),
32 => ("f32", elem_ty), 64 => ("f64", elem_ty),
64 => ("f64", elem_ty), _ => {
_ => { return_error!(InvalidMonomorphizationInvalidFloatVector {
return_error!(InvalidMonomorphizationInvalidFloatVector { span, name, elem_ty: f.name_str(), vec_ty: in_ty }); span,
} name,
elem_ty: f.name_str(),
vec_ty: in_ty
});
} }
} }
else { } else {
return_error!(InvalidMonomorphizationNotFloat { span, name, ty: in_ty }); return_error!(InvalidMonomorphizationNotFloat { span, name, ty: in_ty });
}; };
let vec_ty = bx.cx.type_vector(elem_ty, in_len); let vec_ty = bx.cx.type_vector(elem_ty, in_len);
let (intr_name, fn_ty) = let (intr_name, fn_ty) = match name {
match name { sym::simd_ceil => ("ceil", bx.type_func(&[vec_ty], vec_ty)),
sym::simd_ceil => ("ceil", bx.type_func(&[vec_ty], vec_ty)), sym::simd_fabs => ("fabs", bx.type_func(&[vec_ty], vec_ty)), // TODO(antoyo): pand with 170141183420855150465331762880109871103
sym::simd_fabs => ("fabs", bx.type_func(&[vec_ty], vec_ty)), // TODO(antoyo): pand with 170141183420855150465331762880109871103 sym::simd_fcos => ("cos", bx.type_func(&[vec_ty], vec_ty)),
sym::simd_fcos => ("cos", bx.type_func(&[vec_ty], vec_ty)), sym::simd_fexp2 => ("exp2", bx.type_func(&[vec_ty], vec_ty)),
sym::simd_fexp2 => ("exp2", bx.type_func(&[vec_ty], vec_ty)), sym::simd_fexp => ("exp", bx.type_func(&[vec_ty], vec_ty)),
sym::simd_fexp => ("exp", bx.type_func(&[vec_ty], vec_ty)), sym::simd_flog10 => ("log10", bx.type_func(&[vec_ty], vec_ty)),
sym::simd_flog10 => ("log10", bx.type_func(&[vec_ty], vec_ty)), sym::simd_flog2 => ("log2", bx.type_func(&[vec_ty], vec_ty)),
sym::simd_flog2 => ("log2", bx.type_func(&[vec_ty], vec_ty)), sym::simd_flog => ("log", bx.type_func(&[vec_ty], vec_ty)),
sym::simd_flog => ("log", bx.type_func(&[vec_ty], vec_ty)), sym::simd_floor => ("floor", bx.type_func(&[vec_ty], vec_ty)),
sym::simd_floor => ("floor", bx.type_func(&[vec_ty], vec_ty)), sym::simd_fma => ("fma", bx.type_func(&[vec_ty, vec_ty, vec_ty], vec_ty)),
sym::simd_fma => ("fma", bx.type_func(&[vec_ty, vec_ty, vec_ty], vec_ty)), sym::simd_fpowi => ("powi", bx.type_func(&[vec_ty, bx.type_i32()], vec_ty)),
sym::simd_fpowi => ("powi", bx.type_func(&[vec_ty, bx.type_i32()], vec_ty)), sym::simd_fpow => ("pow", bx.type_func(&[vec_ty, vec_ty], vec_ty)),
sym::simd_fpow => ("pow", bx.type_func(&[vec_ty, vec_ty], vec_ty)), sym::simd_fsin => ("sin", bx.type_func(&[vec_ty], vec_ty)),
sym::simd_fsin => ("sin", bx.type_func(&[vec_ty], vec_ty)), sym::simd_fsqrt => ("sqrt", bx.type_func(&[vec_ty], vec_ty)),
sym::simd_fsqrt => ("sqrt", bx.type_func(&[vec_ty], vec_ty)), sym::simd_round => ("round", bx.type_func(&[vec_ty], vec_ty)),
sym::simd_round => ("round", bx.type_func(&[vec_ty], vec_ty)), sym::simd_trunc => ("trunc", bx.type_func(&[vec_ty], vec_ty)),
sym::simd_trunc => ("trunc", bx.type_func(&[vec_ty], vec_ty)), _ => return_error!(InvalidMonomorphizationUnrecognized { span, name }),
_ => return_error!(InvalidMonomorphizationUnrecognized { span, name }) };
};
let llvm_name = &format!("llvm.{0}.v{1}{2}", intr_name, in_len, elem_ty_str); let llvm_name = &format!("llvm.{0}.v{1}{2}", intr_name, in_len, elem_ty_str);
let function = intrinsic::llvm::intrinsic(llvm_name, &bx.cx); let function = intrinsic::llvm::intrinsic(llvm_name, &bx.cx);
let function: RValue<'gcc> = unsafe { std::mem::transmute(function) }; let function: RValue<'gcc> = unsafe { std::mem::transmute(function) };
let c = bx.call(fn_ty, None, function, &args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(), None); let c = bx.call(
fn_ty,
None,
function,
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
None,
);
Ok(c) Ok(c)
} }
@ -518,7 +556,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
simd_neg: Int => neg, Float => fneg; simd_neg: Int => neg, Float => fneg;
} }
#[cfg(feature="master")] #[cfg(feature = "master")]
if name == sym::simd_saturating_add || name == sym::simd_saturating_sub { if name == sym::simd_saturating_add || name == sym::simd_saturating_sub {
let lhs = args[0].immediate(); let lhs = args[0].immediate();
let rhs = args[1].immediate(); let rhs = args[1].immediate();
@ -536,18 +574,23 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
}); });
} }
}; };
let builtin_name = let builtin_name = match (signed, is_add, in_len, elem_width) {
match (signed, is_add, in_len, elem_width) { (true, true, 32, 8) => "__builtin_ia32_paddsb256", // TODO(antoyo): cast arguments to unsigned.
(true, true, 32, 8) => "__builtin_ia32_paddsb256", // TODO(antoyo): cast arguments to unsigned. (false, true, 32, 8) => "__builtin_ia32_paddusb256",
(false, true, 32, 8) => "__builtin_ia32_paddusb256", (true, true, 16, 16) => "__builtin_ia32_paddsw256",
(true, true, 16, 16) => "__builtin_ia32_paddsw256", (false, true, 16, 16) => "__builtin_ia32_paddusw256",
(false, true, 16, 16) => "__builtin_ia32_paddusw256", (true, false, 16, 16) => "__builtin_ia32_psubsw256",
(true, false, 16, 16) => "__builtin_ia32_psubsw256", (false, false, 16, 16) => "__builtin_ia32_psubusw256",
(false, false, 16, 16) => "__builtin_ia32_psubusw256", (true, false, 32, 8) => "__builtin_ia32_psubsb256",
(true, false, 32, 8) => "__builtin_ia32_psubsb256", (false, false, 32, 8) => "__builtin_ia32_psubusb256",
(false, false, 32, 8) => "__builtin_ia32_psubusb256", _ => unimplemented!(
_ => unimplemented!("signed: {}, is_add: {}, in_len: {}, elem_width: {}", signed, is_add, in_len, elem_width), "signed: {}, is_add: {}, in_len: {}, elem_width: {}",
}; signed,
is_add,
in_len,
elem_width
),
};
let vec_ty = bx.cx.type_vector(elem_ty, in_len as u64); let vec_ty = bx.cx.type_vector(elem_ty, in_len as u64);
let func = bx.context.get_target_builtin_function(builtin_name); let func = bx.context.get_target_builtin_function(builtin_name);
@ -575,8 +618,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
// if overflow occurs, the result is the // if overflow occurs, the result is the
// mathematical result modulo 2^n: // mathematical result modulo 2^n:
Ok(bx.$op(args[1].immediate(), r)) Ok(bx.$op(args[1].immediate(), r))
} } else {
else {
Ok(bx.vector_reduce_op(args[0].immediate(), $vec_op)) Ok(bx.vector_reduce_op(args[0].immediate(), $vec_op))
} }
} }
@ -585,12 +627,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
// ordered arithmetic reductions take an accumulator // ordered arithmetic reductions take an accumulator
let acc = args[1].immediate(); let acc = args[1].immediate();
Ok(bx.$float_reduce(acc, args[0].immediate())) Ok(bx.$float_reduce(acc, args[0].immediate()))
} } else {
else {
Ok(bx.vector_reduce_op(args[0].immediate(), $vec_op)) Ok(bx.vector_reduce_op(args[0].immediate(), $vec_op))
} }
} }
_ => return_error!(InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }), _ => return_error!(InvalidMonomorphizationUnsupportedElement {
span,
name,
in_ty,
elem_ty: in_elem,
ret_ty
}),
}; };
} }
}; };
@ -603,13 +650,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
add, add,
0.0 // TODO: Use this argument. 0.0 // TODO: Use this argument.
); );
arith_red!( arith_red!(simd_reduce_mul_unordered: BinaryOp::Mult, vector_reduce_fmul_fast, false, mul, 1.0);
simd_reduce_mul_unordered: BinaryOp::Mult,
vector_reduce_fmul_fast,
false,
mul,
1.0
);
macro_rules! minmax_red { macro_rules! minmax_red {
($name:ident: $reduction:ident) => { ($name:ident: $reduction:ident) => {
@ -619,8 +660,16 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty } InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty }
); );
return match in_elem.kind() { return match in_elem.kind() {
ty::Int(_) | ty::Uint(_) | ty::Float(_) => Ok(bx.$reduction(args[0].immediate())), ty::Int(_) | ty::Uint(_) | ty::Float(_) => {
_ => return_error!(InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }), Ok(bx.$reduction(args[0].immediate()))
}
_ => return_error!(InvalidMonomorphizationUnsupportedElement {
span,
name,
in_ty,
elem_ty: in_elem,
ret_ty
}),
}; };
} }
}; };
@ -641,7 +690,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
} else { } else {
match in_elem.kind() { match in_elem.kind() {
ty::Int(_) | ty::Uint(_) => {} ty::Int(_) | ty::Uint(_) => {}
_ => return_error!(InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }), _ => return_error!(InvalidMonomorphizationUnsupportedElement {
span,
name,
in_ty,
elem_ty: in_elem,
ret_ty
}),
} }
// boolean reductions operate on vectors of i1s: // boolean reductions operate on vectors of i1s:
@ -654,9 +709,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let r = bx.vector_reduce_op(input, $op); let r = bx.vector_reduce_op(input, $op);
Ok(if !$boolean { r } else { bx.zext(r, bx.type_bool()) }) Ok(if !$boolean { r } else { bx.zext(r, bx.type_bool()) })
} }
_ => return_error!( _ => return_error!(InvalidMonomorphizationUnsupportedElement {
InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty } span,
), name,
in_ty,
elem_ty: in_elem,
ret_ty
}),
}; };
} }
}; };

View file

@ -132,7 +132,7 @@ fn build_fixed_size_array_di_node<'ll, 'tcx>(
let (size, align) = cx.size_and_align_of(array_type); let (size, align) = cx.size_and_align_of(array_type);
let upper_bound = len.eval_usize(cx.tcx, ty::ParamEnv::reveal_all()) as c_longlong; let upper_bound = len.eval_target_usize(cx.tcx, ty::ParamEnv::reveal_all()) as c_longlong;
let subrange = let subrange =
unsafe { Some(llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)) }; unsafe { Some(llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)) };

View file

@ -877,7 +877,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(), ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(),
ty::Array(elem, len) ty::Array(elem, len)
if matches!(elem.kind(), ty::Uint(ty::UintTy::U8)) if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
&& len.try_eval_usize(bx.tcx, ty::ParamEnv::reveal_all()) && len.try_eval_target_usize(bx.tcx, ty::ParamEnv::reveal_all())
== Some(expected_bytes) => == Some(expected_bytes) =>
{ {
let place = PlaceRef::alloca(bx, args[0].layout); let place = PlaceRef::alloca(bx, args[0].layout);
@ -957,9 +957,9 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
// version of this intrinsic. // version of this intrinsic.
match args[2].layout.ty.kind() { match args[2].layout.ty.kind() {
ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => {
len.try_eval_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(|| { len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(
span_bug!(span, "could not evaluate shuffle index array length") || span_bug!(span, "could not evaluate shuffle index array length"),
}) )
} }
_ => return_error!(InvalidMonomorphization::SimdShuffle { _ => return_error!(InvalidMonomorphization::SimdShuffle {
span, span,
@ -1123,7 +1123,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
} }
ty::Array(elem, len) ty::Array(elem, len)
if matches!(elem.kind(), ty::Uint(ty::UintTy::U8)) if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
&& len.try_eval_usize(bx.tcx, ty::ParamEnv::reveal_all()) && len.try_eval_target_usize(bx.tcx, ty::ParamEnv::reveal_all())
== Some(expected_bytes) => == Some(expected_bytes) =>
{ {
// Zero-extend iN to the array length: // Zero-extend iN to the array length:

View file

@ -148,7 +148,7 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
cx.tcx().struct_lockstep_tails_erasing_lifetimes(source, target, bx.param_env()); cx.tcx().struct_lockstep_tails_erasing_lifetimes(source, target, bx.param_env());
match (source.kind(), target.kind()) { match (source.kind(), target.kind()) {
(&ty::Array(_, len), &ty::Slice(_)) => { (&ty::Array(_, len), &ty::Slice(_)) => {
cx.const_usize(len.eval_usize(cx.tcx(), ty::ParamEnv::reveal_all())) cx.const_usize(len.eval_target_usize(cx.tcx(), ty::ParamEnv::reveal_all()))
} }
( (
&ty::Dynamic(ref data_a, _, src_dyn_kind), &ty::Dynamic(ref data_a, _, src_dyn_kind),

View file

@ -181,16 +181,24 @@ fn push_debuginfo_type_name<'tcx>(
push_debuginfo_type_name(tcx, inner_type, true, output, visited); push_debuginfo_type_name(tcx, inner_type, true, output, visited);
match len.kind() { match len.kind() {
ty::ConstKind::Param(param) => write!(output, ",{}>", param.name).unwrap(), ty::ConstKind::Param(param) => write!(output, ",{}>", param.name).unwrap(),
_ => write!(output, ",{}>", len.eval_usize(tcx, ty::ParamEnv::reveal_all())) _ => write!(
.unwrap(), output,
",{}>",
len.eval_target_usize(tcx, ty::ParamEnv::reveal_all())
)
.unwrap(),
} }
} else { } else {
output.push('['); output.push('[');
push_debuginfo_type_name(tcx, inner_type, true, output, visited); push_debuginfo_type_name(tcx, inner_type, true, output, visited);
match len.kind() { match len.kind() {
ty::ConstKind::Param(param) => write!(output, "; {}]", param.name).unwrap(), ty::ConstKind::Param(param) => write!(output, "; {}]", param.name).unwrap(),
_ => write!(output, "; {}]", len.eval_usize(tcx, ty::ParamEnv::reveal_all())) _ => write!(
.unwrap(), output,
"; {}]",
len.eval_target_usize(tcx, ty::ParamEnv::reveal_all())
)
.unwrap(),
} }
} }
} }

View file

@ -100,8 +100,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
} }
} }
let count = let count = self
self.monomorphize(count).eval_usize(bx.cx().tcx(), ty::ParamEnv::reveal_all()); .monomorphize(count)
.eval_target_usize(bx.cx().tcx(), ty::ParamEnv::reveal_all());
bx.write_operand_repeatedly(cg_elem, count, dest); bx.write_operand_repeatedly(cg_elem, count, dest);
} }
@ -492,7 +493,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
if let Some(index) = place.as_local() { if let Some(index) = place.as_local() {
if let LocalRef::Operand(Some(op)) = self.locals[index] { if let LocalRef::Operand(Some(op)) = self.locals[index] {
if let ty::Array(_, n) = op.layout.ty.kind() { if let ty::Array(_, n) = op.layout.ty.kind() {
let n = n.eval_usize(bx.cx().tcx(), ty::ParamEnv::reveal_all()); let n = n.eval_target_usize(bx.cx().tcx(), ty::ParamEnv::reveal_all());
return bx.cx().const_usize(n); return bx.cx().const_usize(n);
} }
} }

View file

@ -107,7 +107,7 @@ pub(crate) fn try_destructure_mir_constant<'tcx>(
// We go to `usize` as we cannot allocate anything bigger anyway. // We go to `usize` as we cannot allocate anything bigger anyway.
let (field_count, variant, down) = match val.ty().kind() { let (field_count, variant, down) = match val.ty().kind() {
ty::Array(_, len) => (len.eval_usize(tcx, param_env) as usize, None, op), ty::Array(_, len) => (len.eval_target_usize(tcx, param_env) as usize, None, op),
ty::Adt(def, _) if def.variants().is_empty() => { ty::Adt(def, _) if def.variants().is_empty() => {
throw_ub!(Unreachable) throw_ub!(Unreachable)
} }

View file

@ -328,8 +328,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
(&ty::Array(_, length), &ty::Slice(_)) => { (&ty::Array(_, length), &ty::Slice(_)) => {
let ptr = self.read_scalar(src)?; let ptr = self.read_scalar(src)?;
// u64 cast is from usize to u64, which is always good // u64 cast is from usize to u64, which is always good
let val = let val = Immediate::new_slice(
Immediate::new_slice(ptr, length.eval_usize(*self.tcx, self.param_env), self); ptr,
length.eval_target_usize(*self.tcx, self.param_env),
self,
);
self.write_immediate(val, dest) self.write_immediate(val, dest)
} }
(ty::Dynamic(data_a, ..), ty::Dynamic(data_b, ..)) => { (ty::Dynamic(data_a, ..), ty::Dynamic(data_b, ..)) => {

View file

@ -473,7 +473,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
// that this is merely a ZST and it is already eligible for promotion. // that this is merely a ZST and it is already eligible for promotion.
// This may require an RFC? // This may require an RFC?
/* /*
ty::Array(_, len) if len.try_eval_usize(cx.tcx, cx.param_env) == Some(0) ty::Array(_, len) if len.try_eval_target_usize(cx.tcx, cx.param_env) == Some(0)
=> true, => true,
*/ */
_ => false, _ => false,

View file

@ -364,31 +364,33 @@ impl<'tcx> Validator<'_, 'tcx> {
ProjectionElem::Index(local) => { ProjectionElem::Index(local) => {
let mut promotable = false; let mut promotable = false;
// Only accept if we can predict the index and are indexing an array. // Only accept if we can predict the index and are indexing an array.
let val = let val = if let TempState::Defined { location: loc, .. } =
if let TempState::Defined { location: loc, .. } = self.temps[local] { self.temps[local]
let block = &self.body[loc.block]; {
if loc.statement_index < block.statements.len() { let block = &self.body[loc.block];
let statement = &block.statements[loc.statement_index]; if loc.statement_index < block.statements.len() {
match &statement.kind { let statement = &block.statements[loc.statement_index];
StatementKind::Assign(box ( match &statement.kind {
_, StatementKind::Assign(box (
Rvalue::Use(Operand::Constant(c)), _,
)) => c.literal.try_eval_usize(self.tcx, self.param_env), Rvalue::Use(Operand::Constant(c)),
_ => None, )) => c.literal.try_eval_target_usize(self.tcx, self.param_env),
} _ => None,
} else {
None
} }
} else { } else {
None None
}; }
} else {
None
};
if let Some(idx) = val { if let Some(idx) = val {
// Determine the type of the thing we are indexing. // Determine the type of the thing we are indexing.
let ty = place_base.ty(self.body, self.tcx).ty; let ty = place_base.ty(self.body, self.tcx).ty;
match ty.kind() { match ty.kind() {
ty::Array(_, len) => { ty::Array(_, len) => {
// It's an array; determine its length. // It's an array; determine its length.
if let Some(len) = len.try_eval_usize(self.tcx, self.param_env) if let Some(len) =
len.try_eval_target_usize(self.tcx, self.param_env)
{ {
// If the index is in-bounds, go ahead. // If the index is in-bounds, go ahead.
if idx < len { if idx < len {
@ -470,7 +472,7 @@ impl<'tcx> Validator<'_, 'tcx> {
// mutably without consequences. However, only &mut [] // mutably without consequences. However, only &mut []
// is allowed right now. // is allowed right now.
if let ty::Array(_, len) = ty.kind() { if let ty::Array(_, len) = ty.kind() {
match len.try_eval_usize(self.tcx, self.param_env) { match len.try_eval_target_usize(self.tcx, self.param_env) {
Some(0) => {} Some(0) => {}
_ => return Err(Unpromotable), _ => return Err(Unpromotable),
} }

View file

@ -901,7 +901,7 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
} }
let len = if let ty::Array(_ty, c) = e.kind() { let len = if let ty::Array(_ty, c) = e.kind() {
c.try_eval_usize(tcx, tcx.param_env(def.did())) c.try_eval_target_usize(tcx, tcx.param_env(def.did()))
} else { } else {
Some(fields.len() as u64) Some(fields.len() as u64)
}; };

View file

@ -1396,7 +1396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> Ty<'tcx> { ) -> Ty<'tcx> {
let tcx = self.tcx; let tcx = self.tcx;
let count = self.array_length_to_const(count); let count = self.array_length_to_const(count);
if let Some(count) = count.try_eval_usize(tcx, self.param_env) { if let Some(count) = count.try_eval_target_usize(tcx, self.param_env) {
self.suggest_array_len(expr, count); self.suggest_array_len(expr, count);
} }
@ -1463,7 +1463,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we // If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we
// don't copy that one element, we move it. Only check for Copy if the length is larger. // don't copy that one element, we move it. Only check for Copy if the length is larger.
if count.try_eval_usize(tcx, self.param_env).map_or(true, |len| len > 1) { if count.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
let lang_item = self.tcx.require_lang_item(LangItem::Copy, None); let lang_item = self.tcx.require_lang_item(LangItem::Copy, None);
let code = traits::ObligationCauseCode::RepeatElementCopy { is_const_fn }; let code = traits::ObligationCauseCode::RepeatElementCopy { is_const_fn };
self.require_type_meets(element_ty, element.span, code, lang_item); self.require_type_meets(element_ty, element.span, code, lang_item);
@ -2602,7 +2602,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
len: ty::Const<'tcx>, len: ty::Const<'tcx>,
) { ) {
if let (Some(len), Ok(user_index)) = if let (Some(len), Ok(user_index)) =
(len.try_eval_usize(self.tcx, self.param_env), field.as_str().parse::<u64>()) (len.try_eval_target_usize(self.tcx, self.param_env), field.as_str().parse::<u64>())
&& let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span) && let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span)
{ {
let help = "instead of using tuple indexing, use array indexing"; let help = "instead of using tuple indexing, use array indexing";

View file

@ -647,7 +647,8 @@ fn check_must_not_suspend_ty<'tcx>(
hir_id, hir_id,
SuspendCheckData { SuspendCheckData {
descr_pre, descr_pre,
plural_len: len.try_eval_usize(fcx.tcx, fcx.param_env).unwrap_or(0) as usize plural_len: len.try_eval_target_usize(fcx.tcx, fcx.param_env).unwrap_or(0)
as usize
+ 1, + 1,
..data ..data
}, },

View file

@ -2063,7 +2063,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
len: ty::Const<'tcx>, len: ty::Const<'tcx>,
min_len: u64, min_len: u64,
) -> (Option<Ty<'tcx>>, Ty<'tcx>) { ) -> (Option<Ty<'tcx>>, Ty<'tcx>) {
if let Some(len) = len.try_eval_usize(self.tcx, self.param_env) { if let Some(len) = len.try_eval_target_usize(self.tcx, self.param_env) {
// Now we know the length... // Now we know the length...
if slice.is_none() { if slice.is_none() {
// ...and since there is no variable-length pattern, // ...and since there is no variable-length pattern,

View file

@ -2605,7 +2605,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
ty.tuple_fields().iter().find_map(|field| ty_find_init_error(cx, field, init)) ty.tuple_fields().iter().find_map(|field| ty_find_init_error(cx, field, init))
} }
Array(ty, len) => { Array(ty, len) => {
if matches!(len.try_eval_usize(cx.tcx, cx.param_env), Some(v) if v > 0) { if matches!(len.try_eval_target_usize(cx.tcx, cx.param_env), Some(v) if v > 0) {
// Array length known at array non-empty -- recurse. // Array length known at array non-empty -- recurse.
ty_find_init_error(cx, *ty, init) ty_find_init_error(cx, *ty, init)
} else { } else {

View file

@ -309,7 +309,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
None None
} }
} }
ty::Array(ty, len) => match len.try_eval_usize(cx.tcx, cx.param_env) { ty::Array(ty, len) => match len.try_eval_target_usize(cx.tcx, cx.param_env) {
// If the array is empty we don't lint, to avoid false positives // If the array is empty we don't lint, to avoid false positives
Some(0) | None => None, Some(0) | None => None,
// If the array is definitely non-empty, we can do `#[must_use]` checking. // If the array is definitely non-empty, we can do `#[must_use]` checking.

View file

@ -2344,9 +2344,13 @@ impl<'tcx> ConstantKind<'tcx> {
} }
#[inline] #[inline]
pub fn try_eval_usize(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option<u64> { pub fn try_eval_target_usize(
&self,
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> Option<u64> {
match self { match self {
Self::Ty(ct) => ct.try_eval_usize(tcx, param_env), Self::Ty(ct) => ct.try_eval_target_usize(tcx, param_env),
Self::Val(val, _) => val.try_to_machine_usize(tcx), Self::Val(val, _) => val.try_to_machine_usize(tcx),
Self::Unevaluated(uneval, _) => { Self::Unevaluated(uneval, _) => {
match tcx.const_eval_resolve(param_env, *uneval, None) { match tcx.const_eval_resolve(param_env, *uneval, None) {

View file

@ -97,7 +97,7 @@ impl<'tcx> PlaceTy<'tcx> {
ty::Slice(..) => self.ty, ty::Slice(..) => self.ty,
ty::Array(inner, _) if !from_end => tcx.mk_array(*inner, (to - from) as u64), ty::Array(inner, _) if !from_end => tcx.mk_array(*inner, (to - from) as u64),
ty::Array(inner, size) if from_end => { ty::Array(inner, size) if from_end => {
let size = size.eval_usize(tcx, param_env); let size = size.eval_target_usize(tcx, param_env);
let len = size - (from as u64) - (to as u64); let len = size - (from as u64) - (to as u64);
tcx.mk_array(*inner, len) tcx.mk_array(*inner, len)
} }

View file

@ -175,7 +175,7 @@ impl<'tcx> Const<'tcx> {
#[inline] #[inline]
/// Creates an interned usize constant. /// Creates an interned usize constant.
pub fn from_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self { pub fn from_target_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self {
Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize)) Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize))
} }
@ -201,7 +201,11 @@ impl<'tcx> Const<'tcx> {
} }
#[inline] #[inline]
pub fn try_eval_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<u64> { pub fn try_eval_target_usize(
self,
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
) -> Option<u64> {
self.kind().eval(tcx, param_env).try_to_machine_usize(tcx) self.kind().eval(tcx, param_env).try_to_machine_usize(tcx)
} }
@ -229,8 +233,8 @@ impl<'tcx> Const<'tcx> {
#[inline] #[inline]
/// Panics if the value cannot be evaluated or doesn't contain a valid `usize`. /// Panics if the value cannot be evaluated or doesn't contain a valid `usize`.
pub fn eval_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 { pub fn eval_target_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 {
self.try_eval_usize(tcx, param_env) self.try_eval_target_usize(tcx, param_env)
.unwrap_or_else(|| bug!("expected usize, got {:#?}", self)) .unwrap_or_else(|| bug!("expected usize, got {:#?}", self))
} }

View file

@ -1787,7 +1787,7 @@ impl<'tcx> TyCtxt<'tcx> {
#[inline] #[inline]
pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> { pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
self.mk_ty(Array(ty, ty::Const::from_usize(self, n))) self.mk_ty(Array(ty, ty::Const::from_target_usize(self, n)))
} }
#[inline] #[inline]

View file

@ -57,7 +57,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
match self { match self {
Self::False => Ok(false), Self::False => Ok(false),
Self::True => Ok(true), Self::True => Ok(true),
Self::ConstIsZero(const_) => match const_.try_eval_usize(tcx, param_env) { Self::ConstIsZero(const_) => match const_.try_eval_target_usize(tcx, param_env) {
None | Some(0) => Ok(true), None | Some(0) => Ok(true),
Some(1..) => Ok(false), Some(1..) => Ok(false),
}, },

View file

@ -511,8 +511,8 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
// we however cannot end up with errors in `Relate` during both // we however cannot end up with errors in `Relate` during both
// `type_of` and `predicates_of`. This means that evaluating the // `type_of` and `predicates_of`. This means that evaluating the
// constants should not cause cycle errors here. // constants should not cause cycle errors here.
let sz_a = sz_a.try_eval_usize(tcx, relation.param_env()); let sz_a = sz_a.try_eval_target_usize(tcx, relation.param_env());
let sz_b = sz_b.try_eval_usize(tcx, relation.param_env()); let sz_b = sz_b.try_eval_target_usize(tcx, relation.param_env());
match (sz_a, sz_b) { match (sz_a, sz_b) {
(Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => Err( (Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => Err(
TypeError::FixedArraySize(expected_found(relation, sz_a_val, sz_b_val)), TypeError::FixedArraySize(expected_found(relation, sz_a_val, sz_b_val)),

View file

@ -1879,7 +1879,7 @@ impl<'tcx> Ty<'tcx> {
// The way we evaluate the `N` in `[T; N]` here only works since we use // The way we evaluate the `N` in `[T; N]` here only works since we use
// `simd_size_and_type` post-monomorphization. It will probably start to ICE // `simd_size_and_type` post-monomorphization. It will probably start to ICE
// if we use it in generic code. See the `simd-array-trait` ui test. // if we use it in generic code. See the `simd-array-trait` ui test.
(f0_len.eval_usize(tcx, ParamEnv::empty()) as u64, *f0_elem_ty) (f0_len.eval_target_usize(tcx, ParamEnv::empty()) as u64, *f0_elem_ty)
} }
// Otherwise, the fields of this Adt are the SIMD components (and we assume they // Otherwise, the fields of this Adt are the SIMD components (and we assume they
// all have the same type). // all have the same type).

View file

@ -55,7 +55,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}) })
} }
ExprKind::Repeat { value, count } => { ExprKind::Repeat { value, count } => {
if Some(0) == count.try_eval_usize(this.tcx, this.param_env) { if Some(0) == count.try_eval_target_usize(this.tcx, this.param_env) {
this.build_zero_repeat(block, value, scope, source_info) this.build_zero_repeat(block, value, scope, source_info)
} else { } else {
let value_operand = unpack!( let value_operand = unpack!(

View file

@ -35,7 +35,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let tcx = self.tcx; let tcx = self.tcx;
let (min_length, exact_size) = if let Some(place_resolved) = place.try_to_place(self) { let (min_length, exact_size) = if let Some(place_resolved) = place.try_to_place(self) {
match place_resolved.ty(&self.local_decls, tcx).ty.kind() { match place_resolved.ty(&self.local_decls, tcx).ty.kind() {
ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true), ty::Array(_, length) => (length.eval_target_usize(tcx, self.param_env), true),
_ => ((prefix.len() + suffix.len()).try_into().unwrap(), false), _ => ((prefix.len() + suffix.len()).try_into().unwrap(), false),
} }
} else { } else {

View file

@ -922,8 +922,8 @@ impl<'tcx> SplitWildcard<'tcx> {
// `cx.is_uninhabited()`). // `cx.is_uninhabited()`).
let all_ctors = match pcx.ty.kind() { let all_ctors = match pcx.ty.kind() {
ty::Bool => smallvec![make_range(0, 1)], ty::Bool => smallvec![make_range(0, 1)],
ty::Array(sub_ty, len) if len.try_eval_usize(cx.tcx, cx.param_env).is_some() => { ty::Array(sub_ty, len) if len.try_eval_target_usize(cx.tcx, cx.param_env).is_some() => {
let len = len.eval_usize(cx.tcx, cx.param_env) as usize; let len = len.eval_target_usize(cx.tcx, cx.param_env) as usize;
if len != 0 && cx.is_uninhabited(*sub_ty) { if len != 0 && cx.is_uninhabited(*sub_ty) {
smallvec![] smallvec![]
} else { } else {
@ -1406,7 +1406,9 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
} }
PatKind::Array { prefix, slice, suffix } | PatKind::Slice { prefix, slice, suffix } => { PatKind::Array { prefix, slice, suffix } | PatKind::Slice { prefix, slice, suffix } => {
let array_len = match pat.ty.kind() { let array_len = match pat.ty.kind() {
ty::Array(_, length) => Some(length.eval_usize(cx.tcx, cx.param_env) as usize), ty::Array(_, length) => {
Some(length.eval_target_usize(cx.tcx, cx.param_env) as usize)
}
ty::Slice(_) => None, ty::Slice(_) => None,
_ => span_bug!(pat.span, "bad ty {:?} for slice pattern", pat.ty), _ => span_bug!(pat.span, "bad ty {:?} for slice pattern", pat.ty),
}; };

View file

@ -416,7 +416,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
ty::Slice(..) => PatKind::Slice { prefix, slice, suffix }, ty::Slice(..) => PatKind::Slice { prefix, slice, suffix },
// Fixed-length array, `[T; len]`. // Fixed-length array, `[T; len]`.
ty::Array(_, len) => { ty::Array(_, len) => {
let len = len.eval_usize(self.tcx, self.param_env); let len = len.eval_target_usize(self.tcx, self.param_env);
assert!(len >= prefix.len() as u64 + suffix.len() as u64); assert!(len >= prefix.len() as u64 + suffix.len() as u64);
PatKind::Array { prefix, slice, suffix } PatKind::Array { prefix, slice, suffix }
} }

View file

@ -890,7 +890,7 @@ where
} }
ty::Dynamic(..) => self.complete_drop(self.succ, self.unwind), ty::Dynamic(..) => self.complete_drop(self.succ, self.unwind),
ty::Array(ety, size) => { ty::Array(ety, size) => {
let size = size.try_eval_usize(self.tcx(), self.elaborator.param_env()); let size = size.try_eval_target_usize(self.tcx(), self.elaborator.param_env());
self.open_drop_for_array(*ety, size) self.open_drop_for_array(*ety, size)
} }
ty::Slice(ety) => self.open_drop_for_array(*ety, None), ty::Slice(ety) => self.open_drop_for_array(*ety, None),

View file

@ -490,7 +490,9 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
}; };
let base_ty = base_place.ty(self.builder.body, self.builder.tcx).ty; let base_ty = base_place.ty(self.builder.body, self.builder.tcx).ty;
let len: u64 = match base_ty.kind() { let len: u64 = match base_ty.kind() {
ty::Array(_, size) => size.eval_usize(self.builder.tcx, self.builder.param_env), ty::Array(_, size) => {
size.eval_target_usize(self.builder.tcx, self.builder.param_env)
}
_ => bug!("from_end: false slice pattern of non-array type"), _ => bug!("from_end: false slice pattern of non-array type"),
}; };
for offset in from..to { for offset in from..to {

View file

@ -1845,7 +1845,7 @@ fn check_must_not_suspend_ty<'tcx>(
param_env, param_env,
SuspendCheckData { SuspendCheckData {
descr_pre, descr_pre,
plural_len: len.try_eval_usize(tcx, param_env).unwrap_or(0) as usize + 1, plural_len: len.try_eval_target_usize(tcx, param_env).unwrap_or(0) as usize + 1,
..data ..data
}, },
) )

View file

@ -143,7 +143,7 @@ impl EnumSizeOpt {
let tmp_ty = tcx.mk_ty(ty::Array( let tmp_ty = tcx.mk_ty(ty::Array(
tcx.types.usize, tcx.types.usize,
Const::from_usize(tcx, num_variants as u64), Const::from_target_usize(tcx, num_variants as u64),
)); ));
let size_array_local = local_decls.push(LocalDecl::new(tmp_ty, span)); let size_array_local = local_decls.push(LocalDecl::new(tmp_ty, span));

View file

@ -112,7 +112,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Search<'tcx> {
return ControlFlow::Continue(()); return ControlFlow::Continue(());
} }
ty::Array(_, n) ty::Array(_, n)
if { n.try_eval_usize(self.tcx, ty::ParamEnv::reveal_all()) == Some(0) } => if { n.try_eval_target_usize(self.tcx, ty::ParamEnv::reveal_all()) == Some(0) } =>
{ {
// rust-lang/rust#62336: ignore type of contents // rust-lang/rust#62336: ignore type of contents
// for empty array. // for empty array.

View file

@ -284,8 +284,9 @@ pub(crate) mod rustc {
} }
ty::Array(ty, len) => { ty::Array(ty, len) => {
let len = let len = len
len.try_eval_usize(tcx, ParamEnv::reveal_all()).ok_or(Err::Unspecified)?; .try_eval_target_usize(tcx, ParamEnv::reveal_all())
.ok_or(Err::Unspecified)?;
let elt = Tree::from_ty(*ty, tcx)?; let elt = Tree::from_ty(*ty, tcx)?;
Ok(std::iter::repeat(elt) Ok(std::iter::repeat(elt)
.take(len as usize) .take(len as usize)

View file

@ -209,7 +209,8 @@ fn layout_of_uncached<'tcx>(
} }
} }
let count = count.try_eval_usize(tcx, param_env).ok_or(LayoutError::Unknown(ty))?; let count =
count.try_eval_target_usize(tcx, param_env).ok_or(LayoutError::Unknown(ty))?;
let element = cx.layout_of(element)?; let element = cx.layout_of(element)?;
let size = element.size.checked_mul(count, dl).ok_or(LayoutError::SizeOverflow(ty))?; let size = element.size.checked_mul(count, dl).ok_or(LayoutError::SizeOverflow(ty))?;

View file

@ -109,7 +109,7 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing {
if let Some(range) = higher::Range::hir(index) { if let Some(range) = higher::Range::hir(index) {
// Ranged indexes, i.e., &x[n..m], &x[n..], &x[..n] and &x[..] // Ranged indexes, i.e., &x[n..m], &x[n..], &x[..n] and &x[..]
if let ty::Array(_, s) = ty.kind() { if let ty::Array(_, s) = ty.kind() {
let size: u128 = if let Some(size) = s.try_eval_usize(cx.tcx, cx.param_env) { let size: u128 = if let Some(size) = s.try_eval_target_usize(cx.tcx, cx.param_env) {
size.into() size.into()
} else { } else {
return; return;

View file

@ -68,7 +68,7 @@ fn is_iterable_array<'tcx>(ty: Ty<'tcx>, cx: &LateContext<'tcx>) -> bool {
// IntoIterator is currently only implemented for array sizes <= 32 in rustc // IntoIterator is currently only implemented for array sizes <= 32 in rustc
match ty.kind() { match ty.kind() {
ty::Array(_, n) => n ty::Array(_, n) => n
.try_eval_usize(cx.tcx, cx.param_env) .try_eval_target_usize(cx.tcx, cx.param_env)
.map_or(false, |val| (0..=32).contains(&val)), .map_or(false, |val| (0..=32).contains(&val)),
_ => false, _ => false,
} }

View file

@ -211,7 +211,7 @@ fn is_end_eq_array_len<'tcx>(
if let ExprKind::Lit(ref lit) = end.kind; if let ExprKind::Lit(ref lit) = end.kind;
if let ast::LitKind::Int(end_int, _) = lit.node; if let ast::LitKind::Int(end_int, _) = lit.node;
if let ty::Array(_, arr_len_const) = indexed_ty.kind(); if let ty::Array(_, arr_len_const) = indexed_ty.kind();
if let Some(arr_len) = arr_len_const.try_eval_usize(cx.tcx, cx.param_env); if let Some(arr_len) = arr_len_const.try_eval_target_usize(cx.tcx, cx.param_env);
then { then {
return match limits { return match limits {
ast::RangeLimits::Closed => end_int + 1 >= arr_len.into(), ast::RangeLimits::Closed => end_int + 1 >= arr_len.into(),

View file

@ -22,7 +22,7 @@ pub(super) fn derefs_to_slice<'tcx>(
ty::Slice(_) => true, ty::Slice(_) => true,
ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()),
ty::Adt(..) => is_type_diagnostic_item(cx, ty, sym::Vec), ty::Adt(..) => is_type_diagnostic_item(cx, ty, sym::Vec),
ty::Array(_, size) => size.try_eval_usize(cx.tcx, cx.param_env).is_some(), ty::Array(_, size) => size.try_eval_target_usize(cx.tcx, cx.param_env).is_some(),
ty::Ref(_, inner, _) => may_slice(cx, *inner), ty::Ref(_, inner, _) => may_slice(cx, *inner),
_ => false, _ => false,
} }

View file

@ -166,7 +166,7 @@ impl MutableKeyType {
Ref(_, inner_ty, mutbl) => mutbl == hir::Mutability::Mut || self.is_interior_mutable_type(cx, inner_ty), Ref(_, inner_ty, mutbl) => mutbl == hir::Mutability::Mut || self.is_interior_mutable_type(cx, inner_ty),
Slice(inner_ty) => self.is_interior_mutable_type(cx, inner_ty), Slice(inner_ty) => self.is_interior_mutable_type(cx, inner_ty),
Array(inner_ty, size) => { Array(inner_ty, size) => {
size.try_eval_usize(cx.tcx, cx.param_env).map_or(true, |u| u != 0) size.try_eval_target_usize(cx.tcx, cx.param_env).map_or(true, |u| u != 0)
&& self.is_interior_mutable_type(cx, inner_ty) && self.is_interior_mutable_type(cx, inner_ty)
}, },
Tuple(fields) => fields.iter().any(|ty| self.is_interior_mutable_type(cx, ty)), Tuple(fields) => fields.iter().any(|ty| self.is_interior_mutable_type(cx, ty)),

View file

@ -62,7 +62,7 @@ fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'_>, item: &Item<'_
// Then check if that that array zero-sized // Then check if that that array zero-sized
let length = Const::from_anon_const(cx.tcx, length.def_id); let length = Const::from_anon_const(cx.tcx, length.def_id);
let length = length.try_eval_usize(cx.tcx, cx.param_env); let length = length.try_eval_target_usize(cx.tcx, cx.param_env);
if let Some(length) = length; if let Some(length) = length;
then { then {
length == 0 length == 0

View file

@ -335,7 +335,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
ExprKind::Tup(tup) => self.multi(tup).map(Constant::Tuple), ExprKind::Tup(tup) => self.multi(tup).map(Constant::Tuple),
ExprKind::Repeat(value, _) => { ExprKind::Repeat(value, _) => {
let n = match self.typeck_results.expr_ty(e).kind() { let n = match self.typeck_results.expr_ty(e).kind() {
ty::Array(_, n) => n.try_eval_usize(self.lcx.tcx, self.lcx.param_env)?, ty::Array(_, n) => n.try_eval_target_usize(self.lcx.tcx, self.lcx.param_env)?,
_ => span_bug!(e.span, "typeck error"), _ => span_bug!(e.span, "typeck error"),
}; };
self.expr(value).map(|v| Constant::Repeat(Box::new(v), n)) self.expr(value).map(|v| Constant::Repeat(Box::new(v), n))

View file

@ -949,7 +949,7 @@ pub fn approx_ty_size<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> u64 {
(Ok(size), _) => size, (Ok(size), _) => size,
(Err(_), ty::Tuple(list)) => list.as_substs().types().map(|t| approx_ty_size(cx, t)).sum(), (Err(_), ty::Tuple(list)) => list.as_substs().types().map(|t| approx_ty_size(cx, t)).sum(),
(Err(_), ty::Array(t, n)) => { (Err(_), ty::Array(t, n)) => {
n.try_eval_usize(cx.tcx, cx.param_env).unwrap_or_default() * approx_ty_size(cx, *t) n.try_eval_target_usize(cx.tcx, cx.param_env).unwrap_or_default() * approx_ty_size(cx, *t)
}, },
(Err(_), ty::Adt(def, subst)) if def.is_struct() => def (Err(_), ty::Adt(def, subst)) if def.is_struct() => def
.variants() .variants()

View file

@ -469,7 +469,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let ty::Array(_, index_len) = index.layout.ty.kind() else { let ty::Array(_, index_len) = index.layout.ty.kind() else {
span_bug!(this.cur_span(), "simd_shuffle index argument has non-array type {}", index.layout.ty) span_bug!(this.cur_span(), "simd_shuffle index argument has non-array type {}", index.layout.ty)
}; };
let index_len = index_len.eval_usize(*this.tcx, this.param_env()); let index_len = index_len.eval_target_usize(*this.tcx, this.param_env());
assert_eq!(left_len, right_len); assert_eq!(left_len, right_len);
assert_eq!(index_len, dest_len); assert_eq!(index_len, dest_len);