mirror of
https://github.com/Noratrieb/uwucc.git
synced 2026-01-15 00:55:05 +01:00
make stack work
This commit is contained in:
parent
e28469fcc0
commit
46e5662aab
15 changed files with 122 additions and 117 deletions
|
|
@ -1,4 +1,5 @@
|
|||
mod registers;
|
||||
mod stack;
|
||||
mod x86_64;
|
||||
|
||||
use std::process::Stdio;
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ pub struct MachineReg(pub usize);
|
|||
pub enum RegValue {
|
||||
/// The SSA register contains an address on the stack.
|
||||
/// The offset is the offset from the start of the function.
|
||||
StackRelative { offset: u64 },
|
||||
StackRelativePtr { offset: u64 },
|
||||
/// The SSA register resides on the stack as it has been spilled.
|
||||
/// This should be rather rare in practice.
|
||||
Spilled { offset: u64 },
|
||||
|
|
@ -65,15 +65,13 @@ pub enum RegValue {
|
|||
pub struct FunctionLayout {
|
||||
/// Where a register comes from at a particular usage of a register.
|
||||
register_uses: FxHashMap<(Location, Register), RegValue>,
|
||||
total_stack_space: u64,
|
||||
}
|
||||
|
||||
pub fn compute_layout(f: &Func) -> FunctionLayout {
|
||||
pub fn compute_layout(_f: &Func) -> FunctionLayout {
|
||||
let register_uses = FxHashMap::default();
|
||||
|
||||
FunctionLayout {
|
||||
register_uses,
|
||||
total_stack_space: 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -102,7 +100,7 @@ impl<'a> ir::pretty::Customizer<'a> for LayoutPrinter<'a> {
|
|||
match layout {
|
||||
Some(RegValue::MachineReg(mach)) => write!(f, "reg-{}", mach.0)?,
|
||||
Some(RegValue::Spilled { offset }) => write!(f, "spill-{offset}")?,
|
||||
Some(RegValue::StackRelative { offset }) => {
|
||||
Some(RegValue::StackRelativePtr { offset }) => {
|
||||
write!(f, "i-forgot-what-this-meant-{offset}")?
|
||||
}
|
||||
None => write!(f, "<unknown>")?,
|
||||
|
|
|
|||
43
codegen/src/stack.rs
Normal file
43
codegen/src/stack.rs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use analysis::ir::{BbIdx, Func, Register, StatementKind};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StackLayout {
|
||||
pub allocas: HashMap<Register, u64>,
|
||||
pub total_size: u64,
|
||||
}
|
||||
|
||||
/// Based on the alloca's in the initial block, this calculcates stack pointer offsets for every allocation.
|
||||
pub fn allocate_stack_space<'cx>(start_align: u64, func: &Func<'cx>) -> StackLayout {
|
||||
assert_eq!(start_align, 8);
|
||||
// REMEMBER: The stack grows down (on x86-64).
|
||||
|
||||
let mut temp_layout = HashMap::new();
|
||||
let mut offset_backwards = 0;
|
||||
|
||||
for stmt in &func.bb(BbIdx::ZERO).statements {
|
||||
if let StatementKind::Alloca {
|
||||
result,
|
||||
size,
|
||||
align,
|
||||
} = stmt.kind
|
||||
{
|
||||
if size != 8 || align != 8 {
|
||||
todo!("non 8 integer {size} {align}")
|
||||
}
|
||||
offset_backwards += 8;
|
||||
temp_layout.insert(result, offset_backwards);
|
||||
}
|
||||
}
|
||||
|
||||
let total_size = offset_backwards;
|
||||
|
||||
StackLayout {
|
||||
allocas: temp_layout
|
||||
.into_iter()
|
||||
.map(|(reg, offset_back)| (reg, total_size - offset_back))
|
||||
.collect(),
|
||||
total_size,
|
||||
}
|
||||
}
|
||||
|
|
@ -40,7 +40,7 @@ use rustc_hash::FxHashMap;
|
|||
|
||||
use crate::{
|
||||
registers::{MachineReg, RegValue},
|
||||
Result,
|
||||
stack, Result,
|
||||
};
|
||||
|
||||
trait IcedErrExt {
|
||||
|
|
@ -61,9 +61,10 @@ struct AsmCtxt<'cx> {
|
|||
a: CodeAssembler,
|
||||
reg_map: FxHashMap<Register, RegValue>,
|
||||
reg_occupancy: Vec<Option<Register>>,
|
||||
current_stack_offset: u64,
|
||||
bb_idx: BbIdx,
|
||||
|
||||
stack_layout: stack::StackLayout,
|
||||
|
||||
// caches
|
||||
last_register_uses: Vec<Option<Location>>,
|
||||
}
|
||||
|
|
@ -98,6 +99,9 @@ impl<'cx> AsmCtxt<'cx> {
|
|||
// Prologue: Save rbp and save rsp in rbp.
|
||||
self.a.push(x::rbp).sp(func.def_span)?;
|
||||
self.a.mov(x::rbp, x::rsp).sp(func.def_span)?;
|
||||
self.a
|
||||
.sub(x::rsp, self.stack_layout.total_size as i32)
|
||||
.sp(func.def_span)?;
|
||||
|
||||
loop {
|
||||
let bb = &func.bbs[self.bb_idx.as_usize()];
|
||||
|
|
@ -108,27 +112,15 @@ impl<'cx> AsmCtxt<'cx> {
|
|||
} = *stmt;
|
||||
|
||||
match *kind {
|
||||
StatementKind::Alloca {
|
||||
result: reg,
|
||||
size,
|
||||
align: _,
|
||||
} => {
|
||||
// For alloca, we allocate some space on the stack by subtracting from RSP.
|
||||
// TODO: Align
|
||||
match size {
|
||||
Operand::Const(c) => {
|
||||
let offset = c.as_i32();
|
||||
self.a.sub(x::rsp, offset).sp(st_sp)?;
|
||||
self.current_stack_offset += offset as u64;
|
||||
}
|
||||
Operand::Reg(_) => {
|
||||
todo!("dynamic alloca is not supported. get a better computer")
|
||||
}
|
||||
};
|
||||
StatementKind::Alloca { result, .. } => {
|
||||
self.reg_map.insert(
|
||||
reg,
|
||||
RegValue::StackRelative {
|
||||
offset: self.current_stack_offset,
|
||||
result,
|
||||
RegValue::StackRelativePtr {
|
||||
offset: *self
|
||||
.stack_layout
|
||||
.allocas
|
||||
.get(&result)
|
||||
.expect("no stack layout slot present for alloc register"),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
@ -149,14 +141,15 @@ impl<'cx> AsmCtxt<'cx> {
|
|||
Operand::Reg(reg) => {
|
||||
let ptr_value = self.reg_map[®];
|
||||
match (ptr_value, value) {
|
||||
(RegValue::StackRelative { offset }, Operand::Const(c)) => {
|
||||
let offset_from_cur = self.current_stack_offset - offset;
|
||||
|
||||
(RegValue::StackRelativePtr { offset }, Operand::Const(c)) => {
|
||||
self.a
|
||||
.mov(x::qword_ptr(x::rsp + offset_from_cur), c.as_i32())
|
||||
.mov(x::qword_ptr(x::rsp + offset), c.as_i32())
|
||||
.sp(st_sp)?;
|
||||
}
|
||||
(RegValue::StackRelative { offset }, Operand::Reg(value)) => {
|
||||
(
|
||||
RegValue::StackRelativePtr { offset },
|
||||
Operand::Reg(value),
|
||||
) => {
|
||||
todo!("stack relative ptr + reg value")
|
||||
}
|
||||
(RegValue::Spilled { .. }, _) => todo!("spilled"),
|
||||
|
|
@ -229,13 +222,16 @@ pub fn generate_func<'cx>(lcx: &'cx LoweringCx<'cx>, func: &Func<'cx>) -> Result
|
|||
let fn_sp = func.def_span;
|
||||
let a = CodeAssembler::new(64).sp(fn_sp)?;
|
||||
|
||||
let stack_layout = stack::allocate_stack_space(8, func);
|
||||
dbg!(&stack_layout);
|
||||
|
||||
let mut cx = AsmCtxt {
|
||||
lcx,
|
||||
a,
|
||||
reg_map: FxHashMap::default(),
|
||||
reg_occupancy: vec![None; 8],
|
||||
current_stack_offset: 0,
|
||||
bb_idx: BbIdx(0),
|
||||
stack_layout,
|
||||
last_register_uses: ir::info::last_register_uses(func),
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue