Instruction generation and implementation for shift and bitwise operators.

This commit is contained in:
Jesse Brault 2026-03-15 16:18:09 -05:00
parent 7e72037d9e
commit fa13697596
5 changed files with 188 additions and 12 deletions

View File

@ -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);
}

View File

@ -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 {

View File

@ -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),

View File

@ -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();

View File

@ -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),
}
}