From c062993130ce069d2c85a80cc6b8528b3c83a399 Mon Sep 17 00:00:00 2001 From: shadow cat Date: Sat, 18 Jul 2026 13:33:59 -0400 Subject: [PATCH] work --- src/arch/mod.rs | 1 + src/arch/x86_64/compile.rs | 196 ++++++++++++++++++++++++++++-- src/arch/x86_64/encode.rs | 18 +-- src/arch/x86_64/mod.rs | 8 +- src/arch/x86_64/test/asm/setup.rs | 6 +- src/arch/x86_64/types/arg.rs | 24 ++-- src/arch/x86_64/types/asm.rs | 128 +++++++++++++++++++ src/arch/x86_64/types/mem.rs | 4 +- src/arch/x86_64/types/mod.rs | 2 + src/arch/x86_64/types/reg.rs | 46 ++++--- src/arch/x86_64/types/width.rs | 4 +- src/backend/ir/id.rs | 11 ++ src/backend/ir/mod.rs | 43 +++++-- src/parser/nodes/asm/x86_64.rs | 6 +- 14 files changed, 429 insertions(+), 68 deletions(-) create mode 100644 src/arch/x86_64/types/asm.rs create mode 100644 src/backend/ir/id.rs diff --git a/src/arch/mod.rs b/src/arch/mod.rs index 28f4de2..b3a9c4d 100644 --- a/src/arch/mod.rs +++ b/src/arch/mod.rs @@ -9,5 +9,6 @@ pub trait Arch: Sized { const NAME: &str; type Asm; type Addr: Addr; + type CallConv; fn compile(p: &Program) -> Result, CompilerMsg>; } diff --git a/src/arch/x86_64/compile.rs b/src/arch/x86_64/compile.rs index 53f2b0e..e2bcb07 100644 --- a/src/arch/x86_64/compile.rs +++ b/src/arch/x86_64/compile.rs @@ -1,14 +1,28 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet, VecDeque}; use super::*; -use crate::backend::{LibImport, LinkedProgram, SymImport, SymTable, Symbol}; -use util::*; +use crate::backend::{Body, LibImport, LinkedProgram, SymImport, SymTable, Symbol, VarId}; pub struct Encoder<'a> { pub code: Code, pub sym_tab: SymTable, pub sym_refs: HashMap>, pub program: &'a Program, + pub vars: VarMap, +} + +#[derive(Clone, Copy)] +pub struct VarUse { + pos: usize, + reg: Option, +} +pub type VarUses = HashMap>; +pub type RegUses = [VecDeque; 16]; + +impl VarUse { + pub fn min(self, other: Self) -> Self { + if self.pos <= other.pos { self } else { other } + } } pub fn compile(p: &Program) -> Result, CompilerMsg> { @@ -19,7 +33,14 @@ pub fn compile(p: &Program) -> Result, CompilerMsg> { for f in &p.funcs { let addr = encoder.code.bytes.len(); encoder.sym_tab.insert(f.sym, addr as u64); - for instr in &f.instrs { + let mut segments = Vec::new(); + calc_uses(&mut segments, &f.body); + } + + for f in &p.funcs { + let addr = encoder.code.bytes.len(); + encoder.sym_tab.insert(f.sym, addr as u64); + for instr in &f.body { encoder.compile_instr(instr)?; } } @@ -60,24 +81,183 @@ pub fn compile(p: &Program) -> Result, CompilerMsg> { }) } +#[derive(Default)] +pub struct SegUses { + var: VarUses, + reg: RegUses, +} + +pub fn calc_uses(segments: &mut Vec, body: &Body) -> (usize, usize) { + let mut pos = 0; + let seg_i = segments.len(); + segments.push(Default::default()); + let mut vars = VarUses::default(); + let mut regs = RegUses::default(); + let volatile = [ + rax, rbx, rcx, rdx, rbp, rsp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15, + ] + .map(|r| r.reg()); + macro_rules! push { + ($var:ident) => { + push!($var, VarUse { pos: 0, reg: None }) + }; + ($var:ident, $pos:expr) => { + vars.entry($var.clone()).or_default().push_back(VarUse { + pos: $pos.pos + pos, + reg: $pos.reg, + }) + }; + } + for instr in body { + match instr { + BInstr::Set { dst, src: _ } => push!(dst), + BInstr::Call { dst, f, args } => { + push!(dst); + for (i, arg) in args.iter().enumerate() { + push!(arg); + if i < 8 { + regs[i].push_back(pos); + } + } + } + BInstr::Copy { dst, src } => { + push!(dst); + push!(src); + } + BInstr::Add { dst, src1, src2 } => { + push!(dst); + push!(src1); + push!(src2); + } + BInstr::If { cond, then, else_ } => { + push!(cond); + pos += 1; + let (seg_i1, len1) = calc_uses(segments, then); + let (seg_i2, len2) = calc_uses(segments, else_); + // insert closest usages + for (var, poss1) in &segments[seg_i1].var { + if let Some(poss2) = segments[seg_i2].var.get(var) { + push!(var, poss1[0].min(poss2[0])); + } else { + push!(var, poss1[0]); + } + } + for (var, poss2) in &segments[seg_i2].var { + if !segments[seg_i1].var.contains_key(var) { + push!(var, poss2[0]); + } + } + pos += len1.max(len2); + continue; + } + BInstr::Loop(instrs) => { + let (seg_i2, len) = calc_uses(segments, instrs); + // insert closest usages + for (var, poss) in &segments[seg_i2].var { + push!(var, poss[0]); + } + // during register allocation, want to insert the first use of each var + // at len + use, because if it jumps back up, that will be the next + // usage rather than if the loop exits; pad ensures there is room so + // the insertions are always before the rest of the usages (after loop) + let pad = (len * 2).saturating_sub(pos); + pos += len + pad; + continue; + } + BInstr::Break(var) => { + if let Some(var) = var { + push!(var); + } + } + BInstr::Return(var) => { + if let Some(var) = var { + push!(var); + } + } + BInstr::Asm(asm) => { + for &(reg, var) in &asm.args { + push!( + var, + VarUse { + pos: 0, + reg: Some(reg) + } + ); + regs[reg as usize].push_back(pos); + } + } + } + pos += 1; + } + segments[seg_i].var = vars; + segments[seg_i].reg = regs; + return (seg_i, pos); +} + type BInstr = crate::backend::Instr; impl<'a> Encoder<'a> { - fn compile_instr(&mut self, instr: &BInstr) -> Result<(), CompilerMsg> { + fn compile_instr(&mut self, instr: &BInstr) -> EncodeRes { match instr { - BInstr::Asm(asm) => { - self.code.extend(asm); - } + BInstr::Asm(asm) => self.asm(asm)?, _ => todo!(), } Ok(()) } + pub fn asm(&mut self, asm: &Asm) -> EncodeRes { + let mut used = HashSet::default(); + let mut vars = HashSet::default(); + for &instr in &asm.instrs { + if let Some(regw) = instr.regw_set() { + used.insert(regw.reg()); + } + for var in instr.vars() { + vars.insert(var); + } + } + let overlap = used.intersection(&self.vars.active.values()); + for var in &vars { + if let Some(reg) = self.vars.active.get(var) + && used.contains(reg) + {} + } + for &instr in &asm.instrs { + match instr { + Instr::Mov { dst, src } => self.code.mov(dst, src)?, + Instr::Push(rvmi) => todo!(), + Instr::Pop(rvm) => todo!(), + Instr::Lea { dst, src } => todo!(), + Instr::Int(code) => self.code.int(code), + Instr::Syscall => self.code.syscall(), + Instr::Call(sym) => self.code.call(sym), + Instr::CallAt(sym) => self.code.call_mem(sym), + Instr::Ret => self.code.ret(), + Instr::Add { dst, src } => todo!(), + Instr::Sub { dst, src } => todo!(), + } + } + Ok(()) + } + pub fn new(program: &'a Program) -> Self { Self { code: Code::default(), sym_tab: SymTable::new(program.sym_count()), sym_refs: Default::default(), + vars: VarMap::default(), program, } } } + +pub struct VarMap { + active: HashMap, +} + +impl Default for VarMap { + fn default() -> Self { + Self { + active: Default::default(), + } + } +} diff --git a/src/arch/x86_64/encode.rs b/src/arch/x86_64/encode.rs index aa4e002..9ef3d00 100644 --- a/src/arch/x86_64/encode.rs +++ b/src/arch/x86_64/encode.rs @@ -1,7 +1,7 @@ use super::*; use crate::backend::Symbol; -type ERes = Result<(), CompilerMsg>; +pub type EncodeRes = Result<(), CompilerMsg>; /// machine code #[derive(Default)] @@ -11,7 +11,7 @@ pub struct Code { } impl Code { - pub fn mov(&mut self, dst: impl RegMem, src: impl Into) -> ERes { + pub fn mov(&mut self, dst: impl RegMem, src: impl Into) -> EncodeRes { let src = src.into(); match dst.kind() { RegMemKind::Reg(mut dst) => match src { @@ -92,7 +92,7 @@ impl Code { Ok(()) } - pub fn push(&mut self, reg: impl Into) -> ERes { + pub fn push(&mut self, reg: impl Into) -> EncodeRes { match reg.into() { RegMemImm::Reg(reg) => match reg.width() { Width::B64 => { @@ -120,7 +120,7 @@ impl Code { Ok(()) } - pub fn pop(&mut self, reg: Reg) -> ERes { + pub fn pop(&mut self, reg: RegW) -> EncodeRes { match reg.width() { Width::B64 | Width::B16 => (), _ => return Err("register must be 64 or 16 bit".into()), @@ -133,7 +133,7 @@ impl Code { Ok(()) } - pub fn lea(&mut self, dst: Reg, sym: Symbol) -> ERes { + pub fn lea(&mut self, dst: RegW, sym: Symbol) -> EncodeRes { self.rex(1, dst, 0, 0)?; self.bytes.push(0x8d); self.modrm(dst, sym); @@ -162,7 +162,7 @@ impl Code { self.bytes.push(0xc3); } - fn add_sub(&mut self, dst: impl RegMem, src: impl Into, ext: u8) -> ERes { + fn add_sub(&mut self, dst: impl RegMem, src: impl Into, ext: u8) -> EncodeRes { match src.into() { RegMemImm::Reg(src) => { if src.width() != dst.width() { @@ -219,11 +219,11 @@ impl Code { Ok(()) } - pub fn add(&mut self, dst: impl RegMem, src: impl Into) -> ERes { + pub fn add(&mut self, dst: impl RegMem, src: impl Into) -> EncodeRes { self.add_sub(dst, src, 0) } - pub fn sub(&mut self, dst: impl RegMem, src: impl Into) -> ERes { + pub fn sub(&mut self, dst: impl RegMem, src: impl Into) -> EncodeRes { self.add_sub(dst, src, 5) } @@ -245,7 +245,7 @@ impl Code { Ok(()) } - fn rex(&mut self, w: impl RexW, r: impl RexBit, x: u8, b: impl RexBit) -> ERes { + fn rex(&mut self, w: impl RexW, r: impl RexBit, x: u8, b: impl RexBit) -> EncodeRes { if r.req() && b.req_no() || r.req_no() && b.req() { return Err("registers incompatible (REX)".into()); } diff --git a/src/arch/x86_64/mod.rs b/src/arch/x86_64/mod.rs index 3346743..a39118f 100644 --- a/src/arch/x86_64/mod.rs +++ b/src/arch/x86_64/mod.rs @@ -20,9 +20,15 @@ pub struct X86_64; impl Arch for X86_64 { const NAME: &str = "x86_64"; - type Asm = Code; + type Asm = Asm; type Addr = u64; + type CallConv = CallConv; fn compile(p: &Program) -> Result, CompilerMsg> { compile(p) } } + +pub struct CallConv { + volatile: Vec, + nonvolatile: Vec, +} diff --git a/src/arch/x86_64/test/asm/setup.rs b/src/arch/x86_64/test/asm/setup.rs index ea58c7f..16edbed 100644 --- a/src/arch/x86_64/test/asm/setup.rs +++ b/src/arch/x86_64/test/asm/setup.rs @@ -36,13 +36,13 @@ pub fn imms() -> impl Iterator { IMMS.iter().cloned() } -pub fn regs() -> impl Iterator { - Reg::IMPORTANT.iter().cloned() +pub fn regs() -> impl Iterator { + RegW::IMPORTANT.iter().cloned() } pub fn mems() -> impl Iterator { gen move { - for ® in Reg::IMPORTANT { + for ® in RegW::IMPORTANT { for &disp in DISPS { for &width in WIDTHS { yield mem(reg, disp, width); diff --git a/src/arch/x86_64/types/arg.rs b/src/arch/x86_64/types/arg.rs index c7ff75b..632919c 100644 --- a/src/arch/x86_64/types/arg.rs +++ b/src/arch/x86_64/types/arg.rs @@ -8,13 +8,13 @@ pub trait RegMem: RexBit + RexW + ModRMRM + Copy + MaybeMem { #[derive(Clone, Copy)] pub enum RegMemKind { - Reg(Reg), + Reg(RegW), Mem(Mem), } #[derive(Clone, Copy)] pub enum RegMemImm { - Reg(Reg), + Reg(RegW), Imm(Imm), Mem(Mem), } @@ -23,7 +23,7 @@ pub trait MaybeMem { fn mem(&self) -> Option; } -impl RegMem for Reg { +impl RegMem for RegW { fn width(&self) -> Width { self.width() } @@ -32,7 +32,7 @@ impl RegMem for Reg { } } -impl MaybeMem for Reg { +impl MaybeMem for RegW { fn mem(&self) -> Option { None } @@ -54,14 +54,14 @@ impl MaybeMem for Mem { } // fromrot -impl From for RegMemImm { - fn from(value: Reg) -> Self { +impl From for RegMemImm { + fn from(value: RegW) -> Self { Self::Reg(value) } } -impl From for RegMemKind { - fn from(value: Reg) -> Self { +impl From for RegMemKind { + fn from(value: RegW) -> Self { Self::Reg(value) } } @@ -115,7 +115,7 @@ pub enum EffAddr { None, } -impl ModRMRM for Reg { +impl ModRMRM for RegW { fn rm(&self) -> u8 { self.base() } @@ -171,7 +171,7 @@ impl ModRMReg for u8 { } } -impl ModRMReg for Reg { +impl ModRMReg for RegW { fn val(&self) -> u8 { self.base() } @@ -207,7 +207,7 @@ impl RexBit for u8 { } } -impl RexBit for Reg { +impl RexBit for RegW { fn rex(&self) -> bool { self.gt8() } @@ -238,7 +238,7 @@ impl RexW for Width { } } -impl RexW for Reg { +impl RexW for RegW { fn rexw(&self) -> bool { self.width().rexw() } diff --git a/src/arch/x86_64/types/asm.rs b/src/arch/x86_64/types/asm.rs new file mode 100644 index 0000000..b567ae3 --- /dev/null +++ b/src/arch/x86_64/types/asm.rs @@ -0,0 +1,128 @@ +use super::*; +use crate::backend::{Symbol, VarId}; + +pub struct Asm { + pub args: Vec<(Reg, VarId)>, + pub instrs: Vec, +} + +pub enum Instr { + Mov { dst: Rvm, src: Rvmi }, + Push(Rvmi), + Pop(Rvm), + Lea { dst: Rv, src: Symbol }, + Int(u8), + Syscall, + Call(Symbol), + CallAt(Symbol), + Ret, + Add { dst: Rvm, src: Rvmi }, + Sub { dst: Rvm, src: Rvmi }, +} + +impl Instr { + pub fn regw_set(&self) -> Option { + match self { + Instr::Mov { dst, src: _ } => dst.reg(), + Instr::Push(_) => None, + Instr::Pop(dst) => dst.reg(), + Instr::Lea { dst, src: _ } => dst.reg(), + Instr::Int(_) => None, + Instr::Syscall => None, + Instr::Call(_) => None, + Instr::CallAt(_) => None, + Instr::Ret => None, + Instr::Add { dst, src: _ } => dst.reg(), + Instr::Sub { dst, src: _ } => dst.reg(), + } + } + pub fn vars(&self) -> impl Iterator { + let mut vars = (None, None); + match self { + Instr::Mov { dst, src } => vars = (dst.var(), src.var()), + Instr::Push(src) => vars.0 = src.var(), + Instr::Pop(dst) => vars.0 = dst.var(), + Instr::Lea { dst, .. } => vars.0 = dst.var(), + Instr::Int(_) => (), + Instr::Syscall => (), + Instr::Call(_) => (), + Instr::CallAt(_) => (), + Instr::Ret => (), + Instr::Add { dst, src } => vars = (dst.var(), src.var()), + Instr::Sub { dst, src } => vars = (dst.var(), src.var()), + } + vars.0.into_iter().chain(vars.1) + } +} + +#[derive(Clone, Copy)] +pub enum Rv { + Reg(RegW), + Var(VarId), +} + +#[derive(Clone, Copy)] +pub enum Rvm { + Reg(RegW), + Var(VarId), + Mem(Mem), +} + +#[derive(Clone, Copy)] +pub enum Rvmi { + Reg(RegW), + Var(VarId), + Mem(Mem), + Imm(Imm), +} + +impl Rv { + pub fn reg(&self) -> Option { + if let &Self::Reg(v) = self { + Some(v) + } else { + None + } + } + pub fn var(&self) -> Option { + if let &Self::Var(v) = self { + Some(v) + } else { + None + } + } +} + +impl Rvm { + pub fn reg(&self) -> Option { + if let &Self::Reg(v) = self { + Some(v) + } else { + None + } + } + pub fn var(&self) -> Option { + if let &Self::Var(v) = self { + Some(v) + } else { + None + } + } +} + +impl Rvmi { + pub fn reg(&self) -> Option { + if let &Self::Reg(v) = self { + Some(v) + } else { + None + } + } + pub fn var(&self) -> Option { + if let &Self::Var(v) = self { + Some(v) + } else { + None + } + } +} diff --git a/src/arch/x86_64/types/mem.rs b/src/arch/x86_64/types/mem.rs index f0628b0..e65452a 100644 --- a/src/arch/x86_64/types/mem.rs +++ b/src/arch/x86_64/types/mem.rs @@ -4,12 +4,12 @@ use super::*; #[derive(Clone, Copy)] pub struct Mem { - pub reg: Reg, + pub reg: RegW, pub disp: i32, pub width: Width, } -pub fn mem(reg: Reg, disp: i32, width: Width) -> Mem { +pub fn mem(reg: RegW, disp: i32, width: Width) -> Mem { Mem { reg, disp, width } } diff --git a/src/arch/x86_64/types/mod.rs b/src/arch/x86_64/types/mod.rs index 3bb1aa0..e2d0475 100644 --- a/src/arch/x86_64/types/mod.rs +++ b/src/arch/x86_64/types/mod.rs @@ -1,10 +1,12 @@ mod arg; +mod asm; mod imm; mod mem; mod reg; mod width; pub use arg::*; +pub use asm::*; pub use imm::*; pub use mem::*; pub use reg::*; diff --git a/src/arch/x86_64/types/reg.rs b/src/arch/x86_64/types/reg.rs index b7f5654..0a471c8 100644 --- a/src/arch/x86_64/types/reg.rs +++ b/src/arch/x86_64/types/reg.rs @@ -1,13 +1,15 @@ use super::Width; #[derive(Clone, Copy, PartialEq)] -pub struct Reg { - val: u8, +pub struct RegW { + reg: Reg, high: bool, width: Width, } -def_regs! { +pub type Reg = u8; + +def_regs! { RegW; 0b0000 : rax eax ax al, 0b0001 : rcx ecx cx cl !_, 0b0010 : rdx edx dx dl, @@ -28,16 +30,20 @@ def_regs! { 0b1111 : r15 r15d r15w r15b, } -impl Reg { +impl RegW { + pub fn reg(&self) -> u8 { + self.reg + } + pub fn base(&self) -> u8 { - self.val & 0b111 + self.reg & 0b111 } /// checks if register is not one of the first 8 (0-7) pub fn gt8(&self) -> bool { - self.val >= 0b1000 + self.reg >= 0b1000 } pub fn gt4(&self) -> bool { - self.val >= 0b0100 + self.reg >= 0b0100 } pub fn width(&self) -> Width { @@ -65,12 +71,12 @@ impl Reg { || (self.gt4() && self.width == Width::B8 && !self.high) } - pub fn incompatible(&self, other: &Reg) -> bool { + pub fn incompatible(&self, other: &RegW) -> bool { (self.requires_rex() && other.high) || (self.high && other.requires_rex()) } - const fn new(val: u8, width: Width, high: bool) -> Self { - Self { val, high, width } + const fn new(reg: u8, width: Width, high: bool) -> Self { + Self { reg, high, width } } } @@ -117,30 +123,30 @@ macro_rules! filter { use filter; macro_rules! def_regs { - ($($val:literal : $B64:ident $B32:ident $B16:ident $B8:ident $(norex=$B8H:ident)? $(!$imp:tt)?,)*) => { + ($reg:ident; $($val:literal : $B64:ident $B32:ident $B16:ident $B8:ident $(norex=$B8H:ident)? $(!$imp:tt)?,)*) => { $( #[allow(non_upper_case_globals)] - pub const $B64: Reg = Reg::new($val, Width::B64, false); + pub const $B64: $reg = $reg::new($val, Width::B64, false); #[allow(non_upper_case_globals)] - pub const $B32: Reg = Reg::new($val, Width::B32, false); + pub const $B32: $reg = $reg::new($val, Width::B32, false); #[allow(non_upper_case_globals)] - pub const $B16: Reg = Reg::new($val, Width::B16, false); + pub const $B16: $reg = $reg::new($val, Width::B16, false); #[allow(non_upper_case_globals)] - pub const $B8 : Reg = Reg::new($val, Width::B8 , false); + pub const $B8 : $reg = $reg::new($val, Width::B8 , false); $( #[allow(non_upper_case_globals)] - pub const $B8H: Reg = Reg::new($val, Width::B8, true); + pub const $B8H: $reg = $reg::new($val, Width::B8, true); )? )* - impl Reg { + impl $reg { // #[cfg(test)] - // pub const ALL: &[Reg] = &[ + // pub const ALL: &[$reg] = &[ // $( $B64, $B32, $B16, $B8, $($B8H,)? )* // ]; #[cfg(test)] - pub const IMPORTANT: &[Reg] = & + pub const IMPORTANT: &[$reg] = & filter!(; $($(!$imp)? $B64 $B32 $B16 $B8 $($B8H)?; )* ) ; @@ -159,7 +165,7 @@ macro_rules! def_regs { }) } } - impl std::fmt::Display for Reg { + impl std::fmt::Display for $reg { #[allow(non_upper_case_globals)] fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", match *self { diff --git a/src/arch/x86_64/types/width.rs b/src/arch/x86_64/types/width.rs index 0241cc9..47316c6 100644 --- a/src/arch/x86_64/types/width.rs +++ b/src/arch/x86_64/types/width.rs @@ -9,8 +9,8 @@ pub enum Width { B64 = 3, } -impl From for Width { - fn from(value: Reg) -> Self { +impl From for Width { + fn from(value: RegW) -> Self { value.width() } } diff --git a/src/backend/ir/id.rs b/src/backend/ir/id.rs new file mode 100644 index 0000000..c152fbe --- /dev/null +++ b/src/backend/ir/id.rs @@ -0,0 +1,11 @@ +ids!(VarId FnId); + +macro_rules! ids { + ($($name:ident)*) => { + $( + #[derive(Clone, Copy, PartialEq, Eq, Hash)] + pub struct $name(usize); + )* + }; +} +use ids; diff --git a/src/backend/ir/mod.rs b/src/backend/ir/mod.rs index 4eb3610..2109e1e 100644 --- a/src/backend/ir/mod.rs +++ b/src/backend/ir/mod.rs @@ -1,6 +1,8 @@ mod addr; +mod id; mod symbol; pub use addr::*; +pub use id::*; pub use symbol::*; use crate::{arch::Arch, backend::LinkedProgram, io::CompilerMsg}; @@ -10,6 +12,7 @@ pub struct Program { pub funcs: Vec>, pub entry: Option, pub external: Vec, + pub call_convs: Vec, sym_info: Vec, sym_count: usize, @@ -21,8 +24,10 @@ pub struct Data { } pub struct Func { - pub instrs: Vec>, + pub params: Vec, + pub body: Body, pub sym: Symbol, + pub conv: usize, } pub struct External { @@ -35,16 +40,38 @@ pub struct SymInfo { pub external: bool, } +pub type Body = Vec>; + pub enum Instr { - Set { dst: VarId, src: Vec }, - Call { dst: FnId, args: Vec }, - Copy { dst: VarId, src: VarId }, + Set { + dst: VarId, + src: Vec, + }, + Call { + dst: VarId, + f: FnId, + args: Vec, + }, + Copy { + dst: VarId, + src: VarId, + }, + Add { + dst: VarId, + src1: VarId, + src2: VarId, + }, + If { + cond: VarId, + then: Body, + else_: Body, + }, + Loop(Body), + Return(Option), + Break(Option), Asm(A::Asm), } -pub type VarId = usize; -pub type FnId = usize; - impl Program { pub fn encode_data(&self, data: &mut Vec, sym_tab: &mut SymTable) { for d in &self.ro_data { @@ -70,7 +97,7 @@ impl Program { name: name.into(), external: false, }); - self.funcs.push(Func { instrs, sym }); + self.funcs.push(Func { body: instrs, sym }); sym } diff --git a/src/parser/nodes/asm/x86_64.rs b/src/parser/nodes/asm/x86_64.rs index 65716c0..da39586 100644 --- a/src/parser/nodes/asm/x86_64.rs +++ b/src/parser/nodes/asm/x86_64.rs @@ -68,17 +68,17 @@ pub fn parse_rmi(ctx: &mut crate::parser::ParseCtx) -> Result RegMemImm::Reg(Reg::parse(ident).ok_or_else(err)?), + Token::Ident(ident) => RegMemImm::Reg(RegW::parse(ident).ok_or_else(err)?), Token::Lit(LitTy::Number(num)) => RegMemImm::Imm(parse_imm(num, ctx.span)?), _ => return Err(err()), }) } -pub fn parse_reg(ctx: &mut crate::parser::ParseCtx) -> Result { +pub fn parse_reg(ctx: &mut crate::parser::ParseCtx) -> Result { let next = ctx.expect_next()?; let err = || CompilerMsg::unexpected_token(&next, ctx.span, "a register"); let Token::Ident(next) = &next else { return Err(err()); }; - Reg::parse(next).ok_or_else(err) + RegW::parse(next).ok_or_else(err) }