summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_codegen_ssa/src/mir/operand.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
commit9835e2ae736235810b4ea1c162ca5e65c547e770 (patch)
tree3fcebf40ed70e581d776a8a4c65923e8ec20e026 /compiler/rustc_codegen_ssa/src/mir/operand.rs
parentReleasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff)
downloadrustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz
rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_codegen_ssa/src/mir/operand.rs')
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs63
1 files changed, 48 insertions, 15 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index b37797fef..2301c3ef1 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -2,6 +2,7 @@ use super::place::PlaceRef;
use super::{FunctionCx, LocalRef};
use crate::base;
+use crate::common::TypeKind;
use crate::glue;
use crate::traits::*;
use crate::MemFlags;
@@ -236,19 +237,47 @@ 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.
- *llval = bx.bitcast(*llval, bx.cx().immediate_backend_type(field));
+ let ty = bx.cx().immediate_backend_type(field);
+ if bx.type_kind(ty) == TypeKind::Pointer {
+ *llval = bx.pointercast(*llval, ty);
+ }
}
(OperandValue::Pair(a, b), Abi::ScalarPair(a_abi, b_abi)) => {
// Bools in union fields needs to be truncated.
*a = bx.to_immediate_scalar(*a, a_abi);
*b = bx.to_immediate_scalar(*b, b_abi);
// HACK(eddyb) have to bitcast pointers until LLVM removes pointee types.
- *a = bx.bitcast(*a, bx.cx().scalar_pair_element_backend_type(field, 0, true));
- *b = bx.bitcast(*b, bx.cx().scalar_pair_element_backend_type(field, 1, true));
+ let a_ty = bx.cx().scalar_pair_element_backend_type(field, 0, true);
+ 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);
+ }
+ if bx.type_kind(b_ty) == TypeKind::Pointer {
+ *b = bx.pointercast(*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!(),
@@ -373,8 +402,6 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
indirect_dest: PlaceRef<'tcx, V>,
) {
debug!("OperandRef::store_unsized: operand={:?}, indirect_dest={:?}", self, indirect_dest);
- let flags = MemFlags::empty();
-
// `indirect_dest` must have `*mut T` type. We extract `T` out of it.
let unsized_ty = indirect_dest
.layout
@@ -387,17 +414,23 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
bug!("store_unsized called with a sized value")
};
- // FIXME: choose an appropriate alignment, or use dynamic align somehow
- let max_align = Align::from_bits(128).unwrap();
- let min_align = Align::from_bits(8).unwrap();
-
- // Allocate an appropriate region on the stack, and copy the value into it
- let (llsize, _) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra));
- let lldst = bx.byte_array_alloca(llsize, max_align);
- bx.memcpy(lldst, max_align, llptr, min_align, llsize, flags);
+ // Allocate an appropriate region on the stack, and copy the value into it. Since alloca
+ // doesn't support dynamic alignment, we allocate an extra align - 1 bytes, and align the
+ // pointer manually.
+ let (size, align) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra));
+ let one = bx.const_usize(1);
+ let align_minus_1 = bx.sub(align, one);
+ let size_extra = bx.add(size, align_minus_1);
+ let min_align = Align::ONE;
+ let alloca = bx.byte_array_alloca(size_extra, min_align);
+ let address = bx.ptrtoint(alloca, bx.type_isize());
+ let neg_address = bx.neg(address);
+ let offset = bx.and(neg_address, align_minus_1);
+ let dst = bx.inbounds_gep(bx.type_i8(), alloca, &[offset]);
+ bx.memcpy(dst, min_align, llptr, min_align, size, MemFlags::empty());
// Store the allocated region and the extra to the indirect place.
- let indirect_operand = OperandValue::Pair(lldst, llextra);
+ let indirect_operand = OperandValue::Pair(dst, llextra);
indirect_operand.store(bx, indirect_dest);
}
}