Move llvm.x86.*
implementations into shims::x86
This commit is contained in:
parent
5ddf866c9c
commit
d6b30b88d0
@ -22,7 +22,7 @@ use rustc_target::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::backtrace::EvalContextExt as _;
|
use super::backtrace::EvalContextExt as _;
|
||||||
use crate::helpers::{convert::Truncate, target_os_is_unix};
|
use crate::helpers::target_os_is_unix;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
/// Returned by `emulate_foreign_item_by_name`.
|
/// Returned by `emulate_foreign_item_by_name`.
|
||||||
@ -981,30 +981,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
throw_unsup_format!("unsupported `llvm.prefetch` type argument: {}", ty);
|
throw_unsup_format!("unsupported `llvm.prefetch` type argument: {}", ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"llvm.x86.addcarry.64" if this.tcx.sess.target.arch == "x86_64" => {
|
// FIXME: Move these to an `arm` submodule.
|
||||||
// Computes u8+u64+u64, returning tuple (u8,u64) comprising the output carry and truncated sum.
|
|
||||||
let [c_in, a, b] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?;
|
|
||||||
let c_in = this.read_scalar(c_in)?.to_u8()?;
|
|
||||||
let a = this.read_scalar(a)?.to_u64()?;
|
|
||||||
let b = this.read_scalar(b)?.to_u64()?;
|
|
||||||
|
|
||||||
#[allow(clippy::arithmetic_side_effects)]
|
|
||||||
// adding two u64 and a u8 cannot wrap in a u128
|
|
||||||
let wide_sum = u128::from(c_in) + u128::from(a) + u128::from(b);
|
|
||||||
#[allow(clippy::arithmetic_side_effects)] // it's a u128, we can shift by 64
|
|
||||||
let (c_out, sum) = ((wide_sum >> 64).truncate::<u8>(), wide_sum.truncate::<u64>());
|
|
||||||
|
|
||||||
let c_out_field = this.project_field(dest, 0)?;
|
|
||||||
this.write_scalar(Scalar::from_u8(c_out), &c_out_field)?;
|
|
||||||
let sum_field = this.project_field(dest, 1)?;
|
|
||||||
this.write_scalar(Scalar::from_u64(sum), &sum_field)?;
|
|
||||||
}
|
|
||||||
"llvm.x86.sse2.pause"
|
|
||||||
if this.tcx.sess.target.arch == "x86" || this.tcx.sess.target.arch == "x86_64" =>
|
|
||||||
{
|
|
||||||
let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
|
||||||
this.yield_active_thread();
|
|
||||||
}
|
|
||||||
"llvm.aarch64.isb" if this.tcx.sess.target.arch == "aarch64" => {
|
"llvm.aarch64.isb" if this.tcx.sess.target.arch == "aarch64" => {
|
||||||
let [arg] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?;
|
let [arg] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?;
|
||||||
let arg = this.read_scalar(arg)?.to_i32()?;
|
let arg = this.read_scalar(arg)?.to_i32()?;
|
||||||
@ -1055,13 +1032,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
name if name.starts_with("llvm.x86.sse.") => {
|
name if name.starts_with("llvm.x86.")
|
||||||
return shims::x86::sse::EvalContextExt::emulate_x86_sse_intrinsic(
|
&& (this.tcx.sess.target.arch == "x86"
|
||||||
this, link_name, abi, args, dest,
|
|| this.tcx.sess.target.arch == "x86_64") =>
|
||||||
);
|
{
|
||||||
}
|
return shims::x86::EvalContextExt::emulate_x86_intrinsic(
|
||||||
name if name.starts_with("llvm.x86.sse2.") => {
|
|
||||||
return shims::x86::sse2::EvalContextExt::emulate_x86_sse2_intrinsic(
|
|
||||||
this, link_name, abi, args, dest,
|
this, link_name, abi, args, dest,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,65 @@
|
|||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
|
use rustc_span::Symbol;
|
||||||
use rustc_target::abi::Size;
|
use rustc_target::abi::Size;
|
||||||
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use helpers::bool_to_simd_element;
|
use helpers::bool_to_simd_element;
|
||||||
|
use helpers::convert::Truncate as _;
|
||||||
|
use shims::foreign_items::EmulateByNameResult;
|
||||||
|
|
||||||
pub(super) mod sse;
|
mod sse;
|
||||||
pub(super) mod sse2;
|
mod sse2;
|
||||||
|
|
||||||
|
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
||||||
|
pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
||||||
|
crate::MiriInterpCxExt<'mir, 'tcx>
|
||||||
|
{
|
||||||
|
fn emulate_x86_intrinsic(
|
||||||
|
&mut self,
|
||||||
|
link_name: Symbol,
|
||||||
|
abi: Abi,
|
||||||
|
args: &[OpTy<'tcx, Provenance>],
|
||||||
|
dest: &PlaceTy<'tcx, Provenance>,
|
||||||
|
) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
|
||||||
|
let this = self.eval_context_mut();
|
||||||
|
// Prefix should have already been checked.
|
||||||
|
let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.").unwrap();
|
||||||
|
match unprefixed_name {
|
||||||
|
"addcarry.64" if this.tcx.sess.target.arch == "x86_64" => {
|
||||||
|
// Computes u8+u64+u64, returning tuple (u8,u64) comprising the output carry and truncated sum.
|
||||||
|
let [c_in, a, b] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?;
|
||||||
|
let c_in = this.read_scalar(c_in)?.to_u8()?;
|
||||||
|
let a = this.read_scalar(a)?.to_u64()?;
|
||||||
|
let b = this.read_scalar(b)?.to_u64()?;
|
||||||
|
|
||||||
|
#[allow(clippy::arithmetic_side_effects)]
|
||||||
|
// adding two u64 and a u8 cannot wrap in a u128
|
||||||
|
let wide_sum = u128::from(c_in) + u128::from(a) + u128::from(b);
|
||||||
|
#[allow(clippy::arithmetic_side_effects)] // it's a u128, we can shift by 64
|
||||||
|
let (c_out, sum) = ((wide_sum >> 64).truncate::<u8>(), wide_sum.truncate::<u64>());
|
||||||
|
|
||||||
|
let c_out_field = this.project_field(dest, 0)?;
|
||||||
|
this.write_scalar(Scalar::from_u8(c_out), &c_out_field)?;
|
||||||
|
let sum_field = this.project_field(dest, 1)?;
|
||||||
|
this.write_scalar(Scalar::from_u64(sum), &sum_field)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
name if name.starts_with("sse.") => {
|
||||||
|
return sse::EvalContextExt::emulate_x86_sse_intrinsic(
|
||||||
|
this, link_name, abi, args, dest,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
name if name.starts_with("sse2.") => {
|
||||||
|
return sse2::EvalContextExt::emulate_x86_sse2_intrinsic(
|
||||||
|
this, link_name, abi, args, dest,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => return Ok(EmulateByNameResult::NotSupported),
|
||||||
|
}
|
||||||
|
Ok(EmulateByNameResult::NeedsJumping)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Floating point comparison operation
|
/// Floating point comparison operation
|
||||||
///
|
///
|
||||||
|
@ -10,7 +10,9 @@ use crate::*;
|
|||||||
use shims::foreign_items::EmulateByNameResult;
|
use shims::foreign_items::EmulateByNameResult;
|
||||||
|
|
||||||
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
||||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
||||||
|
crate::MiriInterpCxExt<'mir, 'tcx>
|
||||||
|
{
|
||||||
fn emulate_x86_sse_intrinsic(
|
fn emulate_x86_sse_intrinsic(
|
||||||
&mut self,
|
&mut self,
|
||||||
link_name: Symbol,
|
link_name: Symbol,
|
||||||
|
@ -13,7 +13,9 @@ use crate::*;
|
|||||||
use shims::foreign_items::EmulateByNameResult;
|
use shims::foreign_items::EmulateByNameResult;
|
||||||
|
|
||||||
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
||||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
||||||
|
crate::MiriInterpCxExt<'mir, 'tcx>
|
||||||
|
{
|
||||||
fn emulate_x86_sse2_intrinsic(
|
fn emulate_x86_sse2_intrinsic(
|
||||||
&mut self,
|
&mut self,
|
||||||
link_name: Symbol,
|
link_name: Symbol,
|
||||||
@ -753,6 +755,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
|
|
||||||
this.write_scalar(Scalar::from_u32(res.try_into().unwrap()), dest)?;
|
this.write_scalar(Scalar::from_u32(res.try_into().unwrap()), dest)?;
|
||||||
}
|
}
|
||||||
|
// Used to implement the `_mm_pause` function.
|
||||||
|
// The intrinsic is used to hint the processor that the code is in a spin-loop.
|
||||||
|
"pause" => {
|
||||||
|
let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||||
|
this.yield_active_thread();
|
||||||
|
}
|
||||||
_ => return Ok(EmulateByNameResult::NotSupported),
|
_ => return Ok(EmulateByNameResult::NotSupported),
|
||||||
}
|
}
|
||||||
Ok(EmulateByNameResult::NeedsJumping)
|
Ok(EmulateByNameResult::NeedsJumping)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user