From af2785eabfed4aad3859f855d0462c811128ec3a Mon Sep 17 00:00:00 2001 From: Goren Barak Date: Sun, 19 Nov 2023 17:33:17 -0500 Subject: [PATCH] THIS DOES NOT COMPILE, but i still want to be open source --- Cargo.toml | 3 ++ src/codegen/fasm.rs | 105 +++++++++++++++++++++++++------------------- src/main.rs | 2 +- src/parse/ast.rs | 22 ++++++---- 4 files changed, 77 insertions(+), 55 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4635933..8462143 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,3 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] + +[profile.dev] +debug=true diff --git a/src/codegen/fasm.rs b/src/codegen/fasm.rs index 2ae1ee3..8629a17 100644 --- a/src/codegen/fasm.rs +++ b/src/codegen/fasm.rs @@ -1,49 +1,54 @@ use crate::parse::ast::*; -pub fn fasm_codegen(exprs: Vec) -> String { +pub fn fasm_codegen(exprs: &Vec, not_a_function: bool) -> String { 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("\nsegment readable writable\n"); + let mut asm_start = String::new(); + if not_a_function { + asm_start.push_str("format ELF64 executable 3\n"); + asm_start.push_str("segment readable executable\n"); + asm_start.push_str("entry _start\n"); + asm_start.push_str("_start:\n"); + asm_data.push_str("\nsegment readable writable\n"); + } + + let topush = if not_a_function { &mut asm_start } else { &mut asm_text }; - for expr in exprs.iter() { - match expr { + for mut expr in exprs.iter() { + match &mut expr { Expr::MathExpr(e) => { - asm_text.push_str(format!("\tmov r10, {}\n", e.left.unwrap()).as_str()); - asm_text.push_str(format!("\tmov r11, {}\n", e.right.unwrap()).as_str()); + topush.push_str(format!("\tmov r10, {}\n", e.left.unwrap()).as_str()); + topush.push_str(format!("\tmov r11, {}\n", e.right.unwrap()).as_str()); match e.operator { // If the operator is addition. - MathOperator::OP_ADD => { - asm_text.push_str("\tadd r10, r11\n"); - asm_text.push_str("\tmov rax, r10\n"); + MathOperator::OP_ADD => { + topush.push_str("\tadd r10, r11\n"); + topush.push_str("\tmov rax, r10\n"); }, // If the operator is multiplication. MathOperator::OP_MULT => { - asm_text.push_str("\timul r10, r11\n"); - asm_text.push_str("\tmov rax, r10\n"); + topush.push_str("\timul r10, r11\n"); + topush.push_str("\tmov rax, r10\n"); }, // If the operator is division. - MathOperator::OP_DIV => { - asm_text.push_str("\tmov rax, r10\n"); - asm_text.push_str("\txor rdx, rdx\n"); - asm_text.push_str("\tidiv r11\n"); + MathOperator::OP_DIV => { + topush.push_str("\tmov rax, r10\n"); + topush.push_str("\txor rdx, rdx\n"); + topush.push_str("\tidiv r11\n"); // The quotient is now stored in %rax. }, // If the operators is subtraction. - MathOperator::OP_SUB => { - asm_text.push_str("\tsub r10, r11\n"); - asm_text.push_str("\tmov rax, r10\n"); + MathOperator::OP_SUB => { + topush.push_str("\tsub r10, r11\n"); + topush.push_str("\tmov rax, r10\n"); }, // If the operator is modulo. - MathOperator::OP_MOD => { - asm_text.push_str("\tmov rax, r10\n"); - asm_text.push_str("\txor rdx, rdx\n"); - asm_text.push_str("\tidiv r11\n"); - asm_text.push_str("\tmov rax, rdx\n"); - // The remainder will now be stored in the %rax register. + MathOperator::OP_MOD => { + topush.push_str("\tmov rax, r10\n"); + topush.push_str("\txor rdx, rdx\n"); + topush.push_str("\tidiv r11\n"); + topush.push_str("\tmov rax, rdx\n"); + // The remainder will now be stored in the %rax register. } } }, @@ -53,64 +58,72 @@ pub fn fasm_codegen(exprs: Vec) -> String { match i { 0 => { // First parameter. Put in %rdi. - asm_text.push_str(format!("\tmov rdi, {}\n", p.value.unwrap()).as_str()); + topush.push_str(format!("\tmov rdi, {}\n", p.value.unwrap()).as_str()); }, 1 => { // Second parameter. Put in %rsi. - asm_text.push_str(format!("\tmov rsi, {}\n", p.value.unwrap()).as_str()); + topush.push_str(format!("\tmov rsi, {}\n", p.value.unwrap()).as_str()); }, 2 => { // Third parameter. Put in %rdx. - asm_text.push_str(format!("\tmov rdx, {}\n", p.value.unwrap()).as_str()); + topush.push_str(format!("\tmov rdx, {}\n", p.value.unwrap()).as_str()); }, 3 => { // Fourth parameter. Put in %rcx. - asm_text.push_str(format!("\tmov rcx, {}\n", p.value.unwrap()).as_str()); + topush.push_str(format!("\tmov rcx, {}\n", p.value.unwrap()).as_str()); }, 4 => { // Fifth parameter. Put in %r8. - asm_text.push_str(format!("\tmov r8, {}\n", p.value.unwrap()).as_str()); + topush.push_str(format!("\tmov r8, {}\n", p.value.unwrap()).as_str()); }, - + 5 => { // Sixth parameter. Put in %r9. - asm_text.push_str(format!("\tmov r9, {}\n", p.value.unwrap()).as_str()); + topush.push_str(format!("\tmov r9, {}\n", p.value.unwrap()).as_str()); }, _ => { // Parameters after the sixth parameter are pushed to the stack. - asm_text.push_str(format!("\tpush {}\n", p.value.unwrap()).as_str()); + topush.push_str(format!("\tpush {}\n", p.value.unwrap()).as_str()); } } } - asm_text.push_str(format!("call {}", e.name).as_str()); + topush.push_str(format!("call {}", e.name).as_str()); }, Expr::VarDefinition(e) => { asm_data.push_str(format!("\t{} dq {}", e.name, e.value.unwrap()).as_str()); }, - Expr::VarReference(e) => { - asm_text.push_str(e.name); + Expr::FunDefinition(e) => { + topush.push_str(format!("{}:\n", e.name).as_str()); + topush.push_str(fasm_codegen(&e.contents, false).as_str()); }, - Expr::Breakpoint => { - asm_text.push_str("\tint3\n"); + Expr::Return(e) => { + topush.push_str(format!("mov rax, {}", e.unwrap()).as_str()); }, - + + Expr::Breakpoint => { + topush.push_str("\tint3\n"); + }, + _ => unimplemented!("sorry unimplemented"), } } - asm_text.push_str("\tmov rax, 60 ; 60 is the system call number for exit.\n"); - asm_text.push_str("\txor rdi, rdi ; 0 is the exit code we want.\n"); - asm_text.push_str("\tsyscall ; this is the instruction to actually perform the system call."); - let asm = format!("{}{}", asm_text, asm_data); + if not_a_function { + asm_start.push_str("\tmov rax, 60 ; 60 is the system call number for exit.\n"); + asm_start.push_str("\txor rdi, rdi ; 0 is the exit code we want.\n"); + asm_start.push_str("\tsyscall ; this is the instruction to actually perform the system call."); + } + + let asm = format!("{}{}{}", asm_start, asm_text, asm_data); println!("{}", asm); asm } diff --git a/src/main.rs b/src/main.rs index c00d864..bd08a98 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,5 +7,5 @@ use crate::parse::ast::*; pub mod parse; fn main() { - fasm_codegen(vec![Expr::VarDefinition(VarDefinition {name: "goren", value: Value::Number(10)}), Expr::MathExpr(Math { left: Value::Var(VarReference { name: "goren"}), right: Value::Number(17), operator: MathOperator::OP_MULT}), Expr::Breakpoint]); + fasm_codegen(&vec![Expr::VarDefinition(VarDefinition {name: "goren", value: Value::Number(10)}), Expr::MathExpr(Math { left: Value::Var(VarReference { name: "goren"}), right: Value::Number(17), operator: MathOperator::OP_MULT}), Expr::FunDefinition(FunDefinition {name: "adder", contents: vec![Expr::MathExpr(Math {left: Value::Param(ParamReference {param_number: 0}), right: Value::Param(ParamReference {param_number: 1}), operator: MathOperator::OP_ADD})]}), Expr::Breakpoint], true); } diff --git a/src/parse/ast.rs b/src/parse/ast.rs index 59480c7..49c2e2e 100644 --- a/src/parse/ast.rs +++ b/src/parse/ast.rs @@ -4,7 +4,7 @@ pub enum Expr<'a> { FunCall(FunCall<'a>), FunDefinition(FunDefinition<'a>), VarDefinition(VarDefinition<'a>), - VarReference(VarReference<'a>), + Return(Value<'a>), Breakpoint } @@ -36,10 +36,8 @@ pub struct FunCall<'a> { #[derive(Debug)] pub struct FunDefinition<'a> { - name: &'a str, - params: Vec>, - contents: Vec>, - return_value: Value<'a>, + pub name: &'a str, + pub contents: Vec>, } #[derive(Debug)] @@ -67,14 +65,14 @@ pub struct VarReference<'a> { } #[derive(Debug, Copy, Clone)] -pub struct ParamReference<'a> { +pub struct ParamReference { pub param_number: u64, } #[derive(Debug, Copy, Clone)] pub enum Value<'a> { Var(VarReference<'a>), - Param(ParamReference<'a>), + Param(ParamReference), Number(u64), } @@ -82,7 +80,15 @@ impl<'a> Value<'a> { pub fn unwrap(&self) -> String { match self { Value::Param(e) => { - + match e.param_number { + 0 => { return "rdi".to_string(); }, + 1 => { return "rsi".to_string(); }, + 2 => { return "rdx".to_string(); }, + 3 => { return "rcx".to_string(); }, + 4 => { return "r8".to_string(); }, + 5 => { return "r9".to_string(); }, + _ => { unimplemented!() } + } }, Value::Number(e) => {