1
Fork 0

Add CastKind::Transmute to MIR

Updates `interpret`, `codegen_ssa`, and `codegen_cranelift` to consume the new cast instead of the intrinsic.

Includes `CastTransmute` for custom MIR building, to be able to test the extra UB.
This commit is contained in:
Scott McMurray 2023-02-24 18:32:52 -08:00
parent a266f11990
commit 64cce5fc7d
55 changed files with 955 additions and 190 deletions

View file

@ -133,6 +133,22 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
bug!()
}
}
Transmute => {
assert!(src.layout.is_sized());
assert!(dest.layout.is_sized());
if src.layout.size != dest.layout.size {
throw_ub_format!(
"transmuting from {}-byte type to {}-byte type: `{}` -> `{}`",
src.layout.size.bytes(),
dest.layout.size.bytes(),
src.layout.ty,
dest.layout.ty,
);
}
self.copy_op(src, dest, /*allow_transmute*/ true)?;
}
}
Ok(())
}

View file

@ -127,7 +127,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// First handle intrinsics without return place.
let ret = match ret {
None => match intrinsic_name {
sym::transmute => throw_ub_format!("transmuting to uninhabited type"),
sym::abort => M::abort(self, "the program aborted execution".to_owned())?,
// Unsupported diverging intrinsic.
_ => return Ok(false),
@ -411,9 +410,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.exact_div(&val, &size, dest)?;
}
sym::transmute => {
self.copy_op(&args[0], dest, /*allow_transmute*/ true)?;
}
sym::assert_inhabited
| sym::assert_zero_valid
| sym::assert_mem_uninitialized_valid => {

View file

@ -621,6 +621,33 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
);
}
}
CastKind::Transmute => {
if let MirPhase::Runtime(..) = self.mir_phase {
// Unlike `mem::transmute`, a MIR `Transmute` is well-formed
// for any two `Sized` types, just potentially UB to run.
if !op_ty.is_sized(self.tcx, self.param_env) {
self.fail(
location,
format!("Cannot transmute from non-`Sized` type {op_ty:?}"),
);
}
if !target_type.is_sized(self.tcx, self.param_env) {
self.fail(
location,
format!("Cannot transmute to non-`Sized` type {target_type:?}"),
);
}
} else {
self.fail(
location,
format!(
"Transmute is not supported in non-runtime phase {:?}.",
self.mir_phase
),
);
}
}
}
}
Rvalue::Repeat(_, _)