Auto merge of #131068 - RalfJung:immediate-offset-sanity-check, r=nnethercote
Don't use Immediate::offset to transmute pointers to integers This applies the relatively new `assert_matches_abi` check in the `offset` operation on immediates, which makes sure that if offsets are used to alter the layout (which is possible because the field layout is arbitrarily picked by the caller), this is not done in a way that breaks the invariant of the `Immediate` type. This leads to ICEs in a GVN mir-opt test, so the second commit fixes GVN. Fixes https://github.com/rust-lang/rust/issues/131064.
This commit is contained in:
commit
a964a92277
6 changed files with 76 additions and 46 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