Started on windows implementation
This commit is contained in:
parent
747c4e59d4
commit
db83d6d9c1
78
Cargo.lock
generated
78
Cargo.lock
generated
|
@ -114,6 +114,26 @@ dependencies = [
|
|||
"tracing-error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "5.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dece029acd3353e3a58ac2e3eb3c8d6c35827a892edc6cc4138ef9c33df46ecd"
|
||||
dependencies = [
|
||||
"dirs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04414300db88f70d74c5ff54e50f9e1d1737d9a5b90f53fcf2e95ca2a9ab554b"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.2.8"
|
||||
|
@ -145,6 +165,17 @@ dependencies = [
|
|||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.27.2"
|
||||
|
@ -215,6 +246,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"clap",
|
||||
"color-eyre",
|
||||
"dirs",
|
||||
"eyre",
|
||||
]
|
||||
|
||||
|
@ -308,6 +340,26 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"redox_syscall",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.21"
|
||||
|
@ -363,6 +415,26 @@ dependencies = [
|
|||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5ab016db510546d856297882807df8da66a16fb8c4101cb8b30054b0d5b2d9c"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.7"
|
||||
|
@ -433,6 +505,12 @@ version = "0.9.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
|
|
@ -7,4 +7,5 @@ edition = "2021"
|
|||
[dependencies]
|
||||
clap = { version = "4.1.8", features = ["derive"] }
|
||||
color-eyre = "0.6.2"
|
||||
dirs = "5.0.0"
|
||||
eyre = "0.6.8"
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
use std::path::{PathBuf, Path};
|
||||
use std::process::{Command, Stdio};
|
||||
use color_eyre::Result;
|
||||
use crate::compile::Folders;
|
||||
use crate::info;
|
||||
|
||||
pub fn linux_x86_64_compile_and_link(of_a: &Path, of_o: &Path, of_c: &Path, quiet: bool) -> Result<()> {
|
||||
pub fn linux_x86_64_compile_and_link(folders: &Folders, quiet: bool) -> Result<()> {
|
||||
|
||||
let nasm_args = [
|
||||
"-felf64",
|
||||
of_a.to_str().unwrap(),
|
||||
folders.of_a.to_str().unwrap(),
|
||||
"-o",
|
||||
of_o.to_str().unwrap()
|
||||
folders.of_o.to_str().unwrap()
|
||||
];
|
||||
|
||||
let ld_args = [
|
||||
of_o.to_str().unwrap(),
|
||||
folders.of_o.to_str().unwrap(),
|
||||
"-o",
|
||||
of_c.to_str().unwrap()
|
||||
folders.of_c.to_str().unwrap()
|
||||
];
|
||||
|
||||
|
|
@ -1,32 +1,20 @@
|
|||
use std::{fs, path::PathBuf, io::{Write, BufWriter}};
|
||||
mod commands;
|
||||
use std::{fs, io::{Write, BufWriter}};
|
||||
use crate::{constants::{Operator, OpType, KeywordType}, Args};
|
||||
use color_eyre::Result;
|
||||
use crate::compile::commands::linux_x86_64_compile_and_link;
|
||||
use commands::linux_x86_64_compile_and_link;
|
||||
use commands::linux_x86_64_run;
|
||||
use crate::constants::InstructionType;
|
||||
use super::commands::linux_x86_64_run;
|
||||
|
||||
use super::Folders;
|
||||
|
||||
|
||||
pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
||||
let mut of_c = PathBuf::from(&args.out_file);
|
||||
let (mut of_o, mut of_a) = if args.out_file == *crate::DEFAULT_OUT_FILE {
|
||||
let of_o = PathBuf::from("/tmp/mclang_comp.o");
|
||||
let of_a = PathBuf::from("/tmp/mclang_comp.nasm");
|
||||
(of_o, of_a)
|
||||
} else {
|
||||
let of_o = PathBuf::from(&args.out_file);
|
||||
let of_a = PathBuf::from(&args.out_file);
|
||||
(of_o, of_a)
|
||||
};
|
||||
pub fn compile(tokens: &[Operator], args: &Args, folders: &Folders) -> Result<i32>{
|
||||
|
||||
of_c.set_extension("");
|
||||
of_o.set_extension("o");
|
||||
of_a.set_extension("nasm");
|
||||
|
||||
|
||||
|
||||
let file = fs::File::create(&of_a)?;
|
||||
let file = fs::File::create(&folders.of_a)?;
|
||||
let mut writer = BufWriter::new(&file);
|
||||
|
||||
|
||||
// println!("{}", tokens.len());
|
||||
let mut strings: Vec<String> = Vec::new();
|
||||
|
||||
|
@ -421,9 +409,9 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
writeln!(writer, "mem: resb {}", crate::compile::MEM_SZ)?;
|
||||
|
||||
writer.flush()?;
|
||||
linux_x86_64_compile_and_link(&of_a, &of_o, &of_c, args.quiet)?;
|
||||
linux_x86_64_compile_and_link(folders, args.quiet)?;
|
||||
if args.run {
|
||||
let c = linux_x86_64_run(&of_c, &[], args.quiet)?;
|
||||
let c = linux_x86_64_run(&folders.of_c, &[], args.quiet)?;
|
||||
return Ok(c);
|
||||
}
|
||||
|
|
@ -1,5 +1,56 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use color_eyre::Result;
|
||||
use eyre::eyre;
|
||||
|
||||
use crate::{constants::{Operator, targets}, Args, error};
|
||||
|
||||
pub mod linux_x86_64;
|
||||
pub mod commands;
|
||||
pub mod win32_x86_64;
|
||||
|
||||
pub const MEM_SZ: usize = 640 * 1000; // 4kb
|
||||
pub const STRING_SZ: usize = 640 * 1000; // 4kb
|
||||
|
||||
pub struct Folders {
|
||||
pub of_c: PathBuf,
|
||||
pub of_o: PathBuf,
|
||||
pub of_a: PathBuf,
|
||||
}
|
||||
|
||||
fn get_folders(args: &Args) -> Folders {
|
||||
let mut of_c = PathBuf::from(&args.out_file);
|
||||
let (mut of_o, mut of_a) = if args.out_file == *crate::DEFAULT_OUT_FILE {
|
||||
let of_o = std::env::temp_dir().join("mclang_comp.o");
|
||||
let of_a = std::env::temp_dir().join("mclang_comp.nasm");
|
||||
(of_o, of_a)
|
||||
} else {
|
||||
let of_o = PathBuf::from(&args.out_file);
|
||||
let of_a = PathBuf::from(&args.out_file);
|
||||
(of_o, of_a)
|
||||
};
|
||||
|
||||
of_c.set_extension("exe");
|
||||
of_o.set_extension("o");
|
||||
of_a.set_extension("nasm");
|
||||
|
||||
Folders {
|
||||
of_a,
|
||||
of_c,
|
||||
of_o
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32> {
|
||||
match args.target.as_str() {
|
||||
targets::LINUX_X86_64 => {
|
||||
linux_x86_64::compile(tokens, args, &get_folders(&args))
|
||||
}
|
||||
targets::WIN32_X86_64 => {
|
||||
win32_x86_64::compile(tokens, args, &get_folders(&args))
|
||||
}
|
||||
t => {
|
||||
error!("Unknown target '{}'", t);
|
||||
Err(eyre!(""))
|
||||
}
|
||||
}
|
||||
}
|
89
src/compile/win32_x86_64/commands.rs
Normal file
89
src/compile/win32_x86_64/commands.rs
Normal file
|
@ -0,0 +1,89 @@
|
|||
use std::path::{PathBuf, Path};
|
||||
use std::process::{Command, Stdio};
|
||||
use color_eyre::Result;
|
||||
use crate::compile::Folders;
|
||||
use crate::info;
|
||||
|
||||
pub fn linux_x86_64_compile_and_link(folders: &Folders, quiet: bool) -> Result<()> {
|
||||
|
||||
let nasm_args = [
|
||||
"-felf64",
|
||||
folders.of_a.to_str().unwrap(),
|
||||
"-o",
|
||||
folders.of_o.to_str().unwrap()
|
||||
];
|
||||
|
||||
let ld_args = [
|
||||
folders.of_o.to_str().unwrap(),
|
||||
"-o",
|
||||
folders.of_c.to_str().unwrap()
|
||||
];
|
||||
|
||||
|
||||
let mut proc = if cfg!(target_os = "windows") {
|
||||
return Ok(());
|
||||
} else {
|
||||
Command::new("nasm")
|
||||
.args(nasm_args)
|
||||
.stdout(Stdio::inherit())
|
||||
.stderr(Stdio::inherit())
|
||||
.spawn()?
|
||||
};
|
||||
if !quiet {
|
||||
info!("running 'nasm {}'", nasm_args.join(" "));
|
||||
}
|
||||
let exit = proc.wait()?;
|
||||
|
||||
if !quiet {
|
||||
info!("nasm process exited with code {}", exit);
|
||||
}
|
||||
|
||||
|
||||
let mut proc2 = if cfg!(target_os = "windows") {
|
||||
return Ok(());
|
||||
} else {
|
||||
Command::new("ld")
|
||||
.args(ld_args)
|
||||
.stdout(Stdio::inherit())
|
||||
.stderr(Stdio::inherit())
|
||||
.spawn()?
|
||||
};
|
||||
if !quiet {
|
||||
info!("running 'ld {}'", ld_args.join(" "));
|
||||
}
|
||||
let exit2 = proc2.wait()?;
|
||||
if !quiet {
|
||||
info!("ld process exited with code {}", exit2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn linux_x86_64_run(bin: &Path, args: &[String], quiet: bool) -> Result<i32> {
|
||||
|
||||
let bin = PathBuf::from(
|
||||
format!("./{}", bin.to_string_lossy())
|
||||
);
|
||||
|
||||
let mut proc = if cfg!(target_os = "windows") {
|
||||
return Ok(0);
|
||||
} else {
|
||||
Command::new(bin.clone())
|
||||
.args(args)
|
||||
.stdout(Stdio::inherit())
|
||||
.stderr(Stdio::inherit())
|
||||
.spawn()?
|
||||
};
|
||||
// println!("{}", quiet);
|
||||
if !quiet {
|
||||
info!("running {} {}", bin.to_string_lossy(), args.join(" "));
|
||||
}
|
||||
let exit = proc.wait()?;
|
||||
if !quiet {
|
||||
info!("{} process exited with code {}", bin.to_string_lossy(), exit);
|
||||
}
|
||||
|
||||
Ok(exit.code().unwrap_or(0))
|
||||
}
|
417
src/compile/win32_x86_64/mod.rs
Normal file
417
src/compile/win32_x86_64/mod.rs
Normal file
|
@ -0,0 +1,417 @@
|
|||
mod commands;
|
||||
use std::{fs, io::{Write, BufWriter}};
|
||||
use crate::{constants::{Operator, OpType, KeywordType}, Args};
|
||||
use color_eyre::Result;
|
||||
use commands::linux_x86_64_compile_and_link;
|
||||
use commands::linux_x86_64_run;
|
||||
use crate::constants::InstructionType;
|
||||
|
||||
use super::Folders;
|
||||
|
||||
pub fn compile(tokens: &[Operator], args: &Args, folders: &Folders) -> Result<i32>{
|
||||
|
||||
let file = fs::File::create(&folders.of_a)?;
|
||||
let mut writer = BufWriter::new(&file);
|
||||
|
||||
// println!("{}", tokens.len());
|
||||
let mut strings: Vec<String> = Vec::new();
|
||||
|
||||
writeln!(writer, "BITS 64")?;
|
||||
writeln!(writer, "segment .text")?;
|
||||
|
||||
writeln!(writer, "print:")?;
|
||||
writeln!(writer, " mov r9, -3689348814741910323")?;
|
||||
writeln!(writer, " sub rsp, 40")?;
|
||||
writeln!(writer, " mov BYTE [rsp+31], 10")?;
|
||||
writeln!(writer, " lea rcx, [rsp+30]")?;
|
||||
writeln!(writer, ".L2:")?;
|
||||
writeln!(writer, " mov rax, rdi")?;
|
||||
writeln!(writer, " lea r8, [rsp+32]")?;
|
||||
writeln!(writer, " mul r9")?;
|
||||
writeln!(writer, " mov rax, rdi")?;
|
||||
writeln!(writer, " sub r8, rcx")?;
|
||||
writeln!(writer, " shr rdx, 3")?;
|
||||
writeln!(writer, " lea rsi, [rdx+rdx*4]")?;
|
||||
writeln!(writer, " add rsi, rsi")?;
|
||||
writeln!(writer, " sub rax, rsi")?;
|
||||
writeln!(writer, " add eax, 48")?;
|
||||
writeln!(writer, " mov BYTE [rcx], al")?;
|
||||
writeln!(writer, " mov rax, rdi")?;
|
||||
writeln!(writer, " mov rdi, rdx")?;
|
||||
writeln!(writer, " mov rdx, rcx")?;
|
||||
writeln!(writer, " sub rcx, 1")?;
|
||||
writeln!(writer, " cmp rax, 9")?;
|
||||
writeln!(writer, " ja .L2")?;
|
||||
writeln!(writer, " lea rax, [rsp+32]")?;
|
||||
writeln!(writer, " mov edi, 1")?;
|
||||
writeln!(writer, " sub rdx, rax")?;
|
||||
writeln!(writer, " xor eax, eax")?;
|
||||
writeln!(writer, " lea rsi, [rsp+32+rdx]")?;
|
||||
writeln!(writer, " mov rdx, r8")?;
|
||||
writeln!(writer, " mov rax, 1")?;
|
||||
writeln!(writer, " syscall")?;
|
||||
writeln!(writer, " add rsp, 40")?;
|
||||
writeln!(writer, " ret")?;
|
||||
|
||||
writeln!(writer, "global _start")?;
|
||||
writeln!(writer, "_start:")?;
|
||||
|
||||
let mut ti = 0;
|
||||
while ti < tokens.len() {
|
||||
let token = &tokens[ti];
|
||||
|
||||
writeln!(writer, "addr_{ti}:")?;
|
||||
match token.typ {
|
||||
// stack
|
||||
OpType::Instruction(InstructionType::PushInt) => {
|
||||
writeln!(writer, " ;; -- push int {}", token.value)?;
|
||||
writeln!(writer, " mov rax, {}", token.value)?;
|
||||
writeln!(writer, " push rax")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::PushStr) => {
|
||||
writeln!(writer, " ;; -- push str \"{}\"", token.text.escape_default())?;
|
||||
writeln!(writer, " mov rax, {}", token.text.len())?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " push str_{}", strings.len())?;
|
||||
strings.push(token.text.clone());
|
||||
ti += 1;
|
||||
}
|
||||
OpType::Instruction(InstructionType::Drop) => {
|
||||
writeln!(writer, " ;; -- drop")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Print) => {
|
||||
writeln!(writer, " ;; -- print")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
writeln!(writer, " call print")?;
|
||||
ti += 1;
|
||||
},
|
||||
|
||||
OpType::Instruction(InstructionType::Dup) => {
|
||||
writeln!(writer, " ;; -- dup")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
|
||||
ti += 1;
|
||||
},
|
||||
|
||||
OpType::Instruction(InstructionType::Rot) => {
|
||||
writeln!(writer, " ;; -- rot")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " pop rcx")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " push rcx")?;
|
||||
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Swap) => {
|
||||
writeln!(writer, " ;; -- swap")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Over) => {
|
||||
writeln!(writer, " ;; -- over")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
|
||||
ti += 1;
|
||||
},
|
||||
|
||||
//mem
|
||||
OpType::Instruction(InstructionType::Mem) => {
|
||||
writeln!(writer, " ;; -- mem")?;
|
||||
writeln!(writer, " push mem")?;
|
||||
ti += 1;
|
||||
}
|
||||
OpType::Instruction(InstructionType::Load8) => {
|
||||
writeln!(writer, " ;; -- load")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " xor rbx, rbx")?;
|
||||
writeln!(writer, " mov bl, [rax]")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
ti += 1;
|
||||
}
|
||||
|
||||
OpType::Instruction(InstructionType::Store8) => {
|
||||
writeln!(writer, " ;; -- store")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " mov [rax], bl")?;
|
||||
ti += 1;
|
||||
}
|
||||
|
||||
// math
|
||||
OpType::Instruction(InstructionType::Plus) => {
|
||||
writeln!(writer, " ;; -- plus")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " add rax, rbx")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Minus) => {
|
||||
writeln!(writer, " ;; -- minus")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " sub rbx, rax")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Equals) => {
|
||||
writeln!(writer, " ;; -- equals")?;
|
||||
writeln!(writer, " mov rcx, 0")?;
|
||||
writeln!(writer, " mov rdx, 1")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " cmp rax, rbx")?;
|
||||
writeln!(writer, " cmove rcx, rdx")?;
|
||||
writeln!(writer, " push rcx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Lt) => {
|
||||
writeln!(writer, " ;; -- lt")?;
|
||||
writeln!(writer, " mov rcx, 0")?;
|
||||
writeln!(writer, " mov rdx, 1")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " cmp rax, rbx")?;
|
||||
writeln!(writer, " cmovl rcx, rdx")?;
|
||||
writeln!(writer, " push rcx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Gt) => {
|
||||
writeln!(writer, " ;; -- gt")?;
|
||||
writeln!(writer, " mov rcx, 0")?;
|
||||
writeln!(writer, " mov rdx, 1")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " cmp rax, rbx")?;
|
||||
writeln!(writer, " cmovg rcx, rdx")?;
|
||||
writeln!(writer, " push rcx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::NotEquals) => {
|
||||
writeln!(writer, " ;; -- not equals")?;
|
||||
writeln!(writer, " mov rcx, 1")?;
|
||||
writeln!(writer, " mov rdx, 0")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " cmp rax, rbx")?;
|
||||
writeln!(writer, " cmove rcx, rdx")?;
|
||||
writeln!(writer, " push rcx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Le) => {
|
||||
writeln!(writer, " ;; -- lt")?;
|
||||
writeln!(writer, " mov rcx, 0")?;
|
||||
writeln!(writer, " mov rdx, 1")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " cmp rax, rbx")?;
|
||||
writeln!(writer, " cmovle rcx, rdx")?;
|
||||
writeln!(writer, " push rcx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Ge) => {
|
||||
writeln!(writer, " ;; -- gt")?;
|
||||
writeln!(writer, " mov rcx, 0")?;
|
||||
writeln!(writer, " mov rdx, 1")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " cmp rax, rbx")?;
|
||||
writeln!(writer, " cmovge rcx, rdx")?;
|
||||
writeln!(writer, " push rcx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Band) => {
|
||||
writeln!(writer, " ;; -- band")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " and rbx, rax")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Bor) => {
|
||||
writeln!(writer, " ;; -- bor")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " or rbx, rax")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Shr) => {
|
||||
writeln!(writer, " ;; -- shr")?;
|
||||
writeln!(writer, " pop rcx")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " shr rbx, cl")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Shl) => {
|
||||
writeln!(writer, " ;; -- shl")?;
|
||||
writeln!(writer, " pop rcx")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " shl rbx, cl")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::DivMod) => {
|
||||
writeln!(writer, " ;; -- div")?;
|
||||
writeln!(writer, " xor rdx, rdx")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " div rbx")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " push rdx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Mul) => {
|
||||
writeln!(writer, " ;; -- mul")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " mul rbx")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
ti += 1;
|
||||
},
|
||||
|
||||
|
||||
// block
|
||||
OpType::Keyword(KeywordType::If) => {
|
||||
writeln!(writer, " ;; -- if")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " test rax, rax")?;
|
||||
writeln!(writer, " jz addr_{}", token.jmp)?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Keyword(KeywordType::Else) => {
|
||||
writeln!(writer, " ;; -- else")?;
|
||||
writeln!(writer, " jmp addr_{}", token.jmp)?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Keyword(KeywordType::While) => {
|
||||
writeln!(writer, " ;; -- while")?;
|
||||
ti += 1;
|
||||
}
|
||||
OpType::Keyword(KeywordType::Do) => {
|
||||
writeln!(writer, " ;; -- do")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " test rax, rax")?;
|
||||
writeln!(writer, " jz addr_{}", token.jmp)?;
|
||||
ti += 1;
|
||||
}
|
||||
OpType::Keyword(KeywordType::End) => {
|
||||
writeln!(writer, " ;; -- end")?;
|
||||
if ti + 1 != token.jmp {
|
||||
writeln!(writer, " jmp addr_{}", token.jmp)?;
|
||||
}
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Syscall0) => {
|
||||
writeln!(writer, " ;; -- syscall0")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " syscall")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Syscall1) => {
|
||||
writeln!(writer, " ;; -- syscall1")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
writeln!(writer, " syscall")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Syscall2) => {
|
||||
writeln!(writer, " ;; -- syscall2")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
writeln!(writer, " pop rsi")?;
|
||||
writeln!(writer, " syscall")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Syscall3) => {
|
||||
writeln!(writer, " ;; -- syscall3")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
writeln!(writer, " pop rsi")?;
|
||||
writeln!(writer, " pop rdx")?;
|
||||
writeln!(writer, " syscall")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Syscall4) => {
|
||||
writeln!(writer, " ;; -- syscall4")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
writeln!(writer, " pop rsi")?;
|
||||
writeln!(writer, " pop rdx")?;
|
||||
writeln!(writer, " pop r10")?;
|
||||
writeln!(writer, " syscall")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Syscall5) => {
|
||||
writeln!(writer, " ;; -- syscall5")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
writeln!(writer, " pop rsi")?;
|
||||
writeln!(writer, " pop rdx")?;
|
||||
writeln!(writer, " pop r10")?;
|
||||
writeln!(writer, " pop r8")?;
|
||||
writeln!(writer, " syscall")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Syscall6) => {
|
||||
writeln!(writer, " ;; -- syscall6")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
writeln!(writer, " pop rsi")?;
|
||||
writeln!(writer, " pop rdx")?;
|
||||
writeln!(writer, " pop r10")?;
|
||||
writeln!(writer, " pop r8")?;
|
||||
writeln!(writer, " pop r9")?;
|
||||
writeln!(writer, " syscall")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::None) | OpType::Keyword(KeywordType::Macro) | OpType::Keyword(KeywordType::Include) => unreachable!()
|
||||
}
|
||||
}
|
||||
writeln!(writer, "addr_{ti}:")?;
|
||||
writeln!(writer, " mov rax, 60")?;
|
||||
writeln!(writer, " mov rdi, 0")?;
|
||||
writeln!(writer, " syscall")?;
|
||||
writeln!(writer, "segment .data")?;
|
||||
for (_, s) in strings.iter().enumerate() {
|
||||
let s_chars = s.chars().map(|c| (c as u32).to_string()).collect::<Vec<String>>();
|
||||
let s_list = s_chars.join(",");
|
||||
writeln!(writer, " str_{}: db {} ; {}", s, s_list, s.escape_default())?;
|
||||
}
|
||||
|
||||
writeln!(writer, "segment .bss")?;
|
||||
writeln!(writer, "mem: resb {}", crate::compile::MEM_SZ)?;
|
||||
|
||||
writer.flush()?;
|
||||
linux_x86_64_compile_and_link(folders, args.quiet)?;
|
||||
if args.run {
|
||||
let c = linux_x86_64_run(&folders.of_c, &[], args.quiet)?;
|
||||
return Ok(c);
|
||||
}
|
||||
|
||||
Ok(0)
|
||||
}
|
|
@ -175,4 +175,10 @@ impl TokenType {
|
|||
}
|
||||
}
|
||||
|
||||
pub type Loc = (String, usize, usize);
|
||||
pub type Loc = (String, usize, usize);
|
||||
|
||||
|
||||
pub mod targets {
|
||||
pub const LINUX_X86_64: &'static str = "linux_x86_64";
|
||||
pub const WIN32_X86_64: &'static str = "win32_x86_64";
|
||||
}
|
18
src/main.rs
18
src/main.rs
|
@ -9,6 +9,7 @@ mod preprocessor;
|
|||
use std::fs;
|
||||
|
||||
use clap::Parser;
|
||||
use constants::targets;
|
||||
|
||||
pub const DEFAULT_OUT_FILE: &str = "a.out";
|
||||
pub const DEFAULT_INCLUDES: [&str;2] = [
|
||||
|
@ -16,6 +17,16 @@ pub const DEFAULT_INCLUDES: [&str;2] = [
|
|||
"~/.mclang/include",
|
||||
];
|
||||
|
||||
pub fn get_target() -> String {
|
||||
if cfg!(windows) {
|
||||
targets::WIN32_X86_64.to_string()
|
||||
} else if cfg!(unix) {
|
||||
targets::LINUX_X86_64.to_string()
|
||||
} else {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug, Clone)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
pub struct Args {
|
||||
|
@ -46,7 +57,10 @@ pub struct Args {
|
|||
/// Add an include directory [default: ["./include", "~/.mclang/include"]]
|
||||
#[arg(long, short='I')]
|
||||
include: Vec<String>,
|
||||
|
||||
|
||||
// what target to interpret or compile to, eg. linux_x86_64 or win32_x86_64
|
||||
#[arg(long, short='T', default_value_t=get_target())]
|
||||
target: String,
|
||||
|
||||
//#[arg(long, short='F')]
|
||||
//features: Vec<String>,
|
||||
|
@ -82,7 +96,7 @@ fn main() {
|
|||
1
|
||||
}
|
||||
} else if args.compile {
|
||||
if let Ok(c) = compile::linux_x86_64::compile(&tokens, &args) { c } else {
|
||||
if let Ok(c) = compile::compile(&tokens, &args) { c } else {
|
||||
error!("Compilation failed, exiting!");
|
||||
1
|
||||
}
|
||||
|
|
18
src/util.rs
18
src/util.rs
|
@ -79,21 +79,3 @@ pub mod logger {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
// pub trait StringExtra{
|
||||
// fn find_idx(&self, pat: char, start: u32) -> Result<u32, ()>;
|
||||
// }
|
||||
// impl StringExtra for String {
|
||||
// fn find_idx(&self, pat: char, start: u32) -> Result<u32, ()> {
|
||||
// let mut col = start;
|
||||
|
||||
// for c in (*self).chars() {
|
||||
// if c == pat {
|
||||
// return Ok(col);
|
||||
// }
|
||||
// col += 1;
|
||||
// }
|
||||
// Err(())
|
||||
|
||||
// }
|
||||
// }
|
52
test.nasm
Normal file
52
test.nasm
Normal file
|
@ -0,0 +1,52 @@
|
|||
BITS 64
|
||||
segment .text
|
||||
print:
|
||||
mov r9, -3689348814741910323
|
||||
sub rsp, 40
|
||||
mov BYTE [rsp+31], 10
|
||||
lea rcx, [rsp+30]
|
||||
.L2:
|
||||
mov rax, rdi
|
||||
lea r8, [rsp+32]
|
||||
mul r9
|
||||
mov rax, rdi
|
||||
sub r8, rcx
|
||||
shr rdx, 3
|
||||
lea rsi, [rdx+rdx*4]
|
||||
add rsi, rsi
|
||||
sub rax, rsi
|
||||
add eax, 48
|
||||
mov BYTE [rcx], al
|
||||
mov rax, rdi
|
||||
mov rdi, rdx
|
||||
mov rdx, rcx
|
||||
sub rcx, 1
|
||||
cmp rax, 9
|
||||
ja .L2
|
||||
lea rax, [rsp+32]
|
||||
mov edi, 1
|
||||
sub rdx, rax
|
||||
xor eax, eax
|
||||
lea rsi, [rsp+32+rdx]
|
||||
mov rdx, r8
|
||||
mov rax, 1
|
||||
syscall
|
||||
add rsp, 40
|
||||
ret
|
||||
global _start
|
||||
_start:
|
||||
addr_0:
|
||||
;; -- push int 32
|
||||
mov rax, 32
|
||||
push rax
|
||||
addr_1:
|
||||
;; -- print
|
||||
pop rdi
|
||||
call print
|
||||
addr_2:
|
||||
mov rax, 60
|
||||
mov rdi, 0
|
||||
syscall
|
||||
segment .data
|
||||
segment .bss
|
||||
mem: resb 640000
|
Loading…
Reference in New Issue
Block a user