work
This commit is contained in:
+81
-29
@@ -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 ® in conv.scratch() {
|
for ® 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(®) = conv.param().get(i) {
|
if let Some(®) = 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(®);
|
used.remove(®);
|
||||||
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user