Update InterpCx::project_field to take FieldIdx
As suggested by Ralf in 142005.
This commit is contained in:
@@ -39,6 +39,13 @@ rustc_index::newtype_index! {
|
||||
pub struct FieldIdx {}
|
||||
}
|
||||
|
||||
impl FieldIdx {
|
||||
/// The second field.
|
||||
///
|
||||
/// For use alongside [`FieldIdx::ZERO`], particularly with scalar pairs.
|
||||
pub const ONE: FieldIdx = FieldIdx::from_u32(1);
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
/// The *source-order* index of a variant in a type.
|
||||
///
|
||||
@@ -274,7 +281,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
|
||||
|
||||
/// Finds the one field that is not a 1-ZST.
|
||||
/// Returns `None` if there are multiple non-1-ZST fields or only 1-ZST-fields.
|
||||
pub fn non_1zst_field<C>(&self, cx: &C) -> Option<(usize, Self)>
|
||||
pub fn non_1zst_field<C>(&self, cx: &C) -> Option<(FieldIdx, Self)>
|
||||
where
|
||||
Ty: TyAbiInterface<'a, C> + Copy,
|
||||
{
|
||||
@@ -288,7 +295,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
|
||||
// More than one non-1-ZST field.
|
||||
return None;
|
||||
}
|
||||
found = Some((field_idx, field));
|
||||
found = Some((FieldIdx::from_usize(field_idx), field));
|
||||
}
|
||||
found
|
||||
}
|
||||
|
||||
@@ -850,7 +850,7 @@ fn asm_clif_type<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> Option<ty
|
||||
// Adapted from https://github.com/rust-lang/rust/blob/f3c66088610c1b80110297c2d9a8b5f9265b013f/compiler/rustc_hir_analysis/src/check/intrinsicck.rs#L136-L151
|
||||
ty::Adt(adt, args) if fx.tcx.is_lang_item(adt.did(), LangItem::MaybeUninit) => {
|
||||
let fields = &adt.non_enum_variant().fields;
|
||||
let ty = fields[FieldIdx::from_u32(1)].ty(fx.tcx, args);
|
||||
let ty = fields[FieldIdx::ONE].ty(fx.tcx, args);
|
||||
let ty::Adt(ty, args) = ty.kind() else {
|
||||
unreachable!("expected first field of `MaybeUninit` to be an ADT")
|
||||
};
|
||||
|
||||
@@ -53,7 +53,7 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
|
||||
.layout()
|
||||
.non_1zst_field(fx)
|
||||
.expect("not exactly one non-1-ZST field in a `DispatchFromDyn` type");
|
||||
arg = arg.value_field(fx, FieldIdx::new(idx));
|
||||
arg = arg.value_field(fx, idx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,8 +62,7 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
|
||||
let inner_layout = fx.layout_of(arg.layout().ty.builtin_deref(true).unwrap());
|
||||
let dyn_star = CPlace::for_ptr(Pointer::new(arg.load_scalar(fx)), inner_layout);
|
||||
let ptr = dyn_star.place_field(fx, FieldIdx::ZERO).to_ptr();
|
||||
let vtable =
|
||||
dyn_star.place_field(fx, FieldIdx::new(1)).to_cvalue(fx).load_scalar(fx);
|
||||
let vtable = dyn_star.place_field(fx, FieldIdx::ONE).to_cvalue(fx).load_scalar(fx);
|
||||
break 'block (ptr, vtable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1077,7 +1077,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
let (idx, _) = op.layout.non_1zst_field(bx).expect(
|
||||
"not exactly one non-1-ZST field in a `DispatchFromDyn` type",
|
||||
);
|
||||
op = op.extract_field(self, bx, idx);
|
||||
op = op.extract_field(self, bx, idx.as_usize());
|
||||
}
|
||||
|
||||
// Now that we have `*dyn Trait` or `&dyn Trait`, split it up into its
|
||||
@@ -1109,7 +1109,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
let (idx, _) = op.layout.non_1zst_field(bx).expect(
|
||||
"not exactly one non-1-ZST field in a `DispatchFromDyn` type",
|
||||
);
|
||||
op = op.extract_field(self, bx, idx);
|
||||
op = op.extract_field(self, bx, idx.as_usize());
|
||||
}
|
||||
|
||||
// Make sure that we've actually unwrapped the rcvr down
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Not in interpret to make sure we do not use private implementation details
|
||||
|
||||
use rustc_abi::VariantIdx;
|
||||
use rustc_abi::{FieldIdx, VariantIdx};
|
||||
use rustc_middle::query::Key;
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
@@ -60,7 +60,7 @@ pub(crate) fn try_destructure_mir_constant_for_user_output<'tcx>(
|
||||
|
||||
let fields_iter = (0..field_count)
|
||||
.map(|i| {
|
||||
let field_op = ecx.project_field(&down, i).discard_err()?;
|
||||
let field_op = ecx.project_field(&down, FieldIdx::from_usize(i)).discard_err()?;
|
||||
let val = op_to_const(&ecx, &field_op, /* for diagnostics */ true);
|
||||
Some((val, field_op.layout.ty))
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use rustc_abi::{BackendRepr, VariantIdx};
|
||||
use rustc_abi::{BackendRepr, FieldIdx, VariantIdx};
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId, ReportedErrorInfo};
|
||||
use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
|
||||
@@ -40,7 +40,7 @@ fn branches<'tcx>(
|
||||
}
|
||||
|
||||
for i in 0..field_count {
|
||||
let field = ecx.project_field(&place, i).unwrap();
|
||||
let field = ecx.project_field(&place, FieldIdx::from_usize(i)).unwrap();
|
||||
let valtree = const_to_valtree_inner(ecx, &field, num_nodes)?;
|
||||
branches.push(valtree);
|
||||
}
|
||||
@@ -437,7 +437,7 @@ fn valtree_into_mplace<'tcx>(
|
||||
ty::Str | ty::Slice(_) | ty::Array(..) => {
|
||||
ecx.project_index(place, i as u64).unwrap()
|
||||
}
|
||||
_ => ecx.project_field(&place_adjusted, i).unwrap(),
|
||||
_ => ecx.project_field(&place_adjusted, FieldIdx::from_usize(i)).unwrap(),
|
||||
};
|
||||
|
||||
debug!(?place_inner);
|
||||
|
||||
@@ -62,7 +62,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
pub(super) fn fn_arg_field(
|
||||
&self,
|
||||
arg: &FnArg<'tcx, M::Provenance>,
|
||||
field: usize,
|
||||
field: FieldIdx,
|
||||
) -> InterpResult<'tcx, FnArg<'tcx, M::Provenance>> {
|
||||
interp_ok(match arg {
|
||||
FnArg::Copy(op) => FnArg::Copy(self.project_field(op, field)?),
|
||||
@@ -600,10 +600,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
Cow::from(
|
||||
args.iter()
|
||||
.map(|a| interp_ok(a.clone()))
|
||||
.chain(
|
||||
(0..untuple_arg.layout().fields.count())
|
||||
.map(|i| self.fn_arg_field(untuple_arg, i)),
|
||||
)
|
||||
.chain((0..untuple_arg.layout().fields.count()).map(|i| {
|
||||
self.fn_arg_field(untuple_arg, FieldIdx::from_usize(i))
|
||||
}))
|
||||
.collect::<InterpResult<'_, Vec<_>>>()?,
|
||||
)
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::assert_matches::assert_matches;
|
||||
|
||||
use rustc_abi::Integer;
|
||||
use rustc_abi::{FieldIdx, Integer};
|
||||
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
|
||||
use rustc_apfloat::{Float, FloatConvert};
|
||||
use rustc_middle::mir::CastKind;
|
||||
@@ -484,6 +484,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
let mut found_cast_field = false;
|
||||
for i in 0..src.layout.fields.count() {
|
||||
let cast_ty_field = cast_ty.field(self, i);
|
||||
let i = FieldIdx::from_usize(i);
|
||||
let src_field = self.project_field(src, i)?;
|
||||
let dst_field = self.project_field(dest, i)?;
|
||||
if src_field.layout.is_1zst() && cast_ty_field.is_1zst() {
|
||||
|
||||
@@ -26,7 +26,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
// No need to validate that the discriminant here because the
|
||||
// `TyAndLayout::for_variant()` call earlier already checks the
|
||||
// variant is valid.
|
||||
let tag_dest = self.project_field(dest, tag_field.as_usize())?;
|
||||
let tag_dest = self.project_field(dest, tag_field)?;
|
||||
self.write_scalar(tag, &tag_dest)
|
||||
}
|
||||
None => {
|
||||
@@ -96,7 +96,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
let tag_layout = self.layout_of(tag_scalar_layout.primitive().to_int_ty(*self.tcx))?;
|
||||
|
||||
// Read tag and sanity-check `tag_layout`.
|
||||
let tag_val = self.read_immediate(&self.project_field(op, tag_field.as_usize())?)?;
|
||||
let tag_val = self.read_immediate(&self.project_field(op, tag_field)?)?;
|
||||
assert_eq!(tag_layout.size, tag_val.layout.size);
|
||||
assert_eq!(tag_layout.backend_repr.is_signed(), tag_val.layout.backend_repr.is_signed());
|
||||
trace!("tag value: {}", tag_val);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::Range;
|
||||
|
||||
use rustc_abi::{self as abi, Size, VariantIdx};
|
||||
use rustc_abi::{self as abi, FieldIdx, Size, VariantIdx};
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
||||
use rustc_middle::{bug, mir, span_bug, ty};
|
||||
@@ -144,22 +144,22 @@ where
|
||||
/// always possible without allocating, so it can take `&self`. Also return the field's layout.
|
||||
/// This supports both struct and array fields, but not slices!
|
||||
///
|
||||
/// This also works for arrays, but then the `usize` index type is restricting.
|
||||
/// For indexing into arrays, use `mplace_index`.
|
||||
/// This also works for arrays, but then the `FieldIdx` index type is restricting.
|
||||
/// For indexing into arrays, use [`Self::project_index`].
|
||||
pub fn project_field<P: Projectable<'tcx, M::Provenance>>(
|
||||
&self,
|
||||
base: &P,
|
||||
field: usize,
|
||||
field: FieldIdx,
|
||||
) -> InterpResult<'tcx, P> {
|
||||
// Slices nominally have length 0, so they will panic somewhere in `fields.offset`.
|
||||
debug_assert!(
|
||||
!matches!(base.layout().ty.kind(), ty::Slice(..)),
|
||||
"`field` projection called on a slice -- call `index` projection instead"
|
||||
);
|
||||
let offset = base.layout().fields.offset(field);
|
||||
let offset = base.layout().fields.offset(field.as_usize());
|
||||
// Computing the layout does normalization, so we get a normalized type out of this
|
||||
// even if the field type is non-normalized (possible e.g. via associated types).
|
||||
let field_layout = base.layout().field(self, field);
|
||||
let field_layout = base.layout().field(self, field.as_usize());
|
||||
|
||||
// Offset may need adjustment for unsized fields.
|
||||
let (meta, offset) = if field_layout.is_unsized() {
|
||||
@@ -244,7 +244,7 @@ where
|
||||
}
|
||||
_ => span_bug!(
|
||||
self.cur_span(),
|
||||
"`mplace_index` called on non-array type {:?}",
|
||||
"`project_index` called on non-array type {:?}",
|
||||
base.layout().ty
|
||||
),
|
||||
};
|
||||
@@ -260,7 +260,7 @@ where
|
||||
) -> InterpResult<'tcx, (P, u64)> {
|
||||
assert!(base.layout().ty.ty_adt_def().unwrap().repr().simd());
|
||||
// SIMD types must be newtypes around arrays, so all we have to do is project to their only field.
|
||||
let array = self.project_field(base, 0)?;
|
||||
let array = self.project_field(base, FieldIdx::ZERO)?;
|
||||
let len = array.len(self)?;
|
||||
interp_ok((array, len))
|
||||
}
|
||||
@@ -384,7 +384,7 @@ where
|
||||
UnwrapUnsafeBinder(target) => base.transmute(self.layout_of(target)?, self)?,
|
||||
// We don't want anything happening here, this is here as a dummy.
|
||||
Subtype(_) => base.transmute(base.layout(), self)?,
|
||||
Field(field, _) => self.project_field(base, field.index())?,
|
||||
Field(field, _) => self.project_field(base, field)?,
|
||||
Downcast(_, variant) => self.project_downcast(base, variant)?,
|
||||
Deref => self.deref_pointer(&base.to_op(self)?)?.into(),
|
||||
Index(local) => {
|
||||
|
||||
@@ -333,7 +333,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
}
|
||||
for (field_index, operand) in operands.iter_enumerated() {
|
||||
let field_index = active_field_index.unwrap_or(field_index);
|
||||
let field_dest = self.project_field(&variant_dest, field_index.as_usize())?;
|
||||
let field_dest = self.project_field(&variant_dest, field_index)?;
|
||||
let op = self.eval_operand(operand, Some(field_dest.layout))?;
|
||||
self.copy_op(&op, &field_dest)?;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use rustc_abi::{Align, Size};
|
||||
use rustc_abi::{Align, FieldIdx, Size};
|
||||
use rustc_middle::mir::interpret::{InterpResult, Pointer};
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
use rustc_middle::ty::{self, ExistentialPredicateStableCmpExt, Ty, TyCtxt, VtblEntry};
|
||||
@@ -137,8 +137,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
matches!(val.layout().ty.kind(), ty::Dynamic(_, _, ty::DynStar)),
|
||||
"`unpack_dyn_star` only makes sense on `dyn*` types"
|
||||
);
|
||||
let data = self.project_field(val, 0)?;
|
||||
let vtable = self.project_field(val, 1)?;
|
||||
let data = self.project_field(val, FieldIdx::ZERO)?;
|
||||
let vtable = self.project_field(val, FieldIdx::ONE)?;
|
||||
let vtable = self.read_pointer(&vtable.to_op(self)?)?;
|
||||
let ty = self.get_ptr_vtable_ty(vtable, Some(expected_trait))?;
|
||||
// `data` is already the right thing but has the wrong type. So we transmute it.
|
||||
|
||||
@@ -112,8 +112,10 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
|
||||
// So we transmute it to a raw pointer.
|
||||
let raw_ptr_ty = Ty::new_mut_ptr(*self.ecx().tcx, self.ecx().tcx.types.unit);
|
||||
let raw_ptr_ty = self.ecx().layout_of(raw_ptr_ty)?;
|
||||
let vtable_field =
|
||||
self.ecx().project_field(v, 1)?.transmute(raw_ptr_ty, self.ecx())?;
|
||||
let vtable_field = self
|
||||
.ecx()
|
||||
.project_field(v, FieldIdx::ONE)?
|
||||
.transmute(raw_ptr_ty, self.ecx())?;
|
||||
self.visit_field(v, 1, &vtable_field)?;
|
||||
|
||||
// Then unpack the first field, and continue.
|
||||
@@ -140,14 +142,16 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
|
||||
|
||||
// `Box` has two fields: the pointer we care about, and the allocator.
|
||||
assert_eq!(v.layout().fields.count(), 2, "`Box` must have exactly 2 fields");
|
||||
let (unique_ptr, alloc) =
|
||||
(self.ecx().project_field(v, 0)?, self.ecx().project_field(v, 1)?);
|
||||
let (unique_ptr, alloc) = (
|
||||
self.ecx().project_field(v, FieldIdx::ZERO)?,
|
||||
self.ecx().project_field(v, FieldIdx::ONE)?,
|
||||
);
|
||||
// Unfortunately there is some type junk in the way here: `unique_ptr` is a `Unique`...
|
||||
// (which means another 2 fields, the second of which is a `PhantomData`)
|
||||
assert_eq!(unique_ptr.layout().fields.count(), 2);
|
||||
let (nonnull_ptr, phantom) = (
|
||||
self.ecx().project_field(&unique_ptr, 0)?,
|
||||
self.ecx().project_field(&unique_ptr, 1)?,
|
||||
self.ecx().project_field(&unique_ptr, FieldIdx::ZERO)?,
|
||||
self.ecx().project_field(&unique_ptr, FieldIdx::ONE)?,
|
||||
);
|
||||
assert!(
|
||||
phantom.layout().ty.ty_adt_def().is_some_and(|adt| adt.is_phantom_data()),
|
||||
@@ -156,7 +160,7 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
|
||||
);
|
||||
// ... that contains a `NonNull`... (gladly, only a single field here)
|
||||
assert_eq!(nonnull_ptr.layout().fields.count(), 1);
|
||||
let raw_ptr = self.ecx().project_field(&nonnull_ptr, 0)?; // the actual raw ptr
|
||||
let raw_ptr = self.ecx().project_field(&nonnull_ptr, FieldIdx::ZERO)?; // the actual raw ptr
|
||||
// ... whose only field finally is a raw ptr we can dereference.
|
||||
self.visit_box(ty, &raw_ptr)?;
|
||||
|
||||
@@ -188,9 +192,8 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
|
||||
}
|
||||
FieldsShape::Arbitrary { memory_index, .. } => {
|
||||
for idx in Self::aggregate_field_iter(memory_index) {
|
||||
let idx = idx.as_usize();
|
||||
let field = self.ecx().project_field(v, idx)?;
|
||||
self.visit_field(v, idx, &field)?;
|
||||
self.visit_field(v, idx.as_usize(), &field)?;
|
||||
}
|
||||
}
|
||||
FieldsShape::Array { .. } => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use rustc_abi::FieldIdx;
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
@@ -41,11 +42,14 @@ fn alloc_caller_location<'tcx>(
|
||||
let location = ecx.allocate(loc_layout, MemoryKind::CallerLocation).unwrap();
|
||||
|
||||
// Initialize fields.
|
||||
ecx.write_immediate(file_wide_ptr, &ecx.project_field(&location, 0).unwrap())
|
||||
ecx.write_immediate(
|
||||
file_wide_ptr,
|
||||
&ecx.project_field(&location, FieldIdx::from_u32(0)).unwrap(),
|
||||
)
|
||||
.expect("writing to memory we just allocated cannot fail");
|
||||
ecx.write_scalar(line, &ecx.project_field(&location, 1).unwrap())
|
||||
ecx.write_scalar(line, &ecx.project_field(&location, FieldIdx::from_u32(1)).unwrap())
|
||||
.expect("writing to memory we just allocated cannot fail");
|
||||
ecx.write_scalar(col, &ecx.project_field(&location, 2).unwrap())
|
||||
ecx.write_scalar(col, &ecx.project_field(&location, FieldIdx::from_u32(2)).unwrap())
|
||||
.expect("writing to memory we just allocated cannot fail");
|
||||
|
||||
location
|
||||
|
||||
@@ -1100,7 +1100,7 @@ fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
|
||||
return;
|
||||
};
|
||||
|
||||
if let Some(second_field) = fields.get(FieldIdx::from_u32(1)) {
|
||||
if let Some(second_field) = fields.get(FieldIdx::ONE) {
|
||||
struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot have multiple fields")
|
||||
.with_span_label(tcx.def_span(second_field.did), "excess field")
|
||||
.emit();
|
||||
|
||||
@@ -171,7 +171,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
||||
_ if ty.references_error() => return None,
|
||||
ty::Adt(adt, args) if self.tcx().is_lang_item(adt.did(), LangItem::MaybeUninit) => {
|
||||
let fields = &adt.non_enum_variant().fields;
|
||||
let ty = fields[FieldIdx::from_u32(1)].ty(self.tcx(), args);
|
||||
let ty = fields[FieldIdx::ONE].ty(self.tcx(), args);
|
||||
// FIXME: Are we just trying to map to the `T` in `MaybeUninit<T>`?
|
||||
// If so, just get it from the args.
|
||||
let ty::Adt(ty, args) = ty.kind() else {
|
||||
|
||||
@@ -616,7 +616,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
|
||||
place,
|
||||
operand,
|
||||
&mut |elem, op| match elem {
|
||||
TrackElem::Field(idx) => self.ecx.project_field(op, idx.as_usize()).discard_err(),
|
||||
TrackElem::Field(idx) => self.ecx.project_field(op, idx).discard_err(),
|
||||
TrackElem::Variant(idx) => self.ecx.project_downcast(op, idx).discard_err(),
|
||||
TrackElem::Discriminant => {
|
||||
let variant = self.ecx.read_discriminant(op).discard_err()?;
|
||||
@@ -890,7 +890,8 @@ fn try_write_constant<'tcx>(
|
||||
|
||||
ty::Tuple(elem_tys) => {
|
||||
for (i, elem) in elem_tys.iter().enumerate() {
|
||||
let Some(field) = map.apply(place, TrackElem::Field(FieldIdx::from_usize(i))) else {
|
||||
let i = FieldIdx::from_usize(i);
|
||||
let Some(field) = map.apply(place, TrackElem::Field(i)) else {
|
||||
throw_machine_stop_str!("missing field in tuple")
|
||||
};
|
||||
let field_dest = ecx.project_field(dest, i)?;
|
||||
@@ -928,7 +929,7 @@ fn try_write_constant<'tcx>(
|
||||
let Some(field) = map.apply(variant_place, TrackElem::Field(i)) else {
|
||||
throw_machine_stop_str!("missing field in ADT")
|
||||
};
|
||||
let field_dest = ecx.project_field(&variant_dest, i.as_usize())?;
|
||||
let field_dest = ecx.project_field(&variant_dest, i)?;
|
||||
try_write_constant(ecx, &field_dest, field, ty, state, map)?;
|
||||
}
|
||||
ecx.write_discriminant(variant_idx, dest)?;
|
||||
|
||||
@@ -438,8 +438,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||
dest.clone()
|
||||
};
|
||||
for (field_index, op) in fields.into_iter().enumerate() {
|
||||
let field_dest =
|
||||
self.ecx.project_field(&variant_dest, field_index).discard_err()?;
|
||||
let field_dest = self
|
||||
.ecx
|
||||
.project_field(&variant_dest, FieldIdx::from_usize(field_index))
|
||||
.discard_err()?;
|
||||
self.ecx.copy_op(op, &field_dest).discard_err()?;
|
||||
}
|
||||
self.ecx
|
||||
@@ -1583,7 +1585,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||
// We needed to check the variant to avoid trying to read the tag
|
||||
// field from an enum where no fields have variants, since that tag
|
||||
// field isn't in the `Aggregate` from which we're getting values.
|
||||
Some((FieldIdx::from_usize(field_idx), field_layout.ty))
|
||||
Some((field_idx, field_layout.ty))
|
||||
} else if let ty::Adt(adt, args) = ty.kind()
|
||||
&& adt.is_struct()
|
||||
&& adt.repr().transparent()
|
||||
|
||||
@@ -388,7 +388,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
||||
lhs,
|
||||
constant,
|
||||
&mut |elem, op| match elem {
|
||||
TrackElem::Field(idx) => self.ecx.project_field(op, idx.as_usize()).discard_err(),
|
||||
TrackElem::Field(idx) => self.ecx.project_field(op, idx).discard_err(),
|
||||
TrackElem::Variant(idx) => self.ecx.project_downcast(op, idx).discard_err(),
|
||||
TrackElem::Discriminant => {
|
||||
let variant = self.ecx.read_discriminant(op).discard_err()?;
|
||||
|
||||
@@ -359,8 +359,8 @@ pub fn create_ecx<'tcx>(
|
||||
let argvs_layout =
|
||||
ecx.layout_of(Ty::new_array(tcx, u8_ptr_type, u64::try_from(argvs.len()).unwrap()))?;
|
||||
let argvs_place = ecx.allocate(argvs_layout, MiriMemoryKind::Machine.into())?;
|
||||
for (idx, arg) in argvs.into_iter().enumerate() {
|
||||
let place = ecx.project_field(&argvs_place, idx)?;
|
||||
for (arg, idx) in argvs.into_iter().zip(0..) {
|
||||
let place = ecx.project_index(&argvs_place, idx)?;
|
||||
ecx.write_immediate(arg, &place)?;
|
||||
}
|
||||
ecx.mark_immutable(&argvs_place);
|
||||
@@ -389,8 +389,8 @@ pub fn create_ecx<'tcx>(
|
||||
ecx.allocate(ecx.layout_of(cmd_type)?, MiriMemoryKind::Machine.into())?;
|
||||
ecx.machine.cmd_line = Some(cmd_place.ptr());
|
||||
// Store the UTF-16 string. We just allocated so we know the bounds are fine.
|
||||
for (idx, &c) in cmd_utf16.iter().enumerate() {
|
||||
let place = ecx.project_field(&cmd_place, idx)?;
|
||||
for (&c, idx) in cmd_utf16.iter().zip(0..) {
|
||||
let place = ecx.project_index(&cmd_place, idx)?;
|
||||
ecx.write_scalar(Scalar::from_u16(c), &place)?;
|
||||
}
|
||||
ecx.mark_immutable(&cmd_place);
|
||||
|
||||
@@ -326,7 +326,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||
) -> InterpResult<'tcx, Option<P>> {
|
||||
let this = self.eval_context_ref();
|
||||
let adt = base.layout().ty.ty_adt_def().unwrap();
|
||||
for (idx, field) in adt.non_enum_variant().fields.iter().enumerate() {
|
||||
for (idx, field) in adt.non_enum_variant().fields.iter_enumerated() {
|
||||
if field.name.as_str() == name {
|
||||
return interp_ok(Some(this.project_field(base, idx)?));
|
||||
}
|
||||
@@ -376,6 +376,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
for (idx, &val) in values.iter().enumerate() {
|
||||
let idx = FieldIdx::from_usize(idx);
|
||||
let field = this.project_field(dest, idx)?;
|
||||
this.write_int(val, &field)?;
|
||||
}
|
||||
@@ -763,10 +764,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||
/// `EINVAL` in this case.
|
||||
fn read_timespec(&mut self, tp: &MPlaceTy<'tcx>) -> InterpResult<'tcx, Option<Duration>> {
|
||||
let this = self.eval_context_mut();
|
||||
let seconds_place = this.project_field(tp, 0)?;
|
||||
let seconds_place = this.project_field(tp, FieldIdx::ZERO)?;
|
||||
let seconds_scalar = this.read_scalar(&seconds_place)?;
|
||||
let seconds = seconds_scalar.to_target_isize(this)?;
|
||||
let nanoseconds_place = this.project_field(tp, 1)?;
|
||||
let nanoseconds_place = this.project_field(tp, FieldIdx::ONE)?;
|
||||
let nanoseconds_scalar = this.read_scalar(&nanoseconds_place)?;
|
||||
let nanoseconds = nanoseconds_scalar.to_target_isize(this)?;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use rustc_abi::{CanonAbi, Size};
|
||||
use rustc_abi::{CanonAbi, FieldIdx, Size};
|
||||
use rustc_middle::ty::layout::LayoutOf as _;
|
||||
use rustc_middle::ty::{self, Instance, Ty};
|
||||
use rustc_span::{BytePos, Loc, Symbol, hygiene};
|
||||
@@ -159,23 +159,23 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||
1 => {
|
||||
this.write_scalar(
|
||||
Scalar::from_target_usize(name.len().to_u64(), this),
|
||||
&this.project_field(dest, 0)?,
|
||||
&this.project_field(dest, FieldIdx::from_u32(0))?,
|
||||
)?;
|
||||
this.write_scalar(
|
||||
Scalar::from_target_usize(filename.len().to_u64(), this),
|
||||
&this.project_field(dest, 1)?,
|
||||
&this.project_field(dest, FieldIdx::from_u32(1))?,
|
||||
)?;
|
||||
}
|
||||
_ => throw_unsup_format!("unknown `miri_resolve_frame` flags {}", flags),
|
||||
}
|
||||
|
||||
this.write_scalar(Scalar::from_u32(lineno), &this.project_field(dest, 2)?)?;
|
||||
this.write_scalar(Scalar::from_u32(colno), &this.project_field(dest, 3)?)?;
|
||||
this.write_scalar(Scalar::from_u32(lineno), &this.project_field(dest, FieldIdx::from_u32(2))?)?;
|
||||
this.write_scalar(Scalar::from_u32(colno), &this.project_field(dest, FieldIdx::from_u32(3))?)?;
|
||||
|
||||
// Support a 4-field struct for now - this is deprecated
|
||||
// and slated for removal.
|
||||
if num_fields == 5 {
|
||||
this.write_pointer(fn_ptr, &this.project_field(dest, 4)?)?;
|
||||
this.write_pointer(fn_ptr, &this.project_field(dest, FieldIdx::from_u32(4))?)?;
|
||||
}
|
||||
|
||||
interp_ok(())
|
||||
|
||||
@@ -2,8 +2,9 @@ use std::ffi::{OsStr, OsString};
|
||||
use std::io::ErrorKind;
|
||||
use std::{env, mem};
|
||||
|
||||
use rustc_abi::Size;
|
||||
use rustc_abi::{FieldIdx, Size};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
|
||||
@@ -118,7 +119,7 @@ fn alloc_env_var<'tcx>(
|
||||
/// Allocates an `environ` block with the given list of pointers.
|
||||
fn alloc_environ_block<'tcx>(
|
||||
ecx: &mut InterpCx<'tcx, MiriMachine<'tcx>>,
|
||||
mut vars: Vec<Pointer>,
|
||||
mut vars: IndexVec<FieldIdx, Pointer>,
|
||||
) -> InterpResult<'tcx, Pointer> {
|
||||
// Add trailing null.
|
||||
vars.push(Pointer::null());
|
||||
@@ -129,7 +130,7 @@ fn alloc_environ_block<'tcx>(
|
||||
u64::try_from(vars.len()).unwrap(),
|
||||
))?;
|
||||
let vars_place = ecx.allocate(vars_layout, MiriMemoryKind::Runtime.into())?;
|
||||
for (idx, var) in vars.into_iter().enumerate() {
|
||||
for (idx, var) in vars.into_iter_enumerated() {
|
||||
let place = ecx.project_field(&vars_place, idx)?;
|
||||
ecx.write_pointer(var, &place)?;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
use core::time::Duration;
|
||||
|
||||
use rustc_abi::FieldIdx;
|
||||
|
||||
use crate::concurrency::sync::FutexRef;
|
||||
use crate::*;
|
||||
|
||||
@@ -214,18 +216,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||
// Only flag allowed is UMTX_ABSTIME.
|
||||
let abs_time = this.eval_libc_u32("UMTX_ABSTIME");
|
||||
|
||||
let timespec_place = this.project_field(ut, 0)?;
|
||||
let timespec_place = this.project_field(ut, FieldIdx::from_u32(0))?;
|
||||
// Inner `timespec` must still be valid.
|
||||
let duration = match this.read_timespec(×pec_place)? {
|
||||
Some(dur) => dur,
|
||||
None => return interp_ok(None),
|
||||
};
|
||||
|
||||
let flags_place = this.project_field(ut, 1)?;
|
||||
let flags_place = this.project_field(ut, FieldIdx::from_u32(1))?;
|
||||
let flags = this.read_scalar(&flags_place)?.to_u32()?;
|
||||
let abs_time_flag = flags == abs_time;
|
||||
|
||||
let clock_id_place = this.project_field(ut, 2)?;
|
||||
let clock_id_place = this.project_field(ut, FieldIdx::from_u32(2))?;
|
||||
let clock_id = this.read_scalar(&clock_id_place)?.to_i32()?;
|
||||
let timeout_clock = this.translate_umtx_time_clock_id(clock_id)?;
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ use std::io;
|
||||
use std::rc::{Rc, Weak};
|
||||
use std::time::Duration;
|
||||
|
||||
use rustc_abi::FieldIdx;
|
||||
|
||||
use crate::concurrency::VClock;
|
||||
use crate::shims::files::{
|
||||
DynFileDescriptionRef, FdId, FileDescription, FileDescriptionRef, WeakFileDescriptionRef,
|
||||
@@ -284,8 +286,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||
|
||||
if op == epoll_ctl_add || op == epoll_ctl_mod {
|
||||
// Read event bitmask and data from epoll_event passed by caller.
|
||||
let mut events = this.read_scalar(&this.project_field(&event, 0)?)?.to_u32()?;
|
||||
let data = this.read_scalar(&this.project_field(&event, 1)?)?.to_u64()?;
|
||||
let mut events = this.read_scalar(&this.project_field(&event, FieldIdx::ZERO)?)?.to_u32()?;
|
||||
let data = this.read_scalar(&this.project_field(&event, FieldIdx::ONE)?)?.to_u64()?;
|
||||
|
||||
// Unset the flag we support to discover if any unsupported flags are used.
|
||||
let mut flags = events;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use rustc_abi::{CanonAbi, Size};
|
||||
use rustc_abi::{CanonAbi, FieldIdx, Size};
|
||||
use rustc_apfloat::Float;
|
||||
use rustc_apfloat::ieee::Single;
|
||||
use rustc_middle::ty::Ty;
|
||||
@@ -54,8 +54,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||
};
|
||||
|
||||
let (sum, cb_out) = carrying_add(this, cb_in, a, b, op)?;
|
||||
this.write_scalar(cb_out, &this.project_field(dest, 0)?)?;
|
||||
this.write_immediate(*sum, &this.project_field(dest, 1)?)?;
|
||||
this.write_scalar(cb_out, &this.project_field(dest, FieldIdx::ZERO)?)?;
|
||||
this.write_immediate(*sum, &this.project_field(dest, FieldIdx::ONE)?)?;
|
||||
}
|
||||
|
||||
// Used to implement the `_addcarryx_u{32, 64}` functions. They are semantically identical with the `_addcarry_u{32, 64}` functions,
|
||||
|
||||
Reference in New Issue
Block a user