Started on windows implementation

This commit is contained in:
MCorange 2023-03-26 20:51:36 +03:00
parent 747c4e59d4
commit db83d6d9c1
14 changed files with 729 additions and 50 deletions

78
Cargo.lock generated
View File

@ -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"

View File

@ -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"

View File

@ -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()
];

View File

@ -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);
}

View File

@ -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!(""))
}
}
}

View 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))
}

View 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)
}

View File

@ -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";
}

View File

@ -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
}

View File

@ -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(())
// }
// }

BIN
test Normal file

Binary file not shown.

BIN
test.exe Normal file

Binary file not shown.

52
test.nasm Normal file
View 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

BIN
test.o Normal file

Binary file not shown.