]> git.lizzy.rs Git - rust.git/commitdiff
make PointerKind directly reflect pointer types
authorRalf Jung <post@ralfj.de>
Tue, 27 Dec 2022 11:31:17 +0000 (12:31 +0100)
committerRalf Jung <post@ralfj.de>
Mon, 6 Feb 2023 10:46:32 +0000 (11:46 +0100)
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.

compiler/rustc_abi/src/lib.rs
compiler/rustc_middle/src/ty/layout.rs
compiler/rustc_ty_utils/src/abi.rs
tests/codegen/function-arguments-noopt.rs

index 5af6206c0bb80dcabec6169f2ec00aabfd3ca146..9126c516d381e24550c7df127e4f014e3646a5ed 100644 (file)
@@ -1439,21 +1439,12 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum PointerKind {
-    /// Most general case, we know no restrictions to tell LLVM.
-    SharedMutable,
-
-    /// `&T` where `T` contains no `UnsafeCell`, is `dereferenceable`, `noalias` and `readonly`.
-    Frozen,
-
-    /// `&mut T` which is `dereferenceable` and `noalias` but not `readonly`.
-    UniqueBorrowed,
-
-    /// `&mut !Unpin`, which is `dereferenceable` but neither `noalias` nor `readonly`.
-    UniqueBorrowedPinned,
-
-    /// `Box<T>`, which is `noalias` (even on return types, unlike the above) but neither `readonly`
-    /// nor `dereferenceable`.
-    UniqueOwned,
+    /// Shared reference. `frozen` indicates the absence of any `UnsafeCell`.
+    SharedRef { frozen: bool },
+    /// Mutable reference. `unpin` indicates the absence of any pinned data.
+    MutableRef { unpin: bool },
+    /// Box.
+    Box,
 }
 
 /// Note that this information is advisory only, and backends are free to ignore it.
index cdcd6281f209bb4d25761ebb9e0a6cd9d1fac8f3..1244922c6d4aa4e40fb7b508970b6990e6925315 100644 (file)
@@ -833,32 +833,17 @@ fn ty_and_layout_pointee_info_at(
                     })
                 }
                 ty::Ref(_, ty, mt) if offset.bytes() == 0 => {
-                    let kind = if tcx.sess.opts.optimize == OptLevel::No {
-                        // Use conservative pointer kind if not optimizing. This saves us the
-                        // Freeze/Unpin queries, and can save time in the codegen backend (noalias
-                        // attributes in LLVM have compile-time cost even in unoptimized builds).
-                        PointerKind::SharedMutable
-                    } else {
-                        match mt {
-                            hir::Mutability::Not => {
-                                if ty.is_freeze(tcx, cx.param_env()) {
-                                    PointerKind::Frozen
-                                } else {
-                                    PointerKind::SharedMutable
-                                }
-                            }
-                            hir::Mutability::Mut => {
-                                // References to self-referential structures should not be considered
-                                // noalias, as another pointer to the structure can be obtained, that
-                                // is not based-on the original reference. We consider all !Unpin
-                                // types to be potentially self-referential here.
-                                if ty.is_unpin(tcx, cx.param_env()) {
-                                    PointerKind::UniqueBorrowed
-                                } else {
-                                    PointerKind::UniqueBorrowedPinned
-                                }
-                            }
-                        }
+                    // Use conservative pointer kind if not optimizing. This saves us the
+                    // Freeze/Unpin queries, and can save time in the codegen backend (noalias
+                    // attributes in LLVM have compile-time cost even in unoptimized builds).
+                    let optimize = tcx.sess.opts.optimize != OptLevel::No;
+                    let kind = match mt {
+                        hir::Mutability::Not => PointerKind::SharedRef {
+                            frozen: optimize && ty.is_freeze(tcx, cx.param_env()),
+                        },
+                        hir::Mutability::Mut => PointerKind::MutableRef {
+                            unpin: optimize && ty.is_unpin(tcx, cx.param_env()),
+                        },
                     };
 
                     tcx.layout_of(param_env.and(ty)).ok().map(|layout| PointeeInfo {
@@ -929,7 +914,7 @@ fn ty_and_layout_pointee_info_at(
                     if let Some(ref mut pointee) = result {
                         if let ty::Adt(def, _) = this.ty.kind() {
                             if def.is_box() && offset.bytes() == 0 {
-                                pointee.safe = Some(PointerKind::UniqueOwned);
+                                pointee.safe = Some(PointerKind::Box);
                             }
                         }
                     }
index 1c74aeca5ab1fae38a6e6234c6ad7b40b292078b..884087987ce08c6e98123a696e70730887c5f703 100644 (file)
@@ -254,15 +254,15 @@ fn adjust_for_rust_scalar<'tcx>(
         if let Some(kind) = pointee.safe {
             attrs.pointee_align = Some(pointee.align);
 
-            // `Box` (`UniqueBorrowed`) are not necessarily dereferenceable
-            // for the entire duration of the function as they can be deallocated
-            // at any time. Same for shared mutable references. If LLVM had a
-            // way to say "dereferenceable on entry" we could use it here.
+            // `Box` are not necessarily dereferenceable for the entire duration of the function as
+            // they can be deallocated at any time. Same for non-frozen shared references (see
+            // <https://github.com/rust-lang/rust/pull/98017>). If LLVM had a way to say
+            // "dereferenceable on entry" we could use it here.
             attrs.pointee_size = match kind {
-                PointerKind::UniqueBorrowed
-                | PointerKind::UniqueBorrowedPinned
-                | PointerKind::Frozen => pointee.size,
-                PointerKind::SharedMutable | PointerKind::UniqueOwned => Size::ZERO,
+                PointerKind::Box | PointerKind::SharedRef { frozen: false } => Size::ZERO,
+                PointerKind::SharedRef { frozen: true } | PointerKind::MutableRef { .. } => {
+                    pointee.size
+                }
             };
 
             // The aliasing rules for `Box<T>` are still not decided, but currently we emit
@@ -278,15 +278,14 @@ fn adjust_for_rust_scalar<'tcx>(
             // `&mut` pointer parameters never alias other parameters,
             // or mutable global data
             //
-            // `&T` where `T` contains no `UnsafeCell<U>` is immutable,
-            // and can be marked as both `readonly` and `noalias`, as
-            // LLVM's definition of `noalias` is based solely on memory
-            // dependencies rather than pointer equality
+            // `&T` where `T` contains no `UnsafeCell<U>` is immutable, and can be marked as both
+            // `readonly` and `noalias`, as LLVM's definition of `noalias` is based solely on memory
+            // dependencies rather than pointer equality. However this only applies to arguments,
+            // not return values.
             let no_alias = match kind {
-                PointerKind::SharedMutable | PointerKind::UniqueBorrowedPinned => false,
-                PointerKind::UniqueBorrowed => noalias_mut_ref,
-                PointerKind::UniqueOwned => noalias_for_box,
-                PointerKind::Frozen => true,
+                PointerKind::SharedRef { frozen } => frozen,
+                PointerKind::MutableRef { unpin } => unpin && noalias_mut_ref,
+                PointerKind::Box => noalias_for_box,
             };
             // We can never add `noalias` in return position; that LLVM attribute has some very surprising semantics
             // (see <https://github.com/rust-lang/unsafe-code-guidelines/issues/385#issuecomment-1368055745>).
@@ -294,7 +293,7 @@ fn adjust_for_rust_scalar<'tcx>(
                 attrs.set(ArgAttribute::NoAlias);
             }
 
-            if kind == PointerKind::Frozen && !is_return {
+            if matches!(kind, PointerKind::SharedRef { frozen: true }) && !is_return {
                 attrs.set(ArgAttribute::ReadOnly);
             }
         }
index ff76405a4ea323338c45c98751756216f76f4f30..0c62e0d35e36d91624e2ac519e56f1cc72d9c91e 100644 (file)
@@ -29,6 +29,12 @@ pub fn borrow(x: &i32) -> &i32 {
   x
 }
 
+// CHECK: align 4 {{i32\*|ptr}} @borrow_mut({{i32\*|ptr}} align 4 %x)
+#[no_mangle]
+pub fn borrow_mut(x: &mut i32) -> &mut i32 {
+  x
+}
+
 // CHECK-LABEL: @borrow_call
 #[no_mangle]
 pub fn borrow_call(x: &i32, f: fn(&i32) -> &i32) -> &i32 {