about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduardo Sánchez Muñoz <eduardosm-dev@e64.io>2023-09-21 19:41:48 +0200
committerEduardo Sánchez Muñoz <eduardosm-dev@e64.io>2023-09-25 07:18:10 +0200
commitd6b30b88d0cc7b2f98b5f343353f97ef9bf2f9e3 (patch)
treeeadaa125ade0a5cfdea4df28b4222c7a006ea0d7
parent5ddf866c9c91afa53d26a3bf13c2cce4dd8bb21d (diff)
downloadrust-d6b30b88d0cc7b2f98b5f343353f97ef9bf2f9e3.tar.gz
rust-d6b30b88d0cc7b2f98b5f343353f97ef9bf2f9e3.zip
Move `llvm.x86.*` implementations into `shims::x86`
-rw-r--r--src/tools/miri/src/shims/foreign_items.rs39
-rw-r--r--src/tools/miri/src/shims/x86/mod.rs58
-rw-r--r--src/tools/miri/src/shims/x86/sse.rs4
-rw-r--r--src/tools/miri/src/shims/x86/sse2.rs10
4 files changed, 75 insertions, 36 deletions
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index f596df1f7a1..0c92ede40fd 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -22,7 +22,7 @@ use rustc_target::{
 };
 
 use super::backtrace::EvalContextExt as _;
-use crate::helpers::{convert::Truncate, target_os_is_unix};
+use crate::helpers::target_os_is_unix;
 use crate::*;
 
 /// 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);
                 }
             }
-            "llvm.x86.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)?;
-            }
-            "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();
-            }
+            // FIXME: Move these to an `arm` submodule.
             "llvm.aarch64.isb" if this.tcx.sess.target.arch == "aarch64" => {
                 let [arg] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?;
                 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.") => {
-                return shims::x86::sse::EvalContextExt::emulate_x86_sse_intrinsic(
-                    this, link_name, abi, args, dest,
-                );
-            }
-            name if name.starts_with("llvm.x86.sse2.") => {
-                return shims::x86::sse2::EvalContextExt::emulate_x86_sse2_intrinsic(
+            name if name.starts_with("llvm.x86.")
+                && (this.tcx.sess.target.arch == "x86"
+                    || this.tcx.sess.target.arch == "x86_64") =>
+            {
+                return shims::x86::EvalContextExt::emulate_x86_intrinsic(
                     this, link_name, abi, args, dest,
                 );
             }
diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs
index cbdc500be78..16eac81fa0a 100644
--- a/src/tools/miri/src/shims/x86/mod.rs
+++ b/src/tools/miri/src/shims/x86/mod.rs
@@ -1,11 +1,65 @@
 use rustc_middle::mir;
+use rustc_span::Symbol;
 use rustc_target::abi::Size;
+use rustc_target::spec::abi::Abi;
 
 use crate::*;
 use helpers::bool_to_simd_element;
+use helpers::convert::Truncate as _;
+use shims::foreign_items::EmulateByNameResult;
+
+mod sse;
+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)?;
+            }
 
-pub(super) mod sse;
-pub(super) mod sse2;
+            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
 ///
diff --git a/src/tools/miri/src/shims/x86/sse.rs b/src/tools/miri/src/shims/x86/sse.rs
index b6b994b45ac..de1e695b6d1 100644
--- a/src/tools/miri/src/shims/x86/sse.rs
+++ b/src/tools/miri/src/shims/x86/sse.rs
@@ -10,7 +10,9 @@ use crate::*;
 use shims::foreign_items::EmulateByNameResult;
 
 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(
         &mut self,
         link_name: Symbol,
diff --git a/src/tools/miri/src/shims/x86/sse2.rs b/src/tools/miri/src/shims/x86/sse2.rs
index 855ebbe7072..2ca882167bf 100644
--- a/src/tools/miri/src/shims/x86/sse2.rs
+++ b/src/tools/miri/src/shims/x86/sse2.rs
@@ -13,7 +13,9 @@ use crate::*;
 use shims::foreign_items::EmulateByNameResult;
 
 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(
         &mut self,
         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)?;
             }
+            // 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),
         }
         Ok(EmulateByNameResult::NeedsJumping)