2016-03-13 01:43:28 -06:00
|
|
|
use rustc::mir::repr as mir;
|
|
|
|
|
2016-03-19 00:03:46 -05:00
|
|
|
use error::{EvalError, EvalResult};
|
|
|
|
use memory::Pointer;
|
|
|
|
|
2016-03-13 01:43:28 -06:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
|
|
pub enum PrimVal {
|
|
|
|
Bool(bool),
|
2016-03-15 00:03:31 -05:00
|
|
|
I8(i8), I16(i16), I32(i32), I64(i64),
|
|
|
|
U8(u8), U16(u16), U32(u32), U64(u64),
|
2016-03-19 00:03:46 -05:00
|
|
|
|
|
|
|
AbstractPtr(Pointer),
|
|
|
|
IntegerPtr(u64),
|
2016-03-13 01:43:28 -06:00
|
|
|
}
|
|
|
|
|
2016-03-19 00:03:46 -05:00
|
|
|
pub fn binary_op(bin_op: mir::BinOp, left: PrimVal, right: PrimVal) -> EvalResult<PrimVal> {
|
2016-04-23 01:39:38 -05:00
|
|
|
use rustc::mir::repr::BinOp::*;
|
|
|
|
use self::PrimVal::*;
|
|
|
|
|
2016-03-13 01:43:28 -06:00
|
|
|
macro_rules! int_binops {
|
|
|
|
($v:ident, $l:ident, $r:ident) => ({
|
|
|
|
match bin_op {
|
2016-03-19 00:03:46 -05:00
|
|
|
Add => $v($l + $r),
|
|
|
|
Sub => $v($l - $r),
|
|
|
|
Mul => $v($l * $r),
|
|
|
|
Div => $v($l / $r),
|
|
|
|
Rem => $v($l % $r),
|
2016-03-13 01:43:28 -06:00
|
|
|
BitXor => $v($l ^ $r),
|
|
|
|
BitAnd => $v($l & $r),
|
2016-03-19 00:03:46 -05:00
|
|
|
BitOr => $v($l | $r),
|
2016-03-13 01:43:28 -06:00
|
|
|
|
|
|
|
// 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),
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-03-19 00:03:46 -05:00
|
|
|
fn unrelated_ptr_ops(bin_op: mir::BinOp) -> EvalResult<PrimVal> {
|
|
|
|
use rustc::mir::repr::BinOp::*;
|
|
|
|
match bin_op {
|
|
|
|
Eq => Ok(Bool(false)),
|
|
|
|
Ne => Ok(Bool(true)),
|
|
|
|
Lt | Le | Gt | Ge => Err(EvalError::InvalidPointerMath),
|
|
|
|
_ => unimplemented!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let val = match (left, right) {
|
2016-03-15 00:03:31 -05:00
|
|
|
(I8(l), I8(r)) => int_binops!(I8, l, r),
|
2016-03-13 01:43:28 -06:00
|
|
|
(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),
|
2016-03-15 00:03:31 -05:00
|
|
|
(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),
|
2016-03-19 00:03:46 -05:00
|
|
|
|
2016-04-23 01:39:38 -05:00
|
|
|
(Bool(l), Bool(r)) => {
|
|
|
|
Bool(match bin_op {
|
|
|
|
Eq => l == r,
|
|
|
|
Ne => l != r,
|
|
|
|
Lt => l < r,
|
|
|
|
Le => l <= r,
|
|
|
|
Gt => l > r,
|
|
|
|
Ge => l >= r,
|
|
|
|
_ => panic!("invalid binary operation on booleans: {:?}", bin_op),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-03-19 00:03:46 -05:00
|
|
|
(IntegerPtr(l), IntegerPtr(r)) => int_binops!(IntegerPtr, l, r),
|
|
|
|
|
|
|
|
(AbstractPtr(_), IntegerPtr(_)) | (IntegerPtr(_), AbstractPtr(_)) =>
|
|
|
|
return unrelated_ptr_ops(bin_op),
|
|
|
|
|
|
|
|
(AbstractPtr(l_ptr), AbstractPtr(r_ptr)) => {
|
|
|
|
if l_ptr.alloc_id != r_ptr.alloc_id {
|
|
|
|
return unrelated_ptr_ops(bin_op);
|
|
|
|
}
|
|
|
|
|
|
|
|
let l = l_ptr.offset;
|
|
|
|
let r = r_ptr.offset;
|
|
|
|
|
|
|
|
match bin_op {
|
|
|
|
Eq => Bool(l == r),
|
|
|
|
Ne => Bool(l != r),
|
|
|
|
Lt => Bool(l < r),
|
|
|
|
Le => Bool(l <= r),
|
|
|
|
Gt => Bool(l > r),
|
|
|
|
Ge => Bool(l >= r),
|
|
|
|
_ => unimplemented!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-13 01:43:28 -06:00
|
|
|
_ => unimplemented!(),
|
2016-03-19 00:03:46 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
Ok(val)
|
2016-03-13 01:43:28 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
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),
|
2016-03-15 00:03:31 -05:00
|
|
|
(Not, I8(n)) => I8(!n),
|
|
|
|
(Neg, I8(n)) => I8(-n),
|
2016-03-13 01:43:28 -06:00
|
|
|
(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),
|
2016-03-15 00:03:31 -05:00
|
|
|
(Not, U8(n)) => U8(!n),
|
|
|
|
(Not, U16(n)) => U16(!n),
|
|
|
|
(Not, U32(n)) => U32(!n),
|
|
|
|
(Not, U64(n)) => U64(!n),
|
2016-03-13 01:43:28 -06:00
|
|
|
_ => unimplemented!(),
|
|
|
|
}
|
|
|
|
}
|