1
Fork 0

Implement pointer primvals and comparison ops on them.

This commit is contained in:
Scott Olson 2016-03-18 23:03:46 -06:00
parent 81f49ed1c0
commit dbc9913b7d
4 changed files with 116 additions and 44 deletions

View file

@ -16,9 +16,9 @@ use std::rc::Rc;
use syntax::ast;
use syntax::codemap::DUMMY_SP;
use error::EvalResult;
use error::{EvalError, EvalResult};
use memory::{self, FieldRepr, Memory, Pointer, Repr};
use primval;
use primval::{self, PrimVal};
const TRACE_EXECUTION: bool = true;
@ -404,19 +404,20 @@ impl<'a, 'tcx: 'a, 'arena> Interpreter<'a, 'tcx, 'arena> {
BinaryOp(bin_op, ref left, ref right) => {
let left_ptr = try!(self.eval_operand(left));
let left_ty = self.operand_ty(left);
let left_val = try!(self.memory.read_primval(left_ptr, left_ty));
let left_val = try!(self.read_primval(left_ptr, left_ty));
let right_ptr = try!(self.eval_operand(right));
let right_ty = self.operand_ty(right);
let right_val = try!(self.memory.read_primval(right_ptr, right_ty));
let right_val = try!(self.read_primval(right_ptr, right_ty));
self.memory.write_primval(dest, primval::binary_op(bin_op, left_val, right_val))
let val = try!(primval::binary_op(bin_op, left_val, right_val));
self.memory.write_primval(dest, val)
}
UnaryOp(un_op, ref operand) => {
let ptr = try!(self.eval_operand(operand));
let ty = self.operand_ty(operand);
let val = try!(self.memory.read_primval(ptr, ty));
let val = try!(self.read_primval(ptr, ty));
self.memory.write_primval(dest, primval::unary_op(un_op, val))
}
@ -627,6 +628,10 @@ impl<'a, 'tcx: 'a, 'arena> Interpreter<'a, 'tcx, 'arena> {
infer::normalize_associated_type(self.tcx, &substituted)
}
fn type_is_sized(&self, ty: ty::Ty<'tcx>) -> bool {
ty.is_sized(&self.tcx.empty_parameter_environment(), DUMMY_SP)
}
fn ty_size(&self, ty: ty::Ty<'tcx>) -> usize {
self.ty_to_repr(ty).size()
}
@ -671,7 +676,7 @@ impl<'a, 'tcx: 'a, 'arena> Interpreter<'a, 'tcx, 'arena> {
ty::TyRef(_, ty::TypeAndMut { ty, .. }) |
ty::TyRawPtr(ty::TypeAndMut { ty, .. }) |
ty::TyBox(ty) => {
if ty.is_sized(&self.tcx.empty_parameter_environment(), DUMMY_SP) {
if self.type_is_sized(ty) {
Repr::Primitive { size: self.memory.pointer_size }
} else {
Repr::Primitive { size: self.memory.pointer_size * 2 }
@ -725,6 +730,46 @@ impl<'a, 'tcx: 'a, 'arena> Interpreter<'a, 'tcx, 'arena> {
}
pub fn read_primval(&mut self, ptr: Pointer, ty: ty::Ty<'tcx>) -> EvalResult<PrimVal> {
use syntax::ast::{IntTy, UintTy};
let val = match ty.sty {
ty::TyBool => PrimVal::Bool(try!(self.memory.read_bool(ptr))),
ty::TyInt(IntTy::I8) => PrimVal::I8(try!(self.memory.read_int(ptr, 1)) as i8),
ty::TyInt(IntTy::I16) => PrimVal::I16(try!(self.memory.read_int(ptr, 2)) as i16),
ty::TyInt(IntTy::I32) => PrimVal::I32(try!(self.memory.read_int(ptr, 4)) as i32),
ty::TyInt(IntTy::I64) => PrimVal::I64(try!(self.memory.read_int(ptr, 8)) as i64),
ty::TyUint(UintTy::U8) => PrimVal::U8(try!(self.memory.read_uint(ptr, 1)) as u8),
ty::TyUint(UintTy::U16) => PrimVal::U16(try!(self.memory.read_uint(ptr, 2)) as u16),
ty::TyUint(UintTy::U32) => PrimVal::U32(try!(self.memory.read_uint(ptr, 4)) as u32),
ty::TyUint(UintTy::U64) => PrimVal::U64(try!(self.memory.read_uint(ptr, 8)) as u64),
// TODO(tsion): Pick the PrimVal dynamically.
ty::TyInt(IntTy::Is) =>
PrimVal::I64(try!(self.memory.read_int(ptr, self.memory.pointer_size))),
ty::TyUint(UintTy::Us) =>
PrimVal::U64(try!(self.memory.read_uint(ptr, self.memory.pointer_size))),
ty::TyRef(_, ty::TypeAndMut { ty, .. }) |
ty::TyRawPtr(ty::TypeAndMut { ty, .. }) => {
if self.type_is_sized(ty) {
match self.memory.read_ptr(ptr) {
Ok(p) => PrimVal::AbstractPtr(p),
Err(EvalError::ReadBytesAsPointer) => {
let n = try!(self.memory.read_uint(ptr, self.memory.pointer_size));
PrimVal::IntegerPtr(n)
}
Err(e) => return Err(e),
}
} else {
panic!("unimplemented: primitive read of fat pointer type: {:?}", ty);
}
}
_ => panic!("primitive read of non-primitive type: {:?}", ty),
};
Ok(val)
}
fn current_frame(&self) -> &Frame<'a, 'tcx> {
self.stack.last().expect("no call frames exist")
}