saving before refactoring experiment

This commit is contained in:
mlokr 2024-05-14 14:01:40 +02:00
parent fb481a0600
commit 9aa5da82c9
5 changed files with 46 additions and 23 deletions

View file

@ -2,10 +2,16 @@ main := fn(): int {
a := 1; a := 1;
b := &a; b := &a;
modify(b); modify(b);
return a - 2; drop(a);
stack_reclamation_edge_case := 0;
return *b - 2;
} }
modify := fn(a: *int): void { modify := fn(a: *int): void {
*a = 2; *a = 2;
return; return;
} }
drop := fn(a: int): void {
return;
}

View file

@ -388,6 +388,7 @@ struct RetReloc {
} }
struct Loop { struct Loop {
var_count: usize,
offset: u32, offset: u32,
relocs: Vec<RetReloc>, relocs: Vec<RetReloc>,
} }
@ -637,7 +638,7 @@ impl<'a> Codegen<'a> {
let reg = self.gpa.allocate(); let reg = self.gpa.allocate();
self.code self.code
.encode(instrs::ld(reg.0, dreg.0, offset, size as _)); .encode(instrs::ld(reg.0, dreg.0, offset, size as _));
self.gpa.free(dreg); self.free_reg(dreg);
reg reg
} }
Loc::DerefRef(dreg, offset) => { Loc::DerefRef(dreg, offset) => {
@ -814,7 +815,7 @@ impl<'a> Codegen<'a> {
let size = self.size_of(val.ty); let size = self.size_of(val.ty);
let stack = self.sa.alloc(size); let stack = self.sa.alloc(size);
self.store_stack(r.0, stack.offset, size as _); self.store_stack(r.0, stack.offset, size as _);
self.gpa.free(r); self.free_reg(r);
Loc::Stack(stack, 0) Loc::Stack(stack, 0)
} }
l => l, l => l,
@ -886,11 +887,14 @@ impl<'a> Codegen<'a> {
}); });
} }
E::Ident { name, id, last } => { E::Ident { name, id, last } => {
let Some(var) = self.vars.iter_mut().find(|v| v.id == id) else { let Some((index, var)) = self.vars.iter_mut().enumerate().find(|(_, v)| v.id == id)
else {
self.report(expr.pos(), format_args!("unknown variable: {}", name)) self.report(expr.pos(), format_args!("unknown variable: {}", name))
}; };
let loc = match last.is_some_and(Cell::get) { let loc = match last.is_some_and(Cell::get)
&& !self.loops.last().is_some_and(|l| l.var_count > index)
{
true => std::mem::replace(&mut var.value.loc, Loc::Imm(0)), true => std::mem::replace(&mut var.value.loc, Loc::Imm(0)),
false => var.value.loc.take_ref(), false => var.value.loc.take_ref(),
}; };
@ -921,7 +925,7 @@ impl<'a> Codegen<'a> {
E::Block { stmts, .. } => { E::Block { stmts, .. } => {
for stmt in stmts { for stmt in stmts {
if let Loc::Reg(reg) = self.expr(stmt)?.loc { if let Loc::Reg(reg) = self.expr(stmt)?.loc {
self.gpa.free(reg); self.free_reg(reg);
} }
} }
Some(Value::VOID) Some(Value::VOID)
@ -938,7 +942,7 @@ impl<'a> Codegen<'a> {
let reg = self.loc_to_reg(cond.loc, 1); let reg = self.loc_to_reg(cond.loc, 1);
let jump_offset = self.code.code.len() as u32; let jump_offset = self.code.code.len() as u32;
self.code.encode(instrs::jeq(reg.0, 0, 0)); self.code.encode(instrs::jeq(reg.0, 0, 0));
self.gpa.free(reg); self.free_reg(reg);
log::dbg!("if-then"); log::dbg!("if-then");
let then_unreachable = self.expr(then).is_none(); let then_unreachable = self.expr(then).is_none();
@ -978,6 +982,7 @@ impl<'a> Codegen<'a> {
log::dbg!("loop"); log::dbg!("loop");
let loop_start = self.code.code.len() as u32; let loop_start = self.code.code.len() as u32;
self.loops.push(Loop { self.loops.push(Loop {
var_count: self.vars.len() as _,
offset: loop_start, offset: loop_start,
relocs: Default::default(), relocs: Default::default(),
}); });
@ -1002,6 +1007,14 @@ impl<'a> Codegen<'a> {
dest.copy_from_slice(&offset.to_ne_bytes()); dest.copy_from_slice(&offset.to_ne_bytes());
} }
for var in self
.vars
.drain(loop_.var_count as usize..)
.collect::<Vec<_>>()
{
self.free_loc(var.value.loc);
}
if is_unreachable { if is_unreachable {
log::dbg!("infinite loop"); log::dbg!("infinite loop");
break 'a None; break 'a None;
@ -1087,7 +1100,7 @@ impl<'a> Codegen<'a> {
if let Some(op) = Self::math_op(op, signed, size) { if let Some(op) = Self::math_op(op, signed, size) {
self.code.encode(op(lhs.0, lhs.0, rhs.0)); self.code.encode(op(lhs.0, lhs.0, rhs.0));
self.gpa.free(rhs); self.free_reg(rhs);
break 'ops Some(Value { break 'ops Some(Value {
ty, ty,
@ -1105,7 +1118,7 @@ impl<'a> Codegen<'a> {
let op_fn = if signed { i::cmps } else { i::cmpu }; let op_fn = if signed { i::cmps } else { i::cmpu };
self.code.encode(op_fn(lhs.0, lhs.0, rhs.0)); self.code.encode(op_fn(lhs.0, lhs.0, rhs.0));
self.gpa.free(rhs); self.free_reg(rhs);
self.code.encode(instrs::cmpui(lhs.0, lhs.0, against)); self.code.encode(instrs::cmpui(lhs.0, lhs.0, against));
if matches!(op, T::Eq | T::Lt | T::Gt) { if matches!(op, T::Eq | T::Lt | T::Gt) {
self.code.encode(instrs::not(lhs.0, lhs.0)); self.code.encode(instrs::not(lhs.0, lhs.0));
@ -1130,6 +1143,10 @@ impl<'a> Codegen<'a> {
} }
} }
fn free_reg(&mut self, reg: LinReg) {
self.gpa.free(reg);
}
fn math_op( fn math_op(
op: T, op: T,
signed: bool, signed: bool,
@ -1160,8 +1177,8 @@ impl<'a> Codegen<'a> {
fn free_loc(&mut self, loc: Loc) { fn free_loc(&mut self, loc: Loc) {
match loc { match loc {
Loc::Reg(reg) => self.gpa.free(reg), Loc::Reg(reg) => self.free_reg(reg),
Loc::Deref(reg, ..) => self.gpa.free(reg), Loc::Deref(reg, ..) => self.free_reg(reg),
Loc::Stack(stack, ..) => self.sa.free(stack), Loc::Stack(stack, ..) => self.sa.free(stack),
_ => {} _ => {}
} }
@ -1199,7 +1216,7 @@ impl<'a> Codegen<'a> {
if let Some(op) = Self::math_op(op, signed, size) { if let Some(op) = Self::math_op(op, signed, size) {
self.code.encode(op(lhs, lhs, rhs.0)); self.code.encode(op(lhs, lhs, rhs.0));
self.gpa.free(rhs); self.free_reg(rhs);
return if let Ctx::Dest(dest) = ctx { return if let Ctx::Dest(dest) = ctx {
self.assign(dest.ty, dest.loc, owned.map_or(Loc::RegRef(lhs), Loc::Reg)); self.assign(dest.ty, dest.loc, owned.map_or(Loc::RegRef(lhs), Loc::Reg));
Some(Value::VOID) Some(Value::VOID)
@ -1264,7 +1281,7 @@ impl<'a> Codegen<'a> {
Loc::RegRef(reg) => self.code.encode(instrs::cp(reg, lhs.0)), Loc::RegRef(reg) => self.code.encode(instrs::cp(reg, lhs.0)),
Loc::Deref(reg, off) => { Loc::Deref(reg, off) => {
self.code.encode(instrs::st(lhs.0, reg.0, off, size as _)); self.code.encode(instrs::st(lhs.0, reg.0, off, size as _));
self.gpa.free(reg); self.free_reg(reg);
} }
Loc::DerefRef(reg, off) => { Loc::DerefRef(reg, off) => {
self.code.encode(instrs::st(lhs.0, reg, off, size as _)); self.code.encode(instrs::st(lhs.0, reg, off, size as _));
@ -1275,7 +1292,7 @@ impl<'a> Codegen<'a> {
} }
l => unimplemented!("{:?}", l), l => unimplemented!("{:?}", l),
} }
self.gpa.free(lhs); self.free_reg(lhs);
} }
..=16 if matches!(right, Loc::RegRef(1)) => { ..=16 if matches!(right, Loc::RegRef(1)) => {
let (lhs, loff) = left.ref_to_ptr(); let (lhs, loff) = left.ref_to_ptr();
@ -1288,8 +1305,8 @@ impl<'a> Codegen<'a> {
self.code self.code
.encode(instrs::bmc(lhs.0, rhs.0, size.try_into().unwrap())); .encode(instrs::bmc(lhs.0, rhs.0, size.try_into().unwrap()));
self.gpa.free(lhs); self.free_reg(lhs);
self.gpa.free(rhs); self.free_reg(rhs);
} }
} }

View file

@ -1,3 +1,3 @@
code size: 452 code size: 475
ret: 55 ret: 55
status: Ok(()) status: Ok(())

View file

@ -1,3 +1,3 @@
code size: 331 code size: 318
ret: 0 ret: 0
status: Ok(()) status: Ok(())

View file

@ -1,3 +1,3 @@
code size: 530 code size: 538
ret: 3 ret: 3
status: Ok(()) status: Ok(())