Skip to content

Commit 0905bad

Browse files
committed
Add CastKind::Transmute to MIR
Nothing actually produces it in this commit.
1 parent c5c7d2b commit 0905bad

26 files changed

+184
-55
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2242,6 +2242,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
22422242
}
22432243
}
22442244
}
2245+
CastKind::Transmute => {
2246+
span_mirbug!(
2247+
self,
2248+
rvalue,
2249+
"Unexpected CastKind::Transmute, should only appear after lowering_intrinsics",
2250+
);
2251+
}
22452252
}
22462253
}
22472254

compiler/rustc_codegen_cranelift/src/base.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,10 @@ fn codegen_stmt<'tcx>(
720720
let operand = codegen_operand(fx, operand);
721721
operand.coerce_dyn_star(fx, lval);
722722
}
723+
Rvalue::Cast(CastKind::Transmute, ref operand, _to_ty) => {
724+
let operand = codegen_operand(fx, operand);
725+
lval.write_cvalue_transmute(fx, operand);
726+
}
723727
Rvalue::Discriminant(place) => {
724728
let place = codegen_place(fx, place);
725729
let value = place.to_cvalue(fx);

compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1789,7 +1789,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
17891789
}
17901790
}
17911791

1792-
fn codegen_transmute_into(
1792+
pub(crate) fn codegen_transmute_into(
17931793
&mut self,
17941794
bx: &mut Bx,
17951795
src: &mir::Operand<'tcx>,

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
135135
dest.codegen_set_discr(bx, variant_index);
136136
}
137137

138+
mir::Rvalue::Cast(mir::CastKind::Transmute, ref operand, _ty) => {
139+
self.codegen_transmute_into(bx, operand, dest);
140+
}
141+
138142
_ => {
139143
assert!(self.rvalue_creates_operand(rvalue, DUMMY_SP));
140144
let temp = self.codegen_rvalue_operand(bx, rvalue);
@@ -344,6 +348,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
344348
};
345349
OperandValue::Immediate(newval)
346350
}
351+
mir::CastKind::Transmute => {
352+
bug!("Transmute operand {:?} in `codegen_rvalue_operand`", operand);
353+
}
347354
};
348355
OperandRef { val, layout: cast }
349356
}
@@ -684,6 +691,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
684691
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
685692
pub fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>, span: Span) -> bool {
686693
match *rvalue {
694+
mir::Rvalue::Cast(mir::CastKind::Transmute, ..) =>
695+
// sometimes this could, but for aggregates it can't
696+
false,
687697
mir::Rvalue::Ref(..) |
688698
mir::Rvalue::CopyForDeref(..) |
689699
mir::Rvalue::AddressOf(..) |

compiler/rustc_const_eval/src/interpret/cast.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
133133
bug!()
134134
}
135135
}
136+
137+
Transmute => {
138+
self.copy_op(src, dest, /*allow_transmute*/ true)?;
139+
}
136140
}
137141
Ok(())
138142
}

compiler/rustc_const_eval/src/transform/validate.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,25 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
619619
);
620620
}
621621
}
622+
CastKind::Transmute => {
623+
let src_layout = self.tcx.layout_of(self.param_env.and(op_ty));
624+
let dst_layout = self.tcx.layout_of(self.param_env.and(*target_type));
625+
if let Err(e) = src_layout {
626+
self.fail(
627+
location,
628+
format!("Unable to compute layout for source type {op_ty:?}: {e}"),
629+
);
630+
}
631+
if let Err(e) = dst_layout {
632+
self.fail(location, format!("Unable to compute layout for destination type {target_type:?}: {e}"));
633+
}
634+
635+
if let (Ok(src_layout), Ok(dst_layout)) = (src_layout, dst_layout) {
636+
if src_layout.layout.size() != dst_layout.layout.size() {
637+
self.fail(location, format!("Source and destination layouts have different sizes: {src_layout:?} vs {dst_layout:?}"));
638+
}
639+
}
640+
}
622641
}
623642
}
624643
Rvalue::Repeat(_, _)

compiler/rustc_middle/src/mir/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1963,7 +1963,8 @@ impl<'tcx> Rvalue<'tcx> {
19631963
| CastKind::PtrToPtr
19641964
| CastKind::Pointer(_)
19651965
| CastKind::PointerFromExposedAddress
1966-
| CastKind::DynStar,
1966+
| CastKind::DynStar
1967+
| CastKind::Transmute,
19671968
_,
19681969
_,
19691970
)

compiler/rustc_middle/src/mir/syntax.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,6 +1189,8 @@ pub enum CastKind {
11891189
IntToFloat,
11901190
PtrToPtr,
11911191
FnPtrToPtr,
1192+
/// Reinterpret the bits of the input as a different type.
1193+
Transmute,
11921194
}
11931195

11941196
#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]

compiler/rustc_mir_transform/src/check_unsafety.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,12 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
132132
self.register_violations(violations, used_unsafe_blocks.iter().copied());
133133
}
134134
},
135+
Rvalue::Cast(CastKind::Transmute, ..) => {
136+
self.require_unsafe(
137+
UnsafetyViolationKind::General,
138+
UnsafetyViolationDetails::CallToUnsafeFunction,
139+
);
140+
}
135141
_ => {}
136142
}
137143
self.super_rvalue(rvalue, location);

compiler/rustc_mir_transform/src/lower_intrinsics.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use crate::MirPass;
44
use rustc_middle::mir::*;
5+
use rustc_middle::ty::inhabitedness::inhabited_predicate::InhabitedPredicate;
56
use rustc_middle::ty::subst::SubstsRef;
67
use rustc_middle::ty::{self, Ty, TyCtxt};
78
use rustc_span::symbol::{sym, Symbol};
@@ -162,6 +163,30 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
162163
terminator.kind = TerminatorKind::Goto { target };
163164
}
164165
}
166+
sym::transmute => {
167+
let dst_ty = destination.ty(local_decls, tcx).ty;
168+
if let Some(target) = *target {
169+
let mut args = args.drain(..);
170+
block.statements.push(Statement {
171+
source_info: terminator.source_info,
172+
kind: StatementKind::Assign(Box::new((
173+
*destination,
174+
Rvalue::Cast(CastKind::Transmute, args.next().unwrap(), dst_ty),
175+
))),
176+
});
177+
assert_eq!(args.next(), None, "Extra argument for transmute intrinsic");
178+
drop(args);
179+
terminator.kind = TerminatorKind::Goto { target };
180+
} else {
181+
debug_assert!(!matches!(
182+
dst_ty.inhabited_predicate(tcx),
183+
InhabitedPredicate::True
184+
));
185+
// `transmute::<_, !>(x)` is UB for anything inhabited,
186+
// and must be unreachable if `x` is uninhabited.
187+
terminator.kind = TerminatorKind::Unreachable;
188+
}
189+
}
165190
_ if intrinsic_name.as_str().starts_with("simd_shuffle") => {
166191
validate_simd_shuffle(tcx, args, terminator.source_info.span);
167192
}

0 commit comments

Comments
 (0)