Compiling fields getters/setters.
This commit is contained in:
parent
51a80bb5ed
commit
320cdcf805
@ -6,18 +6,14 @@ use dmc_lib::ir::ir_return::IrReturn;
|
|||||||
use dmc_lib::ir::ir_statement::IrStatement;
|
use dmc_lib::ir::ir_statement::IrStatement;
|
||||||
use dmc_lib::lexer::Lexer;
|
use dmc_lib::lexer::Lexer;
|
||||||
use dmc_lib::parser::parse_expression;
|
use dmc_lib::parser::parse_expression;
|
||||||
use dmc_lib::source_range::SourceRange;
|
|
||||||
use dmc_lib::symbol::function_symbol::FunctionSymbol;
|
|
||||||
use dmc_lib::symbol_table::SymbolTable;
|
use dmc_lib::symbol_table::SymbolTable;
|
||||||
use dmc_lib::token::TokenKind;
|
use dmc_lib::token::TokenKind;
|
||||||
use dvm_lib::vm::constant::{Constant, StringConstant};
|
use dvm_lib::vm::constant::{Constant, StringConstant};
|
||||||
use dvm_lib::vm::function::Function;
|
use dvm_lib::vm::function::Function;
|
||||||
use dvm_lib::vm::value::Value;
|
use dvm_lib::vm::value::Value;
|
||||||
use dvm_lib::vm::{CallStack, DvmContext, call};
|
use dvm_lib::vm::{CallStack, DvmContext, call};
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
pub fn repl(register_count: usize) {
|
pub fn repl(register_count: usize) {
|
||||||
let mut buffer = String::new();
|
let mut buffer = String::new();
|
||||||
@ -128,19 +124,8 @@ fn compile_expression(
|
|||||||
ir_builder.finish_block();
|
ir_builder.finish_block();
|
||||||
let entry_block = ir_builder.get_block(entry_block_id);
|
let entry_block = ir_builder.get_block(entry_block_id);
|
||||||
|
|
||||||
// synthesize symbol
|
|
||||||
let fake_function_symbol = Rc::new(RefCell::new(FunctionSymbol::new(
|
|
||||||
"__repl",
|
|
||||||
SourceRange::new(0, 0),
|
|
||||||
false,
|
|
||||||
)));
|
|
||||||
|
|
||||||
fake_function_symbol
|
|
||||||
.borrow_mut()
|
|
||||||
.set_return_type_info(expression.type_info().clone());
|
|
||||||
|
|
||||||
let mut ir_function = IrFunction::new(
|
let mut ir_function = IrFunction::new(
|
||||||
fake_function_symbol,
|
"__repl".into(),
|
||||||
&[],
|
&[],
|
||||||
expression.type_info(),
|
expression.type_info(),
|
||||||
entry_block.clone(),
|
entry_block.clone(),
|
||||||
|
|||||||
@ -2,9 +2,11 @@ use crate::ast::constructor::Constructor;
|
|||||||
use crate::ast::field::Field;
|
use crate::ast::field::Field;
|
||||||
use crate::ast::function::Function;
|
use crate::ast::function::Function;
|
||||||
use crate::diagnostic::{Diagnostic, SecondaryLabel};
|
use crate::diagnostic::{Diagnostic, SecondaryLabel};
|
||||||
|
use crate::ir::ir_function::IrFunction;
|
||||||
use crate::source_range::SourceRange;
|
use crate::source_range::SourceRange;
|
||||||
use crate::symbol::class_symbol::ClassSymbol;
|
use crate::symbol::class_symbol::ClassSymbol;
|
||||||
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
@ -14,6 +16,7 @@ pub struct Class {
|
|||||||
constructor: Option<Constructor>,
|
constructor: Option<Constructor>,
|
||||||
fields: Vec<Field>,
|
fields: Vec<Field>,
|
||||||
functions: Vec<Function>,
|
functions: Vec<Function>,
|
||||||
|
class_symbol: Option<Rc<RefCell<ClassSymbol>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Class {
|
impl Class {
|
||||||
@ -30,6 +33,7 @@ impl Class {
|
|||||||
constructor,
|
constructor,
|
||||||
fields,
|
fields,
|
||||||
functions,
|
functions,
|
||||||
|
class_symbol: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,6 +72,9 @@ impl Class {
|
|||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
// save symbol for later
|
||||||
|
self.class_symbol = Some(class_symbol);
|
||||||
|
|
||||||
// 2. push scope
|
// 2. push scope
|
||||||
symbol_table.push_class_scope(&format!("class_scope({})", self.declared_name));
|
symbol_table.push_class_scope(&format!("class_scope({})", self.declared_name));
|
||||||
|
|
||||||
@ -75,7 +82,8 @@ impl Class {
|
|||||||
let fields_diagnostics: Vec<Diagnostic> = self
|
let fields_diagnostics: Vec<Diagnostic> = self
|
||||||
.fields
|
.fields
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.map(|field| field.gather_declared_names(symbol_table))
|
.enumerate()
|
||||||
|
.map(|(field_index, field)| field.gather_declared_names(symbol_table, field_index))
|
||||||
.filter_map(Result::err)
|
.filter_map(Result::err)
|
||||||
.flatten()
|
.flatten()
|
||||||
.collect();
|
.collect();
|
||||||
@ -87,7 +95,9 @@ impl Class {
|
|||||||
// 4. gather constructor
|
// 4. gather constructor
|
||||||
if let Some(constructor) = &mut self.constructor {
|
if let Some(constructor) = &mut self.constructor {
|
||||||
let constructor_symbol = constructor.gather_declared_names(symbol_table)?;
|
let constructor_symbol = constructor.gather_declared_names(symbol_table)?;
|
||||||
class_symbol
|
self.class_symbol
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.set_constructor_symbol(Some(constructor_symbol));
|
.set_constructor_symbol(Some(constructor_symbol));
|
||||||
}
|
}
|
||||||
@ -231,11 +241,29 @@ impl Class {
|
|||||||
Err(diagnostics)
|
Err(diagnostics)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_ir(&self, symbol_table: &SymbolTable) -> Vec<IrFunction> {
|
||||||
|
let mut ir_functions: Vec<IrFunction> = vec![];
|
||||||
|
if let Some(constructor) = &self.constructor {
|
||||||
|
ir_functions.push(constructor.to_ir(
|
||||||
|
self.class_symbol.as_ref().unwrap(),
|
||||||
|
&self.fields,
|
||||||
|
symbol_table,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
for function in &self.functions {
|
||||||
|
ir_functions.push(function.to_ir(symbol_table));
|
||||||
|
}
|
||||||
|
|
||||||
|
ir_functions
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::constants_table::ConstantsTable;
|
||||||
use crate::parser::parse_compilation_unit;
|
use crate::parser::parse_compilation_unit;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -289,5 +317,13 @@ mod tests {
|
|||||||
panic!("{:?}", diagnostics);
|
panic!("{:?}", diagnostics);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut ir_functions = compilation_unit.to_ir(&symbol_table);
|
||||||
|
let mut constants_table = ConstantsTable::new();
|
||||||
|
for ir_function in &mut ir_functions {
|
||||||
|
let (_, stack_size) = ir_function.assign_registers(8);
|
||||||
|
let vm_function = ir_function.assemble(stack_size, &mut constants_table);
|
||||||
|
println!("{}", vm_function)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -136,9 +136,15 @@ impl CompilationUnit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_ir(&self, symbol_table: &SymbolTable) -> Vec<IrFunction> {
|
pub fn to_ir(&self, symbol_table: &SymbolTable) -> Vec<IrFunction> {
|
||||||
|
let mut functions: Vec<IrFunction> = vec![];
|
||||||
self.functions
|
self.functions
|
||||||
.iter()
|
.iter()
|
||||||
.map(|f| f.to_ir(symbol_table))
|
.map(|f| f.to_ir(symbol_table))
|
||||||
.collect()
|
.for_each(|f| functions.push(f));
|
||||||
|
self.classes
|
||||||
|
.iter()
|
||||||
|
.flat_map(|c| c.to_ir(symbol_table))
|
||||||
|
.for_each(|f| functions.push(f));
|
||||||
|
functions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,26 @@
|
|||||||
|
use crate::ast::field::Field;
|
||||||
|
use crate::ast::ir_builder::IrBuilder;
|
||||||
use crate::ast::parameter::Parameter;
|
use crate::ast::parameter::Parameter;
|
||||||
use crate::ast::statement::Statement;
|
use crate::ast::statement::Statement;
|
||||||
use crate::diagnostic::Diagnostic;
|
use crate::diagnostic::Diagnostic;
|
||||||
|
use crate::ir::ir_allocate::IrAllocate;
|
||||||
|
use crate::ir::ir_assign::IrAssign;
|
||||||
|
use crate::ir::ir_expression::IrExpression;
|
||||||
|
use crate::ir::ir_function::IrFunction;
|
||||||
|
use crate::ir::ir_operation::IrOperation;
|
||||||
|
use crate::ir::ir_parameter::IrParameter;
|
||||||
|
use crate::ir::ir_set_field::IrSetField;
|
||||||
|
use crate::ir::ir_statement::IrStatement;
|
||||||
|
use crate::ir::ir_variable::IrVariable;
|
||||||
use crate::source_range::SourceRange;
|
use crate::source_range::SourceRange;
|
||||||
|
use crate::symbol::Symbol;
|
||||||
|
use crate::symbol::class_symbol::ClassSymbol;
|
||||||
use crate::symbol::constructor_symbol::ConstructorSymbol;
|
use crate::symbol::constructor_symbol::ConstructorSymbol;
|
||||||
use crate::symbol::parameter_symbol::ParameterSymbol;
|
use crate::symbol::parameter_symbol::ParameterSymbol;
|
||||||
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
||||||
|
use crate::type_info::TypeInfo;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use std::ops::Neg;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct Constructor {
|
pub struct Constructor {
|
||||||
@ -156,4 +171,71 @@ impl Constructor {
|
|||||||
Err(statements_diagnostics)
|
Err(statements_diagnostics)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_ir(
|
||||||
|
&self,
|
||||||
|
class_symbol: &Rc<RefCell<ClassSymbol>>,
|
||||||
|
fields: &[Field],
|
||||||
|
symbol_table: &SymbolTable,
|
||||||
|
) -> IrFunction {
|
||||||
|
let mut ir_builder = IrBuilder::new();
|
||||||
|
|
||||||
|
let parameters_count = self.parameters.len();
|
||||||
|
let ir_parameters = self
|
||||||
|
.parameters
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, parameter)| {
|
||||||
|
let parameter_symbol = parameter.parameter_symbol().borrow();
|
||||||
|
let offset = (parameters_count as isize).neg() + i as isize;
|
||||||
|
Rc::new(IrParameter::new(
|
||||||
|
parameter_symbol.declared_name(),
|
||||||
|
parameter_symbol.type_info().clone(),
|
||||||
|
offset,
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let entry_block_id = ir_builder.new_block();
|
||||||
|
|
||||||
|
// first, allocate the object into a t var
|
||||||
|
let alloc_assign_destination = IrVariable::new_vr(
|
||||||
|
ir_builder.new_t_var().into(),
|
||||||
|
ir_builder.current_block().id(),
|
||||||
|
&TypeInfo::ClassInstance(class_symbol.clone()),
|
||||||
|
);
|
||||||
|
let self_variable = Rc::new(RefCell::new(alloc_assign_destination));
|
||||||
|
let alloc_assign = IrAssign::new(
|
||||||
|
self_variable.clone(),
|
||||||
|
IrOperation::Allocate(IrAllocate::new(class_symbol.borrow().declared_name_owned())),
|
||||||
|
);
|
||||||
|
ir_builder
|
||||||
|
.current_block_mut()
|
||||||
|
.add_statement(IrStatement::Assign(alloc_assign));
|
||||||
|
|
||||||
|
// next, initialize fields that have an initializer in their declaration
|
||||||
|
for field in fields {
|
||||||
|
if let Some(initializer) = field.initializer() {
|
||||||
|
let ir_expression = initializer.to_ir(&mut ir_builder, symbol_table).unwrap();
|
||||||
|
let ir_set_field = IrSetField::new(
|
||||||
|
&self_variable.clone(),
|
||||||
|
field.field_symbol().borrow().field_index(),
|
||||||
|
ir_expression,
|
||||||
|
);
|
||||||
|
ir_builder
|
||||||
|
.current_block_mut()
|
||||||
|
.add_statement(IrStatement::SetField(ir_set_field));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ir_builder.finish_block();
|
||||||
|
let entry_block = ir_builder.get_block(entry_block_id);
|
||||||
|
|
||||||
|
IrFunction::new(
|
||||||
|
format!("{}::ctor", class_symbol.borrow().declared_name()).into(), // fake function symbol
|
||||||
|
&ir_parameters, // make params
|
||||||
|
&TypeInfo::ClassInstance(class_symbol.clone()),
|
||||||
|
entry_block.clone(),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,6 +52,7 @@ impl Field {
|
|||||||
pub fn gather_declared_names(
|
pub fn gather_declared_names(
|
||||||
&mut self,
|
&mut self,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
|
field_index: usize,
|
||||||
) -> Result<(), Vec<Diagnostic>> {
|
) -> Result<(), Vec<Diagnostic>> {
|
||||||
// 1. insert field symbol
|
// 1. insert field symbol
|
||||||
let to_insert =
|
let to_insert =
|
||||||
@ -75,6 +76,13 @@ impl Field {
|
|||||||
// save for later
|
// save for later
|
||||||
self.field_symbol = Some(field_symbol);
|
self.field_symbol = Some(field_symbol);
|
||||||
|
|
||||||
|
// set field index on symbol
|
||||||
|
self.field_symbol
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.borrow_mut()
|
||||||
|
.set_field_index(field_index);
|
||||||
|
|
||||||
// 2. gather type_use and initializer, if present
|
// 2. gather type_use and initializer, if present
|
||||||
if let Some(type_use) = &mut self.declared_type {
|
if let Some(type_use) = &mut self.declared_type {
|
||||||
type_use.gather_declared_names(symbol_table)?;
|
type_use.gather_declared_names(symbol_table)?;
|
||||||
@ -181,4 +189,8 @@ impl Field {
|
|||||||
Err(diagnostics)
|
Err(diagnostics)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn field_symbol(&self) -> &Rc<RefCell<FieldSymbol>> {
|
||||||
|
self.field_symbol.as_ref().unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -269,7 +269,11 @@ impl Function {
|
|||||||
|
|
||||||
let entry_block = builder.get_block(entry_block_id).clone();
|
let entry_block = builder.get_block(entry_block_id).clone();
|
||||||
IrFunction::new(
|
IrFunction::new(
|
||||||
self.function_symbol.as_ref().unwrap().clone(),
|
self.function_symbol
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.borrow()
|
||||||
|
.declared_name_owned(), // ok for now... but we need to start using the fqn
|
||||||
builder.parameters(),
|
builder.parameters(),
|
||||||
return_type_info,
|
return_type_info,
|
||||||
entry_block,
|
entry_block,
|
||||||
|
|||||||
@ -74,6 +74,9 @@ impl NegativeExpression {
|
|||||||
.expect("Attempt to negate non-value expression");
|
.expect("Attempt to negate non-value expression");
|
||||||
|
|
||||||
match operand_as_ir {
|
match operand_as_ir {
|
||||||
|
IrExpression::Field(self_variable, _) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
IrExpression::Parameter(parameter) => {
|
IrExpression::Parameter(parameter) => {
|
||||||
let destination = Rc::new(RefCell::new(IrVariable::new_vr(
|
let destination = Rc::new(RefCell::new(IrVariable::new_vr(
|
||||||
builder.new_t_var().into(),
|
builder.new_t_var().into(),
|
||||||
|
|||||||
26
dmc-lib/src/ir/ir_allocate.rs
Normal file
26
dmc-lib/src/ir/ir_allocate.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub struct IrAllocate {
|
||||||
|
class_fqn: Rc<str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IrAllocate {
|
||||||
|
pub fn new(class_fqn: Rc<str>) -> Self {
|
||||||
|
Self { class_fqn }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn class_fqn(&self) -> &str {
|
||||||
|
&self.class_fqn
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn class_fqn_owned(&self) -> Rc<str> {
|
||||||
|
self.class_fqn.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for IrAllocate {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "alloc {}", self.class_fqn)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -109,6 +109,10 @@ impl Assemble for IrAssign {
|
|||||||
ir_call.assemble(builder, constants_table);
|
ir_call.assemble(builder, constants_table);
|
||||||
builder.push(Instruction::Pop(Some(destination)));
|
builder.push(Instruction::Pop(Some(destination)));
|
||||||
}
|
}
|
||||||
|
IrOperation::Allocate(ir_allocate) => builder.push(Instruction::Allocate(
|
||||||
|
ir_allocate.class_fqn_owned(),
|
||||||
|
destination,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,8 @@ use crate::ir::ir_variable::{
|
|||||||
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||||
use crate::type_info::TypeInfo;
|
use crate::type_info::TypeInfo;
|
||||||
use dvm_lib::instruction::{
|
use dvm_lib::instruction::{
|
||||||
AddOperand, Location, MoveOperand, MultiplyOperand, PushOperand, ReturnOperand, SubtractOperand,
|
AddOperand, Location, MoveOperand, MultiplyOperand, PushOperand, ReturnOperand,
|
||||||
|
SetFieldOperand, SubtractOperand,
|
||||||
};
|
};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
@ -14,6 +15,7 @@ use std::fmt::{Display, Formatter};
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub enum IrExpression {
|
pub enum IrExpression {
|
||||||
|
Field(Rc<RefCell<IrVariable>>, usize),
|
||||||
Parameter(Rc<IrParameter>),
|
Parameter(Rc<IrParameter>),
|
||||||
Variable(Rc<RefCell<IrVariable>>),
|
Variable(Rc<RefCell<IrVariable>>),
|
||||||
Int(i32),
|
Int(i32),
|
||||||
@ -22,18 +24,11 @@ pub enum IrExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl IrExpression {
|
impl IrExpression {
|
||||||
pub fn type_info(&self) -> TypeInfo {
|
|
||||||
match self {
|
|
||||||
IrExpression::Parameter(ir_parameter) => ir_parameter.type_info().clone(),
|
|
||||||
IrExpression::Variable(ir_variable) => ir_variable.borrow().type_info().clone(),
|
|
||||||
IrExpression::Int(_) => TypeInfo::Integer,
|
|
||||||
IrExpression::Double(_) => TypeInfo::Double,
|
|
||||||
IrExpression::String(_) => TypeInfo::String,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn move_operand(&self, constants_table: &mut ConstantsTable) -> MoveOperand {
|
pub fn move_operand(&self, constants_table: &mut ConstantsTable) -> MoveOperand {
|
||||||
match self {
|
match self {
|
||||||
|
IrExpression::Field(self_variable, _) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
IrExpression::Parameter(ir_parameter) => {
|
IrExpression::Parameter(ir_parameter) => {
|
||||||
MoveOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
MoveOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
||||||
}
|
}
|
||||||
@ -56,6 +51,9 @@ impl IrExpression {
|
|||||||
|
|
||||||
pub fn push_operand(&self, constants_table: &mut ConstantsTable) -> PushOperand {
|
pub fn push_operand(&self, constants_table: &mut ConstantsTable) -> PushOperand {
|
||||||
match self {
|
match self {
|
||||||
|
IrExpression::Field(self_variable, _) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
IrExpression::Parameter(ir_parameter) => {
|
IrExpression::Parameter(ir_parameter) => {
|
||||||
PushOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
PushOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
||||||
}
|
}
|
||||||
@ -78,6 +76,9 @@ impl IrExpression {
|
|||||||
|
|
||||||
pub fn add_operand(&self, constants_table: &mut ConstantsTable) -> AddOperand {
|
pub fn add_operand(&self, constants_table: &mut ConstantsTable) -> AddOperand {
|
||||||
match self {
|
match self {
|
||||||
|
IrExpression::Field(self_variable, _) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
IrExpression::Parameter(ir_parameter) => match ir_parameter.type_info() {
|
IrExpression::Parameter(ir_parameter) => match ir_parameter.type_info() {
|
||||||
TypeInfo::Integer | TypeInfo::Double | TypeInfo::String => {
|
TypeInfo::Integer | TypeInfo::Double | TypeInfo::String => {
|
||||||
AddOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
AddOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
||||||
@ -116,6 +117,9 @@ impl IrExpression {
|
|||||||
|
|
||||||
pub fn subtract_operand(&self) -> SubtractOperand {
|
pub fn subtract_operand(&self) -> SubtractOperand {
|
||||||
match self {
|
match self {
|
||||||
|
IrExpression::Field(self_variable, _) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
IrExpression::Parameter(ir_parameter) => match ir_parameter.type_info() {
|
IrExpression::Parameter(ir_parameter) => match ir_parameter.type_info() {
|
||||||
TypeInfo::Integer | TypeInfo::Double => SubtractOperand::Location(
|
TypeInfo::Integer | TypeInfo::Double => SubtractOperand::Location(
|
||||||
Location::StackFrameOffset(ir_parameter.stack_offset()),
|
Location::StackFrameOffset(ir_parameter.stack_offset()),
|
||||||
@ -151,6 +155,9 @@ impl IrExpression {
|
|||||||
|
|
||||||
pub fn multiply_operand(&self) -> MultiplyOperand {
|
pub fn multiply_operand(&self) -> MultiplyOperand {
|
||||||
match self {
|
match self {
|
||||||
|
IrExpression::Field(self_variable, _) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
IrExpression::Parameter(ir_parameter) => {
|
IrExpression::Parameter(ir_parameter) => {
|
||||||
MultiplyOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
MultiplyOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
||||||
}
|
}
|
||||||
@ -172,6 +179,9 @@ impl IrExpression {
|
|||||||
|
|
||||||
pub fn return_operand(&self, constants_table: &mut ConstantsTable) -> ReturnOperand {
|
pub fn return_operand(&self, constants_table: &mut ConstantsTable) -> ReturnOperand {
|
||||||
match self {
|
match self {
|
||||||
|
IrExpression::Field(self_variable, _) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
IrExpression::Parameter(ir_parameter) => {
|
IrExpression::Parameter(ir_parameter) => {
|
||||||
ReturnOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
ReturnOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
||||||
}
|
}
|
||||||
@ -193,11 +203,39 @@ impl IrExpression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_field_operand(&self, constants_table: &mut ConstantsTable) -> SetFieldOperand {
|
||||||
|
match self {
|
||||||
|
IrExpression::Field(self_variable, _) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
IrExpression::Parameter(ir_parameter) => {
|
||||||
|
SetFieldOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
||||||
|
}
|
||||||
|
IrExpression::Variable(ir_variable) => match ir_variable.borrow().descriptor() {
|
||||||
|
IrVariableDescriptor::VirtualRegister(vr_variable) => {
|
||||||
|
SetFieldOperand::Location(Location::Register(vr_variable.assigned_register()))
|
||||||
|
}
|
||||||
|
IrVariableDescriptor::Stack(stack_variable) => {
|
||||||
|
SetFieldOperand::Location(Location::StackFrameOffset(stack_variable.offset()))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
IrExpression::Int(i) => SetFieldOperand::Int(*i),
|
||||||
|
IrExpression::Double(d) => SetFieldOperand::Double(*d),
|
||||||
|
IrExpression::String(s) => {
|
||||||
|
let constant_name = constants_table.get_or_insert(s);
|
||||||
|
SetFieldOperand::String(constant_name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for IrExpression {
|
impl Display for IrExpression {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
IrExpression::Field(self_variable, field_index) => {
|
||||||
|
write!(f, "{}.{}", self_variable.borrow(), field_index)
|
||||||
|
}
|
||||||
IrExpression::Parameter(ir_parameter) => {
|
IrExpression::Parameter(ir_parameter) => {
|
||||||
write!(f, "{}", ir_parameter)
|
write!(f, "{}", ir_parameter)
|
||||||
}
|
}
|
||||||
@ -219,11 +257,21 @@ impl Display for IrExpression {
|
|||||||
|
|
||||||
impl VrUser for IrExpression {
|
impl VrUser for IrExpression {
|
||||||
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
|
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
|
// no defs for an expression
|
||||||
HashSet::new()
|
HashSet::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
match self {
|
match self {
|
||||||
|
IrExpression::Field(self_variable, field_index) => {
|
||||||
|
if let IrVariableDescriptor::VirtualRegister(vr_variable) =
|
||||||
|
self_variable.borrow().descriptor()
|
||||||
|
{
|
||||||
|
HashSet::from([vr_variable.clone()])
|
||||||
|
} else {
|
||||||
|
HashSet::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
IrExpression::Parameter(_) => HashSet::new(),
|
IrExpression::Parameter(_) => HashSet::new(),
|
||||||
IrExpression::Variable(ir_variable) => {
|
IrExpression::Variable(ir_variable) => {
|
||||||
if let IrVariableDescriptor::VirtualRegister(vr_variable) =
|
if let IrVariableDescriptor::VirtualRegister(vr_variable) =
|
||||||
@ -242,6 +290,9 @@ impl VrUser for IrExpression {
|
|||||||
|
|
||||||
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {
|
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {
|
||||||
match self {
|
match self {
|
||||||
|
IrExpression::Field(self_variable, field_index) => {
|
||||||
|
// no-op, no defs
|
||||||
|
}
|
||||||
IrExpression::Parameter(_) => {
|
IrExpression::Parameter(_) => {
|
||||||
// no-op
|
// no-op
|
||||||
}
|
}
|
||||||
@ -278,6 +329,9 @@ impl VrUser for IrExpression {
|
|||||||
assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
||||||
) {
|
) {
|
||||||
match self {
|
match self {
|
||||||
|
IrExpression::Field(self_variable, field_index) => {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
IrExpression::Parameter(_) => {
|
IrExpression::Parameter(_) => {
|
||||||
// no-op
|
// no-op
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,8 +4,6 @@ use crate::ir::ir_block::IrBlock;
|
|||||||
use crate::ir::ir_parameter::IrParameter;
|
use crate::ir::ir_parameter::IrParameter;
|
||||||
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
||||||
use crate::ir::register_allocation::HasVrUsers;
|
use crate::ir::register_allocation::HasVrUsers;
|
||||||
use crate::symbol::Symbol;
|
|
||||||
use crate::symbol::function_symbol::FunctionSymbol;
|
|
||||||
use crate::type_info::TypeInfo;
|
use crate::type_info::TypeInfo;
|
||||||
use dvm_lib::vm::function::Function;
|
use dvm_lib::vm::function::Function;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
@ -14,7 +12,7 @@ use std::fmt::Display;
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct IrFunction {
|
pub struct IrFunction {
|
||||||
function_symbol: Rc<RefCell<FunctionSymbol>>,
|
fqn: Rc<str>,
|
||||||
parameters: Vec<Rc<IrParameter>>,
|
parameters: Vec<Rc<IrParameter>>,
|
||||||
return_type_info: TypeInfo,
|
return_type_info: TypeInfo,
|
||||||
entry: Rc<RefCell<IrBlock>>,
|
entry: Rc<RefCell<IrBlock>>,
|
||||||
@ -22,13 +20,13 @@ pub struct IrFunction {
|
|||||||
|
|
||||||
impl IrFunction {
|
impl IrFunction {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
function_symbol: Rc<RefCell<FunctionSymbol>>,
|
fqn: Rc<str>,
|
||||||
parameters: &[Rc<IrParameter>],
|
parameters: &[Rc<IrParameter>],
|
||||||
return_type_info: &TypeInfo,
|
return_type_info: &TypeInfo,
|
||||||
entry: Rc<RefCell<IrBlock>>,
|
entry: Rc<RefCell<IrBlock>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
function_symbol,
|
fqn,
|
||||||
parameters: parameters.to_vec(),
|
parameters: parameters.to_vec(),
|
||||||
return_type_info: return_type_info.clone(),
|
return_type_info: return_type_info.clone(),
|
||||||
entry,
|
entry,
|
||||||
@ -47,7 +45,7 @@ impl IrFunction {
|
|||||||
self.entry.borrow().assemble(&mut builder, constants_table);
|
self.entry.borrow().assemble(&mut builder, constants_table);
|
||||||
let instructions = builder.take_instructions();
|
let instructions = builder.take_instructions();
|
||||||
Function::new(
|
Function::new(
|
||||||
self.function_symbol.borrow().declared_name_owned(),
|
self.fqn.clone(),
|
||||||
self.parameters.len(),
|
self.parameters.len(),
|
||||||
stack_size,
|
stack_size,
|
||||||
instructions,
|
instructions,
|
||||||
@ -57,7 +55,7 @@ impl IrFunction {
|
|||||||
|
|
||||||
impl Display for IrFunction {
|
impl Display for IrFunction {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "fn {}(", self.function_symbol.borrow().declared_name())?;
|
write!(f, "fn {}(", self.fqn)?;
|
||||||
for (i, parameter) in self.parameters.iter().enumerate() {
|
for (i, parameter) in self.parameters.iter().enumerate() {
|
||||||
write!(f, "{}: {}", parameter, parameter.type_info())?;
|
write!(f, "{}: {}", parameter, parameter.type_info())?;
|
||||||
if i < self.parameters.len() - 1 {
|
if i < self.parameters.len() - 1 {
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
use crate::ir::ir_add::IrAdd;
|
use crate::ir::ir_add::IrAdd;
|
||||||
|
use crate::ir::ir_allocate::IrAllocate;
|
||||||
use crate::ir::ir_call::IrCall;
|
use crate::ir::ir_call::IrCall;
|
||||||
use crate::ir::ir_expression::IrExpression;
|
use crate::ir::ir_expression::IrExpression;
|
||||||
use crate::ir::ir_multiply::IrMultiply;
|
use crate::ir::ir_multiply::IrMultiply;
|
||||||
@ -14,6 +15,7 @@ pub enum IrOperation {
|
|||||||
Subtract(IrSubtract),
|
Subtract(IrSubtract),
|
||||||
Multiply(IrMultiply),
|
Multiply(IrMultiply),
|
||||||
Call(IrCall),
|
Call(IrCall),
|
||||||
|
Allocate(IrAllocate),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for IrOperation {
|
impl Display for IrOperation {
|
||||||
@ -34,6 +36,9 @@ impl Display for IrOperation {
|
|||||||
IrOperation::Call(ir_call) => {
|
IrOperation::Call(ir_call) => {
|
||||||
write!(f, "{}", ir_call)
|
write!(f, "{}", ir_call)
|
||||||
}
|
}
|
||||||
|
IrOperation::Allocate(ir_allocate) => {
|
||||||
|
write!(f, "{}", ir_allocate)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,6 +51,7 @@ impl VrUser for IrOperation {
|
|||||||
IrOperation::Subtract(ir_subtract) => ir_subtract.vr_definitions(),
|
IrOperation::Subtract(ir_subtract) => ir_subtract.vr_definitions(),
|
||||||
IrOperation::Multiply(ir_multiply) => ir_multiply.vr_definitions(),
|
IrOperation::Multiply(ir_multiply) => ir_multiply.vr_definitions(),
|
||||||
IrOperation::Call(ir_call) => ir_call.vr_definitions(),
|
IrOperation::Call(ir_call) => ir_call.vr_definitions(),
|
||||||
|
IrOperation::Allocate(_) => HashSet::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,6 +62,7 @@ impl VrUser for IrOperation {
|
|||||||
IrOperation::Subtract(ir_subtract) => ir_subtract.vr_uses(),
|
IrOperation::Subtract(ir_subtract) => ir_subtract.vr_uses(),
|
||||||
IrOperation::Multiply(ir_multiply) => ir_multiply.vr_uses(),
|
IrOperation::Multiply(ir_multiply) => ir_multiply.vr_uses(),
|
||||||
IrOperation::Call(ir_call) => ir_call.vr_uses(),
|
IrOperation::Call(ir_call) => ir_call.vr_uses(),
|
||||||
|
IrOperation::Allocate(_) => HashSet::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,6 +83,7 @@ impl VrUser for IrOperation {
|
|||||||
IrOperation::Call(ir_call) => {
|
IrOperation::Call(ir_call) => {
|
||||||
ir_call.propagate_spills(spills);
|
ir_call.propagate_spills(spills);
|
||||||
}
|
}
|
||||||
|
IrOperation::Allocate(_) => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,6 +107,7 @@ impl VrUser for IrOperation {
|
|||||||
IrOperation::Call(ir_call) => {
|
IrOperation::Call(ir_call) => {
|
||||||
ir_call.propagate_register_assignments(assignments);
|
ir_call.propagate_register_assignments(assignments);
|
||||||
}
|
}
|
||||||
|
IrOperation::Allocate(_) => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
98
dmc-lib/src/ir/ir_set_field.rs
Normal file
98
dmc-lib/src/ir/ir_set_field.rs
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
use crate::constants_table::ConstantsTable;
|
||||||
|
use crate::ir::assemble::{Assemble, InstructionsBuilder};
|
||||||
|
use crate::ir::ir_expression::IrExpression;
|
||||||
|
use crate::ir::ir_variable::{IrVariable, IrVariableDescriptor, IrVrVariableDescriptor};
|
||||||
|
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||||
|
use crate::ir::util::propagate_spills;
|
||||||
|
use dvm_lib::instruction::{Instruction, Location};
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub struct IrSetField {
|
||||||
|
target_object: Rc<RefCell<IrVariable>>,
|
||||||
|
field_index: usize,
|
||||||
|
initializer: Box<IrExpression>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IrSetField {
|
||||||
|
pub fn new(
|
||||||
|
target_object: &Rc<RefCell<IrVariable>>,
|
||||||
|
field_index: usize,
|
||||||
|
initializer: IrExpression,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
target_object: target_object.clone(),
|
||||||
|
field_index,
|
||||||
|
initializer: initializer.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VrUser for IrSetField {
|
||||||
|
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
|
// only this, because the target_object is technically not a definition
|
||||||
|
self.initializer.vr_definitions()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
|
let mut set = HashSet::new();
|
||||||
|
match self.target_object.borrow().descriptor() {
|
||||||
|
IrVariableDescriptor::VirtualRegister(vr_variable) => {
|
||||||
|
set.insert(vr_variable.clone());
|
||||||
|
}
|
||||||
|
IrVariableDescriptor::Stack(_) => {}
|
||||||
|
}
|
||||||
|
set.extend(self.initializer.vr_uses());
|
||||||
|
set
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {
|
||||||
|
propagate_spills(&mut self.target_object, spills);
|
||||||
|
self.initializer.propagate_spills(spills);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_register_assignments(
|
||||||
|
&mut self,
|
||||||
|
_assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
||||||
|
) {
|
||||||
|
// no definitions
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_stack_offsets(&mut self, _counter: &mut OffsetCounter) {
|
||||||
|
// no definitions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Assemble for IrSetField {
|
||||||
|
fn assemble(&self, builder: &mut InstructionsBuilder, constants_table: &mut ConstantsTable) {
|
||||||
|
let destination = match self.target_object.borrow().descriptor() {
|
||||||
|
IrVariableDescriptor::VirtualRegister(vr_variable) => {
|
||||||
|
Location::Register(vr_variable.assigned_register())
|
||||||
|
}
|
||||||
|
IrVariableDescriptor::Stack(stack_variable) => {
|
||||||
|
Location::StackFrameOffset(stack_variable.offset())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let set_field_operand = self.initializer.set_field_operand(constants_table);
|
||||||
|
builder.push(Instruction::SetField(
|
||||||
|
destination,
|
||||||
|
self.field_index,
|
||||||
|
set_field_operand,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for IrSetField {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}.{} = {}",
|
||||||
|
self.target_object.borrow(),
|
||||||
|
self.field_index,
|
||||||
|
self.initializer
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,6 +3,7 @@ use crate::ir::assemble::{Assemble, InstructionsBuilder};
|
|||||||
use crate::ir::ir_assign::IrAssign;
|
use crate::ir::ir_assign::IrAssign;
|
||||||
use crate::ir::ir_call::IrCall;
|
use crate::ir::ir_call::IrCall;
|
||||||
use crate::ir::ir_return::IrReturn;
|
use crate::ir::ir_return::IrReturn;
|
||||||
|
use crate::ir::ir_set_field::IrSetField;
|
||||||
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
||||||
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
@ -12,6 +13,7 @@ pub enum IrStatement {
|
|||||||
Assign(IrAssign),
|
Assign(IrAssign),
|
||||||
Call(IrCall),
|
Call(IrCall),
|
||||||
Return(IrReturn),
|
Return(IrReturn),
|
||||||
|
SetField(IrSetField),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VrUser for IrStatement {
|
impl VrUser for IrStatement {
|
||||||
@ -20,6 +22,7 @@ impl VrUser for IrStatement {
|
|||||||
IrStatement::Assign(ir_assign) => ir_assign.vr_definitions(),
|
IrStatement::Assign(ir_assign) => ir_assign.vr_definitions(),
|
||||||
IrStatement::Call(ir_call) => ir_call.vr_definitions(),
|
IrStatement::Call(ir_call) => ir_call.vr_definitions(),
|
||||||
IrStatement::Return(ir_return) => ir_return.vr_definitions(),
|
IrStatement::Return(ir_return) => ir_return.vr_definitions(),
|
||||||
|
IrStatement::SetField(ir_set_field) => ir_set_field.vr_definitions(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,6 +31,7 @@ impl VrUser for IrStatement {
|
|||||||
IrStatement::Assign(ir_assign) => ir_assign.vr_uses(),
|
IrStatement::Assign(ir_assign) => ir_assign.vr_uses(),
|
||||||
IrStatement::Call(ir_call) => ir_call.vr_uses(),
|
IrStatement::Call(ir_call) => ir_call.vr_uses(),
|
||||||
IrStatement::Return(ir_return) => ir_return.vr_uses(),
|
IrStatement::Return(ir_return) => ir_return.vr_uses(),
|
||||||
|
IrStatement::SetField(ir_set_field) => ir_set_field.vr_uses(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,6 +46,9 @@ impl VrUser for IrStatement {
|
|||||||
IrStatement::Return(ir_return) => {
|
IrStatement::Return(ir_return) => {
|
||||||
ir_return.propagate_spills(spills);
|
ir_return.propagate_spills(spills);
|
||||||
}
|
}
|
||||||
|
IrStatement::SetField(ir_set_field) => {
|
||||||
|
ir_set_field.propagate_spills(spills);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +66,9 @@ impl VrUser for IrStatement {
|
|||||||
IrStatement::Return(ir_return) => {
|
IrStatement::Return(ir_return) => {
|
||||||
ir_return.propagate_register_assignments(assignments);
|
ir_return.propagate_register_assignments(assignments);
|
||||||
}
|
}
|
||||||
|
IrStatement::SetField(ir_set_field) => {
|
||||||
|
ir_set_field.propagate_register_assignments(assignments);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,6 +83,9 @@ impl VrUser for IrStatement {
|
|||||||
IrStatement::Return(ir_return) => {
|
IrStatement::Return(ir_return) => {
|
||||||
ir_return.propagate_stack_offsets(counter);
|
ir_return.propagate_stack_offsets(counter);
|
||||||
}
|
}
|
||||||
|
IrStatement::SetField(ir_set_field) => {
|
||||||
|
ir_set_field.propagate_stack_offsets(counter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,6 +102,9 @@ impl Assemble for IrStatement {
|
|||||||
IrStatement::Return(ir_return) => {
|
IrStatement::Return(ir_return) => {
|
||||||
ir_return.assemble(builder, constants_table);
|
ir_return.assemble(builder, constants_table);
|
||||||
}
|
}
|
||||||
|
IrStatement::SetField(ir_set_field) => {
|
||||||
|
ir_set_field.assemble(builder, constants_table);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,6 +121,9 @@ impl Display for IrStatement {
|
|||||||
IrStatement::Return(ir_return) => {
|
IrStatement::Return(ir_return) => {
|
||||||
write!(f, "{}", ir_return)
|
write!(f, "{}", ir_return)
|
||||||
}
|
}
|
||||||
|
IrStatement::SetField(ir_set_field) => {
|
||||||
|
write!(f, "{}", ir_set_field)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -73,6 +73,13 @@ impl IrVariableDescriptor {
|
|||||||
IrVariableDescriptor::Stack(stack_variable) => stack_variable.name(),
|
IrVariableDescriptor::Stack(stack_variable) => stack_variable.name(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn name_owned(&self) -> Rc<str> {
|
||||||
|
match self {
|
||||||
|
IrVariableDescriptor::VirtualRegister(vr_variable) => vr_variable.name_owned(),
|
||||||
|
IrVariableDescriptor::Stack(stack_variable) => stack_variable.name_owned(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Hash, PartialEq, Eq)]
|
#[derive(Clone, Hash, PartialEq, Eq)]
|
||||||
@ -95,6 +102,10 @@ impl IrVrVariableDescriptor {
|
|||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn name_owned(&self) -> Rc<str> {
|
||||||
|
self.name.clone()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn block_id(&self) -> usize {
|
pub fn block_id(&self) -> usize {
|
||||||
self.block_id
|
self.block_id
|
||||||
}
|
}
|
||||||
@ -139,6 +150,10 @@ impl IrStackVariableDescriptor {
|
|||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn name_owned(&self) -> Rc<str> {
|
||||||
|
self.name.clone()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_offset(&mut self, offset: isize) {
|
pub fn set_offset(&mut self, offset: isize) {
|
||||||
self.offset = Some(offset);
|
self.offset = Some(offset);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
mod assemble;
|
mod assemble;
|
||||||
pub mod ir_add;
|
pub mod ir_add;
|
||||||
|
pub mod ir_allocate;
|
||||||
pub mod ir_assign;
|
pub mod ir_assign;
|
||||||
pub mod ir_block;
|
pub mod ir_block;
|
||||||
pub mod ir_call;
|
pub mod ir_call;
|
||||||
@ -9,7 +10,9 @@ pub mod ir_multiply;
|
|||||||
pub mod ir_operation;
|
pub mod ir_operation;
|
||||||
pub mod ir_parameter;
|
pub mod ir_parameter;
|
||||||
pub mod ir_return;
|
pub mod ir_return;
|
||||||
|
pub mod ir_set_field;
|
||||||
pub mod ir_statement;
|
pub mod ir_statement;
|
||||||
pub mod ir_subtract;
|
pub mod ir_subtract;
|
||||||
pub mod ir_variable;
|
pub mod ir_variable;
|
||||||
mod register_allocation;
|
mod register_allocation;
|
||||||
|
mod util;
|
||||||
|
|||||||
22
dmc-lib/src/ir/util.rs
Normal file
22
dmc-lib/src/ir/util.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use crate::ir::ir_variable::{
|
||||||
|
IrStackVariableDescriptor, IrVariable, IrVariableDescriptor, IrVrVariableDescriptor,
|
||||||
|
};
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub fn propagate_spills(
|
||||||
|
ir_variable: &mut Rc<RefCell<IrVariable>>,
|
||||||
|
spills: &HashSet<IrVrVariableDescriptor>,
|
||||||
|
) {
|
||||||
|
let mut borrowed_ir_variable = ir_variable.borrow_mut();
|
||||||
|
if let IrVariableDescriptor::VirtualRegister(vr_variable) = borrowed_ir_variable.descriptor() {
|
||||||
|
if spills.contains(vr_variable) {
|
||||||
|
let name = vr_variable.name_owned();
|
||||||
|
let block_id = vr_variable.block_id();
|
||||||
|
borrowed_ir_variable.set_descriptor(IrVariableDescriptor::Stack(
|
||||||
|
IrStackVariableDescriptor::new(name, block_id),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -39,6 +39,10 @@ impl ClassSymbol {
|
|||||||
self.constructor_symbol = constructor_symbol;
|
self.constructor_symbol = constructor_symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn fields(&self) -> &HashMap<Rc<str>, Rc<RefCell<FieldSymbol>>> {
|
||||||
|
&self.fields
|
||||||
|
}
|
||||||
|
|
||||||
/// A value of `None` indicates that there is no declared constructor for this class.
|
/// A value of `None` indicates that there is no declared constructor for this class.
|
||||||
pub fn constructor_symbol(&self) -> Option<&Rc<RefCell<ConstructorSymbol>>> {
|
pub fn constructor_symbol(&self) -> Option<&Rc<RefCell<ConstructorSymbol>>> {
|
||||||
self.constructor_symbol.as_ref()
|
self.constructor_symbol.as_ref()
|
||||||
|
|||||||
@ -39,6 +39,8 @@ impl ExpressibleSymbol {
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
ExpressibleSymbol::Field(field_symbol) => {
|
ExpressibleSymbol::Field(field_symbol) => {
|
||||||
|
// this, unfortunately, is going to need more context, because fields live longer
|
||||||
|
// than function calls
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
ExpressibleSymbol::Function(_) => {
|
ExpressibleSymbol::Function(_) => {
|
||||||
|
|||||||
@ -7,6 +7,7 @@ pub struct FieldSymbol {
|
|||||||
declared_name: Rc<str>,
|
declared_name: Rc<str>,
|
||||||
declared_name_source_range: SourceRange,
|
declared_name_source_range: SourceRange,
|
||||||
type_info: Option<TypeInfo>,
|
type_info: Option<TypeInfo>,
|
||||||
|
field_index: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FieldSymbol {
|
impl FieldSymbol {
|
||||||
@ -15,6 +16,7 @@ impl FieldSymbol {
|
|||||||
declared_name: declared_name.clone(),
|
declared_name: declared_name.clone(),
|
||||||
declared_name_source_range,
|
declared_name_source_range,
|
||||||
type_info: None,
|
type_info: None,
|
||||||
|
field_index: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,6 +27,14 @@ impl FieldSymbol {
|
|||||||
pub fn type_info(&self) -> &TypeInfo {
|
pub fn type_info(&self) -> &TypeInfo {
|
||||||
self.type_info.as_ref().unwrap()
|
self.type_info.as_ref().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_field_index(&mut self, field_index: usize) {
|
||||||
|
self.field_index = Some(field_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn field_index(&self) -> usize {
|
||||||
|
self.field_index.unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Symbol for FieldSymbol {
|
impl Symbol for FieldSymbol {
|
||||||
|
|||||||
@ -7,6 +7,8 @@ pub type ConstantName = Rc<str>;
|
|||||||
pub type FunctionName = Rc<str>;
|
pub type FunctionName = Rc<str>;
|
||||||
pub type ArgCount = usize;
|
pub type ArgCount = usize;
|
||||||
pub type CallerPopCount = usize;
|
pub type CallerPopCount = usize;
|
||||||
|
pub type ClassFqn = Rc<str>;
|
||||||
|
pub type FieldIndex = usize;
|
||||||
|
|
||||||
pub enum Instruction {
|
pub enum Instruction {
|
||||||
Move(MoveOperand, Location),
|
Move(MoveOperand, Location),
|
||||||
@ -15,6 +17,10 @@ pub enum Instruction {
|
|||||||
InvokeStatic(FunctionName, ArgCount),
|
InvokeStatic(FunctionName, ArgCount),
|
||||||
InvokePlatformStatic(FunctionName, ArgCount),
|
InvokePlatformStatic(FunctionName, ArgCount),
|
||||||
|
|
||||||
|
Allocate(ClassFqn, Location),
|
||||||
|
GetField(Location, FieldIndex, Location),
|
||||||
|
SetField(Location, FieldIndex, SetFieldOperand),
|
||||||
|
|
||||||
Add(AddOperand, AddOperand, Location),
|
Add(AddOperand, AddOperand, Location),
|
||||||
Subtract(SubtractOperand, SubtractOperand, Location),
|
Subtract(SubtractOperand, SubtractOperand, Location),
|
||||||
Multiply(MultiplyOperand, MultiplyOperand, Location),
|
Multiply(MultiplyOperand, MultiplyOperand, Location),
|
||||||
@ -64,6 +70,15 @@ impl Display for Instruction {
|
|||||||
Instruction::Return => {
|
Instruction::Return => {
|
||||||
write!(f, "ret")
|
write!(f, "ret")
|
||||||
}
|
}
|
||||||
|
Instruction::Allocate(class_fqn, location) => {
|
||||||
|
write!(f, "alloc {}, {}", class_fqn, location)
|
||||||
|
}
|
||||||
|
Instruction::GetField(source, field_index, destination) => {
|
||||||
|
write!(f, "getf {}.{}, {}", source, field_index, destination)
|
||||||
|
}
|
||||||
|
Instruction::SetField(target_location, field_index, operand) => {
|
||||||
|
write!(f, "setf {}.{}, {}", target_location, field_index, operand)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -237,3 +252,29 @@ impl Display for ReturnOperand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum SetFieldOperand {
|
||||||
|
Location(Location),
|
||||||
|
Int(i32),
|
||||||
|
Double(f64),
|
||||||
|
String(Rc<str>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for SetFieldOperand {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
SetFieldOperand::Location(location) => {
|
||||||
|
write!(f, "{}", location)
|
||||||
|
}
|
||||||
|
SetFieldOperand::Int(i) => {
|
||||||
|
write!(f, "{}", i)
|
||||||
|
}
|
||||||
|
SetFieldOperand::Double(d) => {
|
||||||
|
write!(f, "{}", d)
|
||||||
|
}
|
||||||
|
SetFieldOperand::String(s) => {
|
||||||
|
write!(f, "{}", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -318,6 +318,29 @@ pub fn call<'a>(
|
|||||||
call_stack.top_mut().increment_ip();
|
call_stack.top_mut().increment_ip();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Object instructions */
|
||||||
|
Instruction::Allocate(class_fqn, destination) => {
|
||||||
|
// let class = context.classes().get(class_fqn).expect("No such class loaded: {}")
|
||||||
|
// let object: Gc<GcCell<Object>> = Object::new(class, heap)
|
||||||
|
// let value = Value::Object(object)
|
||||||
|
// put_value(registers, call_stack.top_mut(), destination, result)
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
Instruction::GetField(source, field_index, destination) => {
|
||||||
|
// let object = load_value(...).unwrap_object();
|
||||||
|
// let field_value = object.fields()[field_index];
|
||||||
|
// put_value(..., destination, field_value.clone());
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
Instruction::SetField(target, field_index, operand) => {
|
||||||
|
// let new_value = to_value(operand);
|
||||||
|
// let object = load_value(... target).unwrap_object();
|
||||||
|
// object.fields_mut()[field_index] = new_value;
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
/* Add instructions */
|
/* Add instructions */
|
||||||
Instruction::Add(left_operand, right_operand, destination) => {
|
Instruction::Add(left_operand, right_operand, destination) => {
|
||||||
let left_value = add_operand_to_value(
|
let left_value = add_operand_to_value(
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user