diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 957ec8629fa..7623daeb96f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -237,13 +237,18 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { }; match (&mut val, field.abi) { - (OperandValue::Immediate(llval), _) => { + ( + OperandValue::Immediate(llval), + Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. }, + ) => { // Bools in union fields needs to be truncated. *llval = bx.to_immediate(*llval, field); // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types. let ty = bx.cx().immediate_backend_type(field); if bx.type_kind(ty) == TypeKind::Pointer { *llval = bx.pointercast(*llval, ty); + } else { + *llval = bx.bitcast(*llval, ty); } } (OperandValue::Pair(a, b), Abi::ScalarPair(a_abi, b_abi)) => { @@ -255,11 +260,31 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { let b_ty = bx.cx().scalar_pair_element_backend_type(field, 1, true); if bx.type_kind(a_ty) == TypeKind::Pointer { *a = bx.pointercast(*a, a_ty); + } else { + *a = bx.bitcast(*a, a_ty); } if bx.type_kind(b_ty) == TypeKind::Pointer { *b = bx.pointercast(*b, b_ty); + } else { + *b = bx.bitcast(*b, b_ty); } } + // Newtype vector of array, e.g. #[repr(simd)] struct S([i32; 4]); + (OperandValue::Immediate(llval), Abi::Aggregate { sized: true }) => { + assert!(matches!(self.layout.abi, Abi::Vector { .. })); + + let llty = bx.cx().backend_type(self.layout); + let llfield_ty = bx.cx().backend_type(field); + + // Can't bitcast an aggregate, so round trip through memory. + let lltemp = bx.alloca(llfield_ty, field.align.abi); + let llptr = bx.pointercast(lltemp, bx.cx().type_ptr_to(llty)); + bx.store(*llval, llptr, field.align.abi); + *llval = bx.load(llfield_ty, lltemp, field.align.abi); + } + (OperandValue::Immediate(_), Abi::Uninhabited | Abi::Aggregate { sized: false }) => { + bug!() + } (OperandValue::Pair(..), _) => bug!(), (OperandValue::Ref(..), _) => bug!(), }