From fa13697596666aeb153fd80cc3cd2fc7d57ff975 Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Sun, 15 Mar 2026 16:18:09 -0500 Subject: [PATCH] Instruction generation and implementation for shift and bitwise operators. --- dmc-lib/src/ir/ir_binary_operation.rs | 30 +++++++-- dmc-lib/src/ir/ir_expression.rs | 17 ++++- dvm-lib/src/instruction.rs | 42 +++++++++++++ dvm-lib/src/vm/mod.rs | 91 ++++++++++++++++++++++++++- dvm-lib/src/vm/operand_helpers.rs | 20 +++++- 5 files changed, 188 insertions(+), 12 deletions(-) diff --git a/dmc-lib/src/ir/ir_binary_operation.rs b/dmc-lib/src/ir/ir_binary_operation.rs index c12ecc1..3e5e0de 100644 --- a/dmc-lib/src/ir/ir_binary_operation.rs +++ b/dmc-lib/src/ir/ir_binary_operation.rs @@ -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); } diff --git a/dmc-lib/src/ir/ir_expression.rs b/dmc-lib/src/ir/ir_expression.rs index 72d775d..8019c35 100644 --- a/dmc-lib/src/ir/ir_expression.rs +++ b/dmc-lib/src/ir/ir_expression.rs @@ -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 { diff --git a/dvm-lib/src/instruction.rs b/dvm-lib/src/instruction.rs index 9c02955..ba16957 100644 --- a/dvm-lib/src/instruction.rs +++ b/dvm-lib/src/instruction.rs @@ -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), 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), diff --git a/dvm-lib/src/vm/mod.rs b/dvm-lib/src/vm/mod.rs index c282529..abc36ff 100644 --- a/dvm-lib/src/vm/mod.rs +++ b/dvm-lib/src/vm/mod.rs @@ -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(); diff --git a/dvm-lib/src/vm/operand_helpers.rs b/dvm-lib/src/vm/operand_helpers.rs index ef0baf9..5490866 100644 --- a/dvm-lib/src/vm/operand_helpers.rs +++ b/dvm-lib/src/vm/operand_helpers.rs @@ -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), + } +}