Skip to content

Commit 35fa9ca

Browse files
committed
fix GVN trying to transmute pointers to integers
1 parent a8f9a32 commit 35fa9ca

File tree

1 file changed

+22
-7
lines changed
  • compiler/rustc_mir_transform/src

1 file changed

+22
-7
lines changed

compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
103103
use rustc_middle::ty::{self, Ty, TyCtxt};
104104
use rustc_span::DUMMY_SP;
105105
use rustc_span::def_id::DefId;
106-
use rustc_target::abi::{self, Abi, FIRST_VARIANT, FieldIdx, Size, VariantIdx};
106+
use rustc_target::abi::{self, Abi, FIRST_VARIANT, FieldIdx, Primitive, Size, VariantIdx};
107107
use smallvec::SmallVec;
108108
use tracing::{debug, instrument, trace};
109109

@@ -568,13 +568,28 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
568568
CastKind::Transmute => {
569569
let value = self.evaluated[value].as_ref()?;
570570
let to = self.ecx.layout_of(to).ok()?;
571-
// `offset` for immediates only supports scalar/scalar-pair ABIs,
572-
// so bail out if the target is not one.
571+
// `offset` for immediates is very limited: it only works between types with
572+
// the same layout. Also, pointers can carry provenance, so let's not try to
573+
// transmute those to anything else.
573574
if value.as_mplace_or_imm().is_right() {
574-
match (value.layout.abi, to.abi) {
575-
(Abi::Scalar(..), Abi::Scalar(..)) => {}
576-
(Abi::ScalarPair(..), Abi::ScalarPair(..)) => {}
577-
_ => return None,
575+
let can_transmute = match (value.layout.abi, to.abi) {
576+
(Abi::Scalar(s1), Abi::Scalar(s2)) => {
577+
s1.size(&self.ecx) == s2.size(&self.ecx)
578+
&& !matches!(s1.primitive(), Primitive::Pointer(..))
579+
}
580+
(Abi::ScalarPair(a1, b1), Abi::ScalarPair(a2, b2)) => {
581+
a1.size(&self.ecx) == a2.size(&self.ecx) &&
582+
b1.size(&self.ecx) == b2.size(&self.ecx) &&
583+
// The alignment of the second component determines its offset, so that also needs to match.
584+
b1.align(&self.ecx) == b2.align(&self.ecx) &&
585+
// None of the inputs may be a pointer.
586+
!matches!(a1.primitive(), Primitive::Pointer(..))
587+
&& !matches!(b1.primitive(), Primitive::Pointer(..))
588+
}
589+
_ => false,
590+
};
591+
if !can_transmute {
592+
return None;
578593
}
579594
}
580595
value.offset(Size::ZERO, to, &self.ecx).discard_err()?

0 commit comments

Comments
 (0)