Pass thin self ptr to virtual calls.

This commit is contained in:
Scott Olson 2016-10-16 02:12:26 -06:00
parent 268bf9c185
commit c1b97f1440
3 changed files with 14 additions and 6 deletions

View File

@ -352,7 +352,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
}
}
ty::TyTrait(..) => {
let vtable = value.expect_vtable(&self.memory)?;
let (_, vtable) = value.expect_ptr_vtable_pair(&self.memory)?;
// the second entry in the vtable is the dynamic size of the object.
let size = self.memory.read_usize(vtable.offset(pointer_size as isize))?;
let align = self.memory.read_usize(vtable.offset(pointer_size as isize * 2))?;

View File

@ -452,7 +452,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
traits::VtableObject(ref data) => {
let idx = self.tcx.get_vtable_index_of_object_method(data, def_id);
if let Some(&mut(ref mut first_arg, ref mut first_ty)) = args.get_mut(0) {
let vtable = first_arg.expect_vtable(&self.memory)?;
let (self_ptr, vtable) = first_arg.expect_ptr_vtable_pair(&self.memory)?;
*first_arg = Value::ByVal(PrimVal::Ptr(self_ptr));
let idx = idx + 3;
let offset = idx * self.memory.pointer_size();
let fn_ptr = self.memory.read_ptr(vtable.offset(offset as isize))?;

View File

@ -29,12 +29,19 @@ impl<'a, 'tcx: 'a> Value {
}
}
pub(super) fn expect_vtable(&self, mem: &Memory<'a, 'tcx>) -> EvalResult<'tcx, Pointer> {
pub(super) fn expect_ptr_vtable_pair(
&self,
mem: &Memory<'a, 'tcx>
) -> EvalResult<'tcx, (Pointer, Pointer)> {
use self::Value::*;
match *self {
ByRef(ptr) => mem.read_ptr(ptr.offset(mem.pointer_size() as isize)),
ByValPair(_, PrimVal::Ptr(vtable)) => Ok(vtable),
_ => unimplemented!(),
ByRef(ptr) => {
let ptr = mem.read_ptr(ptr)?;
let vtable = mem.read_ptr(ptr.offset(mem.pointer_size() as isize))?;
Ok((ptr, vtable))
}
ByValPair(PrimVal::Ptr(ptr), PrimVal::Ptr(vtable)) => Ok((ptr, vtable)),
_ => bug!("expected ptr and vtable, got {:?}", self),
}
}