Rollup merge of #97653 - RalfJung:int-to-ptr, r=oli-obk
add cast kind of from_exposed_addr (int-to-ptr casts) This is basically the dual to https://github.com/rust-lang/rust/pull/97582, for int2ptr casts. Cc `@tmiasko` https://github.com/rust-lang/rust/issues/97649
This commit is contained in:
commit
f116dd76ed
10 changed files with 96 additions and 39 deletions
|
@ -2154,7 +2154,31 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
match (cast_ty_from, cast_ty_to) {
|
match (cast_ty_from, cast_ty_to) {
|
||||||
(Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => (),
|
(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::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) {
|
||||||
|
(Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => (),
|
||||||
|
_ => {
|
||||||
|
span_mirbug!(
|
||||||
|
self,
|
||||||
|
rvalue,
|
||||||
|
"Invalid PointerFromExposedAddress cast {:?} -> {:?}",
|
||||||
|
ty_from,
|
||||||
|
ty
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2163,22 +2187,22 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
let ty_from = op.ty(body, tcx);
|
let ty_from = op.ty(body, tcx);
|
||||||
let cast_ty_from = CastTy::from_ty(ty_from);
|
let cast_ty_from = CastTy::from_ty(ty_from);
|
||||||
let cast_ty_to = CastTy::from_ty(*ty);
|
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) {
|
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::Int(_) | CastTy::Float),
|
||||||
Some(CastTy::Int(_) | CastTy::Float | CastTy::Ptr(_)),
|
Some(CastTy::Int(_) | CastTy::Float),
|
||||||
)
|
)
|
||||||
| (Some(CastTy::Float), Some(CastTy::Int(_) | CastTy::Float))
|
|
||||||
| (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Ptr(_))) => (),
|
| (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Ptr(_))) => (),
|
||||||
|
_ => {
|
||||||
|
span_mirbug!(
|
||||||
|
self,
|
||||||
|
rvalue,
|
||||||
|
"Invalid Misc cast {:?} -> {:?}",
|
||||||
|
ty_from,
|
||||||
|
ty,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -608,7 +608,9 @@ fn codegen_stmt<'tcx>(
|
||||||
lval.write_cvalue(fx, operand.cast_pointer_to(to_layout));
|
lval.write_cvalue(fx, operand.cast_pointer_to(to_layout));
|
||||||
}
|
}
|
||||||
Rvalue::Cast(
|
Rvalue::Cast(
|
||||||
CastKind::Misc | CastKind::PointerExposeAddress,
|
CastKind::Misc
|
||||||
|
| CastKind::PointerExposeAddress
|
||||||
|
| CastKind::PointerFromExposedAddress,
|
||||||
ref operand,
|
ref operand,
|
||||||
to_ty,
|
to_ty,
|
||||||
) => {
|
) => {
|
||||||
|
|
|
@ -269,7 +269,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
mir::CastKind::Pointer(
|
mir::CastKind::Pointer(
|
||||||
PointerCast::MutToConstPointer | PointerCast::ArrayToPointer,
|
PointerCast::MutToConstPointer | PointerCast::ArrayToPointer,
|
||||||
)
|
)
|
||||||
| mir::CastKind::Misc => {
|
| mir::CastKind::Misc
|
||||||
|
// Since int2ptr can have arbitrary integer types as input (so we have to do
|
||||||
|
// sign extension and all that), it is currently best handled in the same code
|
||||||
|
// path as the other integer-to-X casts.
|
||||||
|
| mir::CastKind::PointerFromExposedAddress => {
|
||||||
assert!(bx.cx().is_backend_immediate(cast));
|
assert!(bx.cx().is_backend_immediate(cast));
|
||||||
let ll_t_out = bx.cx().immediate_backend_type(cast);
|
let ll_t_out = bx.cx().immediate_backend_type(cast);
|
||||||
if operand.layout.abi.is_uninhabited() {
|
if operand.layout.abi.is_uninhabited() {
|
||||||
|
|
|
@ -37,6 +37,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
self.write_immediate(res, dest)?;
|
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 => {
|
Misc => {
|
||||||
let src = self.read_immediate(src)?;
|
let src = self.read_immediate(src)?;
|
||||||
let res = self.misc_cast(&src, cast_ty)?;
|
let res = self.misc_cast(&src, cast_ty)?;
|
||||||
|
@ -201,6 +207,24 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into())
|
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(
|
pub fn cast_from_int_like(
|
||||||
&self,
|
&self,
|
||||||
scalar: Scalar<M::PointerTag>, // input value (there is no ScalarTy so we separate data+layout)
|
scalar: Scalar<M::PointerTag>, // input value (there is no ScalarTy so we separate data+layout)
|
||||||
|
@ -225,16 +249,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
Scalar::from_uint(v, size)
|
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::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::F64) if signed => Scalar::from_f64(Double::from_i128(v as i128).value),
|
||||||
Float(FloatTy::F32) => Scalar::from_f32(Single::from_u128(v).value),
|
Float(FloatTy::F32) => Scalar::from_f32(Single::from_u128(v).value),
|
||||||
|
|
|
@ -519,32 +519,30 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rvalue::Cast(
|
|
||||||
CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer),
|
|
||||||
_,
|
|
||||||
_,
|
|
||||||
) => {}
|
|
||||||
|
|
||||||
Rvalue::Cast(
|
Rvalue::Cast(
|
||||||
CastKind::Pointer(
|
CastKind::Pointer(
|
||||||
PointerCast::UnsafeFnPointer
|
PointerCast::MutToConstPointer
|
||||||
|
| PointerCast::ArrayToPointer
|
||||||
|
| PointerCast::UnsafeFnPointer
|
||||||
| PointerCast::ClosureFnPointer(_)
|
| PointerCast::ClosureFnPointer(_)
|
||||||
| PointerCast::ReifyFnPointer,
|
| 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), _, _) => {
|
Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), _, _) => {
|
||||||
// Nothing to check here (`check_local_or_return_ty` ensures no trait objects occur
|
// Unsizing is implemented for CTFE.
|
||||||
// in the type of any local, which also excludes casts).
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => {
|
Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => {
|
||||||
self.check_op(ops::RawPtrToIntCast);
|
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, _, _) => {}
|
Rvalue::Cast(CastKind::Misc, _, _) => {}
|
||||||
|
|
||||||
|
|
|
@ -504,7 +504,8 @@ impl<'tcx> Validator<'_, 'tcx> {
|
||||||
// ptr-to-int casts are not possible in consts and thus not promotable
|
// ptr-to-int casts are not possible in consts and thus not promotable
|
||||||
Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => return Err(Unpromotable),
|
Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => return Err(Unpromotable),
|
||||||
|
|
||||||
// int-to-ptr casts are fine, they just use the integer value at pointer type.
|
// all other casts including int-to-ptr casts are fine, they just use the integer value
|
||||||
|
// at pointer type.
|
||||||
Rvalue::Cast(_, operand, _) => {
|
Rvalue::Cast(_, operand, _) => {
|
||||||
self.validate_operand(operand)?;
|
self.validate_operand(operand)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2613,12 +2613,18 @@ impl<'tcx> Rvalue<'tcx> {
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
|
||||||
pub enum CastKind {
|
pub enum CastKind {
|
||||||
Misc,
|
|
||||||
/// An exposing pointer to address cast. A cast between a pointer and an integer type, or
|
/// An exposing pointer to address cast. A cast between a pointer and an integer type, or
|
||||||
/// between a function pointer and an integer type.
|
/// between a function pointer and an integer type.
|
||||||
/// See the docs on `expose_addr` for more details.
|
/// See the docs on `expose_addr` for more details.
|
||||||
PointerExposeAddress,
|
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),
|
Pointer(PointerCast),
|
||||||
|
/// Remaining unclassified casts.
|
||||||
|
Misc,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
|
#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
|
||||||
|
|
|
@ -196,6 +196,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
(Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => {
|
(Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => {
|
||||||
CastKind::PointerExposeAddress
|
CastKind::PointerExposeAddress
|
||||||
}
|
}
|
||||||
|
(Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => {
|
||||||
|
CastKind::PointerFromExposedAddress
|
||||||
|
}
|
||||||
(_, _) => CastKind::Misc,
|
(_, _) => CastKind::Misc,
|
||||||
};
|
};
|
||||||
let source = unpack!(
|
let source = unpack!(
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
// + literal: Const { ty: fn() {main}, val: Value(Scalar(<ZST>)) }
|
// + 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
|
_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
|
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(_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
|
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
|
nop; // scope 0 at $DIR/reify_fn_ptr.rs:3:11: 5:2
|
||||||
|
|
|
@ -131,7 +131,12 @@ fn check_rvalue<'tcx>(
|
||||||
Rvalue::Cast(CastKind::Misc, operand, _) => {
|
Rvalue::Cast(CastKind::Misc, operand, _) => {
|
||||||
check_operand(tcx, operand, span, body)
|
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)
|
check_operand(tcx, operand, span, body)
|
||||||
},
|
},
|
||||||
Rvalue::Cast(
|
Rvalue::Cast(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue