Complete negation operator.
This commit is contained in:
parent
89f519c45f
commit
efecd6b9c8
@ -168,7 +168,9 @@ impl Expression {
|
||||
Expression::Subtract(subtract_expression) => {
|
||||
Some(subtract_expression.to_ir_expression(builder, symbol_table))
|
||||
}
|
||||
Expression::Negative(_) => todo!(),
|
||||
Expression::Negative(negative_expression) => {
|
||||
Some(negative_expression.to_ir(builder, symbol_table))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,17 @@
|
||||
use crate::ast::expression::Expression;
|
||||
use crate::ast::ir_builder::IrBuilder;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::ir::ir_assign::IrAssign;
|
||||
use crate::ir::ir_expression::IrExpression;
|
||||
use crate::ir::ir_multiply::IrMultiply;
|
||||
use crate::ir::ir_operation::IrOperation;
|
||||
use crate::ir::ir_statement::IrStatement;
|
||||
use crate::ir::ir_variable::IrVariable;
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::symbol_table::SymbolTable;
|
||||
use crate::type_info::TypeInfo;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct NegativeExpression {
|
||||
operand: Box<Expression>,
|
||||
@ -58,6 +67,67 @@ impl NegativeExpression {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_ir(&self, builder: &mut IrBuilder, symbol_table: &SymbolTable) -> IrExpression {
|
||||
let operand_as_ir = self
|
||||
.operand
|
||||
.to_ir(builder, symbol_table)
|
||||
.expect("Attempt to negate non-value expression");
|
||||
|
||||
match operand_as_ir {
|
||||
IrExpression::Parameter(parameter) => {
|
||||
let destination = Rc::new(RefCell::new(IrVariable::new_vr(
|
||||
builder.new_t_var().into(),
|
||||
builder.current_block().id(),
|
||||
parameter.type_info(),
|
||||
)));
|
||||
|
||||
let rhs = match parameter.type_info() {
|
||||
TypeInfo::Integer => IrExpression::Int(-1),
|
||||
TypeInfo::Double => IrExpression::Double(-1.0),
|
||||
_ => panic!("Trying to multiply with a non-integer/double"),
|
||||
};
|
||||
|
||||
let operation =
|
||||
IrOperation::Multiply(IrMultiply::new(IrExpression::Parameter(parameter), rhs));
|
||||
|
||||
let assign = IrAssign::new(destination.clone(), operation);
|
||||
builder
|
||||
.current_block_mut()
|
||||
.add_statement(IrStatement::Assign(assign));
|
||||
|
||||
IrExpression::Variable(destination)
|
||||
}
|
||||
IrExpression::Variable(variable) => {
|
||||
let destination = Rc::new(RefCell::new(IrVariable::new_vr(
|
||||
builder.new_t_var().into(),
|
||||
builder.current_block().id(),
|
||||
variable.borrow().type_info(),
|
||||
)));
|
||||
|
||||
let rhs = match variable.borrow().type_info() {
|
||||
TypeInfo::Integer => IrExpression::Int(-1),
|
||||
TypeInfo::Double => IrExpression::Double(-1.0),
|
||||
_ => panic!("Trying to multiply with a non-integer/double"),
|
||||
};
|
||||
|
||||
let operation =
|
||||
IrOperation::Multiply(IrMultiply::new(IrExpression::Variable(variable), rhs));
|
||||
|
||||
let assign = IrAssign::new(destination.clone(), operation);
|
||||
builder
|
||||
.current_block_mut()
|
||||
.add_statement(IrStatement::Assign(assign));
|
||||
|
||||
IrExpression::Variable(destination)
|
||||
}
|
||||
IrExpression::Int(i) => IrExpression::Int(i * -1),
|
||||
IrExpression::Double(d) => IrExpression::Double(d * -1.0),
|
||||
IrExpression::String(_) => {
|
||||
panic!("Attempt to negate IrExpression::String")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_info(&self) -> &TypeInfo {
|
||||
self.type_info.as_ref().unwrap()
|
||||
}
|
||||
|
||||
@ -101,6 +101,10 @@ impl Assemble for IrAssign {
|
||||
let (left, right) = ir_subtract.operand_pair();
|
||||
builder.push(Instruction::Subtract(left, right, destination));
|
||||
}
|
||||
IrOperation::Multiply(ir_multiply) => {
|
||||
let (left, right) = ir_multiply.operand_pair();
|
||||
builder.push(Instruction::Multiply(left, right, destination));
|
||||
}
|
||||
IrOperation::Call(ir_call) => {
|
||||
ir_call.assemble(builder, constants_table);
|
||||
builder.push(Instruction::Pop(Some(destination)));
|
||||
|
||||
@ -6,7 +6,7 @@ use crate::ir::ir_variable::{
|
||||
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||
use crate::type_info::TypeInfo;
|
||||
use dvm_lib::instruction::{
|
||||
AddOperand, Location, MoveOperand, PushOperand, ReturnOperand, SubtractOperand,
|
||||
AddOperand, Location, MoveOperand, MultiplyOperand, PushOperand, ReturnOperand, SubtractOperand,
|
||||
};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
@ -149,6 +149,27 @@ impl IrExpression {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn multiply_operand(&self) -> MultiplyOperand {
|
||||
match self {
|
||||
IrExpression::Parameter(ir_parameter) => {
|
||||
MultiplyOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
||||
}
|
||||
IrExpression::Variable(ir_variable) => match ir_variable.borrow().descriptor() {
|
||||
IrVariableDescriptor::VirtualRegister(vr_variable) => {
|
||||
MultiplyOperand::Location(Location::Register(vr_variable.assigned_register()))
|
||||
}
|
||||
IrVariableDescriptor::Stack(stack_variable) => {
|
||||
MultiplyOperand::Location(Location::StackFrameOffset(stack_variable.offset()))
|
||||
}
|
||||
},
|
||||
IrExpression::Int(i) => MultiplyOperand::Int(*i),
|
||||
IrExpression::Double(d) => MultiplyOperand::Double(*d),
|
||||
IrExpression::String(_) => {
|
||||
panic!("Attempt to multiply with a string");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn return_operand(&self, constants_table: &mut ConstantsTable) -> ReturnOperand {
|
||||
match self {
|
||||
IrExpression::Parameter(ir_parameter) => {
|
||||
|
||||
67
dmc-lib/src/ir/ir_multiply.rs
Normal file
67
dmc-lib/src/ir/ir_multiply.rs
Normal file
@ -0,0 +1,67 @@
|
||||
use crate::ir::ir_expression::IrExpression;
|
||||
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
||||
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||
use dvm_lib::instruction::MultiplyOperand;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
pub struct IrMultiply {
|
||||
left: Box<IrExpression>,
|
||||
right: Box<IrExpression>,
|
||||
}
|
||||
|
||||
impl IrMultiply {
|
||||
pub fn new(left: IrExpression, right: IrExpression) -> Self {
|
||||
Self {
|
||||
left: left.into(),
|
||||
right: right.into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn operand_pair(&self) -> (MultiplyOperand, MultiplyOperand) {
|
||||
(self.left.multiply_operand(), self.right.multiply_operand())
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for IrMultiply {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{} * {}", self.left, self.right)
|
||||
}
|
||||
}
|
||||
|
||||
impl VrUser for IrMultiply {
|
||||
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||
[&self.left, &self.right]
|
||||
.iter()
|
||||
.flat_map(|ir_expression| ir_expression.vr_definitions())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||
[&self.left, &self.right]
|
||||
.iter()
|
||||
.flat_map(|ir_expression| ir_expression.vr_uses())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {
|
||||
[&mut self.left, &mut self.right]
|
||||
.iter_mut()
|
||||
.for_each(|ir_expression| ir_expression.propagate_spills(spills));
|
||||
}
|
||||
|
||||
fn propagate_register_assignments(
|
||||
&mut self,
|
||||
assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
||||
) {
|
||||
[&mut self.left, &mut self.right]
|
||||
.iter_mut()
|
||||
.for_each(|ir_expression| ir_expression.propagate_register_assignments(assignments));
|
||||
}
|
||||
|
||||
fn propagate_stack_offsets(&mut self, counter: &mut OffsetCounter) {
|
||||
[&mut self.left, &mut self.right]
|
||||
.iter_mut()
|
||||
.for_each(|ir_expression| ir_expression.propagate_stack_offsets(counter));
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
use crate::ir::ir_add::IrAdd;
|
||||
use crate::ir::ir_call::IrCall;
|
||||
use crate::ir::ir_expression::IrExpression;
|
||||
use crate::ir::ir_multiply::IrMultiply;
|
||||
use crate::ir::ir_subtract::IrSubtract;
|
||||
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
||||
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||
@ -11,6 +12,7 @@ pub enum IrOperation {
|
||||
Load(IrExpression),
|
||||
Add(IrAdd),
|
||||
Subtract(IrSubtract),
|
||||
Multiply(IrMultiply),
|
||||
Call(IrCall),
|
||||
}
|
||||
|
||||
@ -26,6 +28,9 @@ impl Display for IrOperation {
|
||||
IrOperation::Subtract(ir_subtract) => {
|
||||
write!(f, "{}", ir_subtract)
|
||||
}
|
||||
IrOperation::Multiply(ir_multiply) => {
|
||||
write!(f, "{}", ir_multiply)
|
||||
}
|
||||
IrOperation::Call(ir_call) => {
|
||||
write!(f, "{}", ir_call)
|
||||
}
|
||||
@ -39,6 +44,7 @@ impl VrUser for IrOperation {
|
||||
IrOperation::Load(ir_expression) => ir_expression.vr_definitions(),
|
||||
IrOperation::Add(ir_add) => ir_add.vr_definitions(),
|
||||
IrOperation::Subtract(ir_subtract) => ir_subtract.vr_definitions(),
|
||||
IrOperation::Multiply(ir_multiply) => ir_multiply.vr_definitions(),
|
||||
IrOperation::Call(ir_call) => ir_call.vr_definitions(),
|
||||
}
|
||||
}
|
||||
@ -48,6 +54,7 @@ impl VrUser for IrOperation {
|
||||
IrOperation::Load(ir_expression) => ir_expression.vr_uses(),
|
||||
IrOperation::Add(ir_add) => ir_add.vr_uses(),
|
||||
IrOperation::Subtract(ir_subtract) => ir_subtract.vr_uses(),
|
||||
IrOperation::Multiply(ir_multiply) => ir_multiply.vr_uses(),
|
||||
IrOperation::Call(ir_call) => ir_call.vr_uses(),
|
||||
}
|
||||
}
|
||||
@ -63,6 +70,9 @@ impl VrUser for IrOperation {
|
||||
IrOperation::Subtract(ir_subtract) => {
|
||||
ir_subtract.propagate_spills(spills);
|
||||
}
|
||||
IrOperation::Multiply(ir_multiply) => {
|
||||
ir_multiply.propagate_spills(spills);
|
||||
}
|
||||
IrOperation::Call(ir_call) => {
|
||||
ir_call.propagate_spills(spills);
|
||||
}
|
||||
@ -83,6 +93,9 @@ impl VrUser for IrOperation {
|
||||
IrOperation::Subtract(ir_subtract) => {
|
||||
ir_subtract.propagate_register_assignments(assignments);
|
||||
}
|
||||
IrOperation::Multiply(ir_multiply) => {
|
||||
ir_multiply.propagate_register_assignments(assignments);
|
||||
}
|
||||
IrOperation::Call(ir_call) => {
|
||||
ir_call.propagate_register_assignments(assignments);
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ pub mod ir_block;
|
||||
pub mod ir_call;
|
||||
pub mod ir_expression;
|
||||
pub mod ir_function;
|
||||
pub mod ir_multiply;
|
||||
pub mod ir_operation;
|
||||
pub mod ir_parameter;
|
||||
pub mod ir_return;
|
||||
|
||||
@ -127,12 +127,13 @@ impl TypeInfo {
|
||||
}
|
||||
|
||||
pub fn can_negate(&self) -> bool {
|
||||
matches!(self, TypeInfo::Integer)
|
||||
matches!(self, TypeInfo::Integer | TypeInfo::Double)
|
||||
}
|
||||
|
||||
pub fn negate_result(&self) -> TypeInfo {
|
||||
match self {
|
||||
TypeInfo::Integer => TypeInfo::Integer,
|
||||
TypeInfo::Double => TypeInfo::Double,
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ pub enum Instruction {
|
||||
|
||||
Add(AddOperand, AddOperand, Location),
|
||||
Subtract(SubtractOperand, SubtractOperand, Location),
|
||||
Multiply(MultiplyOperand, MultiplyOperand, Location),
|
||||
|
||||
Pop(Option<Location>),
|
||||
|
||||
@ -54,6 +55,9 @@ impl Display for Instruction {
|
||||
Instruction::Subtract(left, right, destination) => {
|
||||
write!(f, "sub {}, {}, {}", left, right, destination)
|
||||
}
|
||||
Instruction::Multiply(left, right, destination) => {
|
||||
write!(f, "mul {}, {}, {}", left, right, destination)
|
||||
}
|
||||
Instruction::SetReturnValue(source) => {
|
||||
write!(f, "srv {}", source)
|
||||
}
|
||||
@ -186,6 +190,28 @@ impl Display for SubtractOperand {
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MultiplyOperand {
|
||||
Location(Location),
|
||||
Int(i32),
|
||||
Double(f64),
|
||||
}
|
||||
|
||||
impl Display for MultiplyOperand {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
MultiplyOperand::Location(location) => {
|
||||
write!(f, "{}", location)
|
||||
}
|
||||
MultiplyOperand::Int(i) => {
|
||||
write!(f, "{}", i)
|
||||
}
|
||||
MultiplyOperand::Double(d) => {
|
||||
write!(f, "{}", d)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ReturnOperand {
|
||||
Location(Location),
|
||||
Int(i32),
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use crate::instruction::{AddOperand, SubtractOperand};
|
||||
use crate::instruction::{AddOperand, MultiplyOperand, SubtractOperand};
|
||||
use crate::vm::CallFrame;
|
||||
use crate::vm::constant::Constant;
|
||||
use crate::vm::value::Value;
|
||||
@ -43,3 +43,21 @@ pub fn subtract_operand_to_value(
|
||||
SubtractOperand::Double(d) => Value::Double(*d),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn multiply_operand_to_value(
|
||||
multiply_operand: &MultiplyOperand,
|
||||
registers: &[Value],
|
||||
current_frame: &CallFrame,
|
||||
) -> Value {
|
||||
match multiply_operand {
|
||||
MultiplyOperand::Location(location) => load_value(
|
||||
registers,
|
||||
current_frame.stack(),
|
||||
current_frame.fp(),
|
||||
location,
|
||||
)
|
||||
.clone(),
|
||||
MultiplyOperand::Int(i) => Value::Int(*i),
|
||||
MultiplyOperand::Double(d) => Value::Double(*d),
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,9 @@ use crate::instruction::{Instruction, MoveOperand, PushOperand, ReturnOperand};
|
||||
use crate::platform_function::PlatformFunction;
|
||||
use crate::vm::constant::Constant;
|
||||
use crate::vm::function::Function;
|
||||
use crate::vm::instruction_helpers::{add_operand_to_value, subtract_operand_to_value};
|
||||
use crate::vm::instruction_helpers::{
|
||||
add_operand_to_value, multiply_operand_to_value, subtract_operand_to_value,
|
||||
};
|
||||
use crate::vm::value::Value;
|
||||
use crate::vm::value_util::*;
|
||||
use std::collections::HashMap;
|
||||
@ -389,6 +391,29 @@ pub fn call<'a>(
|
||||
put_value(registers, call_stack.top_mut(), destination, result);
|
||||
call_stack.top_mut().increment_ip();
|
||||
}
|
||||
Instruction::Multiply(left_operand, right_operand, destination) => {
|
||||
let left_value =
|
||||
multiply_operand_to_value(left_operand, registers, call_stack.top());
|
||||
let right_value =
|
||||
multiply_operand_to_value(right_operand, registers, call_stack.top());
|
||||
|
||||
let result = match left_value {
|
||||
Value::Int(li) => match right_value {
|
||||
Value::Int(ri) => Value::Int(li * ri),
|
||||
Value::Double(rd) => Value::Double(li as f64 * rd),
|
||||
_ => panic!("Attempt to multiply {:?} and {:?}", left_value, right_value),
|
||||
},
|
||||
Value::Double(ld) => match right_value {
|
||||
Value::Int(ri) => Value::Double(ld * ri as f64),
|
||||
Value::Double(rd) => Value::Double(ld * rd),
|
||||
_ => panic!("Attempt to multiply {:?} and {:?}", left_value, right_value),
|
||||
},
|
||||
_ => panic!("Attempt to multiply {:?} and {:?}", 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) => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user