This commit is contained in:
2026-07-21 16:22:45 -04:00
parent e4d2dcfe15
commit 780336fbe4
2 changed files with 87 additions and 29 deletions
+81 -29
View File
@@ -1,4 +1,4 @@
use std::collections::{HashMap, HashSet, VecDeque}; use std::collections::{HashMap, HashSet};
use super::*; use super::*;
use crate::backend::{Body, Func, LibImport, LinkedProgram, SymImport, SymTable, Symbol, VarId}; use crate::backend::{Body, Func, LibImport, LinkedProgram, SymImport, SymTable, Symbol, VarId};
@@ -8,8 +8,17 @@ pub struct Encoder<'a> {
pub sym_tab: SymTable<u64>, pub sym_tab: SymTable<u64>,
pub sym_refs: HashMap<Symbol, Vec<usize>>, pub sym_refs: HashMap<Symbol, Vec<usize>>,
pub program: &'a Program<X86_64>, pub program: &'a Program<X86_64>,
pub active: FnData,
}
#[derive(Default)]
struct FnData {
pub segs: Vec<SegUses>, pub segs: Vec<SegUses>,
pub vars: HashMap<VarId, Reg>, pub seg: usize,
pub i: usize,
pub var: HashMap<VarId, RegW>,
pub reg: [Option<VarId>; 16],
pub reg_next: [Option<RegUse>; 16],
} }
pub fn compile(p: &Program<X86_64>) -> Result<LinkedProgram<u64>, CompilerMsg> { pub fn compile(p: &Program<X86_64>) -> Result<LinkedProgram<u64>, CompilerMsg> {
@@ -59,8 +68,8 @@ pub fn compile(p: &Program<X86_64>) -> Result<LinkedProgram<u64>, CompilerMsg> {
#[derive(Default)] #[derive(Default)]
pub struct SegUses { pub struct SegUses {
var: HashMap<VarId, VecDeque<usize>>, var: HashMap<VarId, Vec<usize>>,
reg: [VecDeque<RegUse>; 16], reg: [Vec<RegUse>; 16],
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@@ -75,9 +84,32 @@ impl<'a> Encoder<'a> {
fn func(&mut self, f: &Func<X86_64>) -> ERes { fn func(&mut self, f: &Func<X86_64>) -> ERes {
let addr = self.code.bytes.len(); let addr = self.code.bytes.len();
self.sym_tab.insert(f.sym, addr as u64); self.sym_tab.insert(f.sym, addr as u64);
self.segs.clear(); self.active = Default::default();
self.calc_uses(&f.body); self.calc_uses(&f.body);
for instr in &f.body { for (i, instr) in f.body.iter().enumerate() {
self.active.i = i;
let seg = &self.active.segs[self.active.seg];
for r in 0..self.active.reg_next.len() {
let u = self.active.reg_next[r];
let Some(u) = u else {
continue;
};
if u.pos != r {
continue;
}
// if there's a var currently in the reg
if let Some(var) = self.active.reg[r] {
// done if it's what's needed
if u.var.is_some_and(|v| var == v) {
continue;
}
// otherwise save it
self.save(var);
}
if let Some(var) = u.var {
if let Some(cur) = self.active.var.get(&var) {}
}
}
match instr { match instr {
BInstr::Asm(asm) => self.asm(asm)?, BInstr::Asm(asm) => self.asm(asm)?,
_ => todo!(), _ => todo!(),
@@ -86,20 +118,21 @@ impl<'a> Encoder<'a> {
Ok(()) Ok(())
} }
pub fn calc_uses(&mut self, body: &Body<X86_64>) -> (usize, usize) { fn save(&mut self, var: VarId) {
todo!()
}
fn calc_uses(&mut self, body: &Body<X86_64>) -> (usize, usize) {
let mut pos = 0; let mut pos = 0;
let seg_i = self.segs.len(); let seg_i = self.active.segs.len();
self.segs.push(Default::default()); self.active.segs.push(Default::default());
let mut uses = SegUses::default(); let mut uses = SegUses::default();
macro_rules! push { macro_rules! push {
($var:ident) => { ($var:ident) => {
push!($var, 0) push!($var, 0)
}; };
($var:ident, $pos:expr) => { ($var:ident, $pos:expr) => {
uses.var uses.var.entry($var.clone()).or_default().push(pos + $pos)
.entry($var.clone())
.or_default()
.push_back(pos + $pos)
}; };
} }
for instr in body { for instr in body {
@@ -110,12 +143,12 @@ impl<'a> Encoder<'a> {
push!(dst); push!(dst);
for &reg in conv.scratch() { for &reg in conv.scratch() {
uses.reg[reg as usize].push_back(RegUse { pos, var: None }); uses.reg[reg as usize].push(RegUse { pos, var: None });
} }
for (i, &arg) in args.iter().enumerate() { for (i, &arg) in args.iter().enumerate() {
push!(arg); push!(arg);
if let Some(&reg) = conv.param().get(i) { if let Some(&reg) = conv.param().get(i) {
uses.reg[reg as usize].back_mut().unwrap().var = Some(arg); uses.reg[reg as usize].last_mut().unwrap().var = Some(arg);
} }
} }
} }
@@ -134,15 +167,15 @@ impl<'a> Encoder<'a> {
let (seg_i1, len1) = self.calc_uses(then); let (seg_i1, len1) = self.calc_uses(then);
let (seg_i2, len2) = self.calc_uses(else_); let (seg_i2, len2) = self.calc_uses(else_);
// insert closest usages // insert closest usages
for (var, poss1) in &self.segs[seg_i1].var { for (var, poss1) in &self.active.segs[seg_i1].var {
if let Some(poss2) = self.segs[seg_i2].var.get(var) { if let Some(poss2) = self.active.segs[seg_i2].var.get(var) {
push!(var, poss1[0].min(poss2[0])); push!(var, poss1[0].min(poss2[0]));
} else { } else {
push!(var, poss1[0]); push!(var, poss1[0]);
} }
} }
for (var, poss2) in &self.segs[seg_i2].var { for (var, poss2) in &self.active.segs[seg_i2].var {
if !self.segs[seg_i1].var.contains_key(var) { if !self.active.segs[seg_i1].var.contains_key(var) {
push!(var, poss2[0]); push!(var, poss2[0]);
} }
} }
@@ -152,7 +185,7 @@ impl<'a> Encoder<'a> {
BInstr::Loop(instrs) => { BInstr::Loop(instrs) => {
let (seg_i2, len) = self.calc_uses(instrs); let (seg_i2, len) = self.calc_uses(instrs);
// insert closest usages // insert closest usages
for (var, poss) in &self.segs[seg_i2].var { for (var, poss) in &self.active.segs[seg_i2].var {
push!(var, poss[0]); push!(var, poss[0]);
} }
// during register allocation, want to insert the first use of each var // during register allocation, want to insert the first use of each var
@@ -183,27 +216,44 @@ impl<'a> Encoder<'a> {
for &(reg, var) in &asm.args { for &(reg, var) in &asm.args {
push!(var); push!(var);
used.remove(&reg); used.remove(&reg);
uses.reg[reg as usize].push_back(RegUse { uses.reg[reg as usize].push(RegUse {
pos, pos,
var: Some(var), var: Some(var),
}); });
} }
for reg in used { for reg in used {
uses.reg[reg as usize].push_back(RegUse { pos, var: None }); uses.reg[reg as usize].push(RegUse { pos, var: None });
} }
} }
} }
pos += 1; pos += 1;
} }
self.segs[seg_i] = uses; self.active.segs[seg_i] = uses;
return (seg_i, pos); return (seg_i, pos);
} }
pub fn prep_var(&mut self, var: VarId) -> RegW {
let seg = &mut self.active.segs[self.active.seg];
if let Some(reg) = self.active.var.get(&var) {
*reg
} else {
}
}
pub fn rvm(&mut self, input: Rvm) -> RegMem { pub fn rvm(&mut self, input: Rvm) -> RegMem {
match input { match input {
Rvm::Reg(reg) => reg, Rvm::Reg(reg) => reg.into(),
Rvm::Var(var_id) => todo!(), Rvm::Var(var) => self.prep_var(var).into(),
Rvm::Mem(mem) => todo!(), Rvm::Mem(mem) => mem.into(),
}
}
pub fn rvmi(&mut self, input: Rvmi) -> RegMemImm {
match input {
Rvmi::Reg(reg) => reg.into(),
Rvmi::Var(var) => self.prep_var(var).into(),
Rvmi::Mem(mem) => mem.into(),
Rvmi::Imm(imm) => imm.into(),
} }
} }
@@ -218,15 +268,15 @@ impl<'a> Encoder<'a> {
vars.insert(var); vars.insert(var);
} }
} }
let overlap = used.intersection(&self.vars.values()); let overlap = used.intersection(&self.active.var.values());
for var in &vars { for var in &vars {
if let Some(reg) = self.vars.get(var) if let Some(reg) = self.active.var.get(var)
&& used.contains(reg) && used.contains(reg)
{} {}
} }
for &instr in &asm.instrs { for &instr in &asm.instrs {
match instr { match instr {
Instr::Mov { dst, src } => self.code.mov(dst, src)?, Instr::Mov { dst, src } => self.code.mov(self.rvm(dst), self.rvmi(src))?,
Instr::Push(rvmi) => todo!(), Instr::Push(rvmi) => todo!(),
Instr::Pop(rvm) => todo!(), Instr::Pop(rvm) => todo!(),
Instr::Lea { dst, src } => todo!(), Instr::Lea { dst, src } => todo!(),
@@ -247,7 +297,9 @@ impl<'a> Encoder<'a> {
code: Code::default(), code: Code::default(),
sym_tab: SymTable::new(program.sym_count()), sym_tab: SymTable::new(program.sym_count()),
sym_refs: Default::default(), sym_refs: Default::default(),
seg: 0,
segs: Default::default(), segs: Default::default(),
active: Default::default(),
program, program,
} }
} }
+6
View File
@@ -131,6 +131,12 @@ impl From<i128> for RegMemImm {
} }
} }
impl From<Imm> for RegMemImm {
fn from(value: Imm) -> Self {
Self::Imm(value)
}
}
pub trait ModRMRM { pub trait ModRMRM {
fn rm(&self) -> u8; fn rm(&self) -> u8;
fn addr(&self) -> EffAddr; fn addr(&self) -> EffAddr;