about summary refs log tree commit diff
diff options
context:
space:
mode:
authorScott McMurray <scottmcm@users.noreply.github.com>2025-02-20 22:26:24 -0800
committerScott McMurray <scottmcm@users.noreply.github.com>2025-02-20 22:26:24 -0800
commitda77b39f05711fbecbfcb392314f885eece1e3f5 (patch)
treecfe39783587d42f26fcbd6a5a4d070498b756f3d
parenta18bd8acfc32dbfbbe150cd52eecf24e67fb69b6 (diff)
downloadrust-da77b39f05711fbecbfcb392314f885eece1e3f5.tar.gz
rust-da77b39f05711fbecbfcb392314f885eece1e3f5.zip
Refactor `OperandRef::extract_field` to prep for 838
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs46
1 files changed, 24 insertions, 22 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index faf1300e473..e7e4dfa05d0 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -358,19 +358,33 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
         let field = self.layout.field(bx.cx(), i);
         let offset = self.layout.fields.offset(i);
 
-        let val = if field.is_zst() {
-            OperandValue::ZeroSized
-        } else if field.size == self.layout.size {
-            assert_eq!(offset.bytes(), 0);
-            if let Some(field_val) = fx.codegen_transmute_operand(bx, *self, field) {
-                field_val
-            } else {
-                // we have to go through memory for things like
+        if !bx.is_backend_ref(self.layout) && bx.is_backend_ref(field) {
+            if let BackendRepr::Vector { count, .. } = self.layout.backend_repr
+                && let BackendRepr::Memory { sized: true } = field.backend_repr
+                && count.is_power_of_two()
+            {
+                assert_eq!(field.size, self.layout.size);
+                // This is being deprecated, but for now stdarch still needs it for
                 // Newtype vector of array, e.g. #[repr(simd)] struct S([i32; 4]);
                 let place = PlaceRef::alloca(bx, field);
                 self.val.store(bx, place.val.with_type(self.layout));
-                bx.load_operand(place).val
+                return bx.load_operand(place);
+            } else {
+                // Part of https://github.com/rust-lang/compiler-team/issues/838
+                bug!("Non-ref type {self:?} cannot project to ref field type {field:?}");
             }
+        }
+
+        let val = if field.is_zst() {
+            OperandValue::ZeroSized
+        } else if field.size == self.layout.size {
+            assert_eq!(offset.bytes(), 0);
+            fx.codegen_transmute_operand(bx, *self, field).unwrap_or_else(|| {
+                bug!(
+                    "Expected `codegen_transmute_operand` to handle equal-size \
+                      field {i:?} projection from {self:?} to {field:?}"
+                )
+            })
         } else {
             let (in_scalar, imm) = match (self.val, self.layout.backend_repr) {
                 // Extract a scalar component from a pair.
@@ -385,11 +399,6 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
                     }
                 }
 
-                // `#[repr(simd)]` types are also immediate.
-                (OperandValue::Immediate(llval), BackendRepr::Vector { .. }) => {
-                    (None, bx.extract_element(llval, bx.cx().const_usize(i as u64)))
-                }
-
                 _ => {
                     span_bug!(fx.mir.span, "OperandRef::extract_field({:?}): not applicable", self)
                 }
@@ -415,14 +424,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
                         imm
                     }
                 }
-                BackendRepr::Memory { sized: true } => {
-                    span_bug!(
-                        fx.mir.span,
-                        "Projecting into a simd type with padding doesn't work; \
-                         See <https://github.com/rust-lang/rust/issues/137108>",
-                    );
-                }
-                BackendRepr::ScalarPair(_, _) | BackendRepr::Memory { sized: false } => bug!(),
+                BackendRepr::ScalarPair(_, _) | BackendRepr::Memory { .. } => bug!(),
             })
         };