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:
parent
a266f11990
commit
64cce5fc7d
55 changed files with 955 additions and 190 deletions
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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 => {
|
||||
|
|
|
@ -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(_, _)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue