Skip to content

Commit 0075868

Browse files
committed
Insert satisfying op_to_const bbqing sound here.
1 parent 92e4471 commit 0075868

File tree

3 files changed

+36
-48
lines changed

3 files changed

+36
-48
lines changed

src/librustc_mir/const_eval.rs

+34-46
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use syntax::ast::Mutability;
2121
use syntax::source_map::{Span, DUMMY_SP};
2222

2323
use crate::interpret::{self,
24-
PlaceTy, MPlaceTy, MemPlace, OpTy, ImmTy, Operand, Immediate, Scalar, Pointer,
24+
PlaceTy, MPlaceTy, OpTy, ImmTy, Scalar, Pointer,
2525
RawConst, ConstValue,
2626
EvalResult, EvalError, EvalErrorKind, GlobalId, EvalContext, StackPopCleanup,
2727
Allocation, AllocId, MemoryKind,
@@ -62,43 +62,6 @@ pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
6262
eval_body_using_ecx(&mut ecx, cid, Some(mir), param_env)
6363
}
6464

65-
// FIXME: These two conversion functions are bad hacks. We should just always use allocations.
66-
fn op_to_const<'tcx>(
67-
ecx: &CompileTimeEvalContext<'_, '_, 'tcx>,
68-
op: OpTy<'tcx>,
69-
) -> EvalResult<'tcx, ty::Const<'tcx>> {
70-
// We do not normalize just any data. Only scalar layout and slices.
71-
let normalized_op = match op.layout.abi {
72-
layout::Abi::Scalar(..) => ecx.try_read_immediate(op)?,
73-
layout::Abi::ScalarPair(..) if op.layout.ty.is_slice() => ecx.try_read_immediate(op)?,
74-
_ => match *op {
75-
Operand::Indirect(mplace) => Err(mplace),
76-
Operand::Immediate(val) => Ok(val)
77-
},
78-
};
79-
let (val, alloc) = match normalized_op {
80-
Err(MemPlace { ptr, align, meta }) => {
81-
// extract alloc-offset pair
82-
assert!(meta.is_none());
83-
let ptr = ptr.to_ptr()?;
84-
let alloc = ecx.memory.get(ptr.alloc_id)?;
85-
assert!(alloc.align >= align);
86-
assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= op.layout.size.bytes());
87-
let mut alloc = alloc.clone();
88-
alloc.align = align;
89-
// FIXME shouldn't it be the case that `mark_static_initialized` has already
90-
// interned this? I thought that is the entire point of that `FinishStatic` stuff?
91-
let alloc = ecx.tcx.intern_const_alloc(alloc);
92-
(ConstValue::ByRef, Some((alloc, ptr)))
93-
},
94-
Ok(Immediate::Scalar(x)) =>
95-
(ConstValue::Scalar(x.not_undef()?), None),
96-
Ok(Immediate::ScalarPair(a, b)) =>
97-
(ConstValue::Slice(a.not_undef()?, b.to_usize(ecx)?), None),
98-
};
99-
Ok(ty::Const { val, ty: op.layout.ty, alloc })
100-
}
101-
10265
fn eval_body_and_ecx<'a, 'mir, 'tcx>(
10366
tcx: TyCtxt<'a, 'tcx, 'tcx>,
10467
cid: GlobalId<'tcx>,
@@ -471,18 +434,43 @@ pub fn const_field<'a, 'tcx>(
471434
trace!("const_field: {:?}, {:?}", field, value);
472435
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
473436
let result = (|| {
474-
// get the operand again
475-
let op = ecx.lazy_const_to_op(ty::LazyConst::Evaluated(value), value.ty)?;
437+
let (alloc, ptr) = value.alloc.expect(
438+
"const_field can only be called on aggregates, which should never be created without
439+
a corresponding allocation",
440+
);
441+
let mplace = MPlaceTy::from_aligned_ptr(ptr, ecx.layout_of(value.ty)?);
476442
// downcast
477443
let down = match variant {
478-
None => op,
479-
Some(variant) => ecx.operand_downcast(op, variant)?
444+
None => mplace,
445+
Some(variant) => ecx.mplace_downcast(mplace, variant)?,
480446
};
481447
// then project
482-
let field = ecx.operand_field(down, field.index() as u64)?;
483-
// and finally move back to the const world, always normalizing because
484-
// this is not called for statics.
485-
op_to_const(&ecx, field)
448+
let field = ecx.mplace_field(down, field.index() as u64)?;
449+
let val = match field.layout.abi {
450+
layout::Abi::Scalar(..) => {
451+
let scalar = ecx.try_read_immediate_from_mplace(field)?.unwrap().to_scalar()?;
452+
ConstValue::Scalar(scalar)
453+
}
454+
layout::Abi::ScalarPair(..) if field.layout.ty.is_slice() => {
455+
let (a, b) = ecx.try_read_immediate_from_mplace(field)?.unwrap().to_scalar_pair()?;
456+
ConstValue::Slice(a, b.to_usize(&ecx)?)
457+
},
458+
_ => ConstValue::ByRef,
459+
};
460+
let field_ptr = field.to_ptr().unwrap();
461+
assert_eq!(
462+
ptr.alloc_id,
463+
field_ptr.alloc_id,
464+
"field access of aggregate moved to different allocation",
465+
);
466+
Ok(ty::Const {
467+
val,
468+
ty: field.layout.ty,
469+
alloc: Some((
470+
alloc,
471+
field_ptr,
472+
)),
473+
})
486474
})();
487475
result.map_err(|error| {
488476
let err = error_to_const_error(&ecx, error);

src/librustc_mir/interpret/operand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ pub(super) fn from_known_layout<'tcx>(
269269
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
270270
/// Try reading an immediate in memory; this is interesting particularly for ScalarPair.
271271
/// Returns `None` if the layout does not permit loading this as a value.
272-
pub(super) fn try_read_immediate_from_mplace(
272+
crate fn try_read_immediate_from_mplace(
273273
&self,
274274
mplace: MPlaceTy<'tcx, M::PointerTag>,
275275
) -> EvalResult<'tcx, Option<Immediate<M::PointerTag>>> {

src/librustc_mir/interpret/place.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> {
212212
}
213213

214214
#[inline]
215-
fn from_aligned_ptr(ptr: Pointer<Tag>, layout: TyLayout<'tcx>) -> Self {
215+
crate fn from_aligned_ptr(ptr: Pointer<Tag>, layout: TyLayout<'tcx>) -> Self {
216216
MPlaceTy { mplace: MemPlace::from_ptr(ptr, layout.align.abi), layout }
217217
}
218218

0 commit comments

Comments
 (0)