compile assembly
This commit is contained in:
@@ -14,24 +14,34 @@ impl Codegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn emit_prologue(&mut self) -> Result<(), Box<dyn Error>> {
|
pub fn emit_prologue(&mut self) -> Result<(), Box<dyn Error>> {
|
||||||
writeln!(&mut self.output, "section .data")?;
|
writeln!(
|
||||||
writeln!(&mut self.output, "format db \"%d\", 10, 0")?;
|
&mut self.output,
|
||||||
writeln!(&mut self.output, "section .text")?;
|
"section .data
|
||||||
writeln!(&mut self.output, "global main")?;
|
format db \"%d\", 10, 0
|
||||||
writeln!(&mut self.output, "main:")?;
|
section .text
|
||||||
writeln!(&mut self.output, " extern printf")?;
|
global main
|
||||||
|
main:
|
||||||
|
extern printf"
|
||||||
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn emit_epilogue(&mut self) -> Result<(), Box<dyn Error>> {
|
pub fn emit_epilogue(&mut self) -> Result<(), Box<dyn Error>> {
|
||||||
writeln!(&mut self.output, " mov rdi, format")?;
|
write!(
|
||||||
writeln!(&mut self.output, " mov rsi, rax")?;
|
&mut self.output,
|
||||||
writeln!(&mut self.output, " xor rax, rax")?;
|
"
|
||||||
writeln!(&mut self.output, " call printf")?;
|
mov rdi, format
|
||||||
writeln!(&mut self.output, " mov rax, 0")?;
|
mov rsi, rax
|
||||||
writeln!(&mut self.output, " ret")?;
|
xor rax, rax
|
||||||
writeln!(&mut self.output, "section .note.GNU-stack")?;
|
call printf
|
||||||
writeln!(&mut self.output, " db 0")?;
|
|
||||||
|
mov rax, 0
|
||||||
|
ret
|
||||||
|
|
||||||
|
section .note.GNU-stack
|
||||||
|
db 0
|
||||||
|
"
|
||||||
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,15 +66,37 @@ impl Codegen {
|
|||||||
writeln!(&mut self.output, " cqo")?;
|
writeln!(&mut self.output, " cqo")?;
|
||||||
writeln!(&mut self.output, " idiv rbx")?;
|
writeln!(&mut self.output, " idiv rbx")?;
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
TokenType::Mod => {
|
||||||
|
writeln!(&mut self.output, " cqo")?;
|
||||||
|
writeln!(&mut self.output, " idiv rbx")?;
|
||||||
|
writeln!(&mut self.output, " mov rax, rdx")?;
|
||||||
|
}
|
||||||
|
TokenType::Xor => writeln!(&mut self.output, " xor rax, rbx")?,
|
||||||
|
TokenType::And => todo!(),
|
||||||
|
TokenType::Or => todo!(),
|
||||||
|
TokenType::DoubleEqual => todo!(),
|
||||||
|
TokenType::NotEqual => todo!(),
|
||||||
|
TokenType::Greater => todo!(),
|
||||||
|
TokenType::GreaterEqual => todo!(),
|
||||||
|
TokenType::Less => todo!(),
|
||||||
|
TokenType::LessEqual => todo!(),
|
||||||
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::Grouping(expr) => self.compile_expr(*expr)?,
|
Expr::Grouping(expr) => self.compile_expr(*expr)?,
|
||||||
Expr::Literal(token) => match token.token_type {
|
Expr::Literal(token) => match token.token_type {
|
||||||
TokenType::Number => writeln!(&mut self.output, " mov rax, {}", token.lexeme)?,
|
TokenType::Number => writeln!(&mut self.output, " mov rax, {}", token.lexeme)?,
|
||||||
_ => todo!(),
|
TokenType::String => todo!(),
|
||||||
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
Expr::Unary { op, right } => todo!(),
|
Expr::Unary { op, right } => {
|
||||||
|
self.compile_expr(*right)?;
|
||||||
|
match op.token_type {
|
||||||
|
TokenType::Minus => writeln!(&mut self.output, " neg rax")?,
|
||||||
|
TokenType::Bang => todo!(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
25
src/main.rs
25
src/main.rs
@@ -2,7 +2,12 @@ mod codegen;
|
|||||||
mod parser;
|
mod parser;
|
||||||
mod tokenizer;
|
mod tokenizer;
|
||||||
|
|
||||||
use std::{env, error::Error, fs, process};
|
use std::{
|
||||||
|
env,
|
||||||
|
error::Error,
|
||||||
|
fs,
|
||||||
|
process::{self, Command},
|
||||||
|
};
|
||||||
|
|
||||||
fn compile_file(path: String) -> Result<(), Box<dyn Error>> {
|
fn compile_file(path: String) -> Result<(), Box<dyn Error>> {
|
||||||
let source = fs::read_to_string(path.clone())?;
|
let source = fs::read_to_string(path.clone())?;
|
||||||
@@ -18,7 +23,23 @@ fn compile_file(path: String) -> Result<(), Box<dyn Error>> {
|
|||||||
codegen.emit_prologue()?;
|
codegen.emit_prologue()?;
|
||||||
codegen.compile_expr(expr)?;
|
codegen.compile_expr(expr)?;
|
||||||
codegen.emit_epilogue()?;
|
codegen.emit_epilogue()?;
|
||||||
println!("{}", codegen.get_output());
|
|
||||||
|
fs::write("out.s", codegen.get_output())?;
|
||||||
|
Command::new("nasm")
|
||||||
|
.args(["-f", "elf64", "-o", "out.o", "out.s"])
|
||||||
|
.output()?;
|
||||||
|
|
||||||
|
Command::new("ld")
|
||||||
|
.args([
|
||||||
|
"-dynamic-linker",
|
||||||
|
"/lib64/ld-linux-x86-64.so.2",
|
||||||
|
"-lc",
|
||||||
|
"/usr/lib/x86_64-linux-gnu/crt1.o",
|
||||||
|
"-o",
|
||||||
|
"out",
|
||||||
|
"out.o",
|
||||||
|
])
|
||||||
|
.output()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user