Skip to content

Commit 201ae73

Browse files
committed
make PointerKind directly reflect pointer types
The code that consumes PointerKind (`adjust_for_rust_scalar` in rustc_ty_utils) ended up using PointerKind variants to talk about Rust reference types (& and &mut) anyway, making the old code structure quite confusing: one always had to keep in mind which PointerKind corresponds to which type. So this changes PointerKind to directly reflect the type. This does not change behavior.
1 parent 0c13c17 commit 201ae73

File tree

4 files changed

+40
-59
lines changed

4 files changed

+40
-59
lines changed

compiler/rustc_abi/src/lib.rs

+6-15
Original file line numberDiff line numberDiff line change
@@ -1439,21 +1439,12 @@ impl<V: Idx> fmt::Debug for LayoutS<V> {
14391439

14401440
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
14411441
pub enum PointerKind {
1442-
/// Most general case, we know no restrictions to tell LLVM.
1443-
SharedMutable,
1444-
1445-
/// `&T` where `T` contains no `UnsafeCell`, is `dereferenceable`, `noalias` and `readonly`.
1446-
Frozen,
1447-
1448-
/// `&mut T` which is `dereferenceable` and `noalias` but not `readonly`.
1449-
UniqueBorrowed,
1450-
1451-
/// `&mut !Unpin`, which is `dereferenceable` but neither `noalias` nor `readonly`.
1452-
UniqueBorrowedPinned,
1453-
1454-
/// `Box<T>`, which is `noalias` (even on return types, unlike the above) but neither `readonly`
1455-
/// nor `dereferenceable`.
1456-
UniqueOwned,
1442+
/// Shared reference. `frozen` indicates the absence of any `UnsafeCell`.
1443+
SharedRef { frozen: bool },
1444+
/// Mutable reference. `unpin` indicates the absence of any pinned data.
1445+
MutableRef { unpin: bool },
1446+
/// Box.
1447+
Box,
14571448
}
14581449

14591450
/// Note that this information is advisory only, and backends are free to ignore it.

compiler/rustc_middle/src/ty/layout.rs

+12-27
Original file line numberDiff line numberDiff line change
@@ -833,32 +833,17 @@ where
833833
})
834834
}
835835
ty::Ref(_, ty, mt) if offset.bytes() == 0 => {
836-
let kind = if tcx.sess.opts.optimize == OptLevel::No {
837-
// Use conservative pointer kind if not optimizing. This saves us the
838-
// Freeze/Unpin queries, and can save time in the codegen backend (noalias
839-
// attributes in LLVM have compile-time cost even in unoptimized builds).
840-
PointerKind::SharedMutable
841-
} else {
842-
match mt {
843-
hir::Mutability::Not => {
844-
if ty.is_freeze(tcx, cx.param_env()) {
845-
PointerKind::Frozen
846-
} else {
847-
PointerKind::SharedMutable
848-
}
849-
}
850-
hir::Mutability::Mut => {
851-
// References to self-referential structures should not be considered
852-
// noalias, as another pointer to the structure can be obtained, that
853-
// is not based-on the original reference. We consider all !Unpin
854-
// types to be potentially self-referential here.
855-
if ty.is_unpin(tcx, cx.param_env()) {
856-
PointerKind::UniqueBorrowed
857-
} else {
858-
PointerKind::UniqueBorrowedPinned
859-
}
860-
}
861-
}
836+
// Use conservative pointer kind if not optimizing. This saves us the
837+
// Freeze/Unpin queries, and can save time in the codegen backend (noalias
838+
// attributes in LLVM have compile-time cost even in unoptimized builds).
839+
let optimize = tcx.sess.opts.optimize != OptLevel::No;
840+
let kind = match mt {
841+
hir::Mutability::Not => PointerKind::SharedRef {
842+
frozen: optimize && ty.is_freeze(tcx, cx.param_env()),
843+
},
844+
hir::Mutability::Mut => PointerKind::MutableRef {
845+
unpin: optimize && ty.is_unpin(tcx, cx.param_env()),
846+
},
862847
};
863848

864849
tcx.layout_of(param_env.and(ty)).ok().map(|layout| PointeeInfo {
@@ -929,7 +914,7 @@ where
929914
if let Some(ref mut pointee) = result {
930915
if let ty::Adt(def, _) = this.ty.kind() {
931916
if def.is_box() && offset.bytes() == 0 {
932-
pointee.safe = Some(PointerKind::UniqueOwned);
917+
pointee.safe = Some(PointerKind::Box);
933918
}
934919
}
935920
}

compiler/rustc_ty_utils/src/abi.rs

+16-17
Original file line numberDiff line numberDiff line change
@@ -254,15 +254,15 @@ fn adjust_for_rust_scalar<'tcx>(
254254
if let Some(kind) = pointee.safe {
255255
attrs.pointee_align = Some(pointee.align);
256256

257-
// `Box` (`UniqueBorrowed`) are not necessarily dereferenceable
258-
// for the entire duration of the function as they can be deallocated
259-
// at any time. Same for shared mutable references. If LLVM had a
260-
// way to say "dereferenceable on entry" we could use it here.
257+
// `Box` are not necessarily dereferenceable for the entire duration of the function as
258+
// they can be deallocated at any time. Same for non-frozen shared references (see
259+
// <https://github.com/rust-lang/rust/pull/98017>). If LLVM had a way to say
260+
// "dereferenceable on entry" we could use it here.
261261
attrs.pointee_size = match kind {
262-
PointerKind::UniqueBorrowed
263-
| PointerKind::UniqueBorrowedPinned
264-
| PointerKind::Frozen => pointee.size,
265-
PointerKind::SharedMutable | PointerKind::UniqueOwned => Size::ZERO,
262+
PointerKind::Box | PointerKind::SharedRef { frozen: false } => Size::ZERO,
263+
PointerKind::SharedRef { frozen: true } | PointerKind::MutableRef { .. } => {
264+
pointee.size
265+
}
266266
};
267267

268268
// The aliasing rules for `Box<T>` are still not decided, but currently we emit
@@ -278,23 +278,22 @@ fn adjust_for_rust_scalar<'tcx>(
278278
// `&mut` pointer parameters never alias other parameters,
279279
// or mutable global data
280280
//
281-
// `&T` where `T` contains no `UnsafeCell<U>` is immutable,
282-
// and can be marked as both `readonly` and `noalias`, as
283-
// LLVM's definition of `noalias` is based solely on memory
284-
// dependencies rather than pointer equality
281+
// `&T` where `T` contains no `UnsafeCell<U>` is immutable, and can be marked as both
282+
// `readonly` and `noalias`, as LLVM's definition of `noalias` is based solely on memory
283+
// dependencies rather than pointer equality. However this only applies to arguments,
284+
// not return values.
285285
let no_alias = match kind {
286-
PointerKind::SharedMutable | PointerKind::UniqueBorrowedPinned => false,
287-
PointerKind::UniqueBorrowed => noalias_mut_ref,
288-
PointerKind::UniqueOwned => noalias_for_box,
289-
PointerKind::Frozen => true,
286+
PointerKind::SharedRef { frozen } => frozen,
287+
PointerKind::MutableRef { unpin } => unpin && noalias_mut_ref,
288+
PointerKind::Box => noalias_for_box,
290289
};
291290
// We can never add `noalias` in return position; that LLVM attribute has some very surprising semantics
292291
// (see <https://github.com/rust-lang/unsafe-code-guidelines/issues/385#issuecomment-1368055745>).
293292
if no_alias && !is_return {
294293
attrs.set(ArgAttribute::NoAlias);
295294
}
296295

297-
if kind == PointerKind::Frozen && !is_return {
296+
if matches!(kind, PointerKind::SharedRef { frozen: true }) && !is_return {
298297
attrs.set(ArgAttribute::ReadOnly);
299298
}
300299
}

tests/codegen/function-arguments-noopt.rs

+6
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ pub fn borrow(x: &i32) -> &i32 {
2929
x
3030
}
3131

32+
// CHECK: align 4 {{i32\*|ptr}} @borrow_mut({{i32\*|ptr}} align 4 %x)
33+
#[no_mangle]
34+
pub fn borrow_mut(x: &mut i32) -> &mut i32 {
35+
x
36+
}
37+
3238
// CHECK-LABEL: @borrow_call
3339
#[no_mangle]
3440
pub fn borrow_call(x: &i32, f: fn(&i32) -> &i32) -> &i32 {

0 commit comments

Comments
 (0)