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",
|
"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]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.2.8"
|
version = "0.2.8"
|
||||||
|
@ -145,6 +165,17 @@ dependencies = [
|
||||||
"once_cell",
|
"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]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.27.2"
|
version = "0.27.2"
|
||||||
|
@ -215,6 +246,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
|
"dirs",
|
||||||
"eyre",
|
"eyre",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -308,6 +340,26 @@ dependencies = [
|
||||||
"proc-macro2",
|
"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]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.21"
|
version = "0.1.21"
|
||||||
|
@ -363,6 +415,26 @@ dependencies = [
|
||||||
"winapi-util",
|
"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]]
|
[[package]]
|
||||||
name = "thread_local"
|
name = "thread_local"
|
||||||
version = "1.1.7"
|
version = "1.1.7"
|
||||||
|
@ -433,6 +505,12 @@ version = "0.9.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
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]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
|
|
@ -7,4 +7,5 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "4.1.8", features = ["derive"] }
|
clap = { version = "4.1.8", features = ["derive"] }
|
||||||
color-eyre = "0.6.2"
|
color-eyre = "0.6.2"
|
||||||
|
dirs = "5.0.0"
|
||||||
eyre = "0.6.8"
|
eyre = "0.6.8"
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
use std::path::{PathBuf, Path};
|
use std::path::{PathBuf, Path};
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
|
use crate::compile::Folders;
|
||||||
use crate::info;
|
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 = [
|
let nasm_args = [
|
||||||
"-felf64",
|
"-felf64",
|
||||||
of_a.to_str().unwrap(),
|
folders.of_a.to_str().unwrap(),
|
||||||
"-o",
|
"-o",
|
||||||
of_o.to_str().unwrap()
|
folders.of_o.to_str().unwrap()
|
||||||
];
|
];
|
||||||
|
|
||||||
let ld_args = [
|
let ld_args = [
|
||||||
of_o.to_str().unwrap(),
|
folders.of_o.to_str().unwrap(),
|
||||||
"-o",
|
"-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 crate::{constants::{Operator, OpType, KeywordType}, Args};
|
||||||
use color_eyre::Result;
|
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 crate::constants::InstructionType;
|
||||||
use super::commands::linux_x86_64_run;
|
|
||||||
|
use super::Folders;
|
||||||
|
|
||||||
|
|
||||||
pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
pub fn compile(tokens: &[Operator], args: &Args, folders: &Folders) -> 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)
|
|
||||||
};
|
|
||||||
|
|
||||||
of_c.set_extension("");
|
let file = fs::File::create(&folders.of_a)?;
|
||||||
of_o.set_extension("o");
|
|
||||||
of_a.set_extension("nasm");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let file = fs::File::create(&of_a)?;
|
|
||||||
let mut writer = BufWriter::new(&file);
|
let mut writer = BufWriter::new(&file);
|
||||||
|
|
||||||
|
|
||||||
// println!("{}", tokens.len());
|
// println!("{}", tokens.len());
|
||||||
let mut strings: Vec<String> = Vec::new();
|
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)?;
|
writeln!(writer, "mem: resb {}", crate::compile::MEM_SZ)?;
|
||||||
|
|
||||||
writer.flush()?;
|
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 {
|
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);
|
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 linux_x86_64;
|
||||||
pub mod commands;
|
pub mod win32_x86_64;
|
||||||
|
|
||||||
pub const MEM_SZ: usize = 640 * 1000; // 4kb
|
pub const MEM_SZ: usize = 640 * 1000; // 4kb
|
||||||
pub const STRING_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 std::fs;
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use constants::targets;
|
||||||
|
|
||||||
pub const DEFAULT_OUT_FILE: &str = "a.out";
|
pub const DEFAULT_OUT_FILE: &str = "a.out";
|
||||||
pub const DEFAULT_INCLUDES: [&str;2] = [
|
pub const DEFAULT_INCLUDES: [&str;2] = [
|
||||||
|
@ -16,6 +17,16 @@ pub const DEFAULT_INCLUDES: [&str;2] = [
|
||||||
"~/.mclang/include",
|
"~/.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)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
#[command(author, version, about, long_about = None)]
|
#[command(author, version, about, long_about = None)]
|
||||||
pub struct Args {
|
pub struct Args {
|
||||||
|
@ -46,7 +57,10 @@ pub struct Args {
|
||||||
/// Add an include directory [default: ["./include", "~/.mclang/include"]]
|
/// Add an include directory [default: ["./include", "~/.mclang/include"]]
|
||||||
#[arg(long, short='I')]
|
#[arg(long, short='I')]
|
||||||
include: Vec<String>,
|
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')]
|
//#[arg(long, short='F')]
|
||||||
//features: Vec<String>,
|
//features: Vec<String>,
|
||||||
|
@ -82,7 +96,7 @@ fn main() {
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
} else if args.compile {
|
} 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!");
|
error!("Compilation failed, exiting!");
|
||||||
1
|
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