Instruction generation and implementation for shift and bitwise operators.
This commit is contained in:
parent
7e72037d9e
commit
fa13697596
@ -67,11 +67,31 @@ impl IrBinaryOperation {
|
||||
self.right.subtract_operand(),
|
||||
destination,
|
||||
),
|
||||
IrBinaryOperator::LeftShift => todo!(),
|
||||
IrBinaryOperator::RightShift => todo!(),
|
||||
IrBinaryOperator::BitwiseAnd => todo!(),
|
||||
IrBinaryOperator::BitwiseXor => todo!(),
|
||||
IrBinaryOperator::BitwiseOr => todo!(),
|
||||
IrBinaryOperator::LeftShift => Instruction::LeftShift(
|
||||
self.left.as_location_or_integer(),
|
||||
self.right.as_location_or_integer(),
|
||||
destination,
|
||||
),
|
||||
IrBinaryOperator::RightShift => Instruction::RightShift(
|
||||
self.left.as_location_or_integer(),
|
||||
self.right.as_location_or_integer(),
|
||||
destination,
|
||||
),
|
||||
IrBinaryOperator::BitwiseAnd => Instruction::BitwiseAnd(
|
||||
self.left.as_location_or_integer(),
|
||||
self.right.as_location_or_integer(),
|
||||
destination,
|
||||
),
|
||||
IrBinaryOperator::BitwiseXor => Instruction::BitwiseXor(
|
||||
self.left.as_location_or_integer(),
|
||||
self.right.as_location_or_integer(),
|
||||
destination,
|
||||
),
|
||||
IrBinaryOperator::BitwiseOr => Instruction::BitwiseOr(
|
||||
self.left.as_location_or_integer(),
|
||||
self.right.as_location_or_integer(),
|
||||
destination,
|
||||
),
|
||||
};
|
||||
builder.push(instruction);
|
||||
}
|
||||
|
||||
@ -4,8 +4,8 @@ use crate::ir::ir_variable::{IrVariable, IrVariableDescriptor, IrVrVariableDescr
|
||||
use crate::ir::register_allocation::VrUser;
|
||||
use crate::type_info::TypeInfo;
|
||||
use dvm_lib::instruction::{
|
||||
AddOperand, Location, LocationOrNumber, MoveOperand, MultiplyOperand, PushOperand,
|
||||
ReturnOperand, SetFieldOperand, SubtractOperand,
|
||||
AddOperand, Location, LocationOrInteger, LocationOrNumber, MoveOperand, MultiplyOperand,
|
||||
PushOperand, ReturnOperand, SetFieldOperand, SubtractOperand,
|
||||
};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashSet;
|
||||
@ -218,6 +218,19 @@ impl IrExpression {
|
||||
_ => panic!("Attempt to convert {} to a location or number", self),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_location_or_integer(&self) -> LocationOrInteger {
|
||||
match self {
|
||||
IrExpression::Parameter(ir_parameter) => {
|
||||
LocationOrInteger::Location(ir_parameter.as_location())
|
||||
}
|
||||
IrExpression::Variable(ir_variable) => {
|
||||
LocationOrInteger::Location(ir_variable.borrow().descriptor().as_location())
|
||||
}
|
||||
IrExpression::Int(i) => LocationOrInteger::Int(*i),
|
||||
_ => panic!("Attempt to convert {} to a location or integer", self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for IrExpression {
|
||||
|
||||
@ -38,6 +38,13 @@ pub enum Instruction {
|
||||
Add(AddOperand, AddOperand, Location),
|
||||
Subtract(SubtractOperand, SubtractOperand, Location),
|
||||
|
||||
LeftShift(LocationOrInteger, LocationOrInteger, Location),
|
||||
RightShift(LocationOrInteger, LocationOrInteger, Location),
|
||||
|
||||
BitwiseAnd(LocationOrInteger, LocationOrInteger, Location),
|
||||
BitwiseXor(LocationOrInteger, LocationOrInteger, Location),
|
||||
BitwiseOr(LocationOrInteger, LocationOrInteger, Location),
|
||||
|
||||
Pop(Option<Location>),
|
||||
|
||||
SetReturnValue(ReturnOperand),
|
||||
@ -86,6 +93,23 @@ impl Display for Instruction {
|
||||
write!(f, "sub {}, {}, {}", left, right, destination)
|
||||
}
|
||||
|
||||
Instruction::LeftShift(left, right, destination) => {
|
||||
write!(f, "shl {}, {}, {}", left, right, destination)
|
||||
}
|
||||
Instruction::RightShift(left, right, destination) => {
|
||||
write!(f, "shr {}, {}, {}", left, right, destination)
|
||||
}
|
||||
|
||||
Instruction::BitwiseAnd(left, right, destination) => {
|
||||
write!(f, "and {}, {}, {}", left, right, destination)
|
||||
}
|
||||
Instruction::BitwiseXor(left, right, destination) => {
|
||||
write!(f, "xor {}, {}, {}", left, right, destination)
|
||||
}
|
||||
Instruction::BitwiseOr(left, right, destination) => {
|
||||
write!(f, "or {}, {}, {}", left, right, destination)
|
||||
}
|
||||
|
||||
Instruction::SetReturnValue(source) => {
|
||||
write!(f, "srv {}", source)
|
||||
}
|
||||
@ -164,6 +188,24 @@ impl Display for LocationOrNumber {
|
||||
}
|
||||
}
|
||||
|
||||
pub enum LocationOrInteger {
|
||||
Location(Location),
|
||||
Int(i32),
|
||||
}
|
||||
|
||||
impl Display for LocationOrInteger {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
LocationOrInteger::Location(location) => {
|
||||
write!(f, "{}", location)
|
||||
}
|
||||
LocationOrInteger::Int(i) => {
|
||||
write!(f, "{}", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MoveOperand {
|
||||
Location(Location),
|
||||
Int(i32),
|
||||
|
||||
@ -6,9 +6,9 @@ use crate::vm::function::Function;
|
||||
use crate::vm::object::get_object;
|
||||
use crate::vm::operand::Operand;
|
||||
use crate::vm::operand_helpers::{
|
||||
add_operand_to_value, location_or_number_to_value, move_operand_to_value,
|
||||
multiply_operand_to_value, push_operand_to_value, return_operand_to_value,
|
||||
set_field_operand_to_value, subtract_operand_to_value,
|
||||
add_operand_to_value, location_or_integer_to_value, location_or_number_to_value,
|
||||
move_operand_to_value, multiply_operand_to_value, push_operand_to_value,
|
||||
return_operand_to_value, set_field_operand_to_value, subtract_operand_to_value,
|
||||
};
|
||||
use crate::vm::util::*;
|
||||
use crate::vm::value::Value;
|
||||
@ -560,6 +560,91 @@ pub fn call<'a>(
|
||||
call_stack.top_mut().increment_ip();
|
||||
}
|
||||
|
||||
/* Shift instructions */
|
||||
Instruction::LeftShift(left, right, destination) => {
|
||||
let left_value = location_or_integer_to_value(left, registers, call_stack.top());
|
||||
let right_value = location_or_integer_to_value(right, registers, call_stack.top());
|
||||
|
||||
let result = match left_value {
|
||||
Value::Int(li) => match right_value {
|
||||
Value::Int(ri) => Value::Int(li << ri),
|
||||
_ => panic!("Attempt to left shift {} by {}", left, right),
|
||||
},
|
||||
_ => panic!("Attempt to left shift {} by {}", left_value, right_value),
|
||||
};
|
||||
|
||||
put_value(registers, call_stack.top_mut(), destination, result);
|
||||
call_stack.top_mut().increment_ip();
|
||||
}
|
||||
Instruction::RightShift(left, right, destination) => {
|
||||
let left_value = location_or_integer_to_value(left, registers, call_stack.top());
|
||||
let right_value = location_or_integer_to_value(right, registers, call_stack.top());
|
||||
|
||||
let result = match left_value {
|
||||
Value::Int(li) => match right_value {
|
||||
Value::Int(ri) => Value::Int(li >> ri),
|
||||
_ => panic!("Attempt to right shift {} by {}", left_value, right_value),
|
||||
},
|
||||
_ => panic!("Attempt to right shift {} by {}", left_value, right_value),
|
||||
};
|
||||
|
||||
put_value(registers, call_stack.top_mut(), destination, result);
|
||||
call_stack.top_mut().increment_ip();
|
||||
}
|
||||
|
||||
/* Bitwise instructions */
|
||||
Instruction::BitwiseAnd(left, right, destination) => {
|
||||
let left_value = location_or_integer_to_value(left, registers, call_stack.top());
|
||||
let right_value = location_or_integer_to_value(right, registers, call_stack.top());
|
||||
|
||||
let result = match left_value {
|
||||
Value::Int(li) => match right_value {
|
||||
Value::Int(ri) => Value::Int(li & ri),
|
||||
_ => panic!("Attempt to bitwise and {} by {}", left_value, right_value),
|
||||
},
|
||||
_ => panic!("Attempt to bitwise and {} by {}", left_value, right_value),
|
||||
};
|
||||
|
||||
put_value(registers, call_stack.top_mut(), destination, result);
|
||||
call_stack.top_mut().increment_ip();
|
||||
}
|
||||
Instruction::BitwiseXor(left, right, destination) => {
|
||||
let left_value = location_or_integer_to_value(left, registers, call_stack.top());
|
||||
let right_value = location_or_integer_to_value(right, registers, call_stack.top());
|
||||
|
||||
let result = match left_value {
|
||||
Value::Int(li) => match right_value {
|
||||
Value::Int(ri) => Value::Int(li ^ ri),
|
||||
_ => panic!("Attempt to bitwise xor {} by {}", left_value, right_value),
|
||||
},
|
||||
_ => panic!(
|
||||
"Attempt to left bitwise xor {} by {}",
|
||||
left_value, right_value
|
||||
),
|
||||
};
|
||||
|
||||
put_value(registers, call_stack.top_mut(), destination, result);
|
||||
call_stack.top_mut().increment_ip();
|
||||
}
|
||||
Instruction::BitwiseOr(left, right, destination) => {
|
||||
let left_value = location_or_integer_to_value(left, registers, call_stack.top());
|
||||
let right_value = location_or_integer_to_value(right, registers, call_stack.top());
|
||||
|
||||
let result = match left_value {
|
||||
Value::Int(li) => match right_value {
|
||||
Value::Int(ri) => Value::Int(li | ri),
|
||||
_ => panic!("Attempt to bitwise or {} by {}", left_value, right_value),
|
||||
},
|
||||
_ => panic!(
|
||||
"Attempt to left bitwise or {} by {}",
|
||||
left_value, right_value
|
||||
),
|
||||
};
|
||||
|
||||
put_value(registers, call_stack.top_mut(), destination, result);
|
||||
call_stack.top_mut().increment_ip();
|
||||
}
|
||||
|
||||
/* Pop instructions */
|
||||
Instruction::Pop(maybe_location) => {
|
||||
let value = call_stack.top_mut().stack_mut().pop().unwrap();
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use crate::instruction::{
|
||||
AddOperand, LocationOrNumber, MoveOperand, MultiplyOperand, PushOperand, ReturnOperand,
|
||||
SetFieldOperand, SubtractOperand,
|
||||
AddOperand, LocationOrInteger, LocationOrNumber, MoveOperand, MultiplyOperand, PushOperand,
|
||||
ReturnOperand, SetFieldOperand, SubtractOperand,
|
||||
};
|
||||
use crate::vm::CallFrame;
|
||||
use crate::vm::constant::Constant;
|
||||
@ -155,3 +155,19 @@ pub fn location_or_number_to_value(
|
||||
LocationOrNumber::Double(d) => Value::Double(*d),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn location_or_integer_to_value(
|
||||
location_or_integer: &LocationOrInteger,
|
||||
registers: &[Operand],
|
||||
current_frame: &CallFrame,
|
||||
) -> Value {
|
||||
match location_or_integer {
|
||||
LocationOrInteger::Location(location) => load_value(
|
||||
registers,
|
||||
current_frame.stack(),
|
||||
current_frame.fp(),
|
||||
location,
|
||||
),
|
||||
LocationOrInteger::Int(i) => Value::Int(*i),
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user