use super::{error_to_const_error, CompileTimeEvalContext, CompileTimeInterpreter, MemoryExtra};
use crate::interpret::eval_nullary_intrinsic;
use crate::interpret::{
- intern_const_alloc_recursive, Allocation, ConstValue, GlobalId, ImmTy, Immediate, InternKind,
+ intern_const_alloc_recursive, Allocation, ConstValue, GlobalId, Immediate, InternKind,
InterpCx, InterpResult, MPlaceTy, MemoryKind, OpTy, RawConst, RefTracking, Scalar,
ScalarMaybeUndef, StackPopCleanup,
};
match immediate {
Ok(mplace) => to_const_value(mplace),
// see comment on `let try_as_immediate` above
- Err(ImmTy { imm: Immediate::Scalar(x), .. }) => match x {
- ScalarMaybeUndef::Scalar(s) => ConstValue::Scalar(s),
- ScalarMaybeUndef::Undef => to_const_value(op.assert_mem_place(ecx)),
- },
- Err(ImmTy { imm: Immediate::ScalarPair(a, b), .. }) => {
- let (data, start) = match a.not_undef().unwrap() {
- Scalar::Ptr(ptr) => {
- (ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id), ptr.offset.bytes())
- }
- Scalar::Raw { .. } => (
- ecx.tcx.intern_const_alloc(Allocation::from_byte_aligned_bytes(b"" as &[u8])),
- 0,
- ),
- };
- let len = b.to_machine_usize(&ecx.tcx.tcx).unwrap();
- let start = start.try_into().unwrap();
- let len: usize = len.try_into().unwrap();
- ConstValue::Slice { data, start, end: start + len }
+ Err(imm) => match *imm {
+ Immediate::Scalar(x) => match x {
+ ScalarMaybeUndef::Scalar(s) => ConstValue::Scalar(s),
+ ScalarMaybeUndef::Undef => to_const_value(op.assert_mem_place(ecx)),
+ },
+ Immediate::ScalarPair(a, b) => {
+ let (data, start) = match a.not_undef().unwrap() {
+ Scalar::Ptr(ptr) => {
+ (ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id), ptr.offset.bytes())
+ }
+ Scalar::Raw { .. } => (
+ ecx.tcx.intern_const_alloc(Allocation::from_byte_aligned_bytes(b"" as &[u8])),
+ 0,
+ ),
+ };
+ let len = b.to_machine_usize(&ecx.tcx.tcx).unwrap();
+ let start = start.try_into().unwrap();
+ let len: usize = len.try_into().unwrap();
+ ConstValue::Slice { data, start, end: start + len }
+ }
}
}
}
self.frame_mut().locals = locals;
}
+ M::after_stack_push(self)?;
info!("ENTERING({}) {}", self.cur_frame(), self.frame().instance);
if self.stack.len() > *self.tcx.sess.recursion_limit.get() {
// We want to skip the `info!` below, hence early return.
return Ok(());
}
- // Normal return.
+ // Normal return, figure out where to jump.
if unwinding {
// Follow the unwind edge.
let unwind = next_block.expect("Encountered StackPopCleanup::None when unwinding!");
frame: Frame<'mir, 'tcx, Self::PointerTag>,
) -> InterpResult<'tcx, Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>>;
+ /// Called immediately after a stack frame got pushed and its locals got initialized.
+ fn after_stack_push(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
+ Ok(())
+ }
+
/// Called immediately after a stack frame got popped, but before jumping back to the caller.
fn after_stack_pop(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
// as input for binary and cast operations.
#[derive(Copy, Clone, Debug)]
pub struct ImmTy<'tcx, Tag = ()> {
- pub(crate) imm: Immediate<Tag>,
+ imm: Immediate<Tag>,
pub layout: TyAndLayout<'tcx>,
}
ImmTy { imm: val.into(), layout }
}
+ #[inline]
+ pub fn from_immediate(imm: Immediate<Tag>, layout: TyAndLayout<'tcx>) -> Self {
+ ImmTy { imm, layout }
+ }
+
#[inline]
pub fn try_from_uint(i: impl Into<u128>, layout: TyAndLayout<'tcx>) -> Option<Self> {
Some(Self::from_scalar(Scalar::try_from_uint(i, layout.size)?, layout))
Ok(OpTy { op, layout })
}
- /// Every place can be read from, so we can turn them into an operand
+ /// Every place can be read from, so we can turn them into an operand.
+ /// This will definitely return `Indirect` if the place is a `Ptr`, i.e., this
+ /// will never actually read from memory.
#[inline(always)]
pub fn place_to_op(
&self,
Operand::Immediate(_) if self.layout.is_zst() => {
Ok(MPlaceTy::dangling(self.layout, cx))
}
- Operand::Immediate(imm) => Err(ImmTy { imm, layout: self.layout }),
+ Operand::Immediate(imm) => Err(ImmTy::from_immediate(imm, self.layout)),
}
}
let this_receiver_ptr = self.layout_of(receiver_ptr_ty)?.field(self, 0)?;
// Adjust receiver argument.
args[0] =
- OpTy::from(ImmTy { layout: this_receiver_ptr, imm: receiver_place.ptr.into() });
+ OpTy::from(ImmTy::from_immediate(receiver_place.ptr.into(), this_receiver_ptr));
trace!("Patched self operand to {:#?}", args[0]);
// recurse with concrete function
self.eval_fn_call(drop_fn, caller_abi, &args, ret, unwind)
_ => (instance, place),
};
- let arg = ImmTy {
- imm: place.to_ref(),
- layout: self.layout_of(self.tcx.mk_mut_ptr(place.layout.ty))?,
- };
+ let arg = ImmTy::from_immediate(
+ place.to_ref(),
+ self.layout_of(self.tcx.mk_mut_ptr(place.layout.ty))?,
+ );
let ty = self.tcx.mk_unit(); // return type is ()
let dest = MPlaceTy::dangling(self.layout_of(ty)?, self);