diff --git a/compiler/src/passes/assign/assign.rs b/compiler/src/passes/assign/assign.rs index c245b75..dc9c5bc 100644 --- a/compiler/src/passes/assign/assign.rs +++ b/compiler/src/passes/assign/assign.rs @@ -1,7 +1,7 @@ use crate::passes::assign::{Arg, FunAssigned, X86Assigned}; use crate::passes::select::{Block, Instr, InstrSelected, VarArg, X86Selected}; -use crate::{display, time}; use crate::utils::unique_sym::UniqueSym; +use crate::{display, time}; use functor_derive::Functor; use std::collections::HashMap; diff --git a/compiler/src/passes/assign/display.rs b/compiler/src/passes/assign/display.rs index ddb6971..64edbf8 100644 --- a/compiler/src/passes/assign/display.rs +++ b/compiler/src/passes/assign/display.rs @@ -1,7 +1,7 @@ -use std::fmt::{Display, Formatter}; -use indenter::indented; use crate::passes::assign::{FunAssigned, X86Assigned}; +use indenter::indented; use std::fmt::Write; +use std::fmt::{Display, Formatter}; impl Display for X86Assigned<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { diff --git a/compiler/src/passes/assign/include_liveness.rs b/compiler/src/passes/assign/include_liveness.rs index a769cc5..30b97b3 100644 --- a/compiler/src/passes/assign/include_liveness.rs +++ b/compiler/src/passes/assign/include_liveness.rs @@ -112,7 +112,7 @@ pub fn handle_instr<'p>( match instr { Instr::Add { src, dst, .. } | Instr::Sub { src, dst, .. } - | Instr::And{ src, dst, .. } + | Instr::And { src, dst, .. } | Instr::Or { src, dst, .. } | Instr::Xor { src, dst, .. } => { arg(dst, RW); @@ -129,7 +129,7 @@ pub fn handle_instr<'p>( Instr::Push { src, .. } => { arg(src, R); } - Instr::Pop{ dst, .. } => { + Instr::Pop { dst, .. } => { arg(dst, W); } Instr::Neg { dst, .. } | Instr::Not { dst, .. } => { @@ -151,14 +151,14 @@ pub fn handle_instr<'p>( arg(&VarArg::Reg(reg), R); } } - Instr::Ret => { + Instr::Ret { .. } => { // Because the return value of our function is in RAX, we need to consider it being read at the end of a block. arg(&VarArg::Reg(Reg::RAX), R); } Instr::Setcc { .. } => { arg(&VarArg::Reg(Reg::RAX), W); } - Instr::Mul{ src, .. } => { + Instr::Mul { src, .. } => { arg(&VarArg::Reg(Reg::RDX), W); arg(&VarArg::Reg(Reg::RAX), RW); arg(src, R); diff --git a/compiler/src/passes/assign/mod.rs b/compiler/src/passes/assign/mod.rs index 39e85c6..495af41 100644 --- a/compiler/src/passes/assign/mod.rs +++ b/compiler/src/passes/assign/mod.rs @@ -1,26 +1,23 @@ mod assign; mod color_interference; mod compute_interference; -mod include_liveness; mod display; +mod include_liveness; -use crate::passes::select::{ - Block, FunSelected, Instr, InstrSelected, Reg, VarArg, X86Selected, -}; +use crate::passes::select::{Block, FunSelected, Instr, InstrSelected, Reg, VarArg, X86Selected}; +use crate::passes::validate::Int; use crate::utils::unique_sym::UniqueSym; use derive_more::Display; use functor_derive::Functor; use petgraph::graphmap::GraphMap; use petgraph::Undirected; use std::collections::{HashMap, HashSet}; -use crate::passes::validate::Int; pub struct X86Assigned<'p> { pub fns: HashMap, FunAssigned<'p>>, pub entry: UniqueSym<'p>, } - pub struct FunAssigned<'p> { pub blocks: HashMap, Block<'p, Arg>>, pub entry: UniqueSym<'p>, diff --git a/compiler/src/passes/emit/binary.rs b/compiler/src/passes/emit/binary.rs index aace0db..58d8030 100644 --- a/compiler/src/passes/emit/binary.rs +++ b/compiler/src/passes/emit/binary.rs @@ -1,6 +1,6 @@ use crate::passes::assign::Arg; use crate::passes::emit::encode_reg; -use crate::passes::select::{Reg}; +use crate::passes::select::Reg; pub struct BinaryOpInfo { /// Opcode when src = Reg and dst = Reg | Deref. @@ -63,226 +63,227 @@ pub const MOVQ_INFO: BinaryOpInfo = BinaryOpInfo { }; pub fn encode_binary_instr(op_info: BinaryOpInfo, src: &Arg, dst: &Arg) -> Vec { - match (src, dst) { - (Arg::Reg(src), Arg::Reg(dst)) => { - let (s, sss) = encode_reg(src); - let (d, ddd) = encode_reg(dst); - vec![ - 0b0100_1000 | (s << 2) | d, - op_info.r_rm, - 0b11_000_000 | sss << 3 | ddd, - ] - } - (Arg::Deref { reg: src, off }, Arg::Reg(dst)) => { - let (s, sss) = encode_reg(src); - let (d, ddd) = encode_reg(dst); - let off = *off as i32; - - let mut v = vec![ - 0b0100_1000 | (d << 2) | s, - op_info.rm_r, - 0b10_000_000 | ddd << 3 | sss, - ]; - if matches!(src, Reg::RSP | Reg::R12) { - v.push(0x24); - } - v.extend(off.to_le_bytes()); - v - } - (Arg::Reg(src), Arg::Deref { reg: dst, off }) => { - let (s, sss) = encode_reg(src); - let (d, ddd) = encode_reg(dst); - let off = *off as i32; - - let mut v = vec![ - 0b0100_1000 | (s << 2) | d, - op_info.r_rm, - 0b10_000_000 | sss << 3 | ddd, - ]; - if matches!(dst, Reg::RSP | Reg::R12) { - v.push(0x24); - } - v.extend(off.to_le_bytes()); - v - } - (Arg::Imm(imm), Arg::Reg(dst)) => match imm { - Imm::Imm8(_) => todo!(), - Imm::Imm16(_) => todo!(), - Imm::Imm32(imm) => { - let (d, ddd) = encode_reg(dst); - - let mut v = vec![ - 0b0100_1000 | d, - op_info.i_rm, - 0b11_000_000 | op_info.pad << 3 | ddd, - ]; - v.extend(imm.to_le_bytes()); - v - } - Imm::Imm64(_) => todo!(), - }, - (Arg::Imm(imm), Arg::Deref { reg: dst, off }) => match imm { - Imm::Imm8(_) => todo!(), - Imm::Imm16(_) => todo!(), - Imm::Imm32(imm) => { - let (d, ddd) = encode_reg(dst); - let off = *off as i32; - - let mut v = vec![ - 0b0100_1000 | d, - op_info.i_rm, - 0b10_000_000 | op_info.pad << 3 | ddd, - ]; - if matches!(dst, Reg::RSP | Reg::R12) { - v.push(0x24); - } - v.extend(off.to_le_bytes()); - v.extend(imm.to_le_bytes()); - v - } - Imm::Imm64(_) => todo!(), - }, - (Arg::Deref { .. }, Arg::Deref { .. }) => { - unreachable!("Found binary instruction with 2 derefs."); - } - (_, Arg::Imm { .. }) => { - unreachable!("Found immediate in destination position."); - } - } + todo!() + // match (src, dst) { + // (Arg::Reg(src), Arg::Reg(dst)) => { + // let (s, sss) = encode_reg(src); + // let (d, ddd) = encode_reg(dst); + // vec![ + // 0b0100_1000 | (s << 2) | d, + // op_info.r_rm, + // 0b11_000_000 | sss << 3 | ddd, + // ] + // } + // (Arg::Deref { reg: src, off }, Arg::Reg(dst)) => { + // let (s, sss) = encode_reg(src); + // let (d, ddd) = encode_reg(dst); + // let off = *off as i32; + // + // let mut v = vec![ + // 0b0100_1000 | (d << 2) | s, + // op_info.rm_r, + // 0b10_000_000 | ddd << 3 | sss, + // ]; + // if matches!(src, Reg::RSP | Reg::R12) { + // v.push(0x24); + // } + // v.extend(off.to_le_bytes()); + // v + // } + // (Arg::Reg(src), Arg::Deref { reg: dst, off }) => { + // let (s, sss) = encode_reg(src); + // let (d, ddd) = encode_reg(dst); + // let off = *off as i32; + // + // let mut v = vec![ + // 0b0100_1000 | (s << 2) | d, + // op_info.r_rm, + // 0b10_000_000 | sss << 3 | ddd, + // ]; + // if matches!(dst, Reg::RSP | Reg::R12) { + // v.push(0x24); + // } + // v.extend(off.to_le_bytes()); + // v + // } + // (Arg::Imm(imm), Arg::Reg(dst)) => match imm { + // Imm::Imm8(_) => todo!(), + // Imm::Imm16(_) => todo!(), + // Imm::Imm32(imm) => { + // let (d, ddd) = encode_reg(dst); + // + // let mut v = vec![ + // 0b0100_1000 | d, + // op_info.i_rm, + // 0b11_000_000 | op_info.pad << 3 | ddd, + // ]; + // v.extend(imm.to_le_bytes()); + // v + // } + // Imm::Imm64(_) => todo!(), + // }, + // (Arg::Imm(imm), Arg::Deref { reg: dst, off }) => match imm { + // Imm::Imm8(_) => todo!(), + // Imm::Imm16(_) => todo!(), + // Imm::Imm32(imm) => { + // let (d, ddd) = encode_reg(dst); + // let off = *off as i32; + // + // let mut v = vec![ + // 0b0100_1000 | d, + // op_info.i_rm, + // 0b10_000_000 | op_info.pad << 3 | ddd, + // ]; + // if matches!(dst, Reg::RSP | Reg::R12) { + // v.push(0x24); + // } + // v.extend(off.to_le_bytes()); + // v.extend(imm.to_le_bytes()); + // v + // } + // Imm::Imm64(_) => todo!(), + // }, + // (Arg::Deref { .. }, Arg::Deref { .. }) => { + // unreachable!("Found binary instruction with 2 derefs."); + // } + // (_, Arg::Imm { .. }) => { + // unreachable!("Found immediate in destination position."); + // } + // } } -#[cfg(test)] -mod tests { - use crate::*; - - mod add { - use super::*; - - check!(reg_reg, add!(reg!(RSP), reg!(RDX)), vec![0x48, 0x01, 0xE2]); - check!( - imm_reg, - add!(imm32!(i32::MAX as i64), reg!(RBP)), - vec![0x48, 0x81, 0xC5, 0xFF, 0xFF, 0xFF, 0x7F] - ); - check!( - deref_reg1, - add!(deref!(RBX, i32::MAX as i64), reg!(RDI)), - vec![0x48, 0x03, 0xBB, 0xFF, 0xFF, 0xFF, 0x7F] - ); - check!( - deref_reg2, - add!(deref!(RBX, i32::MAX as i64), reg!(R15)), - vec![0x4C, 0x03, 0xBB, 0xFF, 0xFF, 0xFF, 0x7F] - ); - check!( - reg_deref1, - add!(reg!(RCX), deref!(R15, i32::MAX as i64)), - vec![0x49, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x7F] - ); - check!( - imm_deref1, - add!( - imm32!((i32::MAX - 0xFF) as i64), - deref!(R9, i32::MAX as i64) - ), - vec![0x49, 0x81, 0x81, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0x7F] - ); - check!( - imm_deref2, - add!( - imm32!((i32::MAX - 0xFF) as i64), - deref!(RDX, i32::MAX as i64) - ), - vec![0x48, 0x81, 0x82, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0x7F] - ); - } - - mod sub { - use super::*; - - check!(reg_reg, sub!(reg!(RSP), reg!(RDX)), vec![0x48, 0x29, 0xE2]); - check!( - imm_reg, - sub!(imm32!(i32::MAX as i64), reg!(RBP)), - vec![0x48, 0x81, 0xED, 0xFF, 0xFF, 0xFF, 0x7F] - ); - check!( - deref_reg1, - sub!(deref!(RBX, i32::MAX as i64), reg!(RDI)), - vec![0x48, 0x2B, 0xBB, 0xFF, 0xFF, 0xFF, 0x7F] - ); - check!( - deref_reg2, - sub!(deref!(RBX, i32::MAX as i64), reg!(R15)), - vec![0x4C, 0x2B, 0xBB, 0xFF, 0xFF, 0xFF, 0x7F] - ); - check!( - reg_deref1, - sub!(reg!(RCX), deref!(R15, i32::MAX as i64)), - vec![0x49, 0x29, 0x8F, 0xFF, 0xFF, 0xFF, 0x7F] - ); - check!( - imm_deref1, - sub!( - imm32!((i32::MAX - 0xFF) as i64), - deref!(R9, i32::MAX as i64) - ), - vec![0x49, 0x81, 0xA9, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0x7F] - ); - check!( - imm_deref2, - sub!( - imm32!((i32::MAX - 0xFF) as i64), - deref!(RDX, i32::MAX as i64) - ), - vec![0x48, 0x81, 0xAA, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0x7F] - ); - } - - mod r#move { - use super::*; - - check!(reg_reg, mov!(reg!(RSP), reg!(RDX)), vec![0x48, 0x89, 0xE2]); - check!( - imm_reg, - mov!(imm32!(i32::MAX as i64), reg!(RBP)), - vec![0x48, 0xC7, 0xC5, 0xFF, 0xFF, 0xFF, 0x7F] - ); - check!( - deref_reg1, - mov!(deref!(RBX, i32::MAX as i64), reg!(RDI)), - vec![0x48, 0x8B, 0xBB, 0xFF, 0xFF, 0xFF, 0x7F] - ); - check!( - deref_reg2, - mov!(deref!(RBX, i32::MAX as i64), reg!(R15)), - vec![0x4C, 0x8B, 0xBB, 0xFF, 0xFF, 0xFF, 0x7F] - ); - check!( - reg_deref1, - mov!(reg!(RCX), deref!(R15, i32::MAX as i64)), - vec![0x49, 0x89, 0x8F, 0xFF, 0xFF, 0xFF, 0x7F] - ); - check!( - reg_deref2, - mov!(reg!(R12), deref!(RBP, -56)), - vec![0x4C, 0x89, 0xA5, 0xC8, 0xFF, 0xFF, 0xFF] - ); - check!( - imm_deref1, - mov!( - imm32!((i32::MAX - 0xFF) as i64), - deref!(R9, i32::MAX as i64) - ), - vec![0x49, 0xC7, 0x81, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0x7F] - ); - check!( - imm_deref2, - mov!( - imm32!((i32::MAX - 0xFF) as i64), - deref!(RDX, i32::MAX as i64) - ), - vec![0x48, 0xC7, 0x82, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0x7F] - ); - } -} +// #[cfg(test)] +// mod tests { +// use crate::*; +// +// mod add { +// use super::*; +// +// check!(reg_reg, add!(reg!(RSP), reg!(RDX)), vec![0x48, 0x01, 0xE2]); +// check!( +// imm_reg, +// add!(imm32!(i32::MAX as i64), reg!(RBP)), +// vec![0x48, 0x81, 0xC5, 0xFF, 0xFF, 0xFF, 0x7F] +// ); +// check!( +// deref_reg1, +// add!(deref!(RBX, i32::MAX as i64), reg!(RDI)), +// vec![0x48, 0x03, 0xBB, 0xFF, 0xFF, 0xFF, 0x7F] +// ); +// check!( +// deref_reg2, +// add!(deref!(RBX, i32::MAX as i64), reg!(R15)), +// vec![0x4C, 0x03, 0xBB, 0xFF, 0xFF, 0xFF, 0x7F] +// ); +// check!( +// reg_deref1, +// add!(reg!(RCX), deref!(R15, i32::MAX as i64)), +// vec![0x49, 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x7F] +// ); +// check!( +// imm_deref1, +// add!( +// imm32!((i32::MAX - 0xFF) as i64), +// deref!(R9, i32::MAX as i64) +// ), +// vec![0x49, 0x81, 0x81, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0x7F] +// ); +// check!( +// imm_deref2, +// add!( +// imm32!((i32::MAX - 0xFF) as i64), +// deref!(RDX, i32::MAX as i64) +// ), +// vec![0x48, 0x81, 0x82, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0x7F] +// ); +// } +// +// mod sub { +// use super::*; +// +// check!(reg_reg, sub!(reg!(RSP), reg!(RDX)), vec![0x48, 0x29, 0xE2]); +// check!( +// imm_reg, +// sub!(imm32!(i32::MAX as i64), reg!(RBP)), +// vec![0x48, 0x81, 0xED, 0xFF, 0xFF, 0xFF, 0x7F] +// ); +// check!( +// deref_reg1, +// sub!(deref!(RBX, i32::MAX as i64), reg!(RDI)), +// vec![0x48, 0x2B, 0xBB, 0xFF, 0xFF, 0xFF, 0x7F] +// ); +// check!( +// deref_reg2, +// sub!(deref!(RBX, i32::MAX as i64), reg!(R15)), +// vec![0x4C, 0x2B, 0xBB, 0xFF, 0xFF, 0xFF, 0x7F] +// ); +// check!( +// reg_deref1, +// sub!(reg!(RCX), deref!(R15, i32::MAX as i64)), +// vec![0x49, 0x29, 0x8F, 0xFF, 0xFF, 0xFF, 0x7F] +// ); +// check!( +// imm_deref1, +// sub!( +// imm32!((i32::MAX - 0xFF) as i64), +// deref!(R9, i32::MAX as i64) +// ), +// vec![0x49, 0x81, 0xA9, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0x7F] +// ); +// check!( +// imm_deref2, +// sub!( +// imm32!((i32::MAX - 0xFF) as i64), +// deref!(RDX, i32::MAX as i64) +// ), +// vec![0x48, 0x81, 0xAA, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0x7F] +// ); +// } +// +// mod r#move { +// use super::*; +// +// check!(reg_reg, mov!(reg!(RSP), reg!(RDX)), vec![0x48, 0x89, 0xE2]); +// check!( +// imm_reg, +// mov!(imm32!(i32::MAX as i64), reg!(RBP)), +// vec![0x48, 0xC7, 0xC5, 0xFF, 0xFF, 0xFF, 0x7F] +// ); +// check!( +// deref_reg1, +// mov!(deref!(RBX, i32::MAX as i64), reg!(RDI)), +// vec![0x48, 0x8B, 0xBB, 0xFF, 0xFF, 0xFF, 0x7F] +// ); +// check!( +// deref_reg2, +// mov!(deref!(RBX, i32::MAX as i64), reg!(R15)), +// vec![0x4C, 0x8B, 0xBB, 0xFF, 0xFF, 0xFF, 0x7F] +// ); +// check!( +// reg_deref1, +// mov!(reg!(RCX), deref!(R15, i32::MAX as i64)), +// vec![0x49, 0x89, 0x8F, 0xFF, 0xFF, 0xFF, 0x7F] +// ); +// check!( +// reg_deref2, +// mov!(reg!(R12), deref!(RBP, -56)), +// vec![0x4C, 0x89, 0xA5, 0xC8, 0xFF, 0xFF, 0xFF] +// ); +// check!( +// imm_deref1, +// mov!( +// imm32!((i32::MAX - 0xFF) as i64), +// deref!(R9, i32::MAX as i64) +// ), +// vec![0x49, 0xC7, 0x81, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0x7F] +// ); +// check!( +// imm_deref2, +// mov!( +// imm32!((i32::MAX - 0xFF) as i64), +// deref!(RDX, i32::MAX as i64) +// ), +// vec![0x48, 0xC7, 0x82, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0x7F] +// ); +// } +// } diff --git a/compiler/src/passes/emit/mod.rs b/compiler/src/passes/emit/mod.rs index 2e94d43..9ffd8ff 100644 --- a/compiler/src/passes/emit/mod.rs +++ b/compiler/src/passes/emit/mod.rs @@ -73,57 +73,58 @@ fn emit_instr<'p>( rel_jumps: &mut HashMap>, abs_jumps: &mut HashMap>, ) { - let v = match instr { - Instr::Addq { src, dst } => encode_binary_instr(ADDQ_INFO, src, dst), - Instr::Sub { src, dst } => encode_binary_instr(SUBQ_INFO, src, dst), - Instr::Movq { src, dst } => encode_binary_instr(MOVQ_INFO, src, dst), - Instr::Negq { dst } => encode_unary_instr(NEGQ_INFO, dst), - Instr::Pushq { src } => encode_push_pop(PUSHQ_INFO, src), - Instr::Popq { dst } => encode_push_pop(POPQ_INFO, dst), - Instr::Cmpq { src, dst } => encode_binary_instr(CMPQ_INFO, src, dst), - Instr::Andq { src, dst } => encode_binary_instr(ANDQ_INFO, src, dst), - Instr::Or { src, dst } => encode_binary_instr(ORQ_INFO, src, dst), - Instr::Xorq { src, dst } => encode_binary_instr(XORQ_INFO, src, dst), - Instr::Notq { .. } => todo!(), - Instr::Setcc { cnd } => encode_setcc(cnd), - Instr::CallDirect { lbl, .. } => { - rel_jumps.insert(machine_code.len() + 1, *lbl); - vec![0xE8, 0x00, 0x00, 0x00, 0x00] - } - Instr::CallIndirect { src, .. } => encode_unary_instr(CALLQ_INDIRECT_INFO, src), - Instr::Jmp { lbl } => { - rel_jumps.insert(machine_code.len() + 1, *lbl); - vec![0xE9, 0x00, 0x00, 0x00, 0x00] - } - Instr::Jcc { lbl, cnd } => { - rel_jumps.insert(machine_code.len() + 2, *lbl); - vec![0x0F, encode_cnd(*cnd), 0x00, 0x00, 0x00, 0x00] - } - Instr::Retq => vec![0xC3], - Instr::Syscall { .. } => vec![0x0F, 0x05], - Instr::Divq { divisor } => encode_muldiv_instr( - MulDivOpInfo { - op: 0xF7, - imm_as_src: 0b110, - }, - divisor, - ), - Instr::Mulq { src } => encode_muldiv_instr( - MulDivOpInfo { - op: 0xF7, - imm_as_src: 0b100, - }, - src, - ), - Instr::LoadLbl { lbl, dst } => { - // This instruction creates a 32-bit placeholder and stores the offset so it can be set to `lbl` later. - let bytes = encode_binary_instr(MOVQ_INFO, &imm!(0), dst); - // The label should, regardless of the destination variant, always be stored in the last 4 bytes (we hope). - abs_jumps.insert(machine_code.len() + bytes.len() - 4, *lbl); - bytes - } - }; - machine_code.extend(v); + // let v = match instr { + // Instr::Addq { src, dst } => encode_binary_instr(ADDQ_INFO, src, dst), + // Instr::Sub { src, dst } => encode_binary_instr(SUBQ_INFO, src, dst), + // Instr::Movq { src, dst } => encode_binary_instr(MOVQ_INFO, src, dst), + // Instr::Negq { dst } => encode_unary_instr(NEGQ_INFO, dst), + // Instr::Pushq { src } => encode_push_pop(PUSHQ_INFO, src), + // Instr::Popq { dst } => encode_push_pop(POPQ_INFO, dst), + // Instr::Cmpq { src, dst } => encode_binary_instr(CMPQ_INFO, src, dst), + // Instr::Andq { src, dst } => encode_binary_instr(ANDQ_INFO, src, dst), + // Instr::Or { src, dst } => encode_binary_instr(ORQ_INFO, src, dst), + // Instr::Xorq { src, dst } => encode_binary_instr(XORQ_INFO, src, dst), + // Instr::Notq { .. } => todo!(), + // Instr::Setcc { cnd } => encode_setcc(cnd), + // Instr::CallDirect { lbl, .. } => { + // rel_jumps.insert(machine_code.len() + 1, *lbl); + // vec![0xE8, 0x00, 0x00, 0x00, 0x00] + // } + // Instr::CallIndirect { src, .. } => encode_unary_instr(CALLQ_INDIRECT_INFO, src), + // Instr::Jmp { lbl } => { + // rel_jumps.insert(machine_code.len() + 1, *lbl); + // vec![0xE9, 0x00, 0x00, 0x00, 0x00] + // } + // Instr::Jcc { lbl, cnd } => { + // rel_jumps.insert(machine_code.len() + 2, *lbl); + // vec![0x0F, encode_cnd(*cnd), 0x00, 0x00, 0x00, 0x00] + // } + // Instr::Retq => vec![0xC3], + // Instr::Syscall { .. } => vec![0x0F, 0x05], + // Instr::Divq { divisor } => encode_muldiv_instr( + // MulDivOpInfo { + // op: 0xF7, + // imm_as_src: 0b110, + // }, + // divisor, + // ), + // Instr::Mulq { src } => encode_muldiv_instr( + // MulDivOpInfo { + // op: 0xF7, + // imm_as_src: 0b100, + // }, + // src, + // ), + // Instr::LoadLbl { lbl, dst } => { + // // This instruction creates a 32-bit placeholder and stores the offset so it can be set to `lbl` later. + // let bytes = encode_binary_instr(MOVQ_INFO, &imm!(0), dst); + // // The label should, regardless of the destination variant, always be stored in the last 4 bytes (we hope). + // abs_jumps.insert(machine_code.len() + bytes.len() - 4, *lbl); + // bytes + // } + // }; + // machine_code.extend(v); + todo!() } fn encode_reg(reg: &Reg) -> (u8, u8) { diff --git a/compiler/src/passes/emit/mul_div.rs b/compiler/src/passes/emit/mul_div.rs index b17e6a0..eae762b 100644 --- a/compiler/src/passes/emit/mul_div.rs +++ b/compiler/src/passes/emit/mul_div.rs @@ -21,19 +21,19 @@ pub fn encode_muldiv_instr(op_info: MulDivOpInfo, reg: &Arg) -> Vec { } } -#[cfg(test)] -mod tests { - mod division { - use crate::*; - - check!(div1, div!(reg!(R15)), vec![0x49, 0xF7, 0xF7]); - check!(div2, div!(reg!(RDX)), vec![0x48, 0xF7, 0xF2]); - } - - mod multiply { - use crate::*; - - check!(mul1, mul!(reg!(R15)), vec![0x49, 0xF7, 0xE7]); - check!(mul2, mul!(reg!(RDX)), vec![0x48, 0xF7, 0xE2]); - } -} +// #[cfg(test)] +// mod tests { +// mod division { +// use crate::*; +// +// check!(div1, div!(reg!(R15)), vec![0x49, 0xF7, 0xF7]); +// check!(div2, div!(reg!(RDX)), vec![0x48, 0xF7, 0xF2]); +// } +// +// mod multiply { +// use crate::*; +// +// check!(mul1, mul!(reg!(R15)), vec![0x49, 0xF7, 0xE7]); +// check!(mul2, mul!(reg!(RDX)), vec![0x48, 0xF7, 0xE2]); +// } +// } diff --git a/compiler/src/passes/emit/push_pop.rs b/compiler/src/passes/emit/push_pop.rs index e86a46e..f20bfcc 100644 --- a/compiler/src/passes/emit/push_pop.rs +++ b/compiler/src/passes/emit/push_pop.rs @@ -63,49 +63,49 @@ pub fn encode_push_pop(op_info: PushPopInfo, reg: &Arg) -> Vec { } } -#[cfg(test)] -mod tests { - use crate::*; - - mod push { - use super::*; - - check!(reg1, push!(reg!(RAX)), vec![0x50]); - check!(reg2, push!(reg!(R14)), vec![0x41, 0x56]); - - check!( - deref1, - push!(deref!(RDX, i32::MAX as i64)), - vec![0xFF, 0xB2, 0xFF, 0xFF, 0xFF, 0x7F] - ); - check!( - deref2, - push!(deref!(R11, i32::MAX as i64)), - vec![0x41, 0xFF, 0xB3, 0xFF, 0xFF, 0xFF, 0x7F] - ); - - check!( - imm, - push!(imm32!(i32::MAX as i64)), - vec![0x68, 0xFF, 0xFF, 0xFF, 0x7F] - ); - } - - mod pop { - use super::*; - - check!(reg1, pop!(reg!(RAX)), vec![0x58]); - check!(reg2, pop!(reg!(R14)), vec![0x41, 0x5E]); - - check!( - deref1, - pop!(deref!(RDX, i32::MAX as i64)), - vec![0x8F, 0x82, 0xFF, 0xFF, 0xFF, 0x7F] - ); - check!( - deref2, - pop!(deref!(R11, i32::MAX as i64)), - vec![0x41, 0x8F, 0x83, 0xFF, 0xFF, 0xFF, 0x7F] - ); - } -} +// #[cfg(test)] +// mod tests { +// use crate::*; +// +// mod push { +// use super::*; +// +// check!(reg1, push!(reg!(RAX)), vec![0x50]); +// check!(reg2, push!(reg!(R14)), vec![0x41, 0x56]); +// +// check!( +// deref1, +// push!(deref!(RDX, i32::MAX as i64)), +// vec![0xFF, 0xB2, 0xFF, 0xFF, 0xFF, 0x7F] +// ); +// check!( +// deref2, +// push!(deref!(R11, i32::MAX as i64)), +// vec![0x41, 0xFF, 0xB3, 0xFF, 0xFF, 0xFF, 0x7F] +// ); +// +// check!( +// imm, +// push!(imm32!(i32::MAX as i64)), +// vec![0x68, 0xFF, 0xFF, 0xFF, 0x7F] +// ); +// } +// +// mod pop { +// use super::*; +// +// check!(reg1, pop!(reg!(RAX)), vec![0x58]); +// check!(reg2, pop!(reg!(R14)), vec![0x41, 0x5E]); +// +// check!( +// deref1, +// pop!(deref!(RDX, i32::MAX as i64)), +// vec![0x8F, 0x82, 0xFF, 0xFF, 0xFF, 0x7F] +// ); +// check!( +// deref2, +// pop!(deref!(R11, i32::MAX as i64)), +// vec![0x41, 0x8F, 0x83, 0xFF, 0xFF, 0xFF, 0x7F] +// ); +// } +// } diff --git a/compiler/src/passes/emit/special.rs b/compiler/src/passes/emit/special.rs index e14f5d4..b6dfe35 100644 --- a/compiler/src/passes/emit/special.rs +++ b/compiler/src/passes/emit/special.rs @@ -14,12 +14,12 @@ pub fn encode_setcc(cnd: &Cnd) -> Vec { vec![0x0F, cnd, 0xC0] } -#[cfg(test)] -mod tests { - mod retq { - - use crate::*; - - check!(retq, ret!(), vec![0xC3]); - } -} +// #[cfg(test)] +// mod tests { +// mod retq { +// +// use crate::*; +// +// check!(retq, ret!(), vec![0xC3]); +// } +// } diff --git a/compiler/src/passes/emit/unary.rs b/compiler/src/passes/emit/unary.rs index afa4cae..f79ac9a 100644 --- a/compiler/src/passes/emit/unary.rs +++ b/compiler/src/passes/emit/unary.rs @@ -44,28 +44,28 @@ pub fn encode_unary_instr(op_info: UnaryOpInfo, dst: &Arg) -> Vec { } } -#[cfg(test)] -mod tests { - mod neg { - use crate::*; - - check!(nreg1, neg!(reg!(RSP)), vec![0x48, 0xF7, 0xDC]); - check!(reg2, neg!(reg!(R13)), vec![0x49, 0xF7, 0xDD]); - check!( - deref, - neg!(deref!(RSP, i32::MAX as i64)), - vec![0x48, 0xF7, 0x9C, 0x24, 0xFF, 0xFF, 0xFF, 0x7F] - ); - - check!( - callq_indirect1, - call_indirect!(reg!(RBX), 0), - vec![0x48, 0xFF, 0xD3] - ); - check!( - callq_indirect2, - call_indirect!(reg!(R13), 0), - vec![0x49, 0xFF, 0xD5] - ); - } -} +// #[cfg(test)] +// mod tests { +// mod neg { +// use crate::*; +// +// check!(nreg1, neg!(reg!(RSP)), vec![0x48, 0xF7, 0xDC]); +// check!(reg2, neg!(reg!(R13)), vec![0x49, 0xF7, 0xDD]); +// check!( +// deref, +// neg!(deref!(RSP, i32::MAX as i64)), +// vec![0x48, 0xF7, 0x9C, 0x24, 0xFF, 0xFF, 0xFF, 0x7F] +// ); +// +// check!( +// callq_indirect1, +// call_indirect!(reg!(RBX), 0), +// vec![0x48, 0xFF, 0xD3] +// ); +// check!( +// callq_indirect2, +// call_indirect!(reg!(R13), 0), +// vec![0x49, 0xFF, 0xD5] +// ); +// } +// } diff --git a/compiler/src/passes/parse/grammar.lalrpop b/compiler/src/passes/parse/grammar.lalrpop index 3a02204..a83e270 100644 --- a/compiler/src/passes/parse/grammar.lalrpop +++ b/compiler/src/passes/parse/grammar.lalrpop @@ -4,6 +4,7 @@ use crate::passes::parse::{ use crate::passes::select::{VarArg, Reg}; use functor_derive::Functor; use crate::passes::validate::Int; +use crate::passes::select::Size; grammar; @@ -398,20 +399,19 @@ Comma: Vec = { Spanned: Spanned = => Meta { meta: (l, r - l), inner }; AsmInstr: InstrParsed<'input> = { - "addq" => InstrParsed::Addq { src, dst }, - "subq" => InstrParsed::Subq { src, dst }, - "mulq" => InstrParsed::Mulq { src }, - "divq" => InstrParsed::Divq { divisor }, - "negq" => InstrParsed::Negq { dst }, - "movq" => InstrParsed::Movq { src, dst }, - "pushq" => InstrParsed::Pushq { src }, - "popq" => InstrParsed::Popq { dst }, - "retq" => InstrParsed::Retq, - "andq" => InstrParsed::Andq { src, dst }, - "orq" => InstrParsed::Orq { src, dst }, - "xorq" => InstrParsed::Xorq { src, dst }, - "notq" => InstrParsed::Notq { dst }, - "cmpq" => InstrParsed::Cmpq { src, dst }, + "addq" => InstrParsed::Add { src, dst, size: Size::Bit64 }, + "subq" => InstrParsed::Sub { src, dst, size: Size::Bit64 }, + "mulq" => InstrParsed::Mul { src, size: Size::Bit64 }, + "divq" => InstrParsed::Div { divisor, size: Size::Bit64 }, + "negq" => InstrParsed::Neg { dst, size: Size::Bit64 }, + "movq" => InstrParsed::Mov { src, dst, size: Size::Bit64 }, + "pushq" => InstrParsed::Push { src, size: Size::Bit64 }, + "popq" => InstrParsed::Pop { dst, size: Size::Bit64 }, + "andq" => InstrParsed::And { src, dst, size: Size::Bit64 }, + "orq" => InstrParsed::Or { src, dst, size: Size::Bit64 }, + "xorq" => InstrParsed::Xor { src, dst, size: Size::Bit64 }, + "notq" => InstrParsed::Not { dst, size: Size::Bit64 }, + "cmpq" => InstrParsed::Cmp { src, dst, size: Size::Bit64 }, "syscall" => InstrParsed::Syscall { arity: arity.parse().expect("internal compiler error :(") }, } diff --git a/compiler/src/passes/patch/patch.rs b/compiler/src/passes/patch/patch.rs index 5150b46..90470de 100644 --- a/compiler/src/passes/patch/patch.rs +++ b/compiler/src/passes/patch/patch.rs @@ -58,13 +58,14 @@ fn patch_args<'p>( dst: Arg, op: fn(Arg, Arg) -> Instr>, ) -> Vec>> { - match (&src, &dst) { - (Arg::Deref { .. }, Arg::Deref { .. }) => vec![ - push!(reg!(R8)), - mov!(src, reg!(R8)), - op(reg!(R8), dst), - pop!(reg!(R8)), - ], - _ => vec![op(src, dst)], - } + // match (&src, &dst) { + // (Arg::Deref { .. }, Arg::Deref { .. }) => vec![ + // push!(reg!(R8)), + // mov!(src, reg!(R8)), + // op(reg!(R8), dst), + // pop!(reg!(R8)), + // ], + // _ => vec![op(src, dst)], + // } + todo!() } diff --git a/compiler/src/passes/select/macros.rs b/compiler/src/passes/select/macros.rs index cbf50f5..63a16da 100644 --- a/compiler/src/passes/select/macros.rs +++ b/compiler/src/passes/select/macros.rs @@ -50,7 +50,7 @@ macro_rules! idiv { #[macro_export] macro_rules! mul { ($src:expr, $size:expr) => { - $crate::passes::select::Instr::Mul{ + $crate::passes::select::Instr::Mul { src: $src, size: $size, } @@ -197,7 +197,10 @@ macro_rules! xor { #[macro_export] macro_rules! not { ($dst:expr, $size:expr) => { - $crate::passes::select::Instr::Not { dst: $dst, size: $size, } + $crate::passes::select::Instr::Not { + dst: $dst, + size: $size, + } }; } diff --git a/compiler/src/passes/select/mod.rs b/compiler/src/passes/select/mod.rs index a60d427..b47317e 100644 --- a/compiler/src/passes/select/mod.rs +++ b/compiler/src/passes/select/mod.rs @@ -2,13 +2,13 @@ mod display; pub mod macros; pub mod select; +use crate::passes::validate::Int; use crate::utils::unique_sym::UniqueSym; use derive_more::Display; use functor_derive::Functor; use itertools::Itertools; use std::collections::HashMap; use std::fmt::Display; -use crate::passes::validate::Int; pub struct X86Selected<'p> { pub fns: HashMap, FunSelected<'p>>, @@ -140,8 +140,8 @@ pub enum VarArg { XVar(IdentVars), } -#[derive(Debug, Copy, Clone)] -pub enum Size{ +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum Size { Bit8, Bit16, Bit32, diff --git a/compiler/src/passes/select/select.rs b/compiler/src/passes/select/select.rs index f9b5df1..79f7f03 100644 --- a/compiler/src/passes/select/select.rs +++ b/compiler/src/passes/select/select.rs @@ -37,7 +37,7 @@ fn select_fun(fun: FunEliminated) -> FunSelected { // Function entry & exit let entry = entry_block(&fun, &mut blocks); - let exit = exit_block(&mut blocks); + let exit = exit_block(&fun, &mut blocks); for (block_sym, block) in fun.blocks { let mut instrs = Vec::new(); @@ -61,20 +61,21 @@ fn entry_block<'p>( let mut instrs = Vec::new(); // Save stack pointers. - instrs.push(push!(reg!(RBP))); - instrs.push(mov!(reg!(RSP), reg!(RBP))); + instrs.push(push!(reg!(RBP), Size::Bit64)); + instrs.push(mov!(reg!(RSP), reg!(RBP), Size::Bit64)); // Save callee-saved registers (excluding stack pointers). for reg in CALLEE_SAVED_NO_STACK { - instrs.push(push!(VarArg::Reg(reg))); + instrs.push(push!(VarArg::Reg(reg), Size::Bit64)); } // Prepare temporary stack space - this will be optimized in later passes. - instrs.push(sub!(imm32!(0x1000), reg!(RSP))); + instrs.push(sub!(imm32!(0x1000), reg!(RSP), Size::Bit64)); // Introduce parameters as local variables. for (reg, param) in CALLER_SAVED.into_iter().zip(fun.params.iter()) { - instrs.push(mov!(VarArg::Reg(reg), VarArg::XVar(param.sym))); + // Sometimes not the entire register needs to be moved. But we considered this to be negligible. + instrs.push(mov!(VarArg::Reg(reg), VarArg::XVar(param.sym), Size::Bit64)); } assert!( @@ -90,21 +91,22 @@ fn entry_block<'p>( /// Creates an exit block for the function. fn exit_block<'p>( + fun: &FunEliminated<'p>, blocks: &mut HashMap, Block<'p, VarArg>>>, ) -> UniqueSym<'p> { let exit = gen_sym("exit"); let mut instrs = Vec::new(); // Restore temporary stack space. - instrs.push(add!(imm32!(0x1000), reg!(RSP))); + instrs.push(add!(imm!(0x1000), reg!(RSP), Size::Bit64)); // Restore callee-saved registers (excluding stack pointers). for reg in CALLEE_SAVED_NO_STACK.into_iter().rev() { - instrs.push(pop!(VarArg::Reg(reg))); + instrs.push(pop!(VarArg::Reg(reg), Size::Bit64)); } // Restore stack pointers. - instrs.push(pop!(reg!(RBP))); + instrs.push(pop!(reg!(RBP), Size::Bit64)); instrs.push(ret!()); blocks.insert(exit, Block { instrs }); @@ -163,10 +165,7 @@ fn select_assign<'p>( ) -> Vec> { let dst = var!(dsts[0]); match expr.inner { - ExprEliminated::Atom { - atm, - .. - } => vec![mov!(select_atom(atm), dst)], + ExprEliminated::Atom { atm, .. } => vec![mov!(select_atom(atm), dst)], ExprEliminated::Atom { atm: Atom::Var { sym }, .. diff --git a/compiler/src/passes/validate/constrain/lit.rs b/compiler/src/passes/validate/constrain/lit.rs index 04b6047..b02e91a 100644 --- a/compiler/src/passes/validate/constrain/lit.rs +++ b/compiler/src/passes/validate/constrain/lit.rs @@ -13,19 +13,17 @@ pub fn constrain_lit<'p>( // Get the type of the literal. let typ = match &val { Lit::Int(val) => match val.rfind(&['i', 'u']) { - Some(suffix) => { - match &val[suffix..] { - "i8" => PartialType::Int(IntType::I8), - "u8" => PartialType::Int(IntType::U8), - "i16" => PartialType::Int(IntType::I16), - "u16" => PartialType::Int(IntType::U16), - "i32" => PartialType::Int(IntType::I32), - "u32" => PartialType::Int(IntType::U32), - "i64" => PartialType::Int(IntType::I64), - "u64" => PartialType::Int(IntType::U64), - _ => PartialType::IntAmbiguous, - } - } + Some(suffix) => match &val[suffix..] { + "i8" => PartialType::Int(IntType::I8), + "u8" => PartialType::Int(IntType::U8), + "i16" => PartialType::Int(IntType::I16), + "u16" => PartialType::Int(IntType::U16), + "i32" => PartialType::Int(IntType::I32), + "u32" => PartialType::Int(IntType::U32), + "i64" => PartialType::Int(IntType::I64), + "u64" => PartialType::Int(IntType::U64), + _ => PartialType::IntAmbiguous, + }, None => PartialType::IntAmbiguous, }, Lit::Bool { .. } => PartialType::Bool, diff --git a/compiler/src/passes/validate/resolve.rs b/compiler/src/passes/validate/resolve.rs index cc0d957..192a933 100644 --- a/compiler/src/passes/validate/resolve.rs +++ b/compiler/src/passes/validate/resolve.rs @@ -4,7 +4,8 @@ use crate::passes::select::{Instr, InstrSelected, VarArg}; use crate::passes::validate::error::TypeError; use crate::passes::validate::partial_type::PartialType; use crate::passes::validate::{ - DefConstrained, DefValidated, ExprConstrained, ExprValidated, Int, PrgConstrained, PrgValidated, + DefConstrained, DefValidated, ExprConstrained, ExprValidated, InstrUniquified, Int, + PrgConstrained, PrgValidated, }; use crate::utils::union_find::{UnionFind, UnionIndex}; use crate::utils::unique_sym::UniqueSym; @@ -170,11 +171,7 @@ fn resolve_expr<'p>( Type::Int(int) => match int { IntType::I8 => todo!(), IntType::U8 => Int::U8({ - resolve_int_lit( - val, - expr.meta.span, - u8::from_str_radix, - )? + resolve_int_lit(val, expr.meta.span, u8::from_str_radix)? }), IntType::I16 => Int::I16(resolve_int_lit( val, @@ -317,26 +314,85 @@ pub fn resolve_instr<'p>( }; match instr { - Instr::Addq { src, dst } => add!(map(src), map(dst)), - Instr::Sub { src, dst } => sub!(map(src), map(dst)), - Instr::Divq { divisor } => div!(map(divisor)), - Instr::Mulq { src } => mul!(map(src)), - Instr::Negq { dst } => neg!(map(dst)), - Instr::Movq { src, dst } => mov!(map(src), map(dst)), - Instr::Pushq { src } => push!(map(src)), - Instr::Popq { dst } => pop!(map(dst)), - Instr::Retq => ret!(), - Instr::Syscall { arity } => syscall!(arity), - Instr::Cmpq { src, dst } => cmp!(map(src), map(dst)), - Instr::Andq { src, dst } => and!(map(src), map(dst)), - Instr::Or { src, dst } => or!(map(src), map(dst)), - Instr::Xorq { src, dst } => xor!(map(src), map(dst)), - Instr::Notq { dst } => not!(map(dst)), - Instr::Setcc { cnd } => setcc!(cnd), - Instr::CallDirect { .. } => todo!(), - Instr::Jmp { .. } => todo!(), - Instr::Jcc { .. } => todo!(), - Instr::LoadLbl { .. } => todo!(), - Instr::CallIndirect { .. } => todo!(), + InstrUniquified::Add { src, dst, size } => InstrSelected::Add { + src: map(src), + dst: map(dst), + size, + }, + InstrUniquified::Sub { src, dst, size } => InstrSelected::Sub { + src: map(src), + dst: map(dst), + size, + }, + InstrUniquified::Div { divisor, size } => InstrSelected::Div { + divisor: map(divisor), + size, + }, + InstrUniquified::IDiv { divisor, size } => InstrSelected::IDiv { + divisor: map(divisor), + size, + }, + InstrUniquified::Mul { src, size } => InstrSelected::Mul { + src: map(src), + size, + }, + InstrUniquified::IMul { src, size } => InstrSelected::IMul { + src: map(src), + size, + }, + InstrUniquified::Neg { dst, size } => InstrSelected::Neg { + dst: map(dst), + size, + }, + InstrUniquified::Mov { src, dst, size } => InstrSelected::Mov { + src: map(src), + dst: map(dst), + size, + }, + InstrUniquified::MovSX { src, dst, size } => InstrSelected::MovSX { + src: map(src), + dst: map(dst), + size, + }, + InstrUniquified::Push { src, size } => InstrSelected::Push { + src: map(src), + size, + }, + InstrUniquified::Pop { dst, size } => InstrSelected::Pop { + dst: map(dst), + size, + }, + InstrUniquified::Syscall { arity } => InstrSelected::Syscall { arity }, + InstrUniquified::Cmp { src, dst, size } => InstrSelected::Cmp { + src: map(src), + dst: map(dst), + size, + }, + InstrUniquified::And { src, dst, size } => InstrSelected::And { + src: map(src), + dst: map(dst), + size, + }, + InstrUniquified::Or { src, dst, size } => InstrSelected::Or { + src: map(src), + dst: map(dst), + size, + }, + InstrUniquified::Xor { src, dst, size } => InstrSelected::Xor { + src: map(src), + dst: map(dst), + size, + }, + InstrUniquified::Not { dst, size } => InstrSelected::Not { + dst: map(dst), + size, + }, + InstrUniquified::Setcc { .. } + | InstrUniquified::Ret { .. } + | InstrUniquified::Jmp { .. } + | InstrUniquified::Jcc { .. } + | InstrUniquified::LoadLbl { .. } + | InstrUniquified::CallDirect { .. } + | InstrUniquified::CallIndirect { .. } => unreachable!(), } } diff --git a/compiler/src/passes/validate/uniquify/expr.rs b/compiler/src/passes/validate/uniquify/expr.rs index cd3f0d1..c94188c 100644 --- a/compiler/src/passes/validate/uniquify/expr.rs +++ b/compiler/src/passes/validate/uniquify/expr.rs @@ -121,27 +121,87 @@ fn uniquify_instr<'p>( }; let instr = match instr { - InstrParsed::Addq { src, dst } => add!(map(src)?, map(dst)?), - InstrParsed::Sub { src, dst } => sub!(map(src)?, map(dst)?), - InstrParsed::Divq { divisor } => div!(map(divisor)?), - InstrParsed::Mulq { src } => mul!(map(src)?), - InstrParsed::Negq { dst } => neg!(map(dst)?), - InstrParsed::Movq { src, dst } => mov!(map(src)?, map(dst)?), - InstrParsed::Pushq { src } => push!(map(src)?), - InstrParsed::Popq { dst } => pop!(map(dst)?), - InstrParsed::Retq => ret!(), - InstrParsed::Syscall { arity } => syscall!(arity), - InstrParsed::Cmpq { src, dst } => cmp!(map(src)?, map(dst)?), - InstrParsed::Andq { src, dst } => and!(map(src)?, map(dst)?), - InstrParsed::Or { src, dst } => or!(map(src)?, map(dst)?), - InstrParsed::Xorq { src, dst } => xor!(map(src)?, map(dst)?), - InstrParsed::Notq { dst } => not!(map(dst)?), - InstrParsed::Setcc { cnd } => setcc!(cnd), - InstrParsed::CallDirect { .. } => todo!(), - InstrParsed::Jmp { .. } => todo!(), - InstrParsed::Jcc { .. } => todo!(), - InstrParsed::LoadLbl { .. } => todo!(), - InstrParsed::CallIndirect { .. } => todo!(), + InstrParsed::Add { src, dst, size } => InstrUniquified::Add { + src: map(src)?, + dst: map(dst)?, + size, + }, + InstrParsed::Sub { src, dst, size } => InstrUniquified::Sub { + src: map(src)?, + dst: map(dst)?, + size, + }, + InstrParsed::Div { divisor, size } => InstrUniquified::Div { + divisor: map(divisor)?, + size, + }, + InstrParsed::IDiv { divisor, size } => InstrUniquified::IDiv { + divisor: map(divisor)?, + size, + }, + InstrParsed::Mul { src, size } => InstrUniquified::Mul { + src: map(src)?, + size, + }, + InstrParsed::IMul { src, size } => InstrUniquified::IMul { + src: map(src)?, + size, + }, + InstrParsed::Neg { dst, size } => InstrUniquified::Neg { + dst: map(dst)?, + size, + }, + InstrParsed::Mov { src, dst, size } => InstrUniquified::Mov { + src: map(src)?, + dst: map(dst)?, + size, + }, + InstrParsed::MovSX { src, dst, size } => InstrUniquified::MovSX { + src: map(src)?, + dst: map(dst)?, + size, + }, + InstrParsed::Push { src, size } => InstrUniquified::Push { + src: map(src)?, + size, + }, + InstrParsed::Pop { dst, size } => InstrUniquified::Pop { + dst: map(dst)?, + size, + }, + + InstrParsed::Syscall { arity } => InstrUniquified::Syscall { arity }, + InstrParsed::Cmp { src, dst, size } => InstrUniquified::Cmp { + src: map(src)?, + dst: map(dst)?, + size, + }, + InstrParsed::And { src, dst, size } => InstrUniquified::And { + src: map(src)?, + dst: map(dst)?, + size, + }, + InstrParsed::Or { src, dst, size } => InstrUniquified::Or { + src: map(src)?, + dst: map(dst)?, + size, + }, + InstrParsed::Xor { src, dst, size } => InstrUniquified::Xor { + src: map(src)?, + dst: map(dst)?, + size, + }, + InstrParsed::Not { dst, size } => InstrUniquified::Not { + dst: map(dst)?, + size, + }, + InstrParsed::Setcc { .. } + | InstrParsed::Ret { .. } + | InstrParsed::Jmp { .. } + | InstrParsed::Jcc { .. } + | InstrParsed::LoadLbl { .. } + | InstrParsed::CallDirect { .. } + | InstrParsed::CallIndirect {.. } => unreachable!(), }; Ok(instr) diff --git a/compiler/tests/aoc.rs b/compiler/tests/aoc.rs index f9d5c4b..bd0d490 100644 --- a/compiler/tests/aoc.rs +++ b/compiler/tests/aoc.rs @@ -1,12 +1,12 @@ #![cfg(unix)] +use compiler::compile; use std::fs; use std::fs::File; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use tempfile::TempDir; use test_each_file::test_each_path; -use compiler::compile; fn aoc([program_path, output_path]: [&Path; 2]) { let tempdir = TempDir::with_prefix("spike-aoc").unwrap(); @@ -14,7 +14,12 @@ fn aoc([program_path, output_path]: [&Path; 2]) { let mut input = PathBuf::from(program_path); input.set_file_name("input"); - compile(&program, program_path.file_name().unwrap().to_str().unwrap(), &tempdir.path().join("output")).unwrap(); + compile( + &program, + program_path.file_name().unwrap().to_str().unwrap(), + &tempdir.path().join("output"), + ) + .unwrap(); // Make output executable. Command::new("chmod") @@ -40,7 +45,10 @@ fn aoc([program_path, output_path]: [&Path; 2]) { } }; - assert_eq!(child.wait_with_output().unwrap().stdout, fs::read(output_path).unwrap()); + assert_eq!( + child.wait_with_output().unwrap().stdout, + fs::read(output_path).unwrap() + ); } test_each_path! { for ["sp", "out"] in "./programs/aoc/" => aoc }