summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_codegen_ssa/src/mir/place.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_codegen_ssa/src/mir/place.rs')
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs55
1 files changed, 25 insertions, 30 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index eb590a45a..c0bb3ac56 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -2,7 +2,7 @@ use super::operand::OperandValue;
use super::{FunctionCx, LocalRef};
use crate::common::IntPredicate;
-use crate::glue;
+use crate::size_of_val;
use crate::traits::*;
use rustc_middle::mir;
@@ -99,6 +99,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
let offset = self.layout.fields.offset(ix);
let effective_field_align = self.align.restrict_for_offset(offset);
+ // `simple` is called when we don't need to adjust the offset to
+ // the dynamic alignment of the field.
let mut simple = || {
let llval = match self.layout.abi {
_ if offset.bytes() == 0 => {
@@ -141,35 +143,21 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
};
// Simple cases, which don't need DST adjustment:
- // * no metadata available - just log the case
- // * known alignment - sized types, `[T]`, `str` or a foreign type
- // * packed struct - there is no alignment padding
+ // * known alignment - sized types, `[T]`, `str`
+ // * offset 0 -- rounding up to alignment cannot change the offset
+ // Note that looking at `field.align` is incorrect since that is not necessarily equal
+ // to the dynamic alignment of the type.
match field.ty.kind() {
- _ if self.llextra.is_none() => {
- debug!(
- "unsized field `{}`, of `{:?}` has no metadata for adjustment",
- ix, self.llval
- );
- return simple();
- }
_ if field.is_sized() => return simple(),
- ty::Slice(..) | ty::Str | ty::Foreign(..) => return simple(),
- ty::Adt(def, _) => {
- if def.repr().packed() {
- // FIXME(eddyb) generalize the adjustment when we
- // start supporting packing to larger alignments.
- assert_eq!(self.layout.align.abi.bytes(), 1);
- return simple();
- }
- }
+ ty::Slice(..) | ty::Str => return simple(),
+ _ if offset.bytes() == 0 => return simple(),
_ => {}
}
// We need to get the pointer manually now.
// We do this by casting to a `*i8`, then offsetting it by the appropriate amount.
// We do this instead of, say, simply adjusting the pointer from the result of a GEP
- // because the field may have an arbitrary alignment in the LLVM representation
- // anyway.
+ // because the field may have an arbitrary alignment in the LLVM representation.
//
// To demonstrate:
//
@@ -186,7 +174,16 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
let unaligned_offset = bx.cx().const_usize(offset.bytes());
// Get the alignment of the field
- let (_, unsized_align) = glue::size_and_align_of_dst(bx, field.ty, meta);
+ let (_, mut unsized_align) = size_of_val::size_and_align_of_dst(bx, field.ty, meta);
+
+ // For packed types, we need to cap alignment.
+ if let ty::Adt(def, _) = self.layout.ty.kind()
+ && let Some(packed) = def.repr().pack
+ {
+ let packed = bx.const_usize(packed.bytes());
+ let cmp = bx.icmp(IntPredicate::IntULT, unsized_align, packed);
+ unsized_align = bx.select(cmp, unsized_align, packed)
+ }
// Bump the unaligned offset up to the appropriate alignment
let offset = round_up_const_value_to_alignment(bx, unaligned_offset, unsized_align);
@@ -474,27 +471,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
cg_base.project_index(bx, llindex)
}
mir::ProjectionElem::ConstantIndex { offset, from_end: false, min_length: _ } => {
- let lloffset = bx.cx().const_usize(offset as u64);
+ let lloffset = bx.cx().const_usize(offset);
cg_base.project_index(bx, lloffset)
}
mir::ProjectionElem::ConstantIndex { offset, from_end: true, min_length: _ } => {
- let lloffset = bx.cx().const_usize(offset as u64);
+ let lloffset = bx.cx().const_usize(offset);
let lllen = cg_base.len(bx.cx());
let llindex = bx.sub(lllen, lloffset);
cg_base.project_index(bx, llindex)
}
mir::ProjectionElem::Subslice { from, to, from_end } => {
- let mut subslice = cg_base.project_index(bx, bx.cx().const_usize(from as u64));
+ let mut subslice = cg_base.project_index(bx, bx.cx().const_usize(from));
let projected_ty =
PlaceTy::from_ty(cg_base.layout.ty).projection_ty(tcx, *elem).ty;
subslice.layout = bx.cx().layout_of(self.monomorphize(projected_ty));
if subslice.layout.is_unsized() {
assert!(from_end, "slice subslices should be `from_end`");
- subslice.llextra = Some(bx.sub(
- cg_base.llextra.unwrap(),
- bx.cx().const_usize((from as u64) + (to as u64)),
- ));
+ subslice.llextra =
+ Some(bx.sub(cg_base.llextra.unwrap(), bx.cx().const_usize(from + to)));
}
subslice