From 4d066acda3186cf1b160dc5410beabad1bd24ef5 Mon Sep 17 00:00:00 2001 From: Toni Date: Thu, 29 May 2025 18:47:21 +0200 Subject: [PATCH] codegen --- src/codegen.rs | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 11 ++++++-- 2 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 src/codegen.rs diff --git a/src/codegen.rs b/src/codegen.rs new file mode 100644 index 0000000..53189aa --- /dev/null +++ b/src/codegen.rs @@ -0,0 +1,71 @@ +use std::{error::Error, fmt::Write}; + +use crate::{parser::Expr, tokenizer::TokenType}; + +pub struct Codegen { + output: String, +} + +impl Codegen { + pub fn new() -> Codegen { + Codegen { + output: String::new(), + } + } + + pub fn emit_prologue(&mut self) -> Result<(), Box> { + writeln!(&mut self.output, "section .data")?; + writeln!(&mut self.output, "format db \"%d\", 10, 0")?; + writeln!(&mut self.output, "section .text")?; + writeln!(&mut self.output, "global main")?; + writeln!(&mut self.output, "main:")?; + writeln!(&mut self.output, " extern printf")?; + Ok(()) + } + + pub fn emit_epilogue(&mut self) -> Result<(), Box> { + writeln!(&mut self.output, " mov rdi, format")?; + writeln!(&mut self.output, " mov rsi, rax")?; + writeln!(&mut self.output, " xor rax, rax")?; + writeln!(&mut self.output, " call printf")?; + writeln!(&mut self.output, " mov rax, 0")?; + writeln!(&mut self.output, " ret")?; + writeln!(&mut self.output, "section .note.GNU-stack")?; + writeln!(&mut self.output, " db 0")?; + Ok(()) + } + + pub fn get_output(self) -> String { + self.output + } + + pub fn compile_expr(&mut self, expr: Expr) -> Result<(), Box> { + match expr { + Expr::Binary { left, op, right } => { + self.compile_expr(*left)?; + writeln!(&mut self.output, " push rax")?; + self.compile_expr(*right)?; + writeln!(&mut self.output, " mov rbx, rax")?; + writeln!(&mut self.output, " pop rax")?; + + match op.token_type { + TokenType::Plus => writeln!(&mut self.output, " add rax, rbx")?, + TokenType::Minus => writeln!(&mut self.output, " sub rax, rbx")?, + TokenType::Star => writeln!(&mut self.output, " imul rax, rbx")?, + TokenType::Slash => { + writeln!(&mut self.output, " cqo")?; + writeln!(&mut self.output, " idiv rbx")?; + } + _ => todo!(), + } + } + Expr::Grouping(expr) => self.compile_expr(*expr)?, + Expr::Literal(token) => match token.token_type { + TokenType::Number => writeln!(&mut self.output, " mov rax, {}", token.lexeme)?, + _ => todo!(), + }, + Expr::Unary { op, right } => todo!(), + } + Ok(()) + } +} diff --git a/src/main.rs b/src/main.rs index d4f317e..13e8d2b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +mod codegen; mod parser; mod tokenizer; @@ -9,9 +10,15 @@ fn compile_file(path: String) -> Result<(), Box> { // TODO: basename let tokenizer = tokenizer::Tokenizer::new(path, source); let tokens = tokenizer.tokenize()?; - let parser = parser::Parser::new(tokens); - println!("{:#?}", parser.parse()); + let parser = parser::Parser::new(tokens); + let expr = parser.parse()?; + + let mut codegen = codegen::Codegen::new(); + codegen.emit_prologue()?; + codegen.compile_expr(expr)?; + codegen.emit_epilogue()?; + println!("{}", codegen.get_output()); Ok(()) }