-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
+use std::cell::Cell;
use std::fmt::Write;
use std::mem;
pub(crate) stack: Vec<Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>>,
/// A cache for deduplicating vtables
- pub(super) vtables: FxHashMap<(Ty<'tcx>, ty::PolyExistentialTraitRef<'tcx>), AllocId>,
+ pub(super) vtables: FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), AllocId>,
}
/// A stack frame.
/// `None` represents a local that is currently dead, while a live local
/// can either directly contain `Scalar` or refer to some part of an `Allocation`.
pub locals: IndexVec<mir::Local, LocalValue<Tag>>,
+ pub local_layouts: IndexVec<mir::Local, Cell<Option<TyLayout<'tcx>>>>,
////////////////////////////////////////////////////////////////////////////////
// Current position within the function
self.frame().mir
}
- pub fn substs(&self) -> &'tcx Substs<'tcx> {
- if let Some(frame) = self.stack.last() {
- frame.instance.substs
- } else {
- Substs::empty()
+ pub(super) fn subst_and_normalize_erasing_regions<T: TypeFoldable<'tcx>>(
+ &self,
+ substs: T,
+ ) -> EvalResult<'tcx, T> {
+ match self.stack.last() {
+ Some(frame) => Ok(self.tcx.subst_and_normalize_erasing_regions(
+ frame.instance.substs,
+ self.param_env,
+ &substs,
+ )),
+ None => if substs.needs_subst() {
+ err!(TooGeneric).into()
+ } else {
+ Ok(substs)
+ },
}
}
substs: &'tcx Substs<'tcx>
) -> EvalResult<'tcx, ty::Instance<'tcx>> {
trace!("resolve: {:?}, {:#?}", def_id, substs);
- trace!("substs: {:#?}", self.substs());
trace!("param_env: {:#?}", self.param_env);
- let substs = self.tcx.subst_and_normalize_erasing_regions(
- self.substs(),
- self.param_env,
- &substs,
- );
+ let substs = self.subst_and_normalize_erasing_regions(substs)?;
+ trace!("substs: {:#?}", substs);
ty::Instance::resolve(
*self.tcx,
self.param_env,
}
}
+ pub fn monomorphize_in_frame<T: TypeFoldable<'tcx> + Subst<'tcx>>(
+ &self,
+ t: T,
+ ) -> EvalResult<'tcx, T> {
+ match self.stack.last() {
+ Some(frame) => Ok(self.monomorphize(t, frame.instance.substs)),
+ None => if t.needs_subst() {
+ err!(TooGeneric).into()
+ } else {
+ Ok(t)
+ },
+ }
+ }
+
pub fn monomorphize<T: TypeFoldable<'tcx> + Subst<'tcx>>(
&self,
t: T,
frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
local: mir::Local
) -> EvalResult<'tcx, TyLayout<'tcx>> {
- let local_ty = frame.mir.local_decls[local].ty;
- let local_ty = self.monomorphize(local_ty, frame.instance.substs);
- self.layout_of(local_ty)
+ let cell = &frame.local_layouts[local];
+ if cell.get().is_none() {
+ let local_ty = frame.mir.local_decls[local].ty;
+ let local_ty = self.monomorphize(local_ty, frame.instance.substs);
+ let layout = self.layout_of(local_ty)?;
+ cell.set(Some(layout));
+ }
+
+ Ok(cell.get().unwrap())
}
pub fn str_to_immediate(&mut self, s: &str) -> EvalResult<'tcx, Immediate<M::PointerTag>> {
// empty local array, we fill it in below, after we are inside the stack frame and
// all methods actually know about the frame
locals: IndexVec::new(),
+ local_layouts: IndexVec::from_elem_n(Default::default(), mir.local_decls.len()),
span,
instance,
stmt: 0,
},
}
// Finally, properly initialize all those that still have the dummy value
- for (local, decl) in locals.iter_mut().zip(mir.local_decls.iter()) {
+ for (idx, local) in locals.iter_enumerated_mut() {
match *local {
LocalValue::Live(_) => {
// This needs to be peoperly initialized.
- let layout = self.layout_of(self.monomorphize(decl.ty, instance.substs))?;
+ let layout = self.layout_of_local(self.frame(), idx)?;
*local = LocalValue::Live(self.uninit_operand(layout)?);
}
LocalValue::Dead => {