Update InterpCx::project_field to take FieldIdx

As suggested by Ralf in 142005.
This commit is contained in:
Scott McMurray
2025-06-04 01:44:40 -07:00
parent ccf3198de3
commit 8bce2255e8
26 changed files with 102 additions and 80 deletions

View File

@@ -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
}

View File

@@ -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")
};

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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))
})

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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() {

View File

@@ -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);

View File

@@ -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) => {

View File

@@ -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)?;
}

View File

@@ -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.

View File

@@ -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 { .. } => {

View File

@@ -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

View File

@@ -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();

View File

@@ -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 {

View File

@@ -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)?;

View File

@@ -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()

View File

@@ -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()?;

View File

@@ -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);

View File

@@ -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)?;

View File

@@ -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(())

View File

@@ -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)?;
}

View File

@@ -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(&timespec_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)?;

View File

@@ -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;

View File

@@ -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,