Add unsigned integers.
This commit is contained in:
parent
9e1bb9841e
commit
9d1d96ce07
3 changed files with 118 additions and 43 deletions
|
@ -210,7 +210,7 @@ impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> {
|
|||
_ => panic!("attmpted to switch on non-sum type"),
|
||||
};
|
||||
let discr_val = try!(self.memory.read_primval(adt_ptr, &discr_repr));
|
||||
TerminatorTarget::Block(targets[discr_val.to_int() as usize])
|
||||
TerminatorTarget::Block(targets[discr_val.to_usize()])
|
||||
}
|
||||
|
||||
Call { ref func, ref args, ref destination, .. } => {
|
||||
|
@ -298,7 +298,7 @@ impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> {
|
|||
ty::AdtKind::Enum => match dest_repr {
|
||||
Repr::Sum { ref discr, ref variants, .. } => {
|
||||
if discr.size() > 0 {
|
||||
let discr_val = PrimVal::from_int(variant_idx as i64, discr);
|
||||
let discr_val = PrimVal::from_usize(variant_idx, discr);
|
||||
try!(self.memory.write_primval(dest, discr_val));
|
||||
}
|
||||
self.assign_to_product(
|
||||
|
@ -442,12 +442,18 @@ impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> {
|
|||
match ty.subst(self.tcx, self.current_substs()).sty {
|
||||
ty::TyBool => Repr::Bool,
|
||||
|
||||
ty::TyInt(IntTy::Is) => unimplemented!(),
|
||||
ty::TyInt(IntTy::I8) => Repr::I8,
|
||||
ty::TyInt(IntTy::Is) => Repr::isize(),
|
||||
ty::TyInt(IntTy::I8) => Repr::I8,
|
||||
ty::TyInt(IntTy::I16) => Repr::I16,
|
||||
ty::TyInt(IntTy::I32) => Repr::I32,
|
||||
ty::TyInt(IntTy::I64) => Repr::I64,
|
||||
|
||||
ty::TyUint(UintTy::Us) => Repr::usize(),
|
||||
ty::TyUint(UintTy::U8) => Repr::U8,
|
||||
ty::TyUint(UintTy::U16) => Repr::U16,
|
||||
ty::TyUint(UintTy::U32) => Repr::U32,
|
||||
ty::TyUint(UintTy::U64) => Repr::U64,
|
||||
|
||||
ty::TyTuple(ref fields) => self.make_product_repr(fields.iter().cloned()),
|
||||
|
||||
ty::TyEnum(adt_def, substs) => {
|
||||
|
@ -456,13 +462,13 @@ impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> {
|
|||
let discr = if num_variants <= 1 {
|
||||
Repr::Product { size: 0, fields: vec![] }
|
||||
} else if num_variants <= 1 << 8 {
|
||||
Repr::I8
|
||||
Repr::U8
|
||||
} else if num_variants <= 1 << 16 {
|
||||
Repr::I16
|
||||
Repr::U16
|
||||
} else if num_variants <= 1 << 32 {
|
||||
Repr::I32
|
||||
Repr::U32
|
||||
} else {
|
||||
Repr::I64
|
||||
Repr::U64
|
||||
};
|
||||
|
||||
let variants: Vec<Repr> = adt_def.variants.iter().map(|v| {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use byteorder::{self, ByteOrder};
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::collections::Bound::{Included, Excluded};
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
||||
use error::{EvalError, EvalResult};
|
||||
|
@ -38,10 +39,8 @@ pub struct FieldRepr {
|
|||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Repr {
|
||||
Bool,
|
||||
I8,
|
||||
I16,
|
||||
I32,
|
||||
I64,
|
||||
I8, I16, I32, I64,
|
||||
U8, U16, U32, U64,
|
||||
|
||||
/// The representation for product types including tuples, structs, and the contents of enum
|
||||
/// variants.
|
||||
|
@ -170,10 +169,14 @@ impl Memory {
|
|||
pub fn read_primval(&self, ptr: Pointer, repr: &Repr) -> EvalResult<PrimVal> {
|
||||
match *repr {
|
||||
Repr::Bool => self.read_bool(ptr).map(PrimVal::Bool),
|
||||
Repr::I8 => self.read_i8(ptr).map(PrimVal::I8),
|
||||
Repr::I16 => self.read_i16(ptr).map(PrimVal::I16),
|
||||
Repr::I32 => self.read_i32(ptr).map(PrimVal::I32),
|
||||
Repr::I64 => self.read_i64(ptr).map(PrimVal::I64),
|
||||
Repr::I8 => self.read_i8(ptr).map(PrimVal::I8),
|
||||
Repr::I16 => self.read_i16(ptr).map(PrimVal::I16),
|
||||
Repr::I32 => self.read_i32(ptr).map(PrimVal::I32),
|
||||
Repr::I64 => self.read_i64(ptr).map(PrimVal::I64),
|
||||
Repr::U8 => self.read_u8(ptr).map(PrimVal::U8),
|
||||
Repr::U16 => self.read_u16(ptr).map(PrimVal::U16),
|
||||
Repr::U32 => self.read_u32(ptr).map(PrimVal::U32),
|
||||
Repr::U64 => self.read_u64(ptr).map(PrimVal::U64),
|
||||
_ => panic!("primitive read of non-primitive: {:?}", repr),
|
||||
}
|
||||
}
|
||||
|
@ -181,10 +184,14 @@ impl Memory {
|
|||
pub fn write_primval(&mut self, ptr: Pointer, val: PrimVal) -> EvalResult<()> {
|
||||
match val {
|
||||
PrimVal::Bool(b) => self.write_bool(ptr, b),
|
||||
PrimVal::I8(n) => self.write_i8(ptr, n),
|
||||
PrimVal::I16(n) => self.write_i16(ptr, n),
|
||||
PrimVal::I32(n) => self.write_i32(ptr, n),
|
||||
PrimVal::I64(n) => self.write_i64(ptr, n),
|
||||
PrimVal::I8(n) => self.write_i8(ptr, n),
|
||||
PrimVal::I16(n) => self.write_i16(ptr, n),
|
||||
PrimVal::I32(n) => self.write_i32(ptr, n),
|
||||
PrimVal::I64(n) => self.write_i64(ptr, n),
|
||||
PrimVal::U8(n) => self.write_u8(ptr, n),
|
||||
PrimVal::U16(n) => self.write_u16(ptr, n),
|
||||
PrimVal::U32(n) => self.write_u32(ptr, n),
|
||||
PrimVal::U64(n) => self.write_u64(ptr, n),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,6 +247,44 @@ impl Memory {
|
|||
byteorder::NativeEndian::write_i64(bytes, n);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_u8(&self, ptr: Pointer) -> EvalResult<u8> {
|
||||
self.get_bytes(ptr, 1).map(|b| b[0] as u8)
|
||||
}
|
||||
|
||||
pub fn write_u8(&mut self, ptr: Pointer, n: u8) -> EvalResult<()> {
|
||||
self.get_bytes_mut(ptr, 1).map(|b| b[0] = n as u8)
|
||||
}
|
||||
|
||||
pub fn read_u16(&self, ptr: Pointer) -> EvalResult<u16> {
|
||||
self.get_bytes(ptr, 2).map(byteorder::NativeEndian::read_u16)
|
||||
}
|
||||
|
||||
pub fn write_u16(&mut self, ptr: Pointer, n: u16) -> EvalResult<()> {
|
||||
let bytes = try!(self.get_bytes_mut(ptr, 2));
|
||||
byteorder::NativeEndian::write_u16(bytes, n);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_u32(&self, ptr: Pointer) -> EvalResult<u32> {
|
||||
self.get_bytes(ptr, 4).map(byteorder::NativeEndian::read_u32)
|
||||
}
|
||||
|
||||
pub fn write_u32(&mut self, ptr: Pointer, n: u32) -> EvalResult<()> {
|
||||
let bytes = try!(self.get_bytes_mut(ptr, 4));
|
||||
byteorder::NativeEndian::write_u32(bytes, n);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_u64(&self, ptr: Pointer) -> EvalResult<u64> {
|
||||
self.get_bytes(ptr, 8).map(byteorder::NativeEndian::read_u64)
|
||||
}
|
||||
|
||||
pub fn write_u64(&mut self, ptr: Pointer, n: u64) -> EvalResult<()> {
|
||||
let bytes = try!(self.get_bytes_mut(ptr, 8));
|
||||
byteorder::NativeEndian::write_u64(bytes, n);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Allocation {
|
||||
|
@ -287,13 +332,31 @@ impl Pointer {
|
|||
}
|
||||
|
||||
impl Repr {
|
||||
// TODO(tsion): Choice is based on host machine's type size. Should this be how miri works?
|
||||
pub fn isize() -> Self {
|
||||
match mem::size_of::<isize>() {
|
||||
4 => Repr::I32,
|
||||
8 => Repr::I64,
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(tsion): Choice is based on host machine's type size. Should this be how miri works?
|
||||
pub fn usize() -> Self {
|
||||
match mem::size_of::<isize>() {
|
||||
4 => Repr::U32,
|
||||
8 => Repr::U64,
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn size(&self) -> usize {
|
||||
match *self {
|
||||
Repr::Bool => 1,
|
||||
Repr::I8 => 1,
|
||||
Repr::I16 => 2,
|
||||
Repr::I32 => 4,
|
||||
Repr::I64 => 8,
|
||||
Repr::I8 | Repr::U8 => 1,
|
||||
Repr::I16 | Repr::U16 => 2,
|
||||
Repr::I32 | Repr::U32 => 4,
|
||||
Repr::I64 | Repr::U64 => 8,
|
||||
Repr::Product { size, .. } => size,
|
||||
Repr::Sum { ref discr, max_variant_size, .. } => discr.size() + max_variant_size,
|
||||
Repr::Pointer { .. } => POINTER_SIZE,
|
||||
|
|
|
@ -5,31 +5,29 @@ use memory::Repr;
|
|||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum PrimVal {
|
||||
Bool(bool),
|
||||
I8(i8),
|
||||
I16(i16),
|
||||
I32(i32),
|
||||
I64(i64),
|
||||
I8(i8), I16(i16), I32(i32), I64(i64),
|
||||
U8(u8), U16(u16), U32(u32), U64(u64),
|
||||
}
|
||||
|
||||
impl PrimVal {
|
||||
pub fn from_int(n: i64, repr: &Repr) -> Self {
|
||||
pub fn from_usize(n: usize, repr: &Repr) -> Self {
|
||||
// TODO(tsion): Use checked casts.
|
||||
match *repr {
|
||||
Repr::I8 => PrimVal::I8(n as i8),
|
||||
Repr::I16 => PrimVal::I16(n as i16),
|
||||
Repr::I32 => PrimVal::I32(n as i32),
|
||||
Repr::I64 => PrimVal::I64(n),
|
||||
_ => panic!("attempted to make integer primval from non-integer repr"),
|
||||
Repr::U8 => PrimVal::U8(n as u8),
|
||||
Repr::U16 => PrimVal::U16(n as u16),
|
||||
Repr::U32 => PrimVal::U32(n as u32),
|
||||
Repr::U64 => PrimVal::U64(n as u64),
|
||||
_ => panic!("attempted to make usize primval from non-uint repr"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_int(self) -> i64 {
|
||||
pub fn to_usize(self) -> usize {
|
||||
match self {
|
||||
PrimVal::I8(n) => n as i64,
|
||||
PrimVal::I16(n) => n as i64,
|
||||
PrimVal::I32(n) => n as i64,
|
||||
PrimVal::I64(n) => n,
|
||||
_ => panic!("attempted to make integer from non-integer primval"),
|
||||
PrimVal::U8(n) => n as usize,
|
||||
PrimVal::U16(n) => n as usize,
|
||||
PrimVal::U32(n) => n as usize,
|
||||
PrimVal::U64(n) => n as usize,
|
||||
_ => panic!("attempted to make usize from non-uint primval"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,10 +63,14 @@ pub fn binary_op(bin_op: mir::BinOp, left: PrimVal, right: PrimVal) -> PrimVal {
|
|||
|
||||
use self::PrimVal::*;
|
||||
match (left, right) {
|
||||
(I8(l), I8(r)) => int_binops!(I8, l, r),
|
||||
(I8(l), I8(r)) => int_binops!(I8, l, r),
|
||||
(I16(l), I16(r)) => int_binops!(I16, l, r),
|
||||
(I32(l), I32(r)) => int_binops!(I32, l, r),
|
||||
(I64(l), I64(r)) => int_binops!(I64, l, r),
|
||||
(U8(l), U8(r)) => int_binops!(U8, l, r),
|
||||
(U16(l), U16(r)) => int_binops!(U16, l, r),
|
||||
(U32(l), U32(r)) => int_binops!(U32, l, r),
|
||||
(U64(l), U64(r)) => int_binops!(U64, l, r),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
@ -78,14 +80,18 @@ pub fn unary_op(un_op: mir::UnOp, val: PrimVal) -> PrimVal {
|
|||
use self::PrimVal::*;
|
||||
match (un_op, val) {
|
||||
(Not, Bool(b)) => Bool(!b),
|
||||
(Not, I8(n)) => I8(!n),
|
||||
(Neg, I8(n)) => I8(-n),
|
||||
(Not, I8(n)) => I8(!n),
|
||||
(Neg, I8(n)) => I8(-n),
|
||||
(Not, I16(n)) => I16(!n),
|
||||
(Neg, I16(n)) => I16(-n),
|
||||
(Not, I32(n)) => I32(!n),
|
||||
(Neg, I32(n)) => I32(-n),
|
||||
(Not, I64(n)) => I64(!n),
|
||||
(Neg, I64(n)) => I64(-n),
|
||||
(Not, U8(n)) => U8(!n),
|
||||
(Not, U16(n)) => U16(!n),
|
||||
(Not, U32(n)) => U32(!n),
|
||||
(Not, U64(n)) => U64(!n),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue