Skip to content

Commit f6fafff

Browse files
committed
preserve alignment information for MaybeDangling wrapped references
1 parent b41dbdf commit f6fafff

7 files changed

Lines changed: 42 additions & 37 deletions

File tree

compiler/rustc_abi/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2137,17 +2137,17 @@ pub enum PointerKind {
21372137
/// that must always be okay.
21382138
#[derive(Copy, Clone, Debug)]
21392139
pub struct PointeeInfo {
2140-
/// If this is `None`, then this is a raw pointer, so size and alignment are not guaranteed to
2141-
/// be reliable.
2140+
/// If this is `None`, then this is a raw pointer, so size is not guaranteed to be reliable.
2141+
/// Note that the alignment might still be accurate, if provided.
21422142
pub safe: Option<PointerKind>,
21432143
/// If `safe` is `Some`, then the pointer is either null or dereferenceable for this many bytes.
21442144
/// On a function argument, "dereferenceable" here means "dereferenceable for the entire duration
21452145
/// of this function call", i.e. it is UB for the memory that this pointer points to be freed
21462146
/// while this function is still running.
21472147
/// The size can be zero if the pointer is not dereferenceable.
21482148
pub size: Size,
2149-
/// If `safe` is `Some`, then the pointer is aligned as indicated.
2150-
pub align: Align,
2149+
/// If `Some`, then the pointer is aligned as indicated.
2150+
pub align: Option<Align>,
21512151
}
21522152

21532153
impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {

compiler/rustc_codegen_gcc/src/type_of.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,8 +288,9 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
288288
Float(f) => cx.type_from_float(f),
289289
Pointer(address_space) => {
290290
// If we know the alignment, pick something better than i8.
291-
let pointee = if let Some(pointee) = self.pointee_info_at(cx, offset) {
292-
cx.type_pointee_for_align(pointee.align)
291+
let pointee = if let Some(pointee) = self.pointee_info_at(cx, offset)
292+
&& let Some(align) = pointee.align {
293+
cx.type_pointee_for_align(align)
293294
} else {
294295
cx.type_i8()
295296
};

compiler/rustc_codegen_llvm/src/builder.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -714,9 +714,9 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
714714
}
715715

716716
if let Some(pointee) = layout.pointee_info_at(bx, offset)
717-
&& let Some(_) = pointee.safe
717+
&& let Some(align) = pointee.align
718718
{
719-
bx.align_metadata(load, pointee.align);
719+
bx.align_metadata(load, align);
720720
}
721721
}
722722
abi::Primitive::Float(_) => {}

compiler/rustc_codegen_ssa/src/mir/statement.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use rustc_middle::mir::{self, NonDivergingIntrinsic, StmtDebugInfo};
2-
use rustc_middle::span_bug;
2+
use rustc_middle::{bug, span_bug, ty};
33
use tracing::instrument;
44

55
use super::{FunctionCx, LocalRef};
@@ -77,13 +77,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
7777
let dst_val = self.codegen_operand(bx, dst);
7878
let src_val = self.codegen_operand(bx, src);
7979
let count = self.codegen_operand(bx, count).immediate();
80-
let pointee_layout = dst_val
81-
.layout
82-
.pointee_info_at(bx, rustc_abi::Size::ZERO)
83-
.expect("Expected pointer");
84-
let bytes = bx.mul(count, bx.const_usize(pointee_layout.size.bytes()));
8580

86-
let align = pointee_layout.align;
81+
let &ty::RawPtr(pointee, _) = dst_val.layout.ty.kind() else {
82+
bug!("expected pointer")
83+
};
84+
let pointee_layout = bx
85+
.tcx()
86+
.layout_of(bx.typing_env().as_query_input(pointee))
87+
.expect("expected pointee to have a layout");
88+
89+
let bytes = bx.mul(count, bx.const_usize(pointee_layout.layout.size().bytes()));
90+
91+
let align = pointee_layout.layout.align.abi;
8792
let dst = dst_val.immediate();
8893
let src = src_val.immediate();
8994
bx.memcpy(dst, align, src, align, bytes, crate::MemFlags::empty(), None);

compiler/rustc_middle/src/ty/layout.rs

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,19 +1023,8 @@ where
10231023
let typing_env = cx.typing_env();
10241024

10251025
let pointee_info = match *this.ty.kind() {
1026-
ty::RawPtr(p_ty, _) if offset.bytes() == 0 => {
1027-
tcx.layout_of(typing_env.as_query_input(p_ty)).ok().map(|layout| PointeeInfo {
1028-
size: layout.size,
1029-
align: layout.align.abi,
1030-
safe: None,
1031-
})
1032-
}
1033-
ty::FnPtr(..) if offset.bytes() == 0 => {
1034-
tcx.layout_of(typing_env.as_query_input(this.ty)).ok().map(|layout| PointeeInfo {
1035-
size: layout.size,
1036-
align: layout.align.abi,
1037-
safe: None,
1038-
})
1026+
ty::RawPtr(_, _) | ty::FnPtr(..) if offset.bytes() == 0 => {
1027+
Some(PointeeInfo { size: Size::ZERO, align: None, safe: None })
10391028
}
10401029
ty::Ref(_, ty, mt) if offset.bytes() == 0 => {
10411030
// Use conservative pointer kind if not optimizing. This saves us the
@@ -1055,15 +1044,23 @@ where
10551044

10561045
tcx.layout_of(typing_env.as_query_input(ty)).ok().map(|layout| PointeeInfo {
10571046
size: layout.size,
1058-
align: layout.align.abi,
1047+
align: Some(layout.align.abi),
10591048
safe: Some(kind),
10601049
})
10611050
}
10621051

10631052
ty::Adt(adt_def, ..) if adt_def.is_maybe_dangling() => {
1064-
// FIXME: what is the exact effect of maybe dangling?
1065-
Self::ty_and_layout_pointee_info_at(this.field(cx, 0), cx, offset)
1066-
.map(|info| PointeeInfo { safe: None, ..info })
1053+
Self::ty_and_layout_pointee_info_at(this.field(cx, 0), cx, offset).map(|info| {
1054+
PointeeInfo {
1055+
// Downgrade references to pointers (in llvm this strips noalias)
1056+
safe: None,
1057+
// Make sure we don't assert dereferenceability of the pointer.
1058+
// That is also implied by `safe: None`, but set this explicitly to be sure.
1059+
size: Size::ZERO,
1060+
// Keep the alignment info
1061+
align: info.align,
1062+
}
1063+
})
10671064
}
10681065

10691066
_ => {

compiler/rustc_ty_utils/src/abi.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -315,10 +315,12 @@ fn arg_attrs_for_rust_scalar<'tcx>(
315315
} else {
316316
None
317317
};
318-
if let Some(kind) = kind {
319-
attrs.pointee_align =
320-
Some(pointee.align.min(cx.tcx().sess.target.max_reliable_alignment()));
321318

319+
if let Some(align) = pointee.align {
320+
attrs.pointee_align = Some(align.min(cx.tcx().sess.target.max_reliable_alignment()));
321+
}
322+
323+
if let Some(kind) = kind {
322324
attrs.pointee_size = match kind {
323325
// LLVM dereferenceable attribute has unclear semantics on the return type,
324326
// they seem to be "dereferenceable until the end of the program", which is

tests/codegen-llvm/manually_drop_refs.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub fn f(x: ManuallyDrop<Box<u8>>) -> ManuallyDrop<Box<u8>> {
1515
x
1616
}
1717

18-
// CHECK: define noundef nonnull ptr @g
18+
// CHECK: define noundef nonnull align 1 ptr @g
1919
// CHECK-NOT: noalias
2020
// CHECK-NOT: dereferenceable
2121
// CHECK-SAME: unnamed_addr
@@ -24,7 +24,7 @@ pub fn g(x: ManuallyDrop<&u8>) -> ManuallyDrop<&u8> {
2424
x
2525
}
2626

27-
// CHECK: define noundef nonnull ptr @h
27+
// CHECK: define noundef nonnull align 1 ptr @h
2828
// CHECK-NOT: noalias
2929
// CHECK-NOT: dereferenceable
3030
// CHECK-SAME: unnamed_addr

0 commit comments

Comments
 (0)