Add support for smaller signed integers.
This commit is contained in:
parent
c1edb9f978
commit
6b4d2b11a6
4 changed files with 80 additions and 60 deletions
|
@ -6,6 +6,7 @@ use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use memory::{FieldRepr, IntRepr, Memory, Pointer, Repr};
|
use memory::{FieldRepr, IntRepr, Memory, Pointer, Repr};
|
||||||
|
use primval;
|
||||||
|
|
||||||
const TRACE_EXECUTION: bool = true;
|
const TRACE_EXECUTION: bool = true;
|
||||||
|
|
||||||
|
@ -77,15 +78,6 @@ struct Interpreter<'a, 'tcx: 'a> {
|
||||||
stack: Vec<Frame<'a, 'tcx>>,
|
stack: Vec<Frame<'a, 'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
||||||
pub enum PrimVal {
|
|
||||||
Bool(bool),
|
|
||||||
I8(i8),
|
|
||||||
I16(i16),
|
|
||||||
I32(i32),
|
|
||||||
I64(i64),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> {
|
impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> {
|
||||||
fn new(tcx: &'a TyCtxt<'tcx>, mir_map: &'a MirMap<'tcx>) -> Self {
|
fn new(tcx: &'a TyCtxt<'tcx>, mir_map: &'a MirMap<'tcx>) -> Self {
|
||||||
Interpreter {
|
Interpreter {
|
||||||
|
@ -236,41 +228,6 @@ impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_binary_op(&mut self, bin_op: mir::BinOp, left_operand: &mir::Operand<'tcx>,
|
|
||||||
right_operand: &mir::Operand<'tcx>, dest: Pointer) -> EvalResult<()>
|
|
||||||
{
|
|
||||||
// FIXME(tsion): Check for non-integer binary operations.
|
|
||||||
let (left, left_repr) = try!(self.eval_operand(left_operand));
|
|
||||||
let (right, right_repr) = try!(self.eval_operand(right_operand));
|
|
||||||
|
|
||||||
let left_val = try!(self.memory.read_primval(left, &left_repr));
|
|
||||||
let right_val = try!(self.memory.read_primval(right, &right_repr));
|
|
||||||
|
|
||||||
use rustc::mir::repr::BinOp::*;
|
|
||||||
use self::PrimVal::*;
|
|
||||||
let result_val = match (bin_op, left_val, right_val) {
|
|
||||||
(Add, I64(l), I64(r)) => I64(l + r),
|
|
||||||
(Sub, I64(l), I64(r)) => I64(l - r),
|
|
||||||
(Mul, I64(l), I64(r)) => I64(l * r),
|
|
||||||
(Div, I64(l), I64(r)) => I64(l / r),
|
|
||||||
(Rem, I64(l), I64(r)) => I64(l % r),
|
|
||||||
(BitXor, I64(l), I64(r)) => I64(l ^ r),
|
|
||||||
(BitAnd, I64(l), I64(r)) => I64(l & r),
|
|
||||||
(BitOr, I64(l), I64(r)) => I64(l | r),
|
|
||||||
(Shl, I64(l), I64(r)) => I64(l << r),
|
|
||||||
(Shr, I64(l), I64(r)) => I64(l >> r),
|
|
||||||
(Eq, I64(l), I64(r)) => Bool(l == r),
|
|
||||||
(Lt, I64(l), I64(r)) => Bool(l < r),
|
|
||||||
(Le, I64(l), I64(r)) => Bool(l <= r),
|
|
||||||
(Ne, I64(l), I64(r)) => Bool(l != r),
|
|
||||||
(Ge, I64(l), I64(r)) => Bool(l >= r),
|
|
||||||
(Gt, I64(l), I64(r)) => Bool(l > r),
|
|
||||||
_ => unimplemented!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
self.memory.write_primval(dest, result_val)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assign_to_product(&mut self, dest: Pointer, dest_repr: &Repr,
|
fn assign_to_product(&mut self, dest: Pointer, dest_repr: &Repr,
|
||||||
operands: &[mir::Operand<'tcx>]) -> EvalResult<()> {
|
operands: &[mir::Operand<'tcx>]) -> EvalResult<()> {
|
||||||
match *dest_repr {
|
match *dest_repr {
|
||||||
|
@ -297,23 +254,18 @@ impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> {
|
||||||
self.memory.copy(src, dest, dest_repr.size())
|
self.memory.copy(src, dest, dest_repr.size())
|
||||||
}
|
}
|
||||||
|
|
||||||
BinaryOp(bin_op, ref left, ref right) =>
|
BinaryOp(bin_op, ref left, ref right) => {
|
||||||
self.eval_binary_op(bin_op, left, right, dest),
|
let (left_ptr, left_repr) = try!(self.eval_operand(left));
|
||||||
|
let (right_ptr, right_repr) = try!(self.eval_operand(right));
|
||||||
|
let left_val = try!(self.memory.read_primval(left_ptr, &left_repr));
|
||||||
|
let right_val = try!(self.memory.read_primval(right_ptr, &right_repr));
|
||||||
|
self.memory.write_primval(dest, primval::binary_op(bin_op, left_val, right_val))
|
||||||
|
}
|
||||||
|
|
||||||
UnaryOp(un_op, ref operand) => {
|
UnaryOp(un_op, ref operand) => {
|
||||||
let (src, src_repr) = try!(self.eval_operand(operand));
|
let (ptr, repr) = try!(self.eval_operand(operand));
|
||||||
let src_val = try!(self.memory.read_primval(src, &src_repr));
|
let val = try!(self.memory.read_primval(ptr, &repr));
|
||||||
|
self.memory.write_primval(dest, primval::unary_op(un_op, val))
|
||||||
use rustc::mir::repr::UnOp::*;
|
|
||||||
use self::PrimVal::*;
|
|
||||||
let result_val = match (un_op, src_val) {
|
|
||||||
(Not, Bool(b)) => Bool(!b),
|
|
||||||
(Not, I64(n)) => I64(!n),
|
|
||||||
(Neg, I64(n)) => I64(-n),
|
|
||||||
_ => unimplemented!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
self.memory.write_primval(dest, result_val)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Aggregate(ref kind, ref operands) => {
|
Aggregate(ref kind, ref operands) => {
|
||||||
|
|
|
@ -7,3 +7,4 @@ extern crate syntax;
|
||||||
|
|
||||||
pub mod interpreter;
|
pub mod interpreter;
|
||||||
mod memory;
|
mod memory;
|
||||||
|
mod primval;
|
||||||
|
|
|
@ -2,7 +2,8 @@ use byteorder::{self, ByteOrder};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
use interpreter::{EvalError, EvalResult, PrimVal};
|
use interpreter::{EvalError, EvalResult};
|
||||||
|
use primval::PrimVal;
|
||||||
|
|
||||||
pub struct Memory {
|
pub struct Memory {
|
||||||
next_id: u64,
|
next_id: u64,
|
||||||
|
|
66
src/primval.rs
Normal file
66
src/primval.rs
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
use rustc::mir::repr as mir;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
pub enum PrimVal {
|
||||||
|
Bool(bool),
|
||||||
|
I8(i8),
|
||||||
|
I16(i16),
|
||||||
|
I32(i32),
|
||||||
|
I64(i64),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn binary_op(bin_op: mir::BinOp, left: PrimVal, right: PrimVal) -> PrimVal {
|
||||||
|
macro_rules! int_binops {
|
||||||
|
($v:ident, $l:ident, $r:ident) => ({
|
||||||
|
use rustc::mir::repr::BinOp::*;
|
||||||
|
use self::PrimVal::*;
|
||||||
|
match bin_op {
|
||||||
|
Add => $v($l + $r),
|
||||||
|
Sub => $v($l - $r),
|
||||||
|
Mul => $v($l * $r),
|
||||||
|
Div => $v($l / $r),
|
||||||
|
Rem => $v($l % $r),
|
||||||
|
BitXor => $v($l ^ $r),
|
||||||
|
BitAnd => $v($l & $r),
|
||||||
|
BitOr => $v($l | $r),
|
||||||
|
|
||||||
|
// TODO(tsion): Can have differently-typed RHS.
|
||||||
|
Shl => $v($l << $r),
|
||||||
|
Shr => $v($l >> $r),
|
||||||
|
|
||||||
|
Eq => Bool($l == $r),
|
||||||
|
Ne => Bool($l != $r),
|
||||||
|
Lt => Bool($l < $r),
|
||||||
|
Le => Bool($l <= $r),
|
||||||
|
Gt => Bool($l > $r),
|
||||||
|
Ge => Bool($l >= $r),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
use self::PrimVal::*;
|
||||||
|
match (left, right) {
|
||||||
|
(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),
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unary_op(un_op: mir::UnOp, val: PrimVal) -> PrimVal {
|
||||||
|
use rustc::mir::repr::UnOp::*;
|
||||||
|
use self::PrimVal::*;
|
||||||
|
match (un_op, val) {
|
||||||
|
(Not, Bool(b)) => Bool(!b),
|
||||||
|
(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),
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue