fix GVN trying to transmute pointers to integers
This commit is contained in:
parent
a8f9a32650
commit
7d63efdb8c
3 changed files with 31 additions and 15 deletions
|
@ -103,7 +103,7 @@ use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
|
|||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_target::abi::{self, Abi, FIRST_VARIANT, FieldIdx, Size, VariantIdx};
|
||||
use rustc_target::abi::{self, Abi, FIRST_VARIANT, FieldIdx, Primitive, Size, VariantIdx};
|
||||
use smallvec::SmallVec;
|
||||
use tracing::{debug, instrument, trace};
|
||||
|
||||
|
@ -568,13 +568,29 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
CastKind::Transmute => {
|
||||
let value = self.evaluated[value].as_ref()?;
|
||||
let to = self.ecx.layout_of(to).ok()?;
|
||||
// `offset` for immediates only supports scalar/scalar-pair ABIs,
|
||||
// so bail out if the target is not one.
|
||||
// `offset` for immediates generally only supports projections that match the
|
||||
// type of the immediate. However, as a HACK, we exploit that it can also do
|
||||
// limited transmutes: it only works between types with the same layout, and
|
||||
// cannot transmute pointers to integers.
|
||||
if value.as_mplace_or_imm().is_right() {
|
||||
match (value.layout.abi, to.abi) {
|
||||
(Abi::Scalar(..), Abi::Scalar(..)) => {}
|
||||
(Abi::ScalarPair(..), Abi::ScalarPair(..)) => {}
|
||||
_ => return None,
|
||||
let can_transmute = match (value.layout.abi, to.abi) {
|
||||
(Abi::Scalar(s1), Abi::Scalar(s2)) => {
|
||||
s1.size(&self.ecx) == s2.size(&self.ecx)
|
||||
&& !matches!(s1.primitive(), Primitive::Pointer(..))
|
||||
}
|
||||
(Abi::ScalarPair(a1, b1), Abi::ScalarPair(a2, b2)) => {
|
||||
a1.size(&self.ecx) == a2.size(&self.ecx) &&
|
||||
b1.size(&self.ecx) == b2.size(&self.ecx) &&
|
||||
// The alignment of the second component determines its offset, so that also needs to match.
|
||||
b1.align(&self.ecx) == b2.align(&self.ecx) &&
|
||||
// None of the inputs may be a pointer.
|
||||
!matches!(a1.primitive(), Primitive::Pointer(..))
|
||||
&& !matches!(b1.primitive(), Primitive::Pointer(..))
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
if !can_transmute {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
value.offset(Size::ZERO, to, &self.ecx).discard_err()?
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue