From db83d6d9c1c0db7d0d6dd342427b9a8655efcc04 Mon Sep 17 00:00:00 2001 From: MCorange Date: Sun, 26 Mar 2023 20:51:36 +0300 Subject: [PATCH] Started on windows implementation --- Cargo.lock | 78 ++++ Cargo.toml | 1 + src/compile/{ => linux_x86_64}/commands.rs | 11 +- .../{linux_x86_64.rs => linux_x86_64/mod.rs} | 34 +- src/compile/mod.rs | 53 ++- src/compile/win32_x86_64/commands.rs | 89 ++++ src/compile/win32_x86_64/mod.rs | 417 ++++++++++++++++++ src/constants.rs | 8 +- src/main.rs | 18 +- src/util.rs | 18 - test | Bin 0 -> 3533 bytes test.exe | Bin 0 -> 3533 bytes test.nasm | 52 +++ test.o | Bin 0 -> 588 bytes 14 files changed, 729 insertions(+), 50 deletions(-) rename src/compile/{ => linux_x86_64}/commands.rs (87%) rename src/compile/{linux_x86_64.rs => linux_x86_64/mod.rs} (95%) create mode 100644 src/compile/win32_x86_64/commands.rs create mode 100644 src/compile/win32_x86_64/mod.rs create mode 100644 test create mode 100644 test.exe create mode 100644 test.nasm create mode 100644 test.o diff --git a/Cargo.lock b/Cargo.lock index 54e6f9f..5221b7b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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" diff --git a/Cargo.toml b/Cargo.toml index dde79dd..d268632 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/src/compile/commands.rs b/src/compile/linux_x86_64/commands.rs similarity index 87% rename from src/compile/commands.rs rename to src/compile/linux_x86_64/commands.rs index 98426e6..3dddff7 100644 --- a/src/compile/commands.rs +++ b/src/compile/linux_x86_64/commands.rs @@ -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() ]; diff --git a/src/compile/linux_x86_64.rs b/src/compile/linux_x86_64/mod.rs similarity index 95% rename from src/compile/linux_x86_64.rs rename to src/compile/linux_x86_64/mod.rs index 5b1a7b9..f7e3bc2 100644 --- a/src/compile/linux_x86_64.rs +++ b/src/compile/linux_x86_64/mod.rs @@ -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{ - 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{ - 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 = Vec::new(); @@ -421,9 +409,9 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ 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); } diff --git a/src/compile/mod.rs b/src/compile/mod.rs index 9c22480..3ee20c4 100644 --- a/src/compile/mod.rs +++ b/src/compile/mod.rs @@ -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 { + 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!("")) + } + } +} \ No newline at end of file diff --git a/src/compile/win32_x86_64/commands.rs b/src/compile/win32_x86_64/commands.rs new file mode 100644 index 0000000..3dddff7 --- /dev/null +++ b/src/compile/win32_x86_64/commands.rs @@ -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 { + + 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)) +} \ No newline at end of file diff --git a/src/compile/win32_x86_64/mod.rs b/src/compile/win32_x86_64/mod.rs new file mode 100644 index 0000000..b72541a --- /dev/null +++ b/src/compile/win32_x86_64/mod.rs @@ -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{ + + let file = fs::File::create(&folders.of_a)?; + let mut writer = BufWriter::new(&file); + + // println!("{}", tokens.len()); + let mut strings: Vec = 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::>(); + 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) +} \ No newline at end of file diff --git a/src/constants.rs b/src/constants.rs index aa203bf..d9b13ff 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -175,4 +175,10 @@ impl TokenType { } } -pub type Loc = (String, usize, usize); \ No newline at end of file +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"; +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index b5b0bfa..8c9493b 100644 --- a/src/main.rs +++ b/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, - + + // 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, @@ -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 } diff --git a/src/util.rs b/src/util.rs index 107d7a6..85633b8 100644 --- a/src/util.rs +++ b/src/util.rs @@ -79,21 +79,3 @@ pub mod logger { } } - -// pub trait StringExtra{ -// fn find_idx(&self, pat: char, start: u32) -> Result; -// } -// impl StringExtra for String { -// fn find_idx(&self, pat: char, start: u32) -> Result { -// let mut col = start; - -// for c in (*self).chars() { -// if c == pat { -// return Ok(col); -// } -// col += 1; -// } -// Err(()) - -// } -// } \ No newline at end of file diff --git a/test b/test new file mode 100644 index 0000000000000000000000000000000000000000..06a65882ee5f80256931a519747245dc68677b27 GIT binary patch literal 3533 zcmeHJOKclO82&e=prlIRPzer*ZbbymW#v{}Dk17pTUtwQVQ#M!bBv%4vw z;!)uXK?*{Z;J~>DZg2p}aA{~O#4Cs!2ZRK-7LeLYX?wx^|IDsur*62xDI?9!%=f<^ zp7Dv(??DLw9>6&o0Ss}aQIX$&|C~qi-2N}-;M3{t14FB^eW11KC3ZiKdNB{|4iCd9 zwcEmu*FxJ1?dsyP9YkH>%+AitXR4bufQD6qKhD`*co5(@#D9f{N_(xT$6*Q&G_Otr zJc27tIVx(8H1gZRNvj$&Qs!b0WLyAtCWpeA{8$YM+?l^n`r zrE@lHXujyQlSCdV2X;;|*Yi-`a=b22IjC4LCaF&+MG91q&y)nHf4=>_8t&lFgI`tW z_s_VSjrk|sjXRCa>bzaQ{TpuU3tzim{$6r7pSj>#f4K`c2V3R0EhM-bKe-#n3s- z;Egd7h}`?kAE>Mdo;u|+*`XVTUcKzy!26d_@*Chu`WOf*h6^|~&#{b$bSSB2hG?EH zAvnmE;(3jZs97WL69RSt`54c1ZEK$Ihy|sztzRaP8xx4UN)aW?%K9w1X2c~^Vff=_ zJlfW217WP|`;3vbf`?~_$3WhcNTtB@Zl*`abrBJId9|%iG9Fr#&p%8cKO;ijr+Kc^ z7GFml>8(skX=X{vV{Ed#f0X7uv=~`^6cJPNQ;M|^#Subq>L?m`GV8?=(Qz>*!Y*aZ zuoWSX*-@_}LQGoo2ZR_>A4#5KRzE|8qSR7XCZv8ugc728u1P&bL+Tfxm-I{U1UqO#^Q0-s4urLE!a@_w?&mm9$B@u zxTL8p^^*cMPFX*Rg&%b?loVh`c2;@JJE@4hB=wL+iWBdgV9^RmcV1$hCn_FuFGSa)#PHb*cu%l4PgHn`=%f@5_q|>ih)|`Yeylatva^Td zQsuE7H|j)@<`m^@XW}e>hbot*uu)a48WxXUrF;BT#knU!a$f5-dna!InapCDm4j(P zkku(u&tsyfamMwhpk)W9D literal 0 HcmV?d00001 diff --git a/test.exe b/test.exe new file mode 100644 index 0000000000000000000000000000000000000000..50b8025533acbab8472e23d398f6c77e1cfd70a2 GIT binary patch literal 3533 zcmeHJOKclO82&e=prlIRPzer*ZbSslW#v{}kgDQRTUtwQVQ#M!bBv%4wb zUEvEs3PP3Oz?lO#IDllhG_)1s6~wI)2nlX2LZTO-T7v+oJaE9!O!R5lj)uLq1D)#Z>@QW-H)SQ%mcf_!!Szi zwy@*%(Dp*Ry0l^kQCB##voi~s>Shg~VU=M1WxEUa0vtp97r3vq-%}aNTkT zH>Y3t+9jEbR1kOZ(&24)D?MO0HZKhcxqqKKxN_+7(8hg}U3+6R8V!%){vu8!;t~6g zx=^jO-y3@w*vr6wnE_|j^9351!+8sTe?7~2CKXBQgggl{!}(oBNBSX`thX|XUdHzn zLUfgtEO~2d2HZKkokadRU3>DaDM3H>LU}|)YF3ETIP%aK;oWY`$^fy690u4hks|=F zjgdg)-e>+mWmWLhDVNC(-7xg(W$y;wzl4(C0FTngKu|GUz^QqTXFQ}sNi{P>^K=Qp zLADgnD|AH78hMuxunWjXc&2Mx^L$GzD5Y)vJc0Z%fyk>AQL?P8&ys6KTrw4gKW@gO zZJjX?#=5@G7+EWLc$Rn!!>6BGm}!9S(5S?n=J1irFkDMMphq0#MJzlVl71RBq2C;6b(F?_2P)=xEK>*mojG9 zijc?bs8O<3DG>)q@E)3PbQ_ax}VeLHC3C*DhfMXMy;d5(3WAn?+=5Mq&t z_?(cGfS-+GmaMmv7n4*3?3{=bFA9}o9W=h-7o1@d@$Q1Ck~4`HCT-FzQhS(z=V{iZ-cs_j2S7 JlZT=lybS|%9jO2S literal 0 HcmV?d00001 diff --git a/test.nasm b/test.nasm new file mode 100644 index 0000000..73029a5 --- /dev/null +++ b/test.nasm @@ -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 diff --git a/test.o b/test.o new file mode 100644 index 0000000000000000000000000000000000000000..a62d83f48b8d8099df6f8fc5f8de1c21bdd2a8e0 GIT binary patch literal 588 zcmeZaWM=5AQb-YFWMB|vfB?Oc)QS=)8$@*haSsrK)WCoOLqLLFN@7VOOaMxQ)F7*K zU@$nKmsDJgqU;DK3Kzs_0IKucdG-thcr?G!IOd`v&*jnUqax?g`NOBzMMc5$`$Hhp zQ}cw!!B@;4y(W`97{7UFerP^m(7_0l@aVkm(Rs?F`6Z)A^AFDQlO7;F`$2B@&^%;# zz@xWBM8T)?&<>CYKdVRc5skw;6oBl2_!mw8|Nq}%17z<9VxXj6T4qivhzSJ${xdM7 zGwQ{Zq!yRx0Ta_BGv<$!81!bdMLsW?BU z6dWo4f$m{uC@9LzgT)cpc8G|ckC6n>42Vd4aY