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(),
|
self.right.subtract_operand(),
|
||||||
destination,
|
destination,
|
||||||
),
|
),
|
||||||
IrBinaryOperator::LeftShift => todo!(),
|
IrBinaryOperator::LeftShift => Instruction::LeftShift(
|
||||||
IrBinaryOperator::RightShift => todo!(),
|
self.left.as_location_or_integer(),
|
||||||
IrBinaryOperator::BitwiseAnd => todo!(),
|
self.right.as_location_or_integer(),
|
||||||
IrBinaryOperator::BitwiseXor => todo!(),
|
destination,
|
||||||
IrBinaryOperator::BitwiseOr => todo!(),
|
),
|
||||||
|
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);
|
builder.push(instruction);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,8 +4,8 @@ use crate::ir::ir_variable::{IrVariable, IrVariableDescriptor, IrVrVariableDescr
|
|||||||
use crate::ir::register_allocation::VrUser;
|
use crate::ir::register_allocation::VrUser;
|
||||||
use crate::type_info::TypeInfo;
|
use crate::type_info::TypeInfo;
|
||||||
use dvm_lib::instruction::{
|
use dvm_lib::instruction::{
|
||||||
AddOperand, Location, LocationOrNumber, MoveOperand, MultiplyOperand, PushOperand,
|
AddOperand, Location, LocationOrInteger, LocationOrNumber, MoveOperand, MultiplyOperand,
|
||||||
ReturnOperand, SetFieldOperand, SubtractOperand,
|
PushOperand, ReturnOperand, SetFieldOperand, SubtractOperand,
|
||||||
};
|
};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
@ -218,6 +218,19 @@ impl IrExpression {
|
|||||||
_ => panic!("Attempt to convert {} to a location or number", self),
|
_ => 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 {
|
impl Display for IrExpression {
|
||||||
|
|||||||
@ -38,6 +38,13 @@ pub enum Instruction {
|
|||||||
Add(AddOperand, AddOperand, Location),
|
Add(AddOperand, AddOperand, Location),
|
||||||
Subtract(SubtractOperand, SubtractOperand, 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>),
|
Pop(Option<Location>),
|
||||||
|
|
||||||
SetReturnValue(ReturnOperand),
|
SetReturnValue(ReturnOperand),
|
||||||
@ -86,6 +93,23 @@ impl Display for Instruction {
|
|||||||
write!(f, "sub {}, {}, {}", left, right, destination)
|
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) => {
|
Instruction::SetReturnValue(source) => {
|
||||||
write!(f, "srv {}", 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 {
|
pub enum MoveOperand {
|
||||||
Location(Location),
|
Location(Location),
|
||||||
Int(i32),
|
Int(i32),
|
||||||
|
|||||||
@ -6,9 +6,9 @@ use crate::vm::function::Function;
|
|||||||
use crate::vm::object::get_object;
|
use crate::vm::object::get_object;
|
||||||
use crate::vm::operand::Operand;
|
use crate::vm::operand::Operand;
|
||||||
use crate::vm::operand_helpers::{
|
use crate::vm::operand_helpers::{
|
||||||
add_operand_to_value, location_or_number_to_value, move_operand_to_value,
|
add_operand_to_value, location_or_integer_to_value, location_or_number_to_value,
|
||||||
multiply_operand_to_value, push_operand_to_value, return_operand_to_value,
|
move_operand_to_value, multiply_operand_to_value, push_operand_to_value,
|
||||||
set_field_operand_to_value, subtract_operand_to_value,
|
return_operand_to_value, set_field_operand_to_value, subtract_operand_to_value,
|
||||||
};
|
};
|
||||||
use crate::vm::util::*;
|
use crate::vm::util::*;
|
||||||
use crate::vm::value::Value;
|
use crate::vm::value::Value;
|
||||||
@ -560,6 +560,91 @@ pub fn call<'a>(
|
|||||||
call_stack.top_mut().increment_ip();
|
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 */
|
/* Pop instructions */
|
||||||
Instruction::Pop(maybe_location) => {
|
Instruction::Pop(maybe_location) => {
|
||||||
let value = call_stack.top_mut().stack_mut().pop().unwrap();
|
let value = call_stack.top_mut().stack_mut().pop().unwrap();
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::instruction::{
|
use crate::instruction::{
|
||||||
AddOperand, LocationOrNumber, MoveOperand, MultiplyOperand, PushOperand, ReturnOperand,
|
AddOperand, LocationOrInteger, LocationOrNumber, MoveOperand, MultiplyOperand, PushOperand,
|
||||||
SetFieldOperand, SubtractOperand,
|
ReturnOperand, SetFieldOperand, SubtractOperand,
|
||||||
};
|
};
|
||||||
use crate::vm::CallFrame;
|
use crate::vm::CallFrame;
|
||||||
use crate::vm::constant::Constant;
|
use crate::vm::constant::Constant;
|
||||||
@ -155,3 +155,19 @@ pub fn location_or_number_to_value(
|
|||||||
LocationOrNumber::Double(d) => Value::Double(*d),
|
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