diff --git a/dmc-lib/src/asm/asm_block.rs b/dmc-lib/src/asm/asm_block.rs new file mode 100644 index 0000000..eea1e35 --- /dev/null +++ b/dmc-lib/src/asm/asm_block.rs @@ -0,0 +1,13 @@ +use crate::asm::asm_instruction::AsmInstruction; + +#[derive(Debug)] +pub struct AsmBlock { + id: usize, + instructions: Vec, +} + +impl AsmBlock { + pub fn new(id: usize, instructions: Vec) -> Self { + Self { id, instructions } + } +} diff --git a/dmc-lib/src/asm/asm_function.rs b/dmc-lib/src/asm/asm_function.rs new file mode 100644 index 0000000..46e20f2 --- /dev/null +++ b/dmc-lib/src/asm/asm_function.rs @@ -0,0 +1,16 @@ +use crate::asm::asm_block::AsmBlock; + +#[derive(Debug)] +pub struct AsmFunction { + name: String, + blocks: Vec, +} + +impl AsmFunction { + pub fn new(name: &str, blocks: Vec) -> Self { + Self { + name: name.into(), + blocks, + } + } +} diff --git a/dmc-lib/src/asm/asm_instruction.rs b/dmc-lib/src/asm/asm_instruction.rs new file mode 100644 index 0000000..a3a1f49 --- /dev/null +++ b/dmc-lib/src/asm/asm_instruction.rs @@ -0,0 +1,79 @@ +#[derive(Debug)] +pub enum AsmInstruction { + Move(Move), + Push(Push), + Pop(Pop), + InvokePlatformStatic(InvokePlatformStatic), + LoadConstant(LoadConstant), +} + +#[derive(Debug)] +pub enum Operand { + IntegerLiteral(i64), + Register(usize), +} + +#[derive(Debug)] +pub struct Move { + source: Operand, + destination_register: usize, +} + +impl Move { + pub fn new(source: Operand, destination_register: usize) -> Self { + Self { + source, + destination_register, + } + } +} + +#[derive(Debug)] +pub struct Push { + source: Operand, +} + +impl Push { + pub fn new(source: Operand) -> Self { + Self { source } + } +} + +#[derive(Debug)] +pub struct Pop { + destination_register: usize, +} + +impl Pop { + pub fn new(destination_register: usize) -> Self { + Self { + destination_register, + } + } +} + +#[derive(Debug)] +pub struct InvokePlatformStatic { + name: String, +} + +impl InvokePlatformStatic { + pub fn new(name: &str) -> Self { + Self { name: name.into() } + } +} + +#[derive(Debug)] +pub struct LoadConstant { + name: String, + destination_register: usize, +} + +impl LoadConstant { + pub fn new(name: &str, destination_register: usize) -> Self { + LoadConstant { + name: name.into(), + destination_register, + } + } +} diff --git a/dmc-lib/src/asm/mod.rs b/dmc-lib/src/asm/mod.rs new file mode 100644 index 0000000..be43b61 --- /dev/null +++ b/dmc-lib/src/asm/mod.rs @@ -0,0 +1,3 @@ +pub mod asm_block; +pub mod asm_function; +pub mod asm_instruction; diff --git a/dmc-lib/src/ast/expression_statement.rs b/dmc-lib/src/ast/expression_statement.rs index 8b6ce9e..4e919d2 100644 --- a/dmc-lib/src/ast/expression_statement.rs +++ b/dmc-lib/src/ast/expression_statement.rs @@ -1,6 +1,7 @@ use crate::ast::expression::Expression; use crate::ast::function::FunctionLoweringContext; use crate::diagnostic::Diagnostic; +use crate::ir::ir_expression::IrExpression; use crate::ir::ir_statement::IrStatement; use crate::symbol_table::SymbolTable; @@ -33,6 +34,19 @@ impl ExpressionStatement { pub fn lower_to_ir(&self, context: &mut FunctionLoweringContext) { let ir_expression = self.expression.lower_to_ir(context); - context.add_statement(IrStatement::Expression(ir_expression)); + match ir_expression { + IrExpression::Call(ir_call) => { + context.add_statement(IrStatement::Call(ir_call)); + } + IrExpression::Constant(ir_constant) => { + unimplemented!() + } + IrExpression::IntegerLiteral(i) => { + unimplemented!() + } + IrExpression::Variable(ir_variable) => { + unimplemented!() + } + } } } diff --git a/dmc-lib/src/ast/function.rs b/dmc-lib/src/ast/function.rs index 07152da..36f4383 100644 --- a/dmc-lib/src/ast/function.rs +++ b/dmc-lib/src/ast/function.rs @@ -89,7 +89,7 @@ impl Function { for constant in context.take_constants() { irs.push(Ir::Constant(constant)); } - let ir_function = IrFunction::new(context.take_statements()); + let ir_function = IrFunction::new(&self.declared_name, context.take_statements()); irs.push(Ir::Function(ir_function)); irs } diff --git a/dmc-lib/src/ast/mod.rs b/dmc-lib/src/ast/mod.rs index 46ac3e2..039fd80 100644 --- a/dmc-lib/src/ast/mod.rs +++ b/dmc-lib/src/ast/mod.rs @@ -12,6 +12,8 @@ pub mod string_literal; #[cfg(test)] mod name_tests { + use crate::ir::Ir; + use crate::ir::assemble_context::AssembleContext; use crate::parser::parse_compilation_unit; use crate::symbol_table::SymbolTable; @@ -31,6 +33,15 @@ mod name_tests { for ir in &irs { println!("{:#?}", ir); } + for ir in &irs { + match ir { + Ir::Function(ir_function) => { + let asm_function = ir_function.assemble(&mut AssembleContext::new()); + println!("{:#?}", asm_function); + } + _ => {} + } + } } #[test] @@ -45,6 +56,15 @@ mod name_tests { for ir in &irs { println!("{:#?}", ir); } + for ir in &irs { + match ir { + Ir::Function(ir_function) => { + let asm_function = ir_function.assemble(&mut AssembleContext::new()); + println!("{:#?}", asm_function); + } + _ => {} + } + } } #[test] diff --git a/dmc-lib/src/ir/assemble_context.rs b/dmc-lib/src/ir/assemble_context.rs new file mode 100644 index 0000000..8cbca97 --- /dev/null +++ b/dmc-lib/src/ir/assemble_context.rs @@ -0,0 +1,7 @@ +pub struct AssembleContext {} + +impl AssembleContext { + pub fn new() -> Self { + Self {} + } +} diff --git a/dmc-lib/src/ir/ir_assign.rs b/dmc-lib/src/ir/ir_assign.rs index 2f028df..2d33641 100644 --- a/dmc-lib/src/ir/ir_assign.rs +++ b/dmc-lib/src/ir/ir_assign.rs @@ -1,3 +1,6 @@ +use crate::asm::asm_instruction::{AsmInstruction, LoadConstant, Move, Operand, Pop}; +use crate::ir::assemble_context::AssembleContext; +use crate::ir::ir_constant::IrConstant; use crate::ir::ir_expression::IrExpression; use crate::ir::ir_variable::IrVariable; @@ -14,4 +17,35 @@ impl IrAssign { value: value.into(), } } + + pub fn assemble(&self, context: &mut AssembleContext) -> Vec { + let mut instructions = vec![]; + match self.value.as_ref() { + IrExpression::Call(ir_call) => { + instructions.append(&mut ir_call.assemble(context)); + instructions.push(AsmInstruction::Pop(Pop::new(self.destination.register()))); + } + IrExpression::Constant(ir_constant) => match ir_constant { + IrConstant::String(ir_string_constant) => { + instructions.push(AsmInstruction::LoadConstant(LoadConstant::new( + ir_string_constant.name(), + self.destination.register(), + ))); + } + }, + IrExpression::IntegerLiteral(i) => { + instructions.push(AsmInstruction::Move(Move::new( + Operand::IntegerLiteral(*i), + self.destination.register(), + ))); + } + IrExpression::Variable(ir_variable) => { + instructions.push(AsmInstruction::Move(Move::new( + Operand::Register(ir_variable.register()), + self.destination.register(), + ))) + } + }; + instructions + } } diff --git a/dmc-lib/src/ir/ir_call.rs b/dmc-lib/src/ir/ir_call.rs index b2c07c2..67d449e 100644 --- a/dmc-lib/src/ir/ir_call.rs +++ b/dmc-lib/src/ir/ir_call.rs @@ -1,3 +1,8 @@ +use crate::asm::asm_instruction::{ + AsmInstruction, InvokePlatformStatic, LoadConstant, Operand, Push, +}; +use crate::ir::assemble_context::AssembleContext; +use crate::ir::ir_constant::IrConstant; use crate::ir::ir_expression::IrExpression; #[derive(Debug)] @@ -13,4 +18,36 @@ impl IrCall { arguments, } } + + pub fn assemble(&self, context: &mut AssembleContext) -> Vec { + let mut instructions = vec![]; + for argument in &self.arguments { + match argument { + IrExpression::Call(ir_call) => { + instructions.append(&mut ir_call.assemble(context)); + } + IrExpression::Constant(ir_constant) => { + match ir_constant { + IrConstant::String(string_constant) => { + instructions.push(AsmInstruction::LoadConstant(LoadConstant::new( + string_constant.name(), + 0, + ))); + } + } + instructions.push(AsmInstruction::Push(Push::new(Operand::Register(0)))) + } + IrExpression::IntegerLiteral(i) => { + instructions.push(AsmInstruction::Push(Push::new(Operand::IntegerLiteral(*i)))); + } + IrExpression::Variable(ir_variable) => instructions.push(AsmInstruction::Push( + Push::new(Operand::Register(ir_variable.register())), + )), + } + } + instructions.push(AsmInstruction::InvokePlatformStatic( + InvokePlatformStatic::new(&self.name), + )); + instructions + } } diff --git a/dmc-lib/src/ir/ir_constant.rs b/dmc-lib/src/ir/ir_constant.rs index ed05e09..2fdb575 100644 --- a/dmc-lib/src/ir/ir_constant.rs +++ b/dmc-lib/src/ir/ir_constant.rs @@ -18,4 +18,12 @@ impl IrStringConstant { name: name.into(), } } + + pub fn value(&self) -> &str { + &self.value + } + + pub fn name(&self) -> &str { + &self.name + } } diff --git a/dmc-lib/src/ir/ir_function.rs b/dmc-lib/src/ir/ir_function.rs index 095b69b..235641d 100644 --- a/dmc-lib/src/ir/ir_function.rs +++ b/dmc-lib/src/ir/ir_function.rs @@ -1,12 +1,28 @@ +use crate::asm::asm_block::AsmBlock; +use crate::asm::asm_function::AsmFunction; +use crate::ir::assemble_context::AssembleContext; use crate::ir::ir_statement::IrStatement; #[derive(Debug)] pub struct IrFunction { + name: String, statements: Vec, } impl IrFunction { - pub fn new(statements: Vec) -> Self { - Self { statements } + pub fn new(name: &str, statements: Vec) -> Self { + Self { + name: name.into(), + statements, + } + } + + pub fn assemble(&self, context: &mut AssembleContext) -> AsmFunction { + let mut instructions = vec![]; + for statement in &self.statements { + instructions.append(&mut statement.assemble(context)); + } + let blocks = vec![AsmBlock::new(0, instructions)]; + AsmFunction::new(&self.name, blocks) } } diff --git a/dmc-lib/src/ir/ir_l_value.rs b/dmc-lib/src/ir/ir_l_value.rs deleted file mode 100644 index e0bed77..0000000 --- a/dmc-lib/src/ir/ir_l_value.rs +++ /dev/null @@ -1,6 +0,0 @@ -use crate::ir::ir_variable::IrVariable; - -pub enum IrLhs { - Variable(IrVariable), - FunctionName(String), -} diff --git a/dmc-lib/src/ir/ir_r_value.rs b/dmc-lib/src/ir/ir_r_value.rs deleted file mode 100644 index 7e5c0ec..0000000 --- a/dmc-lib/src/ir/ir_r_value.rs +++ /dev/null @@ -1,8 +0,0 @@ -use crate::ir::ir_constant::IrConstant; -use crate::ir::ir_variable::IrVariable; - -pub enum IrRhs { - Constant(IrConstant), - IntegerLiteral(i64), - Variable(IrVariable), -} diff --git a/dmc-lib/src/ir/ir_statement.rs b/dmc-lib/src/ir/ir_statement.rs index 2c85a8f..9976d13 100644 --- a/dmc-lib/src/ir/ir_statement.rs +++ b/dmc-lib/src/ir/ir_statement.rs @@ -1,8 +1,19 @@ +use crate::asm::asm_instruction::AsmInstruction; +use crate::ir::assemble_context::AssembleContext; use crate::ir::ir_assign::IrAssign; -use crate::ir::ir_expression::IrExpression; +use crate::ir::ir_call::IrCall; #[derive(Debug)] pub enum IrStatement { Assign(IrAssign), - Expression(IrExpression), + Call(IrCall), +} + +impl IrStatement { + pub fn assemble(&self, context: &mut AssembleContext) -> Vec { + match self { + IrStatement::Assign(ir_assign) => ir_assign.assemble(context), + IrStatement::Call(ir_call) => ir_call.assemble(context), + } + } } diff --git a/dmc-lib/src/ir/ir_variable.rs b/dmc-lib/src/ir/ir_variable.rs index c40c7ca..b445c1d 100644 --- a/dmc-lib/src/ir/ir_variable.rs +++ b/dmc-lib/src/ir/ir_variable.rs @@ -1,10 +1,22 @@ #[derive(Debug)] pub struct IrVariable { name: String, + register: Option, } impl IrVariable { pub fn new(name: &str) -> Self { - Self { name: name.into() } + Self { + name: name.into(), + register: None, + } + } + + pub fn set_register(&mut self, register: usize) { + self.register = Some(register); + } + + pub fn register(&self) -> usize { + 0 } } diff --git a/dmc-lib/src/ir/mod.rs b/dmc-lib/src/ir/mod.rs index 4eb46f9..cc789ae 100644 --- a/dmc-lib/src/ir/mod.rs +++ b/dmc-lib/src/ir/mod.rs @@ -1,13 +1,12 @@ use crate::ir::ir_constant::IrConstant; use crate::ir::ir_function::IrFunction; +pub mod assemble_context; pub mod ir_assign; pub mod ir_call; pub mod ir_constant; pub mod ir_expression; pub mod ir_function; -pub mod ir_l_value; -pub mod ir_r_value; pub mod ir_statement; pub mod ir_variable; diff --git a/dmc-lib/src/lib.rs b/dmc-lib/src/lib.rs index d012a96..c6674fc 100644 --- a/dmc-lib/src/lib.rs +++ b/dmc-lib/src/lib.rs @@ -1,3 +1,4 @@ +mod asm; mod ast; mod diagnostic; mod ir;