diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index faf1300e4731e..e7e4dfa05d0c0 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 ", - ); - } - BackendRepr::ScalarPair(_, _) | BackendRepr::Memory { sized: false } => bug!(), + BackendRepr::ScalarPair(_, _) | BackendRepr::Memory { .. } => bug!(), }) };