]> git.lizzy.rs Git - rust.git/commitdiff
add cast kind of from_exposed_addr (int-to-ptr casts)
authorRalf Jung <post@ralfj.de>
Thu, 2 Jun 2022 13:05:37 +0000 (09:05 -0400)
committerRalf Jung <post@ralfj.de>
Thu, 2 Jun 2022 14:46:13 +0000 (10:46 -0400)
compiler/rustc_borrowck/src/type_check/mod.rs
compiler/rustc_codegen_cranelift/src/base.rs
compiler/rustc_codegen_ssa/src/mir/rvalue.rs
compiler/rustc_const_eval/src/interpret/cast.rs
compiler/rustc_const_eval/src/transform/check_consts/check.rs
compiler/rustc_const_eval/src/transform/promote_consts.rs
compiler/rustc_middle/src/mir/mod.rs
compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff
src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs

index abf77acb8c7adeddaf49d2df92c5f86d13365cb1..e5aed1b60ddc1fe56a3e9b451346315ea1077246 100644 (file)
@@ -2154,31 +2154,55 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
                         match (cast_ty_from, cast_ty_to) {
                             (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => (),
                             _ => {
-                                span_mirbug!(self, rvalue, "Invalid cast {:?} -> {:?}", ty_from, ty)
+                                span_mirbug!(
+                                    self,
+                                    rvalue,
+                                    "Invalid PointerExposeAddress cast {:?} -> {:?}",
+                                    ty_from,
+                                    ty
+                                )
                             }
                         }
                     }
 
-                    CastKind::Misc => {
+                    CastKind::PointerFromExposedAddress => {
                         let ty_from = op.ty(body, tcx);
                         let cast_ty_from = CastTy::from_ty(ty_from);
                         let cast_ty_to = CastTy::from_ty(*ty);
                         match (cast_ty_from, cast_ty_to) {
-                            (None, _)
-                            | (_, None | Some(CastTy::FnPtr))
-                            | (Some(CastTy::Float), Some(CastTy::Ptr(_)))
-                            | (
-                                Some(CastTy::Ptr(_) | CastTy::FnPtr),
-                                Some(CastTy::Float | CastTy::Int(_)),
-                            ) => {
-                                span_mirbug!(self, rvalue, "Invalid cast {:?} -> {:?}", ty_from, ty,)
+                            (Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => (),
+                            _ => {
+                                span_mirbug!(
+                                    self,
+                                    rvalue,
+                                    "Invalid PointerFromExposedAddress cast {:?} -> {:?}",
+                                    ty_from,
+                                    ty
+                                )
                             }
+                        }
+                    }
+
+                    CastKind::Misc => {
+                        let ty_from = op.ty(body, tcx);
+                        let cast_ty_from = CastTy::from_ty(ty_from);
+                        let cast_ty_to = CastTy::from_ty(*ty);
+                        // Misc casts are either between floats and ints, or one ptr type to another.
+                        match (cast_ty_from, cast_ty_to) {
                             (
-                                Some(CastTy::Int(_)),
-                                Some(CastTy::Int(_) | CastTy::Float | CastTy::Ptr(_)),
+                                Some(CastTy::Int(_) | CastTy::Float),
+                                Some(CastTy::Int(_) | CastTy::Float),
                             )
-                            | (Some(CastTy::Float), Some(CastTy::Int(_) | CastTy::Float))
                             | (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Ptr(_))) => (),
+                            _ => {
+                                span_mirbug!(
+                                    self,
+                                    rvalue,
+                                    "Invalid Misc cast {:?} -> {:?}",
+                                    ty_from,
+                                    ty,
+                                )
+                            }
                         }
                     }
                 }
index 58bec183c94aa52aee6d0fb3d063ef3790cad4f8..07136e1b76a9f0895780db655019cc6326fce889 100644 (file)
@@ -608,7 +608,9 @@ fn codegen_stmt<'tcx>(
                     lval.write_cvalue(fx, operand.cast_pointer_to(to_layout));
                 }
                 Rvalue::Cast(
-                    CastKind::Misc | CastKind::PointerExposeAddress,
+                    CastKind::Misc
+                    | CastKind::PointerExposeAddress
+                    | CastKind::PointerFromExposedAddress,
                     ref operand,
                     to_ty,
                 ) => {
index 6ff8d4aa4421694587df6627ac786e8161acfd9a..90afb7adcb2b5e03b4328a059db3640bfa26a1f8 100644 (file)
@@ -269,7 +269,8 @@ pub fn codegen_rvalue_operand(
                     mir::CastKind::Pointer(
                         PointerCast::MutToConstPointer | PointerCast::ArrayToPointer,
                     )
-                    | mir::CastKind::Misc => {
+                    | mir::CastKind::Misc
+                    | mir::CastKind::PointerFromExposedAddress => {
                         assert!(bx.cx().is_backend_immediate(cast));
                         let ll_t_out = bx.cx().immediate_backend_type(cast);
                         if operand.layout.abi.is_uninhabited() {
index 520ae409e6b9fa08f1191fa05ba28f41e3ee49c8..73cc59ad1e674361a78c6d9d26af95b60e4c4043 100644 (file)
@@ -37,6 +37,12 @@ pub fn cast(
                 self.write_immediate(res, dest)?;
             }
 
+            PointerFromExposedAddress => {
+                let src = self.read_immediate(src)?;
+                let res = self.pointer_from_exposed_address_cast(&src, cast_ty)?;
+                self.write_immediate(res, dest)?;
+            }
+
             Misc => {
                 let src = self.read_immediate(src)?;
                 let res = self.misc_cast(&src, cast_ty)?;
@@ -201,6 +207,24 @@ pub fn pointer_expose_address_cast(
         Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into())
     }
 
+    pub fn pointer_from_exposed_address_cast(
+        &mut self,
+        src: &ImmTy<'tcx, M::PointerTag>,
+        cast_ty: Ty<'tcx>,
+    ) -> InterpResult<'tcx, Immediate<M::PointerTag>> {
+        assert!(src.layout.ty.is_integral());
+        assert_matches!(cast_ty.kind(), ty::RawPtr(_));
+
+        // First cast to usize.
+        let scalar = src.to_scalar()?;
+        let addr = self.cast_from_int_like(scalar, src.layout, self.tcx.types.usize)?;
+        let addr = addr.to_machine_usize(self)?;
+
+        // Then turn address into pointer.
+        let ptr = M::ptr_from_addr_cast(&self, addr);
+        Ok(Scalar::from_maybe_pointer(ptr, self).into())
+    }
+
     pub fn cast_from_int_like(
         &self,
         scalar: Scalar<M::PointerTag>, // input value (there is no ScalarTy so we separate data+layout)
@@ -225,16 +249,6 @@ pub fn cast_from_int_like(
                 Scalar::from_uint(v, size)
             }
 
-            RawPtr(_) => {
-                assert!(src_layout.ty.is_integral());
-
-                let size = self.pointer_size();
-                let addr = u64::try_from(size.truncate(v)).unwrap();
-
-                let ptr = M::ptr_from_addr_cast(&self, addr);
-                Scalar::from_maybe_pointer(ptr, self)
-            }
-
             Float(FloatTy::F32) if signed => Scalar::from_f32(Single::from_i128(v as i128).value),
             Float(FloatTy::F64) if signed => Scalar::from_f64(Double::from_i128(v as i128).value),
             Float(FloatTy::F32) => Scalar::from_f32(Single::from_u128(v).value),
index c07680515f4e7125f87555bb1aac46ef1fc76ee4..4b98e19376dda0d18b63cfccc009d4a7afc0bde2 100644 (file)
@@ -519,32 +519,30 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
                 }
             }
 
-            Rvalue::Cast(
-                CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer),
-                _,
-                _,
-            ) => {}
-
             Rvalue::Cast(
                 CastKind::Pointer(
-                    PointerCast::UnsafeFnPointer
+                    PointerCast::MutToConstPointer
+                    | PointerCast::ArrayToPointer
+                    | PointerCast::UnsafeFnPointer
                     | PointerCast::ClosureFnPointer(_)
                     | PointerCast::ReifyFnPointer,
                 ),
                 _,
                 _,
             ) => {
-                // Nothing to do here. Function pointer casts are allowed now.
+                // These are all okay; they only change the type, not the data.
             }
 
             Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), _, _) => {
-                // Nothing to check here (`check_local_or_return_ty` ensures no trait objects occur
-                // in the type of any local, which also excludes casts).
+                // Unsizing is implemented for CTFE.
             }
 
             Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => {
                 self.check_op(ops::RawPtrToIntCast);
             }
+            Rvalue::Cast(CastKind::PointerFromExposedAddress, _, _) => {
+                // Since no pointer can ever get exposed (rejected above), this is easy to support.
+            }
 
             Rvalue::Cast(CastKind::Misc, _, _) => {}
 
index cf5d7b6c70a30f09c0d9f57a60806a6d58f5e789..4879e8de10000f4f2ee44eefff13419bba0a5a69 100644 (file)
@@ -504,7 +504,8 @@ fn validate_rvalue(&mut self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable>
             // ptr-to-int casts are not possible in consts and thus not promotable
             Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => return Err(Unpromotable),
 
-            // int-to-ptr casts are fine, they just use the integer value at pointer type.
+            // all ohter casts including int-to-ptr casts are fine, they just use the integer value
+            // at pointer type.
             Rvalue::Cast(_, operand, _) => {
                 self.validate_operand(operand)?;
             }
index d9cdca8bcb5d72f31d9209c71cd589854d7de5f9..f3db359ec334829a39e313b79d655854eb2be56a 100644 (file)
@@ -2613,12 +2613,18 @@ pub fn is_pointer_int_cast(&self) -> bool {
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
 pub enum CastKind {
-    Misc,
     /// An exposing pointer to address cast. A cast between a pointer and an integer type, or
     /// between a function pointer and an integer type.
     /// See the docs on `expose_addr` for more details.
     PointerExposeAddress,
+    /// An address-to-pointer cast that picks up an exposed provenance.
+    /// See the docs on `from_exposed_addr` for more details.
+    PointerFromExposedAddress,
+    /// All sorts of pointer-to-pointer casts. Note that reference-to-raw-ptr casts are
+    /// translated into `&raw mut/const *r`, i.e., they are not actually casts.
     Pointer(PointerCast),
+    /// Remaining unclassified casts.
+    Misc,
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
index 7d08b20631e477c3a58d25dc57924bea4b3ba371..8e87ecd27d2853a113ff22e38365d384dee2f579 100644 (file)
@@ -196,6 +196,9 @@ pub(crate) fn as_rvalue(
                     (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => {
                         CastKind::PointerExposeAddress
                     }
+                    (Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => {
+                        CastKind::PointerFromExposedAddress
+                    }
                     (_, _) => CastKind::Misc,
                 };
                 let source = unpack!(
index 04724b13ca64ce3c9a7067727753da0f669a7403..037febdf3a579de5f53148e69c8ecd436f7ecd97 100644 (file)
@@ -19,7 +19,7 @@
                                            // + literal: Const { ty: fn() {main}, val: Value(Scalar(<ZST>)) }
           _2 = move _3 as usize (PointerExposeAddress); // scope 0 at $DIR/reify_fn_ptr.rs:4:13: 4:26
           StorageDead(_3);                 // scope 0 at $DIR/reify_fn_ptr.rs:4:25: 4:26
-          _1 = move _2 as *const fn() (Misc); // scope 0 at $DIR/reify_fn_ptr.rs:4:13: 4:41
+          _1 = move _2 as *const fn() (PointerFromExposedAddress); // scope 0 at $DIR/reify_fn_ptr.rs:4:13: 4:41
           StorageDead(_2);                 // scope 0 at $DIR/reify_fn_ptr.rs:4:40: 4:41
           StorageDead(_1);                 // scope 0 at $DIR/reify_fn_ptr.rs:4:41: 4:42
           nop;                             // scope 0 at $DIR/reify_fn_ptr.rs:3:11: 5:2
index b1c82ac76e8eb149880e19d56f361cb0714113fe..58abef38ea8be9e1cc7505536de596ac62e8d76f 100644 (file)
@@ -131,7 +131,12 @@ fn check_rvalue<'tcx>(
         Rvalue::Cast(CastKind::Misc, operand, _) => {
             check_operand(tcx, operand, span, body)
         },
-        Rvalue::Cast(CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer), operand, _) => {
+        Rvalue::Cast(
+            CastKind::PointerFromExposedAddress
+            | CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer),
+            operand,
+            _
+        ) => {
             check_operand(tcx, operand, span, body)
         },
         Rvalue::Cast(