Skip to content

Commit

Permalink
Implement Unary minus/plus
Browse files Browse the repository at this point in the history
  • Loading branch information
evilpie committed Oct 17, 2020
1 parent 023bf6c commit 80d168c
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 1 deletion.
32 changes: 31 additions & 1 deletion jit/src/instructions.rs
@@ -1,7 +1,7 @@
use cranelift::prelude::*;
use num_traits::cast::ToPrimitive;
use rustpython_bytecode::bytecode::{
BinaryOperator, CodeObject, ComparisonOperator, Constant, Instruction, Label, NameScope,
UnaryOperator, BinaryOperator, CodeObject, ComparisonOperator, Constant, Instruction, Label, NameScope,
};
use std::collections::HashMap;

Expand Down Expand Up @@ -233,6 +233,36 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
_ => Err(JitCompileError::NotSupported),
}
}
Instruction::UnaryOperation { op, .. } => {
let a = self.stack.pop().ok_or(JitCompileError::BadBytecode)?;

match a.ty {
JitType::Int => match op {
UnaryOperator::Minus => {
// Compile minus as 0 - a.
let zero = self.builder.ins().iconst(types::I64, 0);
let (out, carry) = self.builder.ins().isub_ifbout(zero, a.val);
self.builder.ins().trapif(
IntCC::Overflow,
carry,
TrapCode::IntegerOverflow,
);
self.stack.push(JitValue {
val: out,
ty: JitType::Int,
});
Ok(())
}
UnaryOperator::Plus => {
// Nothing to do
self.stack.push(a);
Ok(())
}
_ => Err(JitCompileError::NotSupported),
},
_ => Err(JitCompileError::NotSupported),
}
}
Instruction::BinaryOperation { op, .. } => {
// the rhs is popped off first
let b = self.stack.pop().ok_or(JitCompileError::BadBytecode)?;
Expand Down
28 changes: 28 additions & 0 deletions jit/tests/int_tests.rs
Expand Up @@ -54,3 +54,31 @@ fn test_gt() {
assert_eq!(gt(-1, -10), Ok(1));
assert_eq!(gt(1, -1), Ok(1));
}

#[test]
fn test_minus() {
let minus = jit_function! { minus(a:i64) -> i64 => r##"
def minus(a: int):
return -a
"## };

assert_eq!(minus(5), Ok(-5));
assert_eq!(minus(12), Ok(-12));
assert_eq!(minus(-7), Ok(7));
assert_eq!(minus(-3), Ok(3));
assert_eq!(minus(0), Ok(0));
}

#[test]
fn test_plus() {
let plus = jit_function! { plus(a:i64) -> i64 => r##"
def plus(a: int):
return +a
"## };

assert_eq!(plus(5), Ok(5));
assert_eq!(plus(12), Ok(12));
assert_eq!(plus(-7), Ok(-7));
assert_eq!(plus(-3), Ok(-3));
assert_eq!(plus(0), Ok(0));
}

0 comments on commit 80d168c

Please sign in to comment.