From 5be778ba80ba584020ebee698384d2ce96fb3f60 Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Fri, 13 Mar 2026 16:19:53 -0500 Subject: [PATCH] Fix some ir-related things with fields. --- dmc-lib/src/ast/constructor.rs | 12 ++++++- dmc-lib/src/ast/function.rs | 28 ++++------------ dmc-lib/src/ast/ir_builder.rs | 16 +++++---- dmc-lib/src/ir/ir_assign.rs | 16 +++------ dmc-lib/src/ir/ir_get_field_ref.rs | 28 ++++++++-------- dmc-lib/src/ir/ir_get_field_ref_mut.rs | 24 +++++--------- dmc-lib/src/ir/ir_parameter_or_variable.rs | 38 ++++++++++++++++++++++ dmc-lib/src/ir/mod.rs | 1 + dmc-lib/src/symbol/expressible_symbol.rs | 4 +-- 9 files changed, 95 insertions(+), 72 deletions(-) create mode 100644 dmc-lib/src/ir/ir_parameter_or_variable.rs diff --git a/dmc-lib/src/ast/constructor.rs b/dmc-lib/src/ast/constructor.rs index 664b17b..2b409f4 100644 --- a/dmc-lib/src/ast/constructor.rs +++ b/dmc-lib/src/ast/constructor.rs @@ -10,6 +10,8 @@ use crate::ir::ir_function::IrFunction; use crate::ir::ir_get_field_ref_mut::IrGetFieldRefMut; use crate::ir::ir_operation::IrOperation; use crate::ir::ir_parameter::IrParameter; +use crate::ir::ir_parameter_or_variable::IrParameterOrVariable; +use crate::ir::ir_return::IrReturn; use crate::ir::ir_set_field::IrSetField; use crate::ir::ir_statement::IrStatement; use crate::ir::ir_variable::IrVariable; @@ -223,7 +225,7 @@ impl Constructor { if let Some(initializer) = field.initializer() { // get a mut ref to the field let ir_get_field_ref_mut = IrGetFieldRefMut::new( - self_variable.clone(), + IrParameterOrVariable::Variable(self_variable.clone()), field.field_symbol().borrow().field_index(), ); let field_mut_ref_variable_name: Rc = ir_builder.new_t_var().into(); @@ -263,6 +265,14 @@ impl Constructor { } } + // return complete self object + let ir_return_statement = IrStatement::Return(IrReturn::new(Some(IrExpression::Variable( + self_variable.clone(), + )))); + ir_builder + .current_block_mut() + .add_statement(ir_return_statement); + ir_builder.finish_block(); let entry_block = ir_builder.get_block(entry_block_id); diff --git a/dmc-lib/src/ast/function.rs b/dmc-lib/src/ast/function.rs index 4ba6ee0..6f63f8c 100644 --- a/dmc-lib/src/ast/function.rs +++ b/dmc-lib/src/ast/function.rs @@ -3,17 +3,13 @@ use crate::ast::parameter::Parameter; use crate::ast::statement::Statement; use crate::ast::type_use::TypeUse; use crate::diagnostic::Diagnostic; -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_statement::IrStatement; -use crate::ir::ir_variable::IrVariable; +use crate::ir::ir_parameter_or_variable::IrParameterOrVariable; use crate::source_range::SourceRange; -use crate::symbol::Symbol; use crate::symbol::class_symbol::ClassSymbol; use crate::symbol::function_symbol::FunctionSymbol; +use crate::symbol::Symbol; use crate::symbol_table::{SymbolInsertError, SymbolTable}; use crate::type_info::TypeInfo; use std::cell::RefCell; @@ -288,23 +284,11 @@ impl Function { let entry_block_id = builder.new_block(); // preamble - // if we are a method, we need to put parameter 0 in a register - if let Some(class_symbol) = class_context { - let self_variable = IrVariable::new_vr( - "__self".into(), - entry_block_id, - &TypeInfo::ClassInstance(class_symbol.clone()), - ); - let as_rc = Rc::new(RefCell::new(self_variable)); + // if we are a method, we need to set the self parameter on the builder + if let Some(_) = class_context { let parameter_0 = builder.parameters()[0].clone(); - // put it in the self variable - builder - .current_block_mut() - .add_statement(IrStatement::Assign(IrAssign::new( - as_rc.clone(), - IrOperation::Load(IrExpression::Parameter(parameter_0)), - ))); - builder.set_self_variable(as_rc); + // put it in the self parameter + builder.set_self_parameter_or_variable(IrParameterOrVariable::IrParameter(parameter_0)); } let function_symbol = self.function_symbol.as_ref().unwrap().borrow(); diff --git a/dmc-lib/src/ast/ir_builder.rs b/dmc-lib/src/ast/ir_builder.rs index 28878f0..176970e 100644 --- a/dmc-lib/src/ast/ir_builder.rs +++ b/dmc-lib/src/ast/ir_builder.rs @@ -1,5 +1,6 @@ use crate::ir::ir_block::IrBlock; use crate::ir::ir_parameter::IrParameter; +use crate::ir::ir_parameter_or_variable::IrParameterOrVariable; use crate::ir::ir_statement::IrStatement; use crate::ir::ir_variable::IrVariable; use std::cell::RefCell; @@ -12,7 +13,7 @@ pub struct IrBuilder { t_var_counter: usize, blocks: HashMap>>, current_block_builder: Option, - self_variable: Option>>, + self_parameter_or_variable: Option, field_variables: HashMap, Rc>>, mut_field_variables: HashMap, Rc>>, } @@ -25,7 +26,7 @@ impl IrBuilder { t_var_counter: 0, blocks: HashMap::new(), current_block_builder: None, - self_variable: None, + self_parameter_or_variable: None, field_variables: HashMap::new(), mut_field_variables: HashMap::new(), } @@ -80,12 +81,15 @@ impl IrBuilder { format!("t{}", id) } - pub fn set_self_variable(&mut self, self_variable: Rc>) { - self.self_variable = Some(self_variable); + pub fn set_self_parameter_or_variable( + &mut self, + self_parameter_or_variable: IrParameterOrVariable, + ) { + self.self_parameter_or_variable = Some(self_parameter_or_variable); } - pub fn self_variable(&self) -> &Rc> { - self.self_variable.as_ref().unwrap() + pub fn self_parameter_or_variable(&self) -> &IrParameterOrVariable { + self.self_parameter_or_variable.as_ref().unwrap() } pub fn field_pointer_variables(&self) -> &HashMap, Rc>> { diff --git a/dmc-lib/src/ir/ir_assign.rs b/dmc-lib/src/ir/ir_assign.rs index 0692966..b17c8e2 100644 --- a/dmc-lib/src/ir/ir_assign.rs +++ b/dmc-lib/src/ir/ir_assign.rs @@ -83,26 +83,20 @@ impl Assemble for IrAssign { match self.initializer.as_ref() { IrOperation::GetFieldRef(ir_get_field_ref) => { - let self_location = ir_get_field_ref - .self_variable() - .borrow() - .descriptor() - .as_location(); + let self_location = ir_get_field_ref.self_parameter_or_variable().as_location(); builder.push(Instruction::GetFieldPointer( self_location, ir_get_field_ref.field_index(), destination, )); } - IrOperation::GetFieldRefMut(ir_get_field_ref) => { - let self_location = ir_get_field_ref - .self_variable() - .borrow() - .descriptor() + IrOperation::GetFieldRefMut(ir_get_field_ref_mut) => { + let self_location = ir_get_field_ref_mut + .self_parameter_or_variable() .as_location(); builder.push(Instruction::GetFieldPointerMut( self_location, - ir_get_field_ref.field_index(), + ir_get_field_ref_mut.field_index(), destination, )); } diff --git a/dmc-lib/src/ir/ir_get_field_ref.rs b/dmc-lib/src/ir/ir_get_field_ref.rs index 76f1cee..3dcf46e 100644 --- a/dmc-lib/src/ir/ir_get_field_ref.rs +++ b/dmc-lib/src/ir/ir_get_field_ref.rs @@ -1,25 +1,24 @@ -use crate::ir::ir_variable::{IrVariable, IrVariableDescriptor, IrVrVariableDescriptor}; +use crate::ir::ir_parameter_or_variable::IrParameterOrVariable; +use crate::ir::ir_variable::IrVrVariableDescriptor; use crate::ir::register_allocation::{OffsetCounter, VrUser}; -use std::cell::RefCell; use std::collections::{HashMap, HashSet}; use std::fmt::{Display, Formatter}; -use std::rc::Rc; pub struct IrGetFieldRef { - self_variable: Rc>, + self_parameter_or_variable: IrParameterOrVariable, field_index: usize, } impl IrGetFieldRef { - pub fn new(self_variable: Rc>, field_index: usize) -> Self { + pub fn new(self_parameter_or_variable: IrParameterOrVariable, field_index: usize) -> Self { Self { - self_variable, + self_parameter_or_variable, field_index, } } - pub fn self_variable(&self) -> &Rc> { - &self.self_variable + pub fn self_parameter_or_variable(&self) -> &IrParameterOrVariable { + &self.self_parameter_or_variable } pub fn field_index(&self) -> usize { @@ -29,7 +28,11 @@ impl IrGetFieldRef { impl Display for IrGetFieldRef { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "&{}.{}", self.self_variable.borrow(), self.field_index) + write!( + f, + "&{}.{}", + self.self_parameter_or_variable, self.field_index + ) } } @@ -39,12 +42,7 @@ impl VrUser for IrGetFieldRef { } fn vr_uses(&self) -> HashSet { - match self.self_variable.borrow().descriptor() { - IrVariableDescriptor::VirtualRegister(vr_variable) => { - HashSet::from([vr_variable.clone()]) - } - IrVariableDescriptor::Stack(_) => HashSet::new(), - } + HashSet::new() } fn propagate_spills(&mut self, spills: &HashSet) {} diff --git a/dmc-lib/src/ir/ir_get_field_ref_mut.rs b/dmc-lib/src/ir/ir_get_field_ref_mut.rs index f5b8b8a..ff854f0 100644 --- a/dmc-lib/src/ir/ir_get_field_ref_mut.rs +++ b/dmc-lib/src/ir/ir_get_field_ref_mut.rs @@ -1,25 +1,24 @@ -use crate::ir::ir_variable::{IrVariable, IrVariableDescriptor, IrVrVariableDescriptor}; +use crate::ir::ir_parameter_or_variable::IrParameterOrVariable; +use crate::ir::ir_variable::IrVrVariableDescriptor; use crate::ir::register_allocation::{OffsetCounter, VrUser}; -use std::cell::RefCell; use std::collections::{HashMap, HashSet}; use std::fmt::{Display, Formatter}; -use std::rc::Rc; pub struct IrGetFieldRefMut { - self_variable: Rc>, + self_parameter_or_variable: IrParameterOrVariable, field_index: usize, } impl IrGetFieldRefMut { - pub fn new(self_variable: Rc>, field_index: usize) -> Self { + pub fn new(self_parameter_or_variable: IrParameterOrVariable, field_index: usize) -> Self { Self { - self_variable, + self_parameter_or_variable, field_index, } } - pub fn self_variable(&self) -> &Rc> { - &self.self_variable + pub fn self_parameter_or_variable(&self) -> &IrParameterOrVariable { + &self.self_parameter_or_variable } pub fn field_index(&self) -> usize { @@ -32,7 +31,7 @@ impl Display for IrGetFieldRefMut { write!( f, "&mut {}.{}", - self.self_variable.borrow(), + self.self_parameter_or_variable, self.field_index() ) } @@ -44,12 +43,7 @@ impl VrUser for IrGetFieldRefMut { } fn vr_uses(&self) -> HashSet { - match self.self_variable.borrow().descriptor() { - IrVariableDescriptor::VirtualRegister(vr_variable) => { - HashSet::from([vr_variable.clone()]) - } - IrVariableDescriptor::Stack(stack_variable) => HashSet::new(), - } + HashSet::new() } fn propagate_spills(&mut self, spills: &HashSet) {} diff --git a/dmc-lib/src/ir/ir_parameter_or_variable.rs b/dmc-lib/src/ir/ir_parameter_or_variable.rs new file mode 100644 index 0000000..895e7cf --- /dev/null +++ b/dmc-lib/src/ir/ir_parameter_or_variable.rs @@ -0,0 +1,38 @@ +use crate::ir::ir_parameter::IrParameter; +use crate::ir::ir_variable::IrVariable; +use dvm_lib::instruction::Location; +use std::cell::RefCell; +use std::fmt::{Display, Formatter}; +use std::rc::Rc; + +#[derive(Clone)] +pub enum IrParameterOrVariable { + IrParameter(Rc), + Variable(Rc>), +} + +impl IrParameterOrVariable { + pub fn as_location(&self) -> Location { + match self { + IrParameterOrVariable::IrParameter(ir_parameter) => { + Location::StackFrameOffset(ir_parameter.stack_offset()) + } + IrParameterOrVariable::Variable(ir_variable) => { + ir_variable.borrow().descriptor().as_location() + } + } + } +} + +impl Display for IrParameterOrVariable { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + IrParameterOrVariable::IrParameter(ir_parameter) => { + write!(f, "{}", ir_parameter) + } + IrParameterOrVariable::Variable(ir_variable) => { + write!(f, "{}", ir_variable.borrow()) + } + } + } +} diff --git a/dmc-lib/src/ir/mod.rs b/dmc-lib/src/ir/mod.rs index 1248fc8..726bdaf 100644 --- a/dmc-lib/src/ir/mod.rs +++ b/dmc-lib/src/ir/mod.rs @@ -11,6 +11,7 @@ pub mod ir_get_field_ref_mut; pub mod ir_multiply; pub mod ir_operation; pub mod ir_parameter; +pub mod ir_parameter_or_variable; pub mod ir_read_field; pub mod ir_return; pub mod ir_set_field; diff --git a/dmc-lib/src/symbol/expressible_symbol.rs b/dmc-lib/src/symbol/expressible_symbol.rs index 9ad5762..6b76261 100644 --- a/dmc-lib/src/symbol/expressible_symbol.rs +++ b/dmc-lib/src/symbol/expressible_symbol.rs @@ -61,13 +61,13 @@ impl ExpressibleSymbol { ); let as_rc = Rc::new(RefCell::new(field_ref_variable)); let to_insert = as_rc.clone(); - let self_variable = builder.self_variable().clone(); + let self_parameter_or_variable = builder.self_parameter_or_variable().clone(); builder .current_block_mut() .add_statement(IrStatement::Assign(IrAssign::new( as_rc, IrOperation::GetFieldRef(IrGetFieldRef::new( - self_variable, + self_parameter_or_variable.clone(), field_symbol.borrow().field_index(), )), )));