Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a9ef67f

Browse files
committedApr 24, 2024·
Refactoring after the PlaceValue addition
I added `PlaceValue` in 123775, but kept that one line-by-line simple because it touched so many places. This goes through to add more helpers & docs, and change some `PlaceRef` to `PlaceValue` where the type didn't need to be included. No behaviour changes.
1 parent 29a56a3 commit a9ef67f

File tree

7 files changed

+158
-131
lines changed

7 files changed

+158
-131
lines changed
 

‎compiler/rustc_codegen_ssa/src/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
282282
}
283283

284284
if src_f.layout.ty == dst_f.layout.ty {
285-
bx.typed_place_copy(dst_f, src_f);
285+
bx.typed_place_copy(dst_f.val, src_f.val, src_f.layout);
286286
} else {
287287
coerce_unsized_into(bx, src_f, dst_f);
288288
}

‎compiler/rustc_codegen_ssa/src/mir/block.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -1453,9 +1453,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
14531453
Some(pointee_align) => cmp::max(pointee_align, arg.layout.align.abi),
14541454
None => arg.layout.align.abi,
14551455
};
1456-
let scratch = PlaceRef::alloca_aligned(bx, arg.layout, required_align);
1457-
op.val.store(bx, scratch);
1458-
(scratch.val.llval, scratch.val.align, true)
1456+
let scratch = PlaceValue::alloca(bx, arg.layout.size, required_align);
1457+
op.val.store(bx, scratch.with_type(arg.layout));
1458+
(scratch.llval, scratch.align, true)
14591459
}
14601460
PassMode::Cast { .. } => {
14611461
let scratch = PlaceRef::alloca(bx, arg.layout);
@@ -1474,10 +1474,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
14741474
// For `foo(packed.large_field)`, and types with <4 byte alignment on x86,
14751475
// alignment requirements may be higher than the type's alignment, so copy
14761476
// to a higher-aligned alloca.
1477-
let scratch = PlaceRef::alloca_aligned(bx, arg.layout, required_align);
1478-
let op_place = PlaceRef { val: op_place_val, layout: op.layout };
1479-
bx.typed_place_copy(scratch, op_place);
1480-
(scratch.val.llval, scratch.val.align, true)
1477+
let scratch = PlaceValue::alloca(bx, arg.layout.size, required_align);
1478+
bx.typed_place_copy(scratch, op_place_val, op.layout);
1479+
(scratch.llval, scratch.align, true)
14811480
} else {
14821481
(op_place_val.llval, op_place_val.align, true)
14831482
}
@@ -1566,7 +1565,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
15661565
if place_val.llextra.is_some() {
15671566
bug!("closure arguments must be sized");
15681567
}
1569-
let tuple_ptr = PlaceRef { val: place_val, layout: tuple.layout };
1568+
let tuple_ptr = place_val.with_type(tuple.layout);
15701569
for i in 0..tuple.layout.fields.count() {
15711570
let field_ptr = tuple_ptr.project_field(bx, i);
15721571
let field = bx.load_operand(field_ptr);

‎compiler/rustc_codegen_ssa/src/mir/intrinsic.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::operand::{OperandRef, OperandValue};
1+
use super::operand::OperandRef;
22
use super::place::PlaceRef;
33
use super::FunctionCx;
44
use crate::errors;
@@ -92,9 +92,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
9292
// into the (unoptimized) direct swapping implementation, so we disable it.
9393
|| bx.sess().target.arch == "spirv"
9494
{
95-
let x_place = PlaceRef::new_sized(args[0].immediate(), pointee_layout);
96-
let y_place = PlaceRef::new_sized(args[1].immediate(), pointee_layout);
97-
bx.typed_place_swap(x_place, y_place);
95+
let align = pointee_layout.align.abi;
96+
let x_place = args[0].val.deref(align);
97+
let y_place = args[1].val.deref(align);
98+
bx.typed_place_swap(x_place, y_place, pointee_layout);
9899
return Ok(());
99100
}
100101
}
@@ -112,15 +113,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
112113
sym::va_end => bx.va_end(args[0].immediate()),
113114
sym::size_of_val => {
114115
let tp_ty = fn_args.type_at(0);
115-
let meta =
116-
if let OperandValue::Pair(_, meta) = args[0].val { Some(meta) } else { None };
116+
let (_, meta) = args[0].val.pointer_parts();
117117
let (llsize, _) = size_of_val::size_and_align_of_dst(bx, tp_ty, meta);
118118
llsize
119119
}
120120
sym::min_align_of_val => {
121121
let tp_ty = fn_args.type_at(0);
122-
let meta =
123-
if let OperandValue::Pair(_, meta) = args[0].val { Some(meta) } else { None };
122+
let (_, meta) = args[0].val.pointer_parts();
124123
let (_, llalign) = size_of_val::size_and_align_of_dst(bx, tp_ty, meta);
125124
llalign
126125
}

‎compiler/rustc_codegen_ssa/src/mir/operand.rs

+37-10
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,32 @@ pub enum OperandValue<V> {
5757
ZeroSized,
5858
}
5959

60+
impl<V: CodegenObject> OperandValue<V> {
61+
/// Treat this value as a pointer and return the data pointer and
62+
/// optional metadata as backend values.
63+
///
64+
/// If you're making a place, use [`Self::deref`] instead.
65+
pub fn pointer_parts(self) -> (V, Option<V>) {
66+
match self {
67+
OperandValue::Immediate(llptr) => (llptr, None),
68+
OperandValue::Pair(llptr, llextra) => (llptr, Some(llextra)),
69+
_ => bug!("OperandValue cannot be a pointer: {self:?}"),
70+
}
71+
}
72+
73+
/// Treat this value as a pointer and return the place to which it points.
74+
///
75+
/// The pointer immediate doesn't inherently know its alignment,
76+
/// so you need to pass it in. If you want to get it from a type's ABI
77+
/// alignment, then maybe you want [`OperandRef::deref`] instead.
78+
///
79+
/// This is the inverse of [`PlaceValue::address`].
80+
pub fn deref(self, align: Align) -> PlaceValue<V> {
81+
let (llval, llextra) = self.pointer_parts();
82+
PlaceValue { llval, llextra, align }
83+
}
84+
}
85+
6086
/// An `OperandRef` is an "SSA" reference to a Rust value, along with
6187
/// its type.
6288
///
@@ -204,6 +230,15 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
204230
}
205231
}
206232

233+
/// Asserts that this operand is a pointer (or reference) and returns
234+
/// the place to which it points. (This requires no code to be emitted
235+
/// as we represent places using the pointer to the place.)
236+
///
237+
/// This uses [`Ty::builtin_deref`] to include the type of the place and
238+
/// assumes the place is aligned to the pointee's usual ABI alignment.
239+
///
240+
/// If you don't need the type, see [`OperandValue::pointer_parts`]
241+
/// or [`OperandValue::deref`].
207242
pub fn deref<Cx: LayoutTypeMethods<'tcx>>(self, cx: &Cx) -> PlaceRef<'tcx, V> {
208243
if self.layout.ty.is_box() {
209244
// Derefer should have removed all Box derefs
@@ -217,15 +252,8 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
217252
.unwrap_or_else(|| bug!("deref of non-pointer {:?}", self))
218253
.ty;
219254

220-
let (llptr, llextra) = match self.val {
221-
OperandValue::Immediate(llptr) => (llptr, None),
222-
OperandValue::Pair(llptr, llextra) => (llptr, Some(llextra)),
223-
OperandValue::Ref(..) => bug!("Deref of by-Ref operand {:?}", self),
224-
OperandValue::ZeroSized => bug!("Deref of ZST operand {:?}", self),
225-
};
226255
let layout = cx.layout_of(projected_ty);
227-
let val = PlaceValue { llval: llptr, llextra, align: layout.align.abi };
228-
PlaceRef { val, layout }
256+
self.val.deref(layout.align.abi).with_type(layout)
229257
}
230258

231259
/// If this operand is a `Pair`, we return an aggregate with the two values.
@@ -418,8 +446,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
418446
if val.llextra.is_some() {
419447
bug!("cannot directly store unsized values");
420448
}
421-
let source_place = PlaceRef { val, layout: dest.layout };
422-
bx.typed_place_copy_with_flags(dest, source_place, flags);
449+
bx.typed_place_copy_with_flags(dest.val, val, dest.layout, flags);
423450
}
424451
OperandValue::Immediate(s) => {
425452
let val = bx.from_immediate(s);

‎compiler/rustc_codegen_ssa/src/mir/place.rs

+56-41
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@ use rustc_middle::mir;
99
use rustc_middle::mir::tcx::PlaceTy;
1010
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
1111
use rustc_middle::ty::{self, Ty};
12-
use rustc_target::abi::{Align, FieldsShape, Int, Pointer, TagEncoding};
12+
use rustc_target::abi::{Align, FieldsShape, Int, Pointer, Size, TagEncoding};
1313
use rustc_target::abi::{VariantIdx, Variants};
1414

1515
/// The location and extra runtime properties of the place.
1616
///
1717
/// Typically found in a [`PlaceRef`] or an [`OperandValue::Ref`].
18+
///
19+
/// As a location in memory, this has no specific type. If you want to
20+
/// load or store it using a typed operation, use [`Self::with_type`].
1821
#[derive(Copy, Clone, Debug)]
1922
pub struct PlaceValue<V> {
2023
/// A pointer to the contents of the place.
@@ -34,6 +37,41 @@ impl<V: CodegenObject> PlaceValue<V> {
3437
pub fn new_sized(llval: V, align: Align) -> PlaceValue<V> {
3538
PlaceValue { llval, llextra: None, align }
3639
}
40+
41+
/// Allocates a stack slot in the function for a value
42+
/// of the specified size and alignment.
43+
///
44+
/// The allocation itself is untyped.
45+
pub fn alloca<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx, Value = V>>(
46+
bx: &mut Bx,
47+
size: Size,
48+
align: Align,
49+
) -> PlaceValue<V> {
50+
let llval = bx.alloca(size, align);
51+
PlaceValue::new_sized(llval, align)
52+
}
53+
54+
/// Creates a `PlaceRef` to this location with the given type.
55+
pub fn with_type<'tcx>(self, layout: TyAndLayout<'tcx>) -> PlaceRef<'tcx, V> {
56+
debug_assert!(
57+
layout.is_unsized() || layout.abi.is_uninhabited() || self.llextra.is_none(),
58+
"Had pointer metadata {:?} for sized type {layout:?}",
59+
self.llextra,
60+
);
61+
PlaceRef { val: self, layout }
62+
}
63+
64+
/// Gets the pointer to this place as an [`OperandValue::Immediate`]
65+
/// or, for those needing metadata, an [`OperandValue::Pair`].
66+
///
67+
/// This is the inverse of [`OperandValue::deref`].
68+
pub fn address(self) -> OperandValue<V> {
69+
if let Some(llextra) = self.llextra {
70+
OperandValue::Pair(self.llval, llextra)
71+
} else {
72+
OperandValue::Immediate(self.llval)
73+
}
74+
}
3775
}
3876

3977
#[derive(Copy, Clone, Debug)]
@@ -51,9 +89,7 @@ pub struct PlaceRef<'tcx, V> {
5189

5290
impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
5391
pub fn new_sized(llval: V, layout: TyAndLayout<'tcx>) -> PlaceRef<'tcx, V> {
54-
assert!(layout.is_sized());
55-
let val = PlaceValue::new_sized(llval, layout.align.abi);
56-
PlaceRef { val, layout }
92+
PlaceRef::new_sized_aligned(llval, layout, layout.align.abi)
5793
}
5894

5995
pub fn new_sized_aligned(
@@ -62,27 +98,17 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
6298
align: Align,
6399
) -> PlaceRef<'tcx, V> {
64100
assert!(layout.is_sized());
65-
let val = PlaceValue::new_sized(llval, align);
66-
PlaceRef { val, layout }
101+
PlaceValue::new_sized(llval, align).with_type(layout)
67102
}
68103

69104
// FIXME(eddyb) pass something else for the name so no work is done
70105
// unless LLVM IR names are turned on (e.g. for `--emit=llvm-ir`).
71106
pub fn alloca<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
72107
bx: &mut Bx,
73108
layout: TyAndLayout<'tcx>,
74-
) -> Self {
75-
Self::alloca_aligned(bx, layout, layout.align.abi)
76-
}
77-
78-
pub fn alloca_aligned<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
79-
bx: &mut Bx,
80-
layout: TyAndLayout<'tcx>,
81-
align: Align,
82109
) -> Self {
83110
assert!(layout.is_sized(), "tried to statically allocate unsized place");
84-
let tmp = bx.alloca(layout.size, align);
85-
Self::new_sized_aligned(tmp, layout, align)
111+
PlaceValue::alloca(bx, layout.size, layout.align.abi).with_type(layout)
86112
}
87113

88114
/// Returns a place for an indirect reference to an unsized place.
@@ -131,18 +157,12 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
131157
} else {
132158
bx.inbounds_ptradd(self.val.llval, bx.const_usize(offset.bytes()))
133159
};
134-
PlaceRef {
135-
val: PlaceValue {
136-
llval,
137-
llextra: if bx.cx().type_has_metadata(field.ty) {
138-
self.val.llextra
139-
} else {
140-
None
141-
},
142-
align: effective_field_align,
143-
},
144-
layout: field,
145-
}
160+
let val = PlaceValue {
161+
llval,
162+
llextra: if bx.cx().type_has_metadata(field.ty) { self.val.llextra } else { None },
163+
align: effective_field_align,
164+
};
165+
val.with_type(field)
146166
};
147167

148168
// Simple cases, which don't need DST adjustment:
@@ -197,7 +217,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
197217
let ptr = bx.inbounds_ptradd(self.val.llval, offset);
198218
let val =
199219
PlaceValue { llval: ptr, llextra: self.val.llextra, align: effective_field_align };
200-
PlaceRef { val, layout: field }
220+
val.with_type(field)
201221
}
202222

203223
/// Obtain the actual discriminant of a value.
@@ -386,18 +406,13 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
386406
layout.size
387407
};
388408

389-
PlaceRef {
390-
val: PlaceValue {
391-
llval: bx.inbounds_gep(
392-
bx.cx().backend_type(self.layout),
393-
self.val.llval,
394-
&[bx.cx().const_usize(0), llindex],
395-
),
396-
llextra: None,
397-
align: self.val.align.restrict_for_offset(offset),
398-
},
399-
layout,
400-
}
409+
let llval = bx.inbounds_gep(
410+
bx.cx().backend_type(self.layout),
411+
self.val.llval,
412+
&[bx.cx().const_usize(0), llindex],
413+
);
414+
let align = self.val.align.restrict_for_offset(offset);
415+
PlaceValue::new_sized(llval, align).with_type(layout)
401416
}
402417

403418
pub fn project_downcast<Bx: BuilderMethods<'a, 'tcx, Value = V>>(

‎compiler/rustc_codegen_ssa/src/mir/rvalue.rs

+14-38
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
7272
if val.llextra.is_some() {
7373
bug!("unsized coercion on an unsized rvalue");
7474
}
75-
let source = PlaceRef { val, layout: operand.layout };
76-
base::coerce_unsized_into(bx, source, dest);
75+
base::coerce_unsized_into(bx, val.with_type(operand.layout), dest);
7776
}
7877
OperandValue::ZeroSized => {
7978
bug!("unsized coercion on a ZST rvalue");
@@ -182,10 +181,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
182181
OperandValue::Immediate(..) | OperandValue::Pair(..) => {
183182
// When we have immediate(s), the alignment of the source is irrelevant,
184183
// so we can store them using the destination's alignment.
185-
src.val.store(
186-
bx,
187-
PlaceRef::new_sized_aligned(dst.val.llval, src.layout, dst.val.align),
188-
);
184+
src.val.store(bx, dst.val.with_type(src.layout));
189185
}
190186
}
191187
}
@@ -223,8 +219,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
223219
OperandValue::Ref(source_place_val) => {
224220
debug_assert_eq!(source_place_val.llextra, None);
225221
debug_assert!(matches!(operand_kind, OperandValueKind::Ref));
226-
let fake_place = PlaceRef { val: source_place_val, layout: cast };
227-
Some(bx.load_operand(fake_place).val)
222+
Some(bx.load_operand(source_place_val.with_type(cast)).val)
228223
}
229224
OperandValue::ZeroSized => {
230225
let OperandValueKind::ZeroSized = operand_kind else {
@@ -452,23 +447,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
452447
}
453448
mir::CastKind::PointerCoercion(PointerCoercion::Unsize) => {
454449
assert!(bx.cx().is_backend_scalar_pair(cast));
455-
let (lldata, llextra) = match operand.val {
456-
OperandValue::Pair(lldata, llextra) => {
457-
// unsize from a fat pointer -- this is a
458-
// "trait-object-to-supertrait" coercion.
459-
(lldata, Some(llextra))
460-
}
461-
OperandValue::Immediate(lldata) => {
462-
// "standard" unsize
463-
(lldata, None)
464-
}
465-
OperandValue::Ref(..) => {
466-
bug!("by-ref operand {:?} in `codegen_rvalue_operand`", operand);
467-
}
468-
OperandValue::ZeroSized => {
469-
bug!("zero-sized operand {:?} in `codegen_rvalue_operand`", operand);
470-
}
471-
};
450+
let (lldata, llextra) = operand.val.pointer_parts();
472451
let (lldata, llextra) =
473452
base::unsize_ptr(bx, lldata, operand.layout.ty, cast.ty, llextra);
474453
OperandValue::Pair(lldata, llextra)
@@ -489,12 +468,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
489468
}
490469
}
491470
mir::CastKind::DynStar => {
492-
let (lldata, llextra) = match operand.val {
493-
OperandValue::Ref(..) => todo!(),
494-
OperandValue::Immediate(v) => (v, None),
495-
OperandValue::Pair(v, l) => (v, Some(l)),
496-
OperandValue::ZeroSized => bug!("ZST -- which is not PointerLike -- in DynStar"),
497-
};
471+
let (lldata, llextra) = operand.val.pointer_parts();
498472
let (lldata, llextra) =
499473
base::cast_to_dyn_star(bx, lldata, operand.layout, cast.ty, llextra);
500474
OperandValue::Pair(lldata, llextra)
@@ -780,16 +754,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
780754
mk_ptr_ty: impl FnOnce(TyCtxt<'tcx>, Ty<'tcx>) -> Ty<'tcx>,
781755
) -> OperandRef<'tcx, Bx::Value> {
782756
let cg_place = self.codegen_place(bx, place.as_ref());
757+
let val = cg_place.val.address();
783758

784759
let ty = cg_place.layout.ty;
760+
debug_assert!(
761+
if bx.cx().type_has_metadata(ty) {
762+
matches!(val, OperandValue::Pair(..))
763+
} else {
764+
matches!(val, OperandValue::Immediate(..))
765+
},
766+
"Address of place was unexpectedly {val:?} for pointee type {ty:?}",
767+
);
785768

786-
// Note: places are indirect, so storing the `llval` into the
787-
// destination effectively creates a reference.
788-
let val = if !bx.cx().type_has_metadata(ty) {
789-
OperandValue::Immediate(cg_place.val.llval)
790-
} else {
791-
OperandValue::Pair(cg_place.val.llval, cg_place.val.llextra.unwrap())
792-
};
793769
OperandRef { val, layout: self.cx.layout_of(mk_ptr_ty(self.cx.tcx(), ty)) }
794770
}
795771

‎compiler/rustc_codegen_ssa/src/traits/builder.rs

+36-25
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,15 @@ pub trait BuilderMethods<'a, 'tcx>:
186186
align: Align,
187187
flags: MemFlags,
188188
) -> Self::Value;
189+
fn store_to_place_with_flags(
190+
&mut self,
191+
val: Self::Value,
192+
place: PlaceValue<Self::Value>,
193+
flags: MemFlags,
194+
) -> Self::Value {
195+
debug_assert_eq!(place.llextra, None);
196+
self.store_with_flags(val, place.llval, place.align, flags)
197+
}
189198
fn atomic_store(
190199
&mut self,
191200
val: Self::Value,
@@ -286,35 +295,36 @@ pub trait BuilderMethods<'a, 'tcx>:
286295
/// (For example, typed load-stores with alias metadata.)
287296
fn typed_place_copy(
288297
&mut self,
289-
dst: PlaceRef<'tcx, Self::Value>,
290-
src: PlaceRef<'tcx, Self::Value>,
298+
dst: PlaceValue<Self::Value>,
299+
src: PlaceValue<Self::Value>,
300+
layout: TyAndLayout<'tcx>,
291301
) {
292-
self.typed_place_copy_with_flags(dst, src, MemFlags::empty());
302+
self.typed_place_copy_with_flags(dst, src, layout, MemFlags::empty());
293303
}
294304

295305
fn typed_place_copy_with_flags(
296306
&mut self,
297-
dst: PlaceRef<'tcx, Self::Value>,
298-
src: PlaceRef<'tcx, Self::Value>,
307+
dst: PlaceValue<Self::Value>,
308+
src: PlaceValue<Self::Value>,
309+
layout: TyAndLayout<'tcx>,
299310
flags: MemFlags,
300311
) {
301-
debug_assert!(src.val.llextra.is_none(), "cannot directly copy from unsized values");
302-
debug_assert!(dst.val.llextra.is_none(), "cannot directly copy into unsized values");
303-
debug_assert_eq!(dst.layout.size, src.layout.size);
312+
debug_assert!(layout.is_sized(), "cannot typed-copy an unsigned type");
313+
debug_assert!(src.llextra.is_none(), "cannot directly copy from unsized values");
314+
debug_assert!(dst.llextra.is_none(), "cannot directly copy into unsized values");
304315
if flags.contains(MemFlags::NONTEMPORAL) {
305316
// HACK(nox): This is inefficient but there is no nontemporal memcpy.
306-
let ty = self.backend_type(dst.layout);
307-
let val = self.load_from_place(ty, src.val);
308-
self.store_with_flags(val, dst.val.llval, dst.val.align, flags);
309-
} else if self.sess().opts.optimize == OptLevel::No && self.is_backend_immediate(dst.layout)
310-
{
317+
let ty = self.backend_type(layout);
318+
let val = self.load_from_place(ty, src);
319+
self.store_to_place_with_flags(val, dst, flags);
320+
} else if self.sess().opts.optimize == OptLevel::No && self.is_backend_immediate(layout) {
311321
// If we're not optimizing, the aliasing information from `memcpy`
312322
// isn't useful, so just load-store the value for smaller code.
313-
let temp = self.load_operand(src);
314-
temp.val.store_with_flags(self, dst, flags);
315-
} else if !dst.layout.is_zst() {
316-
let bytes = self.const_usize(dst.layout.size.bytes());
317-
self.memcpy(dst.val.llval, dst.val.align, src.val.llval, src.val.align, bytes, flags);
323+
let temp = self.load_operand(src.with_type(layout));
324+
temp.val.store_with_flags(self, dst.with_type(layout), flags);
325+
} else if !layout.is_zst() {
326+
let bytes = self.const_usize(layout.size.bytes());
327+
self.memcpy(dst.llval, dst.align, src.llval, src.align, bytes, flags);
318328
}
319329
}
320330

@@ -327,18 +337,19 @@ pub trait BuilderMethods<'a, 'tcx>:
327337
/// cases (in non-debug), preferring the fallback body instead.
328338
fn typed_place_swap(
329339
&mut self,
330-
left: PlaceRef<'tcx, Self::Value>,
331-
right: PlaceRef<'tcx, Self::Value>,
340+
left: PlaceValue<Self::Value>,
341+
right: PlaceValue<Self::Value>,
342+
layout: TyAndLayout<'tcx>,
332343
) {
333-
let mut temp = self.load_operand(left);
344+
let mut temp = self.load_operand(left.with_type(layout));
334345
if let OperandValue::Ref(..) = temp.val {
335346
// The SSA value isn't stand-alone, so we need to copy it elsewhere
336-
let alloca = PlaceRef::alloca(self, left.layout);
337-
self.typed_place_copy(alloca, left);
347+
let alloca = PlaceRef::alloca(self, layout);
348+
self.typed_place_copy(alloca.val, left, layout);
338349
temp = self.load_operand(alloca);
339350
}
340-
self.typed_place_copy(left, right);
341-
temp.val.store(self, right);
351+
self.typed_place_copy(left, right, layout);
352+
temp.val.store(self, right.with_type(layout));
342353
}
343354

344355
fn select(

0 commit comments

Comments
 (0)
Please sign in to comment.