work
This commit is contained in:
+40
-36
@@ -12,18 +12,13 @@ pub struct Encoder<'a> {
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct VarUse {
|
||||
pub struct RegUse {
|
||||
pos: usize,
|
||||
reg: Option<Reg>,
|
||||
}
|
||||
pub type VarUses = HashMap<VarId, VecDeque<VarUse>>;
|
||||
pub type RegUses = [VecDeque<usize>; 16];
|
||||
|
||||
impl VarUse {
|
||||
pub fn min(self, other: Self) -> Self {
|
||||
if self.pos <= other.pos { self } else { other }
|
||||
}
|
||||
// required var, if any
|
||||
var: Option<VarId>,
|
||||
}
|
||||
pub type VarUses = HashMap<VarId, VecDeque<usize>>;
|
||||
pub type RegUses = [VecDeque<RegUse>; 16];
|
||||
|
||||
pub fn compile(p: &Program<X86_64>) -> Result<LinkedProgram<u64>, CompilerMsg> {
|
||||
let mut encoder = Encoder::new(p);
|
||||
@@ -34,7 +29,7 @@ pub fn compile(p: &Program<X86_64>) -> Result<LinkedProgram<u64>, CompilerMsg> {
|
||||
let addr = encoder.code.bytes.len();
|
||||
encoder.sym_tab.insert(f.sym, addr as u64);
|
||||
let mut segments = Vec::new();
|
||||
calc_uses(&mut segments, &f.body);
|
||||
calc_uses(&mut segments, &f.body, p);
|
||||
}
|
||||
|
||||
for f in &p.funcs {
|
||||
@@ -87,36 +82,38 @@ pub struct SegUses {
|
||||
reg: RegUses,
|
||||
}
|
||||
|
||||
pub fn calc_uses(segments: &mut Vec<SegUses>, body: &Body<X86_64>) -> (usize, usize) {
|
||||
pub fn calc_uses(
|
||||
segments: &mut Vec<SegUses>,
|
||||
body: &Body<X86_64>,
|
||||
p: &Program<X86_64>,
|
||||
) -> (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 })
|
||||
push!($var, 0)
|
||||
};
|
||||
($var:ident, $pos:expr) => {
|
||||
vars.entry($var.clone()).or_default().push_back(VarUse {
|
||||
pos: $pos.pos + pos,
|
||||
reg: $pos.reg,
|
||||
})
|
||||
vars.entry($var.clone()).or_default().push_back(pos + $pos)
|
||||
};
|
||||
}
|
||||
for instr in body {
|
||||
match instr {
|
||||
BInstr::Set { dst, src: _ } => push!(dst),
|
||||
BInstr::Call { dst, f, args } => {
|
||||
let conv = &p.call_convs[p.funcs[f].conv];
|
||||
push!(dst);
|
||||
for (i, arg) in args.iter().enumerate() {
|
||||
|
||||
for ® in conv.scratch() {
|
||||
regs[reg as usize].push_back(RegUse { pos, var: None });
|
||||
}
|
||||
for (i, &arg) in args.iter().enumerate() {
|
||||
push!(arg);
|
||||
if i < 8 {
|
||||
regs[i].push_back(pos);
|
||||
if let Some(®) = conv.param().get(i) {
|
||||
regs[reg as usize].back_mut().unwrap().var = Some(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -132,8 +129,8 @@ pub fn calc_uses(segments: &mut Vec<SegUses>, body: &Body<X86_64>) -> (usize, us
|
||||
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_);
|
||||
let (seg_i1, len1) = calc_uses(segments, then, p);
|
||||
let (seg_i2, len2) = calc_uses(segments, else_, p);
|
||||
// insert closest usages
|
||||
for (var, poss1) in &segments[seg_i1].var {
|
||||
if let Some(poss2) = segments[seg_i2].var.get(var) {
|
||||
@@ -151,7 +148,7 @@ pub fn calc_uses(segments: &mut Vec<SegUses>, body: &Body<X86_64>) -> (usize, us
|
||||
continue;
|
||||
}
|
||||
BInstr::Loop(instrs) => {
|
||||
let (seg_i2, len) = calc_uses(segments, instrs);
|
||||
let (seg_i2, len) = calc_uses(segments, instrs, p);
|
||||
// insert closest usages
|
||||
for (var, poss) in &segments[seg_i2].var {
|
||||
push!(var, poss[0]);
|
||||
@@ -175,15 +172,22 @@ pub fn calc_uses(segments: &mut Vec<SegUses>, body: &Body<X86_64>) -> (usize, us
|
||||
}
|
||||
}
|
||||
BInstr::Asm(asm) => {
|
||||
let mut used = HashSet::new();
|
||||
for i in &asm.instrs {
|
||||
if let Some(reg) = i.dst_reg() {
|
||||
used.insert(reg.reg());
|
||||
}
|
||||
}
|
||||
for &(reg, var) in &asm.args {
|
||||
push!(
|
||||
var,
|
||||
VarUse {
|
||||
pos: 0,
|
||||
reg: Some(reg)
|
||||
}
|
||||
);
|
||||
regs[reg as usize].push_back(pos);
|
||||
push!(var);
|
||||
used.remove(®);
|
||||
regs[reg as usize].push_back(RegUse {
|
||||
pos,
|
||||
var: Some(var),
|
||||
});
|
||||
}
|
||||
for reg in used {
|
||||
regs[reg as usize].push_back(RegUse { pos, var: None });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -208,7 +212,7 @@ impl<'a> Encoder<'a> {
|
||||
let mut used = HashSet::default();
|
||||
let mut vars = HashSet::default();
|
||||
for &instr in &asm.instrs {
|
||||
if let Some(regw) = instr.regw_set() {
|
||||
if let Some(regw) = instr.dst_reg() {
|
||||
used.insert(regw.reg());
|
||||
}
|
||||
for var in instr.vars() {
|
||||
|
||||
Reference in New Issue
Block a user