about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbjorn3 <17426603+bjorn3@users.noreply.github.com>2025-04-14 09:13:37 +0000
committerbjorn3 <17426603+bjorn3@users.noreply.github.com>2025-04-14 09:13:37 +0000
commit1afce7c3548ff31174cb060f3217b1994d982bed (patch)
tree39769319b75a8e55d9e48f240999fb94f593930b
parentf99bdfef831f86e3d32c9aade7e41020b067d393 (diff)
downloadrust-1afce7c3548ff31174cb060f3217b1994d982bed.tar.gz
rust-1afce7c3548ff31174cb060f3217b1994d982bed.zip
Implement simd_insert_dyn and simd_extract_dyn intrinsics
-rw-r--r--src/intrinsics/simd.rs28
-rw-r--r--src/value_and_place.rs28
2 files changed, 56 insertions, 0 deletions
diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs
index dd6d8dbb6f5..7a041469bcc 100644
--- a/src/intrinsics/simd.rs
+++ b/src/intrinsics/simd.rs
@@ -283,6 +283,20 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
             ret_lane.write_cvalue(fx, val);
         }
 
+        sym::simd_insert_dyn => {
+            intrinsic_args!(fx, args => (base, idx, val); intrinsic);
+
+            if !base.layout().ty.is_simd() {
+                report_simd_type_validation_error(fx, intrinsic, span, base.layout().ty);
+                return;
+            }
+
+            let idx = idx.load_scalar(fx);
+
+            ret.write_cvalue(fx, base);
+            ret.write_lane_dyn(fx, idx, val);
+        }
+
         sym::simd_extract => {
             let (v, idx) = match args {
                 [v, idx] => (v, idx),
@@ -318,6 +332,20 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
             ret.write_cvalue(fx, ret_lane);
         }
 
+        sym::simd_extract_dyn => {
+            intrinsic_args!(fx, args => (v, idx); intrinsic);
+
+            if !v.layout().ty.is_simd() {
+                report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty);
+                return;
+            }
+
+            let idx = idx.load_scalar(fx);
+
+            let ret_lane = v.value_lane_dyn(fx, idx);
+            ret.write_cvalue(fx, ret_lane);
+        }
+
         sym::simd_neg
         | sym::simd_bswap
         | sym::simd_bitreverse
diff --git a/src/value_and_place.rs b/src/value_and_place.rs
index f8a19589fdd..9fd71cd6f77 100644
--- a/src/value_and_place.rs
+++ b/src/value_and_place.rs
@@ -806,6 +806,34 @@ impl<'tcx> CPlace<'tcx> {
         }
     }
 
+    /// Write a value to an individual lane in a SIMD vector.
+    pub(crate) fn write_lane_dyn(
+        self,
+        fx: &mut FunctionCx<'_, '_, 'tcx>,
+        lane_idx: Value,
+        value: CValue<'tcx>,
+    ) {
+        let layout = self.layout();
+        assert!(layout.ty.is_simd());
+        let (_lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
+        let lane_layout = fx.layout_of(lane_ty);
+        assert_eq!(lane_layout, value.layout());
+
+        match self.inner {
+            CPlaceInner::Var(_, _) => unreachable!(),
+            CPlaceInner::VarPair(_, _, _) => unreachable!(),
+            CPlaceInner::Addr(ptr, None) => {
+                let field_offset = fx
+                    .bcx
+                    .ins()
+                    .imul_imm(lane_idx, i64::try_from(lane_layout.size.bytes()).unwrap());
+                let field_ptr = ptr.offset_value(fx, field_offset);
+                CPlace::for_ptr(field_ptr, lane_layout).write_cvalue(fx, value);
+            }
+            CPlaceInner::Addr(_, Some(_)) => unreachable!(),
+        }
+    }
+
     pub(crate) fn place_index(
         self,
         fx: &mut FunctionCx<'_, '_, 'tcx>,