mirror of
https://github.com/Noratrieb/uwucc.git
synced 2026-01-14 16:45:07 +01:00
dom
This commit is contained in:
parent
ebe01c7521
commit
92243712e7
4 changed files with 89 additions and 26 deletions
|
|
@ -32,7 +32,7 @@
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
mod custom;
|
mod custom;
|
||||||
mod info;
|
pub mod info;
|
||||||
mod pretty;
|
mod pretty;
|
||||||
mod validate;
|
mod validate;
|
||||||
mod visit;
|
mod visit;
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,7 @@ pub fn last_register_uses(func: &Func<'_>) -> Vec<Option<Location>> {
|
||||||
|
|
||||||
let mut check_op = |op: Operand, stmt| match op {
|
let mut check_op = |op: Operand, stmt| match op {
|
||||||
Operand::Reg(reg) => {
|
Operand::Reg(reg) => {
|
||||||
dbg!(("reg use", reg, stmt));
|
|
||||||
if uses[reg.as_usize()].is_none() {
|
if uses[reg.as_usize()].is_none() {
|
||||||
dbg!("insert!");
|
|
||||||
uses[reg.as_usize()] = Some(Location { bb, stmt })
|
uses[reg.as_usize()] = Some(Location { bb, stmt })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -70,6 +68,29 @@ pub fn last_register_uses(func: &Func<'_>) -> Vec<Option<Location>> {
|
||||||
uses
|
uses
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn dominates_location(f: &Func<'_>, dom: Location, sub: Location) -> bool {
|
||||||
|
// TODO: Can this be made more efficient by caching renumberings of bbs?
|
||||||
|
if dom.bb == sub.bb {
|
||||||
|
return match (dom.stmt, sub.stmt) {
|
||||||
|
(None, Some(_)) => true,
|
||||||
|
(Some(d_i), Some(s_i)) if d_i < s_i => true,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut seen = FxHashSet::default();
|
||||||
|
let mut worklist = vec![dom.bb];
|
||||||
|
|
||||||
|
while let Some(bb) = worklist.pop() {
|
||||||
|
if !seen.insert(bb) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
worklist.extend(f.bb(bb).term.successors());
|
||||||
|
}
|
||||||
|
|
||||||
|
seen.contains(&sub.bb)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ pub fn generate<'cx>(lcx: &'cx LoweringCx<'cx>, ir: &Ir<'cx>) -> Result<()> {
|
||||||
let output = std::process::Command::new("cc")
|
let output = std::process::Command::new("cc")
|
||||||
.arg("main.o")
|
.arg("main.o")
|
||||||
.stdout(Stdio::inherit())
|
.stdout(Stdio::inherit())
|
||||||
.stdout(Stdio::inherit())
|
.stderr(Stdio::inherit())
|
||||||
.output()
|
.output()
|
||||||
.map_err(|err| analysis::Error::new_without_span(format!("failed to spawn `cc`: {err}")))?;
|
.map_err(|err| analysis::Error::new_without_span(format!("failed to spawn `cc`: {err}")))?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@
|
||||||
//! | %r15 | callee-saved register; optionally used as GOT base pointer | Yes |
|
//! | %r15 | callee-saved register; optionally used as GOT base pointer | Yes |
|
||||||
|
|
||||||
use analysis::{
|
use analysis::{
|
||||||
ir::{BbIdx, Func, Operand, Register, Statement, StatementKind},
|
ir::{self, BbIdx, Func, Location, Operand, Register, Statement, StatementKind},
|
||||||
LoweringCx,
|
LoweringCx,
|
||||||
};
|
};
|
||||||
use iced_x86::{
|
use iced_x86::{
|
||||||
|
|
@ -91,22 +91,59 @@ impl<T> IcedErrExt for Result<T, IcedError> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A machine register from our register list described in the module documentation.
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
struct MachineReg(usize);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
enum RegValue {
|
enum RegValue {
|
||||||
|
/// The SSA register resides on the stack as it has been spilled.
|
||||||
Stack { offset: u64 },
|
Stack { offset: u64 },
|
||||||
|
/// The SSA register resides in a machine register
|
||||||
|
MachineReg(MachineReg),
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AsmCtxt<'cx> {
|
struct AsmCtxt<'cx> {
|
||||||
lcx: &'cx LoweringCx<'cx>,
|
lcx: &'cx LoweringCx<'cx>,
|
||||||
a: CodeAssembler,
|
a: CodeAssembler,
|
||||||
reg_map: FxHashMap<Register, RegValue>,
|
reg_map: FxHashMap<Register, RegValue>,
|
||||||
|
reg_occupancy: Vec<Option<Register>>,
|
||||||
current_stack_offset: u64,
|
current_stack_offset: u64,
|
||||||
bb_idx: BbIdx,
|
bb_idx: BbIdx,
|
||||||
|
|
||||||
|
// caches
|
||||||
|
last_register_uses: Vec<Option<Location>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'cx> AsmCtxt<'cx> {
|
impl<'cx> AsmCtxt<'cx> {
|
||||||
|
fn allocate_result_ssa_reg(
|
||||||
|
&mut self,
|
||||||
|
f: &Func<'_>,
|
||||||
|
reg: Register,
|
||||||
|
location: Location,
|
||||||
|
) -> RegValue {
|
||||||
|
for (i, opt_reg) in self.reg_occupancy.iter_mut().enumerate() {
|
||||||
|
if let Some(reg) = opt_reg.as_mut() {
|
||||||
|
if let Some(last_use) = self.last_register_uses[reg.as_usize()] {
|
||||||
|
if ir::info::dominates_location(f, last_use, location) {
|
||||||
|
// The last use dominates our location - the SSA reg is dead now.
|
||||||
|
*opt_reg = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if opt_reg.is_none() {
|
||||||
|
*opt_reg = Some(reg);
|
||||||
|
return RegValue::MachineReg(MachineReg(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
todo!("spill.")
|
||||||
|
}
|
||||||
|
|
||||||
fn generate_func(&mut self, func: &Func<'cx>) -> Result<()> {
|
fn generate_func(&mut self, func: &Func<'cx>) -> Result<()> {
|
||||||
// TODO: Prologue
|
// TODO: Prologue
|
||||||
|
self.a.push(x::rbx);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let bb = &func.bbs[self.bb_idx.as_usize()];
|
let bb = &func.bbs[self.bb_idx.as_usize()];
|
||||||
|
|
@ -149,6 +186,7 @@ impl<'cx> AsmCtxt<'cx> {
|
||||||
let value = self.reg_map[®];
|
let value = self.reg_map[®];
|
||||||
let stack_offset = match value {
|
let stack_offset = match value {
|
||||||
RegValue::Stack { offset } => offset,
|
RegValue::Stack { offset } => offset,
|
||||||
|
RegValue::MachineReg(_) => todo!("machine reg"),
|
||||||
};
|
};
|
||||||
//let rhs = match value {
|
//let rhs = match value {
|
||||||
// Operand::Const(c) => {}
|
// Operand::Const(c) => {}
|
||||||
|
|
@ -167,24 +205,26 @@ impl<'cx> AsmCtxt<'cx> {
|
||||||
ptr,
|
ptr,
|
||||||
size,
|
size,
|
||||||
align,
|
align,
|
||||||
} => todo!(),
|
} => todo!("loads."),
|
||||||
StatementKind::BinOp {
|
StatementKind::BinOp {
|
||||||
kind,
|
kind,
|
||||||
lhs,
|
lhs,
|
||||||
rhs,
|
rhs,
|
||||||
result,
|
result,
|
||||||
} => todo!(),
|
} => todo!("binary operations"),
|
||||||
StatementKind::UnaryOperation { rhs, kind, result } => todo!(),
|
StatementKind::UnaryOperation { rhs, kind, result } => {
|
||||||
|
todo!("unary operations")
|
||||||
|
}
|
||||||
StatementKind::PtrOffset {
|
StatementKind::PtrOffset {
|
||||||
result,
|
result,
|
||||||
ptr: reg,
|
ptr: reg,
|
||||||
amount,
|
amount,
|
||||||
} => todo!(),
|
} => todo!("pointer offset :D"),
|
||||||
StatementKind::Call {
|
StatementKind::Call {
|
||||||
result,
|
result,
|
||||||
func,
|
func,
|
||||||
ref args,
|
ref args,
|
||||||
} => todo!(),
|
} => todo!("function calls 💀"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -205,8 +245,10 @@ pub fn generate_func<'cx>(lcx: &'cx LoweringCx<'cx>, func: &Func<'cx>) -> Result
|
||||||
lcx,
|
lcx,
|
||||||
a,
|
a,
|
||||||
reg_map: FxHashMap::default(),
|
reg_map: FxHashMap::default(),
|
||||||
|
reg_occupancy: vec![None; 8],
|
||||||
current_stack_offset: 0,
|
current_stack_offset: 0,
|
||||||
bb_idx: BbIdx(0),
|
bb_idx: BbIdx(0),
|
||||||
|
last_register_uses: ir::info::last_register_uses(func),
|
||||||
};
|
};
|
||||||
|
|
||||||
cx.generate_func(func)?;
|
cx.generate_func(func)?;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue