Skip to content

Commit cc0fbdf

Browse files
committed
Automatically prefer integer addresses for zst MPlace
1 parent ee84c30 commit cc0fbdf

File tree

7 files changed

+26
-53
lines changed

7 files changed

+26
-53
lines changed

src/librustc_mir/const_eval/eval_queries.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ pub(super) fn op_to_const<'tcx>(
115115
// by-val is if we are in const_field, i.e., if this is (a field of) something that we
116116
// "tried to make immediate" before. We wouldn't do that for non-slice scalar pairs or
117117
// structs containing such.
118-
op.try_as_mplace()
118+
op.try_as_mplace(ecx)
119119
};
120120
let val = match immediate {
121121
Ok(mplace) => {
@@ -132,7 +132,7 @@ pub(super) fn op_to_const<'tcx>(
132132
// `Immediate` is when we are called from `const_field`, and that `Immediate`
133133
// comes from a constant so it can happen have `Undef`, because the indirect
134134
// memory that was read had undefined bytes.
135-
let mplace = op.assert_mem_place();
135+
let mplace = op.assert_mem_place(ecx);
136136
let ptr = mplace.ptr.assert_ptr();
137137
let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
138138
ConstValue::ByRef { alloc, offset: ptr.offset }

src/librustc_mir/interpret/operand.rs

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
267267
&self,
268268
op: OpTy<'tcx, M::PointerTag>,
269269
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
270-
match op.try_as_mplace() {
270+
match op.try_as_mplace(self) {
271271
Ok(mplace) => Ok(self.force_mplace_ptr(mplace)?.into()),
272272
Err(imm) => Ok(imm.into()), // Nothing to cast/force
273273
}
@@ -335,7 +335,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
335335
&self,
336336
src: OpTy<'tcx, M::PointerTag>,
337337
) -> InterpResult<'tcx, Result<ImmTy<'tcx, M::PointerTag>, MPlaceTy<'tcx, M::PointerTag>>> {
338-
Ok(match src.try_as_mplace() {
338+
Ok(match src.try_as_mplace(self) {
339339
Ok(mplace) => {
340340
if let Some(val) = self.try_read_immediate_from_mplace(mplace)? {
341341
Ok(val)
@@ -383,7 +383,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
383383
op: OpTy<'tcx, M::PointerTag>,
384384
field: u64,
385385
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
386-
let base = match op.try_as_mplace() {
386+
let base = match op.try_as_mplace(self) {
387387
Ok(mplace) => {
388388
// The easy case
389389
let field = self.mplace_field(mplace, field)?;
@@ -420,7 +420,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
420420
variant: VariantIdx,
421421
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
422422
// Downcasts only change the layout
423-
Ok(match op.try_as_mplace() {
423+
Ok(match op.try_as_mplace(self) {
424424
Ok(mplace) => self.mplace_downcast(mplace, variant)?.into(),
425425
Err(..) => {
426426
let layout = op.layout.for_variant(self, variant);
@@ -439,30 +439,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
439439
Field(field, _) => self.operand_field(base, field.index() as u64)?,
440440
Downcast(_, variant) => self.operand_downcast(base, variant)?,
441441
Deref => self.deref_operand(base)?.into(),
442-
ConstantIndex { .. } | Index(_) if base.layout.is_zst() => {
443-
OpTy {
444-
op: Operand::Immediate(Scalar::zst().into()),
445-
// the actual index doesn't matter, so we just pick a convenient one like 0
446-
layout: base.layout.field(self, 0)?,
447-
}
448-
}
449-
Subslice { from, to, from_end } if base.layout.is_zst() => {
450-
let elem_ty = if let ty::Array(elem_ty, _) = base.layout.ty.kind {
451-
elem_ty
452-
} else {
453-
bug!("slices shouldn't be zero-sized");
454-
};
455-
assert!(!from_end, "arrays shouldn't be subsliced from the end");
456-
457-
OpTy {
458-
op: Operand::Immediate(Scalar::zst().into()),
459-
layout: self.layout_of(self.tcx.mk_array(elem_ty, (to - from) as u64))?,
460-
}
461-
}
462442
Subslice { .. } | ConstantIndex { .. } | Index(_) => {
463443
// The rest should only occur as mplace, we do not use Immediates for types
464444
// allowing such operations. This matches place_projection forcing an allocation.
465-
let mplace = base.assert_mem_place();
445+
let mplace = base.assert_mem_place(self);
466446
self.mplace_projection(mplace, proj_elem)?.into()
467447
}
468448
})

src/librustc_mir/interpret/place.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -200,16 +200,17 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> {
200200
// These are defined here because they produce a place.
201201
impl<'tcx, Tag: ::std::fmt::Debug + Copy> OpTy<'tcx, Tag> {
202202
#[inline(always)]
203-
pub fn try_as_mplace(self) -> Result<MPlaceTy<'tcx, Tag>, ImmTy<'tcx, Tag>> {
203+
pub fn try_as_mplace(self, cx: &impl HasDataLayout) -> Result<MPlaceTy<'tcx, Tag>, ImmTy<'tcx, Tag>> {
204204
match *self {
205205
Operand::Indirect(mplace) => Ok(MPlaceTy { mplace, layout: self.layout }),
206+
Operand::Immediate(_) if self.layout.is_zst() => Ok(MPlaceTy::dangling(self.layout, cx)),
206207
Operand::Immediate(imm) => Err(ImmTy { imm, layout: self.layout }),
207208
}
208209
}
209210

210211
#[inline(always)]
211-
pub fn assert_mem_place(self) -> MPlaceTy<'tcx, Tag> {
212-
self.try_as_mplace().unwrap()
212+
pub fn assert_mem_place(self, cx: &impl HasDataLayout) -> MPlaceTy<'tcx, Tag> {
213+
self.try_as_mplace(cx).unwrap()
213214
}
214215
}
215216

@@ -305,7 +306,7 @@ where
305306
/// On success, returns `None` for zero-sized accesses (where nothing else is
306307
/// left to do) and a `Pointer` to use for the actual access otherwise.
307308
#[inline]
308-
pub fn check_mplace_access(
309+
pub(super) fn check_mplace_access(
309310
&self,
310311
place: MPlaceTy<'tcx, M::PointerTag>,
311312
size: Option<Size>,
@@ -338,7 +339,7 @@ where
338339

339340
/// Force `place.ptr` to a `Pointer`.
340341
/// Can be helpful to avoid lots of `force_ptr` calls later, if this place is used a lot.
341-
pub fn force_mplace_ptr(
342+
pub(super) fn force_mplace_ptr(
342343
&self,
343344
mut place: MPlaceTy<'tcx, M::PointerTag>,
344345
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
@@ -415,7 +416,7 @@ where
415416

416417
// Iterates over all fields of an array. Much more efficient than doing the
417418
// same by repeatedly calling `mplace_array`.
418-
pub fn mplace_array_fields(
419+
pub(super) fn mplace_array_fields(
419420
&self,
420421
base: MPlaceTy<'tcx, Tag>,
421422
) -> InterpResult<'tcx, impl Iterator<Item = InterpResult<'tcx, MPlaceTy<'tcx, Tag>>> + 'tcx>
@@ -430,7 +431,7 @@ where
430431
Ok((0..len).map(move |i| base.offset(i * stride, None, layout, dl)))
431432
}
432433

433-
pub fn mplace_subslice(
434+
fn mplace_subslice(
434435
&self,
435436
base: MPlaceTy<'tcx, M::PointerTag>,
436437
from: u64,
@@ -471,7 +472,7 @@ where
471472
base.offset(from_offset, meta, layout, self)
472473
}
473474

474-
pub fn mplace_downcast(
475+
pub(super) fn mplace_downcast(
475476
&self,
476477
base: MPlaceTy<'tcx, M::PointerTag>,
477478
variant: VariantIdx,
@@ -482,7 +483,7 @@ where
482483
}
483484

484485
/// Project into an mplace
485-
pub fn mplace_projection(
486+
pub(super) fn mplace_projection(
486487
&self,
487488
base: MPlaceTy<'tcx, M::PointerTag>,
488489
proj_elem: &mir::PlaceElem<'tcx>,

src/librustc_mir/interpret/terminator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
378378
}
379379
None => {
380380
// Unsized self.
381-
args[0].assert_mem_place()
381+
args[0].assert_mem_place(self)
382382
}
383383
};
384384
// Find and consult vtable

src/librustc_mir/interpret/validity.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -571,12 +571,9 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
571571
) -> InterpResult<'tcx> {
572572
match op.layout.ty.kind {
573573
ty::Str => {
574-
let mplace = op.assert_mem_place(); // strings are never immediate
575-
try_validation!(
576-
self.ecx.read_str(mplace),
577-
"uninitialized or non-UTF-8 data in str",
578-
self.path
579-
);
574+
let mplace = op.assert_mem_place(self.ecx); // strings are never immediate
575+
try_validation!(self.ecx.read_str(mplace),
576+
"uninitialized or non-UTF-8 data in str", self.path);
580577
}
581578
ty::Array(tys, ..) | ty::Slice(tys)
582579
if {
@@ -604,7 +601,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
604601
return Ok(());
605602
}
606603
// non-ZST array cannot be immediate, slices are never immediate
607-
let mplace = op.assert_mem_place();
604+
let mplace = op.assert_mem_place(self.ecx);
608605
// This is the length of the array/slice.
609606
let len = mplace.len(self.ecx)?;
610607
// zero length slices have nothing to be checked

src/librustc_mir/interpret/visitor.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ macro_rules! make_value_visitor {
223223
match v.layout().ty.kind {
224224
ty::Dynamic(..) => {
225225
// immediate trait objects are not a thing
226-
let dest = v.to_op(self.ecx())?.assert_mem_place();
226+
let dest = v.to_op(self.ecx())?.assert_mem_place(self.ecx());
227227
let inner = self.ecx().unpack_dyn_trait(dest)?.1;
228228
trace!("walk_value: dyn object layout: {:#?}", inner.layout);
229229
// recurse with the inner type
@@ -292,13 +292,7 @@ macro_rules! make_value_visitor {
292292
},
293293
layout::FieldPlacement::Array { .. } => {
294294
// Let's get an mplace first.
295-
let mplace = if v.layout().is_zst() {
296-
// it's a ZST, the memory content cannot matter
297-
MPlaceTy::dangling(v.layout(), self.ecx())
298-
} else {
299-
// non-ZST array/slice/str cannot be immediate
300-
v.to_op(self.ecx())?.assert_mem_place()
301-
};
295+
let mplace = v.to_op(self.ecx())?.assert_mem_place(self.ecx());
302296
// Now we can go over all the fields.
303297
let iter = self.ecx().mplace_array_fields(mplace)?
304298
.map(|f| f.and_then(|f| {

src/librustc_mir/transform/const_prop.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
707707
ScalarMaybeUndef::Scalar(r),
708708
)) => l.is_bits() && r.is_bits(),
709709
interpret::Operand::Indirect(_) if mir_opt_level >= 2 => {
710-
intern_const_alloc_recursive(&mut self.ecx, None, op.assert_mem_place())
710+
let mplace = op.assert_mem_place(&self.ecx);
711+
intern_const_alloc_recursive(&mut self.ecx, None, mplace)
711712
.expect("failed to intern alloc");
712713
true
713714
}

0 commit comments

Comments
 (0)