Auto merge of #123897 - matthiaskrgr:rollup-v0vvcw2, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #123530 (Enable building tier2 target riscv32im-unknown-none-elf) - #123642 (do not allow using local llvm while using rustc from ci) - #123716 (Update documentation of Path::to_path_buf and Path::ancestors) - #123876 (Update backtrace submodule) - #123888 (Replace a `DefiningOpaqueTypes::No` with `Yes` by asserting that one side of the comparison is a type variable.) - #123890 (removed (mostly) unused code) - #123891 (Miri subtree update) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
618c300497
14 changed files with 129 additions and 227 deletions
|
@ -505,7 +505,6 @@ fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
}
|
||||
|
||||
pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
let _indenter = indenter();
|
||||
match tcx.def_kind(def_id) {
|
||||
DefKind::Static { .. } => {
|
||||
tcx.ensure().typeck(def_id);
|
||||
|
|
|
@ -103,7 +103,6 @@ use rustc_trait_selection::traits::ObligationCtxt;
|
|||
|
||||
use crate::errors;
|
||||
use crate::require_c_abi_if_c_variadic;
|
||||
use crate::util::common::indenter;
|
||||
|
||||
use self::compare_impl_item::collect_return_position_impl_trait_in_trait_tys;
|
||||
use self::region::region_scope_tree;
|
||||
|
|
|
@ -103,7 +103,6 @@ use rustc_middle::middle;
|
|||
use rustc_middle::mir::interpret::GlobalId;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::util;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::{symbol::sym, Span};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
|
|
@ -561,9 +561,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
// Unify `interior` with `witness` and collect all the resulting obligations.
|
||||
let span = self.tcx.hir().body(body_id).value.span;
|
||||
let ty::Infer(ty::InferTy::TyVar(_)) = interior.kind() else {
|
||||
span_bug!(span, "coroutine interior witness not infer: {:?}", interior.kind())
|
||||
};
|
||||
let ok = self
|
||||
.at(&self.misc(span), self.param_env)
|
||||
.eq(DefineOpaqueTypes::No, interior, witness)
|
||||
// Will never define opaque types, as all we do is instantiate a type variable.
|
||||
.eq(DefineOpaqueTypes::Yes, interior, witness)
|
||||
.expect("Failed to unify coroutine interior type");
|
||||
let mut obligations = ok.obligations;
|
||||
|
||||
|
|
|
@ -1,8 +1,3 @@
|
|||
use rustc_data_structures::sync::Lock;
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
|
@ -26,46 +21,6 @@ pub fn to_readable_str(mut val: usize) -> String {
|
|||
groups.join("_")
|
||||
}
|
||||
|
||||
pub fn record_time<T, F>(accu: &Lock<Duration>, f: F) -> T
|
||||
where
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
let start = Instant::now();
|
||||
let rv = f();
|
||||
let duration = start.elapsed();
|
||||
let mut accu = accu.lock();
|
||||
*accu += duration;
|
||||
rv
|
||||
}
|
||||
|
||||
pub fn indent<R, F>(op: F) -> R
|
||||
where
|
||||
R: Debug,
|
||||
F: FnOnce() -> R,
|
||||
{
|
||||
// Use in conjunction with the log post-processor like `src/etc/indenter`
|
||||
// to make debug output more readable.
|
||||
debug!(">>");
|
||||
let r = op();
|
||||
debug!("<< (Result = {:?})", r);
|
||||
r
|
||||
}
|
||||
|
||||
pub struct Indenter {
|
||||
_cannot_construct_outside_of_this_module: (),
|
||||
}
|
||||
|
||||
impl Drop for Indenter {
|
||||
fn drop(&mut self) {
|
||||
debug!("<<");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn indenter() -> Indenter {
|
||||
debug!(">>");
|
||||
Indenter { _cannot_construct_outside_of_this_module: () }
|
||||
}
|
||||
|
||||
// const wrapper for `if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }`
|
||||
pub const fn c_name(name: &'static str) -> &'static str {
|
||||
// FIXME Simplify the implementation once more `str` methods get const-stable.
|
||||
|
|
|
@ -181,9 +181,9 @@ pub enum TyKind<I: Interner> {
|
|||
/// Looking at the following example, the witness for this coroutine
|
||||
/// may end up as something like `for<'a> [Vec<i32>, &'a Vec<i32>]`:
|
||||
///
|
||||
/// ```ignore UNSOLVED (ask @compiler-errors, should this error? can we just swap the yields?)
|
||||
/// ```
|
||||
/// #![feature(coroutines)]
|
||||
/// |a| {
|
||||
/// static |a| {
|
||||
/// let x = &vec![3];
|
||||
/// yield a;
|
||||
/// yield x[0];
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
#
|
||||
# Note that many of the LLVM options are not currently supported for
|
||||
# downloading. Currently only the "assertions" option can be toggled.
|
||||
#download-ci-llvm = if rust.channel == "dev" { "if-unchanged" } else { false }
|
||||
#download-ci-llvm = if rust.channel == "dev" || rust.download-rustc != false { "if-unchanged" } else { false }
|
||||
|
||||
# Indicates whether the LLVM build is a Release or Debug build
|
||||
#optimize = true
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 6fa4b85b9962c3e1be8c2e5cc605cd078134152b
|
||||
Subproject commit e15130618237eb3e2d4b622549f9647b4c1d9ca3
|
|
@ -2143,10 +2143,10 @@ impl Path {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::path::Path;
|
||||
/// use std::path::{Path, PathBuf};
|
||||
///
|
||||
/// let path_buf = Path::new("foo.txt").to_path_buf();
|
||||
/// assert_eq!(path_buf, std::path::PathBuf::from("foo.txt"));
|
||||
/// assert_eq!(path_buf, PathBuf::from("foo.txt"));
|
||||
/// ```
|
||||
#[rustc_conversion_suggestion]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
|
@ -2278,10 +2278,9 @@ impl Path {
|
|||
/// Produces an iterator over `Path` and its ancestors.
|
||||
///
|
||||
/// The iterator will yield the `Path` that is returned if the [`parent`] method is used zero
|
||||
/// or more times. That means, the iterator will yield `&self`, `&self.parent().unwrap()`,
|
||||
/// `&self.parent().unwrap().parent().unwrap()` and so on. If the [`parent`] method returns
|
||||
/// [`None`], the iterator will do likewise. The iterator will always yield at least one value,
|
||||
/// namely `&self`.
|
||||
/// or more times. If the [`parent`] method returns [`None`], the iterator will do likewise.
|
||||
/// The iterator will always yield at least one value, namely `Some(&self)`. Next it will yield
|
||||
/// `&self.parent()`, `&self.parent().and_then(Path::parent)` and so on.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
|
@ -2483,9 +2483,20 @@ impl Config {
|
|||
llvm::is_ci_llvm_available(self, asserts)
|
||||
}
|
||||
};
|
||||
|
||||
match download_ci_llvm {
|
||||
None => self.channel == "dev" && if_unchanged(),
|
||||
Some(StringOrBool::Bool(b)) => b,
|
||||
None => {
|
||||
(self.channel == "dev" || self.download_rustc_commit.is_some()) && if_unchanged()
|
||||
}
|
||||
Some(StringOrBool::Bool(b)) => {
|
||||
if !b && self.download_rustc_commit.is_some() {
|
||||
panic!(
|
||||
"`llvm.download-ci-llvm` cannot be set to `false` if `rust.download-rustc` is set to `true` or `if-unchanged`."
|
||||
);
|
||||
}
|
||||
|
||||
b
|
||||
}
|
||||
// FIXME: "if-available" is deprecated. Remove this block later (around mid 2024)
|
||||
// to not break builds between the recent-to-old checkouts.
|
||||
Some(StringOrBool::String(s)) if s == "if-available" => {
|
||||
|
|
|
@ -99,6 +99,7 @@ ENV TARGETS=$TARGETS,thumbv8m.base-none-eabi
|
|||
ENV TARGETS=$TARGETS,thumbv8m.main-none-eabi
|
||||
ENV TARGETS=$TARGETS,thumbv8m.main-none-eabihf
|
||||
ENV TARGETS=$TARGETS,riscv32i-unknown-none-elf
|
||||
ENV TARGETS=$TARGETS,riscv32im-unknown-none-elf
|
||||
ENV TARGETS=$TARGETS,riscv32imc-unknown-none-elf
|
||||
ENV TARGETS=$TARGETS,riscv32imac-unknown-none-elf
|
||||
ENV TARGETS=$TARGETS,riscv32imafc-unknown-none-elf
|
||||
|
@ -130,6 +131,8 @@ ENV CFLAGS_armv5te_unknown_linux_musleabi="-march=armv5te -marm -mfloat-abi=soft
|
|||
CFLAGS_aarch64_unknown_none=-mstrict-align -march=armv8-a+fp+simd \
|
||||
CC_riscv32i_unknown_none_elf=riscv32-unknown-elf-gcc \
|
||||
CFLAGS_riscv32i_unknown_none_elf=-march=rv32i -mabi=ilp32 \
|
||||
CC_riscv32im_unknown_none_elf=riscv32-unknown-elf-gcc \
|
||||
CFLAGS_riscv32im_unknown_none_elf=-march=rv32im -mabi=ilp32 \
|
||||
CC_riscv32imc_unknown_none_elf=riscv32-unknown-elf-gcc \
|
||||
CFLAGS_riscv32imc_unknown_none_elf=-march=rv32imc -mabi=ilp32 \
|
||||
CC_riscv32imac_unknown_none_elf=riscv32-unknown-elf-gcc \
|
||||
|
|
|
@ -454,15 +454,10 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
|
|||
continue;
|
||||
}
|
||||
// If the REPLACE_LIBRS hack is enabled and we are building a `lib.rs` file, and a
|
||||
// `lib.miri.rs` file exists, then build that instead. We only consider relative paths
|
||||
// as cargo uses those for files in the workspace; dependencies from crates.io get
|
||||
// absolute paths.
|
||||
// `lib.miri.rs` file exists, then build that instead.
|
||||
if replace_librs {
|
||||
let path = Path::new(&arg);
|
||||
if path.is_relative()
|
||||
&& path.file_name().is_some_and(|f| f == "lib.rs")
|
||||
&& path.is_file()
|
||||
{
|
||||
if path.file_name().is_some_and(|f| f == "lib.rs") && path.is_file() {
|
||||
let miri_rs = Path::new(&arg).with_extension("miri.rs");
|
||||
if miri_rs.is_file() {
|
||||
if verbose > 0 {
|
||||
|
|
|
@ -468,6 +468,86 @@ fn unary_op_ps<'tcx>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
enum ShiftOp {
|
||||
/// Shift left, logically (shift in zeros) -- same as shift left, arithmetically
|
||||
Left,
|
||||
/// Shift right, logically (shift in zeros)
|
||||
RightLogic,
|
||||
/// Shift right, arithmetically (shift in sign)
|
||||
RightArith,
|
||||
}
|
||||
|
||||
/// Shifts each element of `left` by a scalar amount. The shift amount
|
||||
/// is determined by the lowest 64 bits of `right` (which is a 128-bit vector).
|
||||
///
|
||||
/// For logic shifts, when right is larger than BITS - 1, zero is produced.
|
||||
/// For arithmetic right-shifts, when right is larger than BITS - 1, the sign
|
||||
/// bit is copied to remaining bits.
|
||||
fn shift_simd_by_scalar<'tcx>(
|
||||
this: &mut crate::MiriInterpCx<'_, 'tcx>,
|
||||
left: &OpTy<'tcx, Provenance>,
|
||||
right: &OpTy<'tcx, Provenance>,
|
||||
which: ShiftOp,
|
||||
dest: &MPlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, ()> {
|
||||
let (left, left_len) = this.operand_to_simd(left)?;
|
||||
let (dest, dest_len) = this.mplace_to_simd(dest)?;
|
||||
|
||||
assert_eq!(dest_len, left_len);
|
||||
// `right` may have a different length, and we only care about its
|
||||
// lowest 64bit anyway.
|
||||
|
||||
// Get the 64-bit shift operand and convert it to the type expected
|
||||
// by checked_{shl,shr} (u32).
|
||||
// It is ok to saturate the value to u32::MAX because any value
|
||||
// above BITS - 1 will produce the same result.
|
||||
let shift = u32::try_from(extract_first_u64(this, right)?).unwrap_or(u32::MAX);
|
||||
|
||||
for i in 0..dest_len {
|
||||
let left = this.read_scalar(&this.project_index(&left, i)?)?;
|
||||
let dest = this.project_index(&dest, i)?;
|
||||
|
||||
let res = match which {
|
||||
ShiftOp::Left => {
|
||||
let left = left.to_uint(dest.layout.size)?;
|
||||
let res = left.checked_shl(shift).unwrap_or(0);
|
||||
// `truncate` is needed as left-shift can make the absolute value larger.
|
||||
Scalar::from_uint(dest.layout.size.truncate(res), dest.layout.size)
|
||||
}
|
||||
ShiftOp::RightLogic => {
|
||||
let left = left.to_uint(dest.layout.size)?;
|
||||
let res = left.checked_shr(shift).unwrap_or(0);
|
||||
// No `truncate` needed as right-shift can only make the absolute value smaller.
|
||||
Scalar::from_uint(res, dest.layout.size)
|
||||
}
|
||||
ShiftOp::RightArith => {
|
||||
let left = left.to_int(dest.layout.size)?;
|
||||
// On overflow, copy the sign bit to the remaining bits
|
||||
let res = left.checked_shr(shift).unwrap_or(left >> 127);
|
||||
// No `truncate` needed as right-shift can only make the absolute value smaller.
|
||||
Scalar::from_int(res, dest.layout.size)
|
||||
}
|
||||
};
|
||||
this.write_scalar(res, &dest)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Takes a 128-bit vector, transmutes it to `[u64; 2]` and extracts
|
||||
/// the first value.
|
||||
fn extract_first_u64<'tcx>(
|
||||
this: &crate::MiriInterpCx<'_, 'tcx>,
|
||||
op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, u64> {
|
||||
// Transmute vector to `[u64; 2]`
|
||||
let array_layout = this.layout_of(Ty::new_array(this.tcx.tcx, this.tcx.types.u64, 2))?;
|
||||
let op = op.transmute(array_layout, this)?;
|
||||
|
||||
// Get the first u64 from the array
|
||||
this.read_scalar(&this.project_index(&op, 0)?)?.to_u64()
|
||||
}
|
||||
|
||||
// Rounds the first element of `right` according to `rounding`
|
||||
// and copies the remaining elements from `left`.
|
||||
fn round_first<'tcx, F: rustc_apfloat::Float>(
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use rustc_apfloat::ieee::Double;
|
||||
use rustc_middle::ty::layout::LayoutOf as _;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_span::Symbol;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use super::{bin_op_simd_float_all, bin_op_simd_float_first, convert_float_to_int, FloatBinOp};
|
||||
use super::{
|
||||
bin_op_simd_float_all, bin_op_simd_float_first, convert_float_to_int, shift_simd_by_scalar,
|
||||
FloatBinOp, ShiftOp,
|
||||
};
|
||||
use crate::*;
|
||||
use shims::foreign_items::EmulateForeignItemResult;
|
||||
|
||||
|
@ -109,156 +110,27 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
|||
this.write_scalar(Scalar::from_u64(res.into()), &dest)?;
|
||||
}
|
||||
}
|
||||
// Used to implement the _mm_{sll,srl,sra}_epi16 functions.
|
||||
// Shifts 16-bit packed integers in left by the amount in right.
|
||||
// Both operands are vectors of 16-bit integers. However, right is
|
||||
// interpreted as a single 64-bit integer (remaining bits are ignored).
|
||||
// For logic shifts, when right is larger than 15, zero is produced.
|
||||
// For arithmetic shifts, when right is larger than 15, the sign bit
|
||||
// Used to implement the _mm_{sll,srl,sra}_epi{16,32,64} functions
|
||||
// (except _mm_sra_epi64, which is not available in SSE2).
|
||||
// Shifts N-bit packed integers in left by the amount in right.
|
||||
// Both operands are 128-bit vectors. However, right is interpreted as
|
||||
// a single 64-bit integer (remaining bits are ignored).
|
||||
// For logic shifts, when right is larger than N - 1, zero is produced.
|
||||
// For arithmetic shifts, when right is larger than N - 1, the sign bit
|
||||
// is copied to remaining bits.
|
||||
"psll.w" | "psrl.w" | "psra.w" => {
|
||||
"psll.w" | "psrl.w" | "psra.w" | "psll.d" | "psrl.d" | "psra.d" | "psll.q"
|
||||
| "psrl.q" => {
|
||||
let [left, right] =
|
||||
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
|
||||
let (left, left_len) = this.operand_to_simd(left)?;
|
||||
let (right, right_len) = this.operand_to_simd(right)?;
|
||||
let (dest, dest_len) = this.mplace_to_simd(dest)?;
|
||||
|
||||
assert_eq!(dest_len, left_len);
|
||||
assert_eq!(dest_len, right_len);
|
||||
|
||||
enum ShiftOp {
|
||||
Sll,
|
||||
Srl,
|
||||
Sra,
|
||||
}
|
||||
let which = match unprefixed_name {
|
||||
"psll.w" => ShiftOp::Sll,
|
||||
"psrl.w" => ShiftOp::Srl,
|
||||
"psra.w" => ShiftOp::Sra,
|
||||
"psll.w" | "psll.d" | "psll.q" => ShiftOp::Left,
|
||||
"psrl.w" | "psrl.d" | "psrl.q" => ShiftOp::RightLogic,
|
||||
"psra.w" | "psra.d" => ShiftOp::RightArith,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
// Get the 64-bit shift operand and convert it to the type expected
|
||||
// by checked_{shl,shr} (u32).
|
||||
// It is ok to saturate the value to u32::MAX because any value
|
||||
// above 15 will produce the same result.
|
||||
let shift = extract_first_u64(this, &right)?.try_into().unwrap_or(u32::MAX);
|
||||
|
||||
for i in 0..dest_len {
|
||||
let left = this.read_scalar(&this.project_index(&left, i)?)?.to_u16()?;
|
||||
let dest = this.project_index(&dest, i)?;
|
||||
|
||||
let res = match which {
|
||||
ShiftOp::Sll => left.checked_shl(shift).unwrap_or(0),
|
||||
ShiftOp::Srl => left.checked_shr(shift).unwrap_or(0),
|
||||
#[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)]
|
||||
ShiftOp::Sra => {
|
||||
// Convert u16 to i16 to use arithmetic shift
|
||||
let left = left as i16;
|
||||
// Copy the sign bit to the remaining bits
|
||||
left.checked_shr(shift).unwrap_or(left >> 15) as u16
|
||||
}
|
||||
};
|
||||
|
||||
this.write_scalar(Scalar::from_u16(res), &dest)?;
|
||||
}
|
||||
}
|
||||
// Used to implement the _mm_{sll,srl,sra}_epi32 functions.
|
||||
// 32-bit equivalent to the shift functions above.
|
||||
"psll.d" | "psrl.d" | "psra.d" => {
|
||||
let [left, right] =
|
||||
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
|
||||
let (left, left_len) = this.operand_to_simd(left)?;
|
||||
let (right, right_len) = this.operand_to_simd(right)?;
|
||||
let (dest, dest_len) = this.mplace_to_simd(dest)?;
|
||||
|
||||
assert_eq!(dest_len, left_len);
|
||||
assert_eq!(dest_len, right_len);
|
||||
|
||||
enum ShiftOp {
|
||||
Sll,
|
||||
Srl,
|
||||
Sra,
|
||||
}
|
||||
let which = match unprefixed_name {
|
||||
"psll.d" => ShiftOp::Sll,
|
||||
"psrl.d" => ShiftOp::Srl,
|
||||
"psra.d" => ShiftOp::Sra,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
// Get the 64-bit shift operand and convert it to the type expected
|
||||
// by checked_{shl,shr} (u32).
|
||||
// It is ok to saturate the value to u32::MAX because any value
|
||||
// above 31 will produce the same result.
|
||||
let shift = extract_first_u64(this, &right)?.try_into().unwrap_or(u32::MAX);
|
||||
|
||||
for i in 0..dest_len {
|
||||
let left = this.read_scalar(&this.project_index(&left, i)?)?.to_u32()?;
|
||||
let dest = this.project_index(&dest, i)?;
|
||||
|
||||
let res = match which {
|
||||
ShiftOp::Sll => left.checked_shl(shift).unwrap_or(0),
|
||||
ShiftOp::Srl => left.checked_shr(shift).unwrap_or(0),
|
||||
#[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)]
|
||||
ShiftOp::Sra => {
|
||||
// Convert u32 to i32 to use arithmetic shift
|
||||
let left = left as i32;
|
||||
// Copy the sign bit to the remaining bits
|
||||
left.checked_shr(shift).unwrap_or(left >> 31) as u32
|
||||
}
|
||||
};
|
||||
|
||||
this.write_scalar(Scalar::from_u32(res), &dest)?;
|
||||
}
|
||||
}
|
||||
// Used to implement the _mm_{sll,srl}_epi64 functions.
|
||||
// 64-bit equivalent to the shift functions above, except _mm_sra_epi64,
|
||||
// which is not available in SSE2.
|
||||
"psll.q" | "psrl.q" => {
|
||||
let [left, right] =
|
||||
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
|
||||
let (left, left_len) = this.operand_to_simd(left)?;
|
||||
let (right, right_len) = this.operand_to_simd(right)?;
|
||||
let (dest, dest_len) = this.mplace_to_simd(dest)?;
|
||||
|
||||
assert_eq!(dest_len, left_len);
|
||||
assert_eq!(dest_len, right_len);
|
||||
|
||||
enum ShiftOp {
|
||||
Sll,
|
||||
Srl,
|
||||
}
|
||||
let which = match unprefixed_name {
|
||||
"psll.q" => ShiftOp::Sll,
|
||||
"psrl.q" => ShiftOp::Srl,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
// Get the 64-bit shift operand and convert it to the type expected
|
||||
// by checked_{shl,shr} (u32).
|
||||
// It is ok to saturate the value to u32::MAX because any value
|
||||
// above 63 will produce the same result.
|
||||
let shift = this
|
||||
.read_scalar(&this.project_index(&right, 0)?)?
|
||||
.to_u64()?
|
||||
.try_into()
|
||||
.unwrap_or(u32::MAX);
|
||||
|
||||
for i in 0..dest_len {
|
||||
let left = this.read_scalar(&this.project_index(&left, i)?)?.to_u64()?;
|
||||
let dest = this.project_index(&dest, i)?;
|
||||
|
||||
let res = match which {
|
||||
ShiftOp::Sll => left.checked_shl(shift).unwrap_or(0),
|
||||
ShiftOp::Srl => left.checked_shr(shift).unwrap_or(0),
|
||||
};
|
||||
|
||||
this.write_scalar(Scalar::from_u64(res), &dest)?;
|
||||
}
|
||||
shift_simd_by_scalar(this, left, right, which, dest)?;
|
||||
}
|
||||
// Used to implement the _mm_cvtps_epi32, _mm_cvttps_epi32, _mm_cvtpd_epi32
|
||||
// and _mm_cvttpd_epi32 functions.
|
||||
|
@ -585,17 +457,3 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
|||
Ok(EmulateForeignItemResult::NeedsJumping)
|
||||
}
|
||||
}
|
||||
|
||||
/// Takes a 128-bit vector, transmutes it to `[u64; 2]` and extracts
|
||||
/// the first value.
|
||||
fn extract_first_u64<'tcx>(
|
||||
this: &crate::MiriInterpCx<'_, 'tcx>,
|
||||
op: &MPlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, u64> {
|
||||
// Transmute vector to `[u64; 2]`
|
||||
let u64_array_layout = this.layout_of(Ty::new_array(this.tcx.tcx, this.tcx.types.u64, 2))?;
|
||||
let op = op.transmute(u64_array_layout, this)?;
|
||||
|
||||
// Get the first u64 from the array
|
||||
this.read_scalar(&this.project_index(&op, 0)?)?.to_u64()
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue