Auto merge of #61959 - oli-obk:const_field_ice, r=eddyb
Fix a hash collision issue on the `const_field` query fixes #61530
This commit is contained in:
commit
38cd9489f7
@ -175,13 +175,18 @@ fn hash_stable<W: StableHasherResult>(
|
||||
hcx: &mut StableHashingContext<'a>,
|
||||
hasher: &mut StableHasher<W>,
|
||||
) {
|
||||
self.bytes.hash_stable(hcx, hasher);
|
||||
for reloc in self.relocations.iter() {
|
||||
let mir::interpret::Allocation {
|
||||
bytes, relocations, undef_mask, align, mutability,
|
||||
extra: _,
|
||||
} = self;
|
||||
bytes.hash_stable(hcx, hasher);
|
||||
relocations.len().hash_stable(hcx, hasher);
|
||||
for reloc in relocations.iter() {
|
||||
reloc.hash_stable(hcx, hasher);
|
||||
}
|
||||
self.undef_mask.hash_stable(hcx, hasher);
|
||||
self.align.hash_stable(hcx, hasher);
|
||||
self.mutability.hash_stable(hcx, hasher);
|
||||
undef_mask.hash_stable(hcx, hasher);
|
||||
align.hash_stable(hcx, hasher);
|
||||
mutability.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -260,7 +260,7 @@ fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
|
||||
ConstValue::Param(_) |
|
||||
ConstValue::Scalar(_) |
|
||||
ConstValue::Slice { .. } |
|
||||
ConstValue::ByRef(..) |
|
||||
ConstValue::ByRef { .. } |
|
||||
ConstValue::Unevaluated(..) => {}
|
||||
}
|
||||
|
||||
|
@ -247,7 +247,7 @@ pub fn get_bytes_mut(
|
||||
assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`");
|
||||
self.check_bounds(cx, ptr, size, CheckInAllocMsg::MemoryAccessTest)?;
|
||||
|
||||
self.mark_definedness(ptr, size, true)?;
|
||||
self.mark_definedness(ptr, size, true);
|
||||
self.clear_relocations(cx, ptr, size)?;
|
||||
|
||||
AllocationExtra::memory_written(self, ptr, size)?;
|
||||
@ -406,7 +406,10 @@ pub fn write_scalar(
|
||||
{
|
||||
let val = match val {
|
||||
ScalarMaybeUndef::Scalar(scalar) => scalar,
|
||||
ScalarMaybeUndef::Undef => return self.mark_definedness(ptr, type_size, false),
|
||||
ScalarMaybeUndef::Undef => {
|
||||
self.mark_definedness(ptr, type_size, false);
|
||||
return Ok(());
|
||||
},
|
||||
};
|
||||
|
||||
let bytes = match val.to_bits_or_ptr(type_size, cx) {
|
||||
@ -550,16 +553,15 @@ pub fn mark_definedness(
|
||||
ptr: Pointer<Tag>,
|
||||
size: Size,
|
||||
new_state: bool,
|
||||
) -> InterpResult<'tcx> {
|
||||
) {
|
||||
if size.bytes() == 0 {
|
||||
return Ok(());
|
||||
return;
|
||||
}
|
||||
self.undef_mask.set_range(
|
||||
ptr.offset,
|
||||
ptr.offset + size,
|
||||
new_state,
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,14 +43,21 @@ pub enum ConstValue<'tcx> {
|
||||
end: usize,
|
||||
},
|
||||
|
||||
/// An allocation together with a pointer into the allocation.
|
||||
/// Invariant: the pointer's `AllocId` resolves to the allocation.
|
||||
/// The alignment exists to allow `const_field` to have `ByRef` access to nonprimitive fields
|
||||
/// of `repr(packed)` structs. The alignment may be lower than the type of this constant.
|
||||
/// This permits reads with lower alignment than what the type would normally require.
|
||||
/// FIXME(RalfJ,oli-obk): The alignment checks are part of miri, but const eval doesn't really
|
||||
/// need them. Disabling them may be too hard though.
|
||||
ByRef(Pointer, Align, &'tcx Allocation),
|
||||
/// A value not represented/representable by `Scalar` or `Slice`
|
||||
ByRef {
|
||||
/// The alignment exists to allow `const_field` to have `ByRef` access to nonprimitive
|
||||
/// fields of `repr(packed)` structs. The alignment may be lower than the type of this
|
||||
/// constant. This permits reads with lower alignment than what the type would normally
|
||||
/// require.
|
||||
/// FIXME(RalfJ,oli-obk): The alignment checks are part of miri, but const eval doesn't
|
||||
/// really need them. Disabling them may be too hard though.
|
||||
align: Align,
|
||||
/// Offset into `alloc`
|
||||
offset: Size,
|
||||
/// The backing memory of the value, may contain more memory than needed for just the value
|
||||
/// in order to share `Allocation`s between values
|
||||
alloc: &'tcx Allocation,
|
||||
},
|
||||
|
||||
/// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other
|
||||
/// variants when the code is monomorphic enough for that.
|
||||
@ -67,7 +74,7 @@ pub fn try_to_scalar(&self) -> Option<Scalar> {
|
||||
ConstValue::Param(_) |
|
||||
ConstValue::Infer(_) |
|
||||
ConstValue::Placeholder(_) |
|
||||
ConstValue::ByRef(..) |
|
||||
ConstValue::ByRef{ .. } |
|
||||
ConstValue::Unevaluated(..) |
|
||||
ConstValue::Slice { .. } => None,
|
||||
ConstValue::Scalar(val) => Some(val),
|
||||
|
@ -186,7 +186,7 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String, debug: bool) {
|
||||
// as well as the unprintable types of constants (see `push_type_name` for more details).
|
||||
pub fn push_const_name(&self, c: &Const<'tcx>, output: &mut String, debug: bool) {
|
||||
match c.val {
|
||||
ConstValue::Scalar(..) | ConstValue::Slice { .. } | ConstValue::ByRef(..) => {
|
||||
ConstValue::Scalar(..) | ConstValue::Slice { .. } | ConstValue::ByRef { .. } => {
|
||||
// FIXME(const_generics): we could probably do a better job here.
|
||||
write!(output, "{:?}", c).unwrap()
|
||||
}
|
||||
|
@ -594,7 +594,7 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
|
||||
ty: a.ty,
|
||||
}))
|
||||
}
|
||||
(ConstValue::ByRef(..), _) => {
|
||||
(ConstValue::ByRef { .. }, _) => {
|
||||
bug!(
|
||||
"non-Scalar ConstValue encountered in super_relate_consts {:?} {:?}",
|
||||
a,
|
||||
|
@ -1335,7 +1335,8 @@ fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> {
|
||||
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
match *self {
|
||||
ConstValue::ByRef(ptr, align, alloc) => ConstValue::ByRef(ptr, align, alloc),
|
||||
ConstValue::ByRef { offset, align, alloc } =>
|
||||
ConstValue::ByRef { offset, align, alloc },
|
||||
ConstValue::Infer(ic) => ConstValue::Infer(ic.fold_with(folder)),
|
||||
ConstValue::Param(p) => ConstValue::Param(p.fold_with(folder)),
|
||||
ConstValue::Placeholder(p) => ConstValue::Placeholder(p),
|
||||
@ -1348,7 +1349,7 @@ fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
match *self {
|
||||
ConstValue::ByRef(..) => false,
|
||||
ConstValue::ByRef { .. } => false,
|
||||
ConstValue::Infer(ic) => ic.visit_with(visitor),
|
||||
ConstValue::Param(p) => p.visit_with(visitor),
|
||||
ConstValue::Placeholder(_) => false,
|
||||
|
@ -71,7 +71,9 @@ pub fn codegen_static_initializer(
|
||||
let static_ = cx.tcx.const_eval(param_env.and(cid))?;
|
||||
|
||||
let alloc = match static_.val {
|
||||
ConstValue::ByRef(ptr, align, alloc) if ptr.offset.bytes() == 0 && align == alloc.align => {
|
||||
ConstValue::ByRef {
|
||||
offset, align, alloc,
|
||||
} if offset.bytes() == 0 && align == alloc.align => {
|
||||
alloc
|
||||
},
|
||||
_ => bug!("static const eval returned {:#?}", static_),
|
||||
|
@ -109,8 +109,8 @@ pub fn from_const<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
|
||||
let b_llval = bx.const_usize((end - start) as u64);
|
||||
OperandValue::Pair(a_llval, b_llval)
|
||||
},
|
||||
ConstValue::ByRef(ptr, align, alloc) => {
|
||||
return bx.load_operand(bx.from_const_alloc(layout, align, alloc, ptr.offset));
|
||||
ConstValue::ByRef { offset, align, alloc } => {
|
||||
return bx.load_operand(bx.from_const_alloc(layout, align, alloc, offset));
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -424,8 +424,8 @@ pub fn codegen_place(
|
||||
let layout = cx.layout_of(self.monomorphize(&ty));
|
||||
match bx.tcx().const_eval(param_env.and(cid)) {
|
||||
Ok(val) => match val.val {
|
||||
mir::interpret::ConstValue::ByRef(ptr, align, alloc) => {
|
||||
bx.cx().from_const_alloc(layout, align, alloc, ptr.offset)
|
||||
mir::interpret::ConstValue::ByRef { offset, align, alloc } => {
|
||||
bx.cx().from_const_alloc(layout, align, alloc, offset)
|
||||
}
|
||||
_ => bug!("promoteds should have an allocation: {:?}", val),
|
||||
},
|
||||
|
@ -99,7 +99,7 @@ fn op_to_const<'tcx>(
|
||||
Ok(mplace) => {
|
||||
let ptr = mplace.ptr.to_ptr().unwrap();
|
||||
let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
|
||||
ConstValue::ByRef(ptr, mplace.align, alloc)
|
||||
ConstValue::ByRef { offset: ptr.offset, align: mplace.align, alloc }
|
||||
},
|
||||
// see comment on `let try_as_immediate` above
|
||||
Err(ImmTy { imm: Immediate::Scalar(x), .. }) => match x {
|
||||
@ -113,7 +113,7 @@ fn op_to_const<'tcx>(
|
||||
let mplace = op.to_mem_place();
|
||||
let ptr = mplace.ptr.to_ptr().unwrap();
|
||||
let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
|
||||
ConstValue::ByRef(ptr, mplace.align, alloc)
|
||||
ConstValue::ByRef { offset: ptr.offset, align: mplace.align, alloc }
|
||||
},
|
||||
},
|
||||
Err(ImmTy { imm: Immediate::ScalarPair(a, b), .. }) => {
|
||||
@ -541,11 +541,11 @@ fn validate_and_turn_into_const<'tcx>(
|
||||
if tcx.is_static(def_id) || cid.promoted.is_some() {
|
||||
let ptr = mplace.ptr.to_ptr()?;
|
||||
Ok(tcx.mk_const(ty::Const {
|
||||
val: ConstValue::ByRef(
|
||||
ptr,
|
||||
mplace.align,
|
||||
ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id),
|
||||
),
|
||||
val: ConstValue::ByRef {
|
||||
offset: ptr.offset,
|
||||
align: mplace.align,
|
||||
alloc: ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id),
|
||||
},
|
||||
ty: mplace.layout.ty,
|
||||
}))
|
||||
} else {
|
||||
|
@ -217,12 +217,12 @@ fn fold_const_value_deref(
|
||||
// the easy case, deref a reference
|
||||
(ConstValue::Scalar(Scalar::Ptr(p)), x, y) if x == y => {
|
||||
let alloc = self.tcx.alloc_map.lock().unwrap_memory(p.alloc_id);
|
||||
ConstValue::ByRef(
|
||||
p,
|
||||
ConstValue::ByRef {
|
||||
offset: p.offset,
|
||||
// FIXME(oli-obk): this should be the type's layout
|
||||
alloc.align,
|
||||
align: alloc.align,
|
||||
alloc,
|
||||
)
|
||||
}
|
||||
},
|
||||
// unsize array to slice if pattern is array but match value or other patterns are slice
|
||||
(ConstValue::Scalar(Scalar::Ptr(p)), ty::Array(t, n), ty::Slice(u)) => {
|
||||
@ -1436,9 +1436,10 @@ fn slice_pat_covered_by_const<'tcx>(
|
||||
suffix: &[Pattern<'tcx>],
|
||||
) -> Result<bool, ErrorReported> {
|
||||
let data: &[u8] = match (const_val.val, &const_val.ty.sty) {
|
||||
(ConstValue::ByRef(ptr, _, alloc), ty::Array(t, n)) => {
|
||||
(ConstValue::ByRef { offset, alloc, .. }, ty::Array(t, n)) => {
|
||||
assert_eq!(*t, tcx.types.u8);
|
||||
let n = n.assert_usize(tcx).unwrap();
|
||||
let ptr = Pointer::new(AllocId(0), offset);
|
||||
alloc.get_bytes(&tcx, ptr, Size::from_bytes(n)).unwrap()
|
||||
},
|
||||
(ConstValue::Slice { data, start, end }, ty::Slice(t)) => {
|
||||
@ -1758,9 +1759,9 @@ fn specialize<'p, 'a: 'p, 'tcx>(
|
||||
let (alloc, offset, n, ty) = match value.ty.sty {
|
||||
ty::Array(t, n) => {
|
||||
match value.val {
|
||||
ConstValue::ByRef(ptr, _, alloc) => (
|
||||
ConstValue::ByRef { offset, alloc, .. } => (
|
||||
alloc,
|
||||
ptr.offset,
|
||||
offset,
|
||||
n.unwrap_usize(cx.tcx),
|
||||
t,
|
||||
),
|
||||
@ -1778,7 +1779,7 @@ fn specialize<'p, 'a: 'p, 'tcx>(
|
||||
(end - start) as u64,
|
||||
t,
|
||||
),
|
||||
ConstValue::ByRef(..) => {
|
||||
ConstValue::ByRef { .. } => {
|
||||
// FIXME(oli-obk): implement `deref` for `ConstValue`
|
||||
return None;
|
||||
},
|
||||
|
@ -538,10 +538,11 @@ pub(super) fn eval_operands(
|
||||
self.layout_of(self.monomorphize(val.ty)?)
|
||||
})?;
|
||||
let op = match val.val {
|
||||
ConstValue::ByRef(ptr, align, _alloc) => {
|
||||
ConstValue::ByRef { offset, align, alloc } => {
|
||||
let id = self.tcx.alloc_map.lock().create_memory_alloc(alloc);
|
||||
// We rely on mutability being set correctly in that allocation to prevent writes
|
||||
// where none should happen.
|
||||
let ptr = self.tag_static_base_pointer(ptr);
|
||||
let ptr = self.tag_static_base_pointer(Pointer::new(id, offset));
|
||||
Operand::Indirect(MemPlace::from_ptr(ptr, align))
|
||||
},
|
||||
ConstValue::Scalar(x) =>
|
||||
|
@ -1262,7 +1262,7 @@ fn collect_const<'tcx>(
|
||||
ConstValue::Scalar(Scalar::Ptr(ptr)) =>
|
||||
collect_miri(tcx, ptr.alloc_id, output),
|
||||
ConstValue::Slice { data: alloc, start: _, end: _ } |
|
||||
ConstValue::ByRef(_, _, alloc) => {
|
||||
ConstValue::ByRef { alloc, .. } => {
|
||||
for &((), id) in alloc.relocations.values() {
|
||||
collect_miri(tcx, id, output);
|
||||
}
|
||||
|
@ -1448,8 +1448,8 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: DefId, span: Span)
|
||||
};
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
if let Ok(static_) = tcx.const_eval(param_env.and(cid)) {
|
||||
let alloc = if let ConstValue::ByRef(_, _, allocation) = static_.val {
|
||||
allocation
|
||||
let alloc = if let ConstValue::ByRef { alloc, .. } = static_.val {
|
||||
alloc
|
||||
} else {
|
||||
bug!("Matching on non-ByRef static")
|
||||
};
|
||||
|
17
src/test/incremental/issue-61530.rs
Normal file
17
src/test/incremental/issue-61530.rs
Normal file
@ -0,0 +1,17 @@
|
||||
#![feature(repr_simd, platform_intrinsics)]
|
||||
|
||||
// revisions:rpass1 rpass2
|
||||
|
||||
#[repr(simd)]
|
||||
struct I32x2(i32, i32);
|
||||
|
||||
extern "platform-intrinsic" {
|
||||
fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let _: I32x2 = simd_shuffle2(I32x2(1, 2), I32x2(3, 4), [0, 0]);
|
||||
let _: I32x2 = simd_shuffle2(I32x2(1, 2), I32x2(3, 4), [0, 0]);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user