WIP assembly gen
This commit is contained in:
parent
97bd50fa55
commit
e3a1223ac9
139
src/main.rs
139
src/main.rs
@ -1,6 +1,7 @@
|
||||
use core::panic;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::fmt::format;
|
||||
use std::fs;
|
||||
use std::iter::Peekable;
|
||||
use std::process::exit;
|
||||
@ -218,9 +219,147 @@ fn compile(file_content: &String, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec
|
||||
{
|
||||
None
|
||||
};
|
||||
if !interpret
|
||||
{
|
||||
match generate_assembly_linux_x64(&operations, &functions, &intrinsics, &arrays, debug)
|
||||
{
|
||||
Ok(()) => return Ok(None),
|
||||
Err(error) => return Err(error.to_string()),
|
||||
}
|
||||
}
|
||||
return Ok(output);
|
||||
}
|
||||
|
||||
struct AssemblyData
|
||||
{
|
||||
strings: String,
|
||||
code: String,
|
||||
arrays: String,
|
||||
}
|
||||
|
||||
fn merge_assemblies(data: &mut AssemblyData, data2: AssemblyData)
|
||||
{
|
||||
data.arrays += data2.arrays.as_str();
|
||||
data.code += data2.code.as_str();
|
||||
data.strings += data2.strings.as_str();
|
||||
}
|
||||
|
||||
const ASSEMBLY_LINUX_X64_QUEUE_LENGTH: u32 = 1024;
|
||||
const ASSEMBLY_LINUX_X64_HEADER: &str = "format ELF64 executable 3\n";
|
||||
const ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE: &str = "\tcmp r8, r9\n\tcmove r8, r10\n\tcmove r9, r10\n";
|
||||
const ASSEMBLY_LINUX_X64_EXIT: &str = "\tmov rax, 60\n\tmov rdi, 0\n\tsyscall\n";
|
||||
|
||||
fn generate_assembly_linux_x64(operations: &Vec<Operation>, functions: &Vec<Function>, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec<Datatype>)>, arrays: &Vec<Arr>, debug: bool) -> Result<(), std::io::Error>
|
||||
{
|
||||
let mut data = AssemblyData
|
||||
{
|
||||
arrays: format!("segment readable writeable\n\tqueue: rq {}\n", ASSEMBLY_LINUX_X64_QUEUE_LENGTH),
|
||||
strings: String::from("segment readable\n"),
|
||||
code: String::from("segment executable\n"),
|
||||
};
|
||||
for array in arrays
|
||||
{
|
||||
data.arrays += format!("\tarr_{}: rq {}\n", array.name, array.length).as_str();
|
||||
}
|
||||
for function in functions
|
||||
{
|
||||
merge_assemblies(&mut data, generate_assembly_linux_x64_function(function.name.as_str(), &function.content, functions, intrinsics, arrays, debug));
|
||||
}
|
||||
merge_assemblies(&mut data, generate_assembly_linux_x64_function("_start", operations, functions, intrinsics, arrays, debug));
|
||||
data.code += ASSEMBLY_LINUX_X64_EXIT;
|
||||
|
||||
return fs::write("out.asm", format!("{}{}{}{}", ASSEMBLY_LINUX_X64_HEADER, data.code, data.arrays, data.strings));
|
||||
}
|
||||
|
||||
// r8: head
|
||||
// r9: tail
|
||||
// r10: base
|
||||
|
||||
fn generate_assembly_linux_x64_block(operations: &Vec<Operation>, functions: &Vec<Function>, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec<Datatype>)>, arrays: &Vec<Arr>, debug: bool) -> AssemblyData
|
||||
{
|
||||
let mut data = AssemblyData
|
||||
{
|
||||
arrays: String::new(),
|
||||
code: String::new(),
|
||||
strings: String::new(),
|
||||
};
|
||||
for operation in operations
|
||||
{
|
||||
match operation
|
||||
{
|
||||
Operation::Dequeue(line, col) =>
|
||||
{
|
||||
data.code += format!("\t;;deq {}:{}\n", line, col).as_str();
|
||||
data.code += "\tinc r8\n";
|
||||
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
||||
}
|
||||
Operation::Enqueue(datatype, value, line, col) =>
|
||||
{
|
||||
data.code += format!("\t;;enq {:?} {} {}:{}\n", datatype, value, line, col).as_str();
|
||||
match datatype
|
||||
{
|
||||
Datatype::Int | Datatype::Bool =>
|
||||
{
|
||||
data.code += format!("\tmov qword [queue+r9], {}\n", value).as_str();
|
||||
}
|
||||
_ => todo!("enq {:?}", datatype)
|
||||
}
|
||||
data.code += "\tinc r9\n";
|
||||
}
|
||||
Operation::While(while_operations, line, col) =>
|
||||
{
|
||||
data.code += format!("\t;;while {}:{}\n", line, col).as_str();
|
||||
data.code += format!("while_{}_{}:\n", line, col).as_str();
|
||||
data.code += "\tcmp qword [queue+r8], 0\n";
|
||||
data.code += format!("\tje while_{}_{}_end\n", line, col).as_str();
|
||||
data.code += "\tinc r8\n";
|
||||
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
||||
merge_assemblies(&mut data, generate_assembly_linux_x64_block(while_operations, functions, intrinsics, arrays, debug));
|
||||
data.code += format!("\tjmp while_{}_{}\n", line, col).as_str();
|
||||
data.code += format!("while_{}_{}_end:\n", line, col).as_str();
|
||||
data.code += "\tinc r8\n";
|
||||
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
||||
}
|
||||
Operation::Dup(line, col) =>
|
||||
{
|
||||
data.code += format!("\t;;dup {}:{}\n", line, col).as_str();
|
||||
data.code += "\tmov qword [queue+r9], [queue+r8]\n";
|
||||
data.code += "\tinc r9\n";
|
||||
}
|
||||
Operation::Intrinsic(name, line, col) =>
|
||||
{
|
||||
data.code += format!("\t;;intrinsic {} {}:{}", name, line, col).as_str();
|
||||
match name.as_str()
|
||||
{
|
||||
"print" =>
|
||||
{
|
||||
// For now printing numbers directly is unsupported
|
||||
data.code += "\trax, 1\n";
|
||||
data.code += "\trdi, 1\n";
|
||||
data.code += "\tmov rsi, [queue+r8]\n";
|
||||
data.code += "\tmov "
|
||||
}
|
||||
_ => todo!("intrinsic {} {}:{}", name, line, col)
|
||||
}
|
||||
}
|
||||
_ => todo!("{:?}", operation)
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
fn generate_assembly_linux_x64_function(name: &str, operations: &Vec<Operation>, functions: &Vec<Function>, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec<Datatype>)>, arrays: &Vec<Arr>, debug: bool) -> AssemblyData
|
||||
{
|
||||
let mut data = AssemblyData
|
||||
{
|
||||
arrays: String::new(),
|
||||
code: format!("{}:\n", name),
|
||||
strings: String::new(),
|
||||
};
|
||||
merge_assemblies(&mut data, generate_assembly_linux_x64_block(operations, functions, intrinsics, arrays, debug));
|
||||
return data;
|
||||
}
|
||||
|
||||
fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, functions: &Vec<Function>, arrays: &mut Vec<Arr>, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec<Datatype>)>, debug: bool) -> Result<String,String>
|
||||
{
|
||||
let mut output = String::new();
|
||||
|
Loading…
x
Reference in New Issue
Block a user