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::lexer::Lexer;
|
||||
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::token::TokenKind;
|
||||
use dvm_lib::vm::constant::{Constant, StringConstant};
|
||||
use dvm_lib::vm::function::Function;
|
||||
use dvm_lib::vm::value::Value;
|
||||
use dvm_lib::vm::{CallStack, DvmContext, call};
|
||||
use std::cell::RefCell;
|
||||
use std::io;
|
||||
use std::io::Write;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub fn repl(register_count: usize) {
|
||||
let mut buffer = String::new();
|
||||
@ -128,19 +124,8 @@ fn compile_expression(
|
||||
ir_builder.finish_block();
|
||||
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(
|
||||
fake_function_symbol,
|
||||
"__repl".into(),
|
||||
&[],
|
||||
expression.type_info(),
|
||||
entry_block.clone(),
|
||||
|
||||
@ -2,9 +2,11 @@ use crate::ast::constructor::Constructor;
|
||||
use crate::ast::field::Field;
|
||||
use crate::ast::function::Function;
|
||||
use crate::diagnostic::{Diagnostic, SecondaryLabel};
|
||||
use crate::ir::ir_function::IrFunction;
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::symbol::class_symbol::ClassSymbol;
|
||||
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashSet;
|
||||
use std::rc::Rc;
|
||||
|
||||
@ -14,6 +16,7 @@ pub struct Class {
|
||||
constructor: Option<Constructor>,
|
||||
fields: Vec<Field>,
|
||||
functions: Vec<Function>,
|
||||
class_symbol: Option<Rc<RefCell<ClassSymbol>>>,
|
||||
}
|
||||
|
||||
impl Class {
|
||||
@ -30,6 +33,7 @@ impl Class {
|
||||
constructor,
|
||||
fields,
|
||||
functions,
|
||||
class_symbol: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,6 +72,9 @@ impl Class {
|
||||
}
|
||||
})?;
|
||||
|
||||
// save symbol for later
|
||||
self.class_symbol = Some(class_symbol);
|
||||
|
||||
// 2. push scope
|
||||
symbol_table.push_class_scope(&format!("class_scope({})", self.declared_name));
|
||||
|
||||
@ -75,7 +82,8 @@ impl Class {
|
||||
let fields_diagnostics: Vec<Diagnostic> = self
|
||||
.fields
|
||||
.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)
|
||||
.flatten()
|
||||
.collect();
|
||||
@ -87,7 +95,9 @@ impl Class {
|
||||
// 4. gather constructor
|
||||
if let Some(constructor) = &mut self.constructor {
|
||||
let constructor_symbol = constructor.gather_declared_names(symbol_table)?;
|
||||
class_symbol
|
||||
self.class_symbol
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.borrow_mut()
|
||||
.set_constructor_symbol(Some(constructor_symbol));
|
||||
}
|
||||
@ -231,11 +241,29 @@ impl Class {
|
||||
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)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::constants_table::ConstantsTable;
|
||||
use crate::parser::parse_compilation_unit;
|
||||
|
||||
#[test]
|
||||
@ -289,5 +317,13 @@ mod tests {
|
||||
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> {
|
||||
let mut functions: Vec<IrFunction> = vec![];
|
||||
self.functions
|
||||
.iter()
|
||||
.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::statement::Statement;
|
||||
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::symbol::Symbol;
|
||||
use crate::symbol::class_symbol::ClassSymbol;
|
||||
use crate::symbol::constructor_symbol::ConstructorSymbol;
|
||||
use crate::symbol::parameter_symbol::ParameterSymbol;
|
||||
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
||||
use crate::type_info::TypeInfo;
|
||||
use std::cell::RefCell;
|
||||
use std::ops::Neg;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct Constructor {
|
||||
@ -156,4 +171,71 @@ impl Constructor {
|
||||
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(
|
||||
&mut self,
|
||||
symbol_table: &mut SymbolTable,
|
||||
field_index: usize,
|
||||
) -> Result<(), Vec<Diagnostic>> {
|
||||
// 1. insert field symbol
|
||||
let to_insert =
|
||||
@ -75,6 +76,13 @@ impl Field {
|
||||
// save for later
|
||||
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
|
||||
if let Some(type_use) = &mut self.declared_type {
|
||||
type_use.gather_declared_names(symbol_table)?;
|
||||
@ -181,4 +189,8 @@ impl Field {
|
||||
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();
|
||||
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(),
|
||||
return_type_info,
|
||||
entry_block,
|
||||
|
||||
@ -74,6 +74,9 @@ impl NegativeExpression {
|
||||
.expect("Attempt to negate non-value expression");
|
||||
|
||||
match operand_as_ir {
|
||||
IrExpression::Field(self_variable, _) => {
|
||||
todo!()
|
||||
}
|
||||
IrExpression::Parameter(parameter) => {
|
||||
let destination = Rc::new(RefCell::new(IrVariable::new_vr(
|
||||
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);
|
||||
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::type_info::TypeInfo;
|
||||
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::collections::{HashMap, HashSet};
|
||||
@ -14,6 +15,7 @@ use std::fmt::{Display, Formatter};
|
||||
use std::rc::Rc;
|
||||
|
||||
pub enum IrExpression {
|
||||
Field(Rc<RefCell<IrVariable>>, usize),
|
||||
Parameter(Rc<IrParameter>),
|
||||
Variable(Rc<RefCell<IrVariable>>),
|
||||
Int(i32),
|
||||
@ -22,18 +24,11 @@ pub enum 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 {
|
||||
match self {
|
||||
IrExpression::Field(self_variable, _) => {
|
||||
todo!()
|
||||
}
|
||||
IrExpression::Parameter(ir_parameter) => {
|
||||
MoveOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
||||
}
|
||||
@ -56,6 +51,9 @@ impl IrExpression {
|
||||
|
||||
pub fn push_operand(&self, constants_table: &mut ConstantsTable) -> PushOperand {
|
||||
match self {
|
||||
IrExpression::Field(self_variable, _) => {
|
||||
todo!()
|
||||
}
|
||||
IrExpression::Parameter(ir_parameter) => {
|
||||
PushOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
||||
}
|
||||
@ -78,6 +76,9 @@ impl IrExpression {
|
||||
|
||||
pub fn add_operand(&self, constants_table: &mut ConstantsTable) -> AddOperand {
|
||||
match self {
|
||||
IrExpression::Field(self_variable, _) => {
|
||||
todo!()
|
||||
}
|
||||
IrExpression::Parameter(ir_parameter) => match ir_parameter.type_info() {
|
||||
TypeInfo::Integer | TypeInfo::Double | TypeInfo::String => {
|
||||
AddOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
||||
@ -116,6 +117,9 @@ impl IrExpression {
|
||||
|
||||
pub fn subtract_operand(&self) -> SubtractOperand {
|
||||
match self {
|
||||
IrExpression::Field(self_variable, _) => {
|
||||
todo!()
|
||||
}
|
||||
IrExpression::Parameter(ir_parameter) => match ir_parameter.type_info() {
|
||||
TypeInfo::Integer | TypeInfo::Double => SubtractOperand::Location(
|
||||
Location::StackFrameOffset(ir_parameter.stack_offset()),
|
||||
@ -151,6 +155,9 @@ impl IrExpression {
|
||||
|
||||
pub fn multiply_operand(&self) -> MultiplyOperand {
|
||||
match self {
|
||||
IrExpression::Field(self_variable, _) => {
|
||||
todo!()
|
||||
}
|
||||
IrExpression::Parameter(ir_parameter) => {
|
||||
MultiplyOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
||||
}
|
||||
@ -172,6 +179,9 @@ impl IrExpression {
|
||||
|
||||
pub fn return_operand(&self, constants_table: &mut ConstantsTable) -> ReturnOperand {
|
||||
match self {
|
||||
IrExpression::Field(self_variable, _) => {
|
||||
todo!()
|
||||
}
|
||||
IrExpression::Parameter(ir_parameter) => {
|
||||
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 {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
IrExpression::Field(self_variable, field_index) => {
|
||||
write!(f, "{}.{}", self_variable.borrow(), field_index)
|
||||
}
|
||||
IrExpression::Parameter(ir_parameter) => {
|
||||
write!(f, "{}", ir_parameter)
|
||||
}
|
||||
@ -219,11 +257,21 @@ impl Display for IrExpression {
|
||||
|
||||
impl VrUser for IrExpression {
|
||||
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||
// no defs for an expression
|
||||
HashSet::new()
|
||||
}
|
||||
|
||||
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||
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::Variable(ir_variable) => {
|
||||
if let IrVariableDescriptor::VirtualRegister(vr_variable) =
|
||||
@ -242,6 +290,9 @@ impl VrUser for IrExpression {
|
||||
|
||||
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {
|
||||
match self {
|
||||
IrExpression::Field(self_variable, field_index) => {
|
||||
// no-op, no defs
|
||||
}
|
||||
IrExpression::Parameter(_) => {
|
||||
// no-op
|
||||
}
|
||||
@ -278,6 +329,9 @@ impl VrUser for IrExpression {
|
||||
assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
||||
) {
|
||||
match self {
|
||||
IrExpression::Field(self_variable, field_index) => {
|
||||
// no-op
|
||||
}
|
||||
IrExpression::Parameter(_) => {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@ -4,8 +4,6 @@ use crate::ir::ir_block::IrBlock;
|
||||
use crate::ir::ir_parameter::IrParameter;
|
||||
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
||||
use crate::ir::register_allocation::HasVrUsers;
|
||||
use crate::symbol::Symbol;
|
||||
use crate::symbol::function_symbol::FunctionSymbol;
|
||||
use crate::type_info::TypeInfo;
|
||||
use dvm_lib::vm::function::Function;
|
||||
use std::cell::RefCell;
|
||||
@ -14,7 +12,7 @@ use std::fmt::Display;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct IrFunction {
|
||||
function_symbol: Rc<RefCell<FunctionSymbol>>,
|
||||
fqn: Rc<str>,
|
||||
parameters: Vec<Rc<IrParameter>>,
|
||||
return_type_info: TypeInfo,
|
||||
entry: Rc<RefCell<IrBlock>>,
|
||||
@ -22,13 +20,13 @@ pub struct IrFunction {
|
||||
|
||||
impl IrFunction {
|
||||
pub fn new(
|
||||
function_symbol: Rc<RefCell<FunctionSymbol>>,
|
||||
fqn: Rc<str>,
|
||||
parameters: &[Rc<IrParameter>],
|
||||
return_type_info: &TypeInfo,
|
||||
entry: Rc<RefCell<IrBlock>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
function_symbol,
|
||||
fqn,
|
||||
parameters: parameters.to_vec(),
|
||||
return_type_info: return_type_info.clone(),
|
||||
entry,
|
||||
@ -47,7 +45,7 @@ impl IrFunction {
|
||||
self.entry.borrow().assemble(&mut builder, constants_table);
|
||||
let instructions = builder.take_instructions();
|
||||
Function::new(
|
||||
self.function_symbol.borrow().declared_name_owned(),
|
||||
self.fqn.clone(),
|
||||
self.parameters.len(),
|
||||
stack_size,
|
||||
instructions,
|
||||
@ -57,7 +55,7 @@ impl IrFunction {
|
||||
|
||||
impl Display for IrFunction {
|
||||
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() {
|
||||
write!(f, "{}: {}", parameter, parameter.type_info())?;
|
||||
if i < self.parameters.len() - 1 {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use crate::ir::ir_add::IrAdd;
|
||||
use crate::ir::ir_allocate::IrAllocate;
|
||||
use crate::ir::ir_call::IrCall;
|
||||
use crate::ir::ir_expression::IrExpression;
|
||||
use crate::ir::ir_multiply::IrMultiply;
|
||||
@ -14,6 +15,7 @@ pub enum IrOperation {
|
||||
Subtract(IrSubtract),
|
||||
Multiply(IrMultiply),
|
||||
Call(IrCall),
|
||||
Allocate(IrAllocate),
|
||||
}
|
||||
|
||||
impl Display for IrOperation {
|
||||
@ -34,6 +36,9 @@ impl Display for IrOperation {
|
||||
IrOperation::Call(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::Multiply(ir_multiply) => ir_multiply.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::Multiply(ir_multiply) => ir_multiply.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) => {
|
||||
ir_call.propagate_spills(spills);
|
||||
}
|
||||
IrOperation::Allocate(_) => (),
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,6 +107,7 @@ impl VrUser for IrOperation {
|
||||
IrOperation::Call(ir_call) => {
|
||||
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_call::IrCall;
|
||||
use crate::ir::ir_return::IrReturn;
|
||||
use crate::ir::ir_set_field::IrSetField;
|
||||
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
||||
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
@ -12,6 +13,7 @@ pub enum IrStatement {
|
||||
Assign(IrAssign),
|
||||
Call(IrCall),
|
||||
Return(IrReturn),
|
||||
SetField(IrSetField),
|
||||
}
|
||||
|
||||
impl VrUser for IrStatement {
|
||||
@ -20,6 +22,7 @@ impl VrUser for IrStatement {
|
||||
IrStatement::Assign(ir_assign) => ir_assign.vr_definitions(),
|
||||
IrStatement::Call(ir_call) => ir_call.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::Call(ir_call) => ir_call.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) => {
|
||||
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) => {
|
||||
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) => {
|
||||
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) => {
|
||||
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) => {
|
||||
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(),
|
||||
}
|
||||
}
|
||||
|
||||
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)]
|
||||
@ -95,6 +102,10 @@ impl IrVrVariableDescriptor {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn name_owned(&self) -> Rc<str> {
|
||||
self.name.clone()
|
||||
}
|
||||
|
||||
pub fn block_id(&self) -> usize {
|
||||
self.block_id
|
||||
}
|
||||
@ -139,6 +150,10 @@ impl IrStackVariableDescriptor {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn name_owned(&self) -> Rc<str> {
|
||||
self.name.clone()
|
||||
}
|
||||
|
||||
pub fn set_offset(&mut self, offset: isize) {
|
||||
self.offset = Some(offset);
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
mod assemble;
|
||||
pub mod ir_add;
|
||||
pub mod ir_allocate;
|
||||
pub mod ir_assign;
|
||||
pub mod ir_block;
|
||||
pub mod ir_call;
|
||||
@ -9,7 +10,9 @@ pub mod ir_multiply;
|
||||
pub mod ir_operation;
|
||||
pub mod ir_parameter;
|
||||
pub mod ir_return;
|
||||
pub mod ir_set_field;
|
||||
pub mod ir_statement;
|
||||
pub mod ir_subtract;
|
||||
pub mod ir_variable;
|
||||
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;
|
||||
}
|
||||
|
||||
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.
|
||||
pub fn constructor_symbol(&self) -> Option<&Rc<RefCell<ConstructorSymbol>>> {
|
||||
self.constructor_symbol.as_ref()
|
||||
|
||||
@ -39,6 +39,8 @@ impl ExpressibleSymbol {
|
||||
todo!()
|
||||
}
|
||||
ExpressibleSymbol::Field(field_symbol) => {
|
||||
// this, unfortunately, is going to need more context, because fields live longer
|
||||
// than function calls
|
||||
todo!()
|
||||
}
|
||||
ExpressibleSymbol::Function(_) => {
|
||||
|
||||
@ -7,6 +7,7 @@ pub struct FieldSymbol {
|
||||
declared_name: Rc<str>,
|
||||
declared_name_source_range: SourceRange,
|
||||
type_info: Option<TypeInfo>,
|
||||
field_index: Option<usize>,
|
||||
}
|
||||
|
||||
impl FieldSymbol {
|
||||
@ -15,6 +16,7 @@ impl FieldSymbol {
|
||||
declared_name: declared_name.clone(),
|
||||
declared_name_source_range,
|
||||
type_info: None,
|
||||
field_index: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,6 +27,14 @@ impl FieldSymbol {
|
||||
pub fn type_info(&self) -> &TypeInfo {
|
||||
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 {
|
||||
|
||||
@ -7,6 +7,8 @@ pub type ConstantName = Rc<str>;
|
||||
pub type FunctionName = Rc<str>;
|
||||
pub type ArgCount = usize;
|
||||
pub type CallerPopCount = usize;
|
||||
pub type ClassFqn = Rc<str>;
|
||||
pub type FieldIndex = usize;
|
||||
|
||||
pub enum Instruction {
|
||||
Move(MoveOperand, Location),
|
||||
@ -15,6 +17,10 @@ pub enum Instruction {
|
||||
InvokeStatic(FunctionName, ArgCount),
|
||||
InvokePlatformStatic(FunctionName, ArgCount),
|
||||
|
||||
Allocate(ClassFqn, Location),
|
||||
GetField(Location, FieldIndex, Location),
|
||||
SetField(Location, FieldIndex, SetFieldOperand),
|
||||
|
||||
Add(AddOperand, AddOperand, Location),
|
||||
Subtract(SubtractOperand, SubtractOperand, Location),
|
||||
Multiply(MultiplyOperand, MultiplyOperand, Location),
|
||||
@ -64,6 +70,15 @@ impl Display for Instruction {
|
||||
Instruction::Return => {
|
||||
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();
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
Instruction::Add(left_operand, right_operand, destination) => {
|
||||
let left_value = add_operand_to_value(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user