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,
+ )
+ }
}
}
}
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,
) => {
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() {
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)?;
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)
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),
}
}
- 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, _, _) => {}
// 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)?;
}
#[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)]
(Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => {
CastKind::PointerExposeAddress
}
+ (Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => {
+ CastKind::PointerFromExposedAddress
+ }
(_, _) => CastKind::Misc,
};
let source = unpack!(
// + 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
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(