From 4ed9e7064a5aacf611fb9329bbefeea8c198a98d Mon Sep 17 00:00:00 2001 From: Goren Barak Date: Thu, 16 Nov 2023 19:01:52 -0500 Subject: [PATCH] added some more things to the backend --- .gitignore | 1 + README.md | 1 + src/codegen/fasm.rs | 99 +++++++++++++++++++++++++++++++++------------ src/lex/parse.rs | 2 +- src/main.rs | 5 ++- src/parse/ast.rs | 28 +++++++++---- 6 files changed, 102 insertions(+), 34 deletions(-) create mode 100644 README.md diff --git a/.gitignore b/.gitignore index ea8c4bf..c2a9b6f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +tags diff --git a/README.md b/README.md new file mode 100644 index 0000000..3439d8d --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# SkyLang diff --git a/src/codegen/fasm.rs b/src/codegen/fasm.rs index 287be42..2b8e2c0 100644 --- a/src/codegen/fasm.rs +++ b/src/codegen/fasm.rs @@ -1,53 +1,102 @@ use crate::parse::ast::*; pub fn fasm_codegen(expr: Expr) -> String { - let mut asm = String::new(); - - asm.push_str("format ELF64 executable 3\n"); - asm.push_str("segment readable executable\n"); - asm.push_str("entry _start\n"); - asm.push_str("_start:\n"); + let mut asm_text = String::new(); + let mut asm_data = String::new(); + + asm_text.push_str("format ELF64 executable 3\n"); + asm_text.push_str("segment readable executable\n"); + asm_text.push_str("entry _start\n"); + asm_text.push_str("_start:\n"); + asm_data.push_str("segment readable writeable\n"); match expr { Expr::MathExpr(e) => { - asm.push_str(format!("\tmov r10, {:?}\n", e.left).as_str()); - asm.push_str(format!("\tmov r11, {:?}\n", e.right).as_str()); + asm_text.push_str(format!("\tmov r10, {:?}\n", e.left).as_str()); + asm_text.push_str(format!("\tmov r11, {:?}\n", e.right).as_str()); match e.operator { // If the operator is addition. MathOperator::OP_ADD => { - asm.push_str("\tadd r10, r11\n"); - asm.push_str("\tmov rax, r10\n"); + asm_text.push_str("\tadd r10, r11\n"); + asm_text.push_str("\tmov rax, r10\n"); }, // If the operator is multiplication. MathOperator::OP_MULT => { - asm.push_str("\timul r10, r11\n"); - asm.push_str("\tmov rax, r10\n"); + asm_text.push_str("\timul r10, r11\n"); + asm_text.push_str("\tmov rax, r10\n"); }, // If the operator is division. MathOperator::OP_DIV => { - asm.push_str("\tmov rax, r10\n"); - asm.push_str("\tmov rdx, r11\n"); - asm.push_str("\tidiv r10, r11\n"); - asm.push_str("\tmov rax, r10\n"); + asm_text.push_str("\tmov rax, r10\n"); + asm_text.push_str("\tmov rdx, r11\n"); + asm_text.push_str("\tidiv r10, r11\n"); + asm_text.push_str("\tmov rax, r10\n"); }, // If the operators is subtraction. MathOperator::OP_SUB => { - asm.push_str("\tsub r10, r11\n"); - asm.push_str("\tmov rax, r10\n"); + asm_text.push_str("\tsub r10, r11\n"); + asm_text.push_str("\tmov rax, r10\n"); }, // If the operator is modulo. MathOperator::OP_MOD => { - asm.push_str("\tmov rax, r10\n"); - asm.push_str("\tmov rdx, r11\n"); - asm.push_str("\tidiv r10, r11\n"); - asm.push_str("\tmov rax, rdx\n"); + asm_text.push_str("\tmov rax, r10\n"); + asm_text.push_str("\tmov rdx, r11\n"); + asm_text.push_str("\tidiv r10, r11\n"); + asm_text.push_str("\tmov rax, rdx\n"); - }, - _ => unimplemented!("sorry unimplemented"), + } } }, + + Expr::FunCall(e) => { + for (i, p) in e.params.iter().enumerate() { + match i { + 0 => { + // First parameter. Put in %rdi. + asm_text.push_str(format!("\tmov rdi, {:?}\n", p.value).as_str()); + }, + + 1 => { + // Second parameter. Put in %rsi. + asm_text.push_str(format!("\tmov rsi, {:?}\n", p.value).as_str()); + }, + + 2 => { + // Third parameter. Put in %rdx. + asm_text.push_str(format!("\tmov rdx, {:?}\n", p.value).as_str()); + }, + + 3 => { + // Fourth parameter. Put in %rcx. + asm_text.push_str(format!("\tmov rcx, {:?}\n", p.value).as_str()); + }, + + 4 => { + // Fifth parameter. Put in %r8. + asm_text.push_str(format!("\tmov r8, {:?}\n", p.value).as_str()); + }, + + 5 => { + // Sixth parameter. Put in %r9. + asm_text.push_str(format!("\tmov r9, {:?}\n", p.value).as_str()); + }, + + _ => { + // Parameters after the sixth parameter are pushed to the stack. + asm_text.push_str(format!("\tpush {:?}\n", p.value).as_str()); + } + } + } + + asm_text.push_str(format!("call {:?}", e.name).as_str()); + }, + + Expr::VarDefenition(e) => { + asm_data.push_str(format!("{} dq {:?}", e.name, e.value).as_str()); + }, + _ => unimplemented!("sorry unimplemented"), } - + let asm = format!("{}{}", asm_text, asm_data); println!("{}", asm); asm } diff --git a/src/lex/parse.rs b/src/lex/parse.rs index 03002cf..55e2468 100644 --- a/src/lex/parse.rs +++ b/src/lex/parse.rs @@ -59,7 +59,7 @@ pub fn match_keyword<'a>(word: &'a str) -> Option> { _ => None }; - + tok } diff --git a/src/main.rs b/src/main.rs index f640c0a..e47a548 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,5 +5,8 @@ use crate::parse::ast::*; pub mod parse; fn main() { - fasm_codegen(Expr::MathExpr(Math {left: 1, right: 2, operator: MathOperator::OP_DIV})); + fasm_codegen(Expr::VarDefenition(VarDefenition { + name: "hi", + value: 100, + })); } diff --git a/src/parse/ast.rs b/src/parse/ast.rs index 4c180ea..f875bb6 100644 --- a/src/parse/ast.rs +++ b/src/parse/ast.rs @@ -1,7 +1,9 @@ #[derive(Debug)] pub enum Expr<'a> { MathExpr(Math), - FunCallExpr(FunCall<'a>), + FunCall(FunCall<'a>), + FunDefenition(FunDefenition<'a>), + VarDefenition(VarDefenition<'a>), } // MATH EXPRESSION @@ -26,19 +28,31 @@ pub enum MathOperator { #[derive(Debug)] pub struct FunCall<'a> { - name: &'a str, - params: Vec>, + pub name: &'a str, + pub params: Vec, } #[derive(Debug)] -pub struct FunDefention<'a> { +pub struct FunDefenition<'a> { name: &'a str, - params: Vec>, + params: Vec>, contents: Vec>, - return_value: Expr<'a>, + return_value: &'a Expr<'a>, } #[derive(Debug)] -pub struct FunParam<'a> { +pub struct FunParamDef<'a> { name: &'a str, } + +#[derive(Debug)] +pub struct FunParamCall { + // Everything is a u64 for now. + pub value: u64, +} + +#[derive(Debug)] +pub struct VarDefenition<'a> { + pub name: &'a str, + pub value: u64, +}