1
0
Fork 0
forked from koniifer/ableos

making the variables smarter (only putting then on stack when they get referenced)

This commit is contained in:
mlokr 2024-05-16 12:23:37 +02:00
parent 8b81cfef37
commit 589a30c8a3
6 changed files with 88 additions and 32 deletions

View file

@ -984,14 +984,14 @@ impl<'a> Codegen<'a> {
} }
} }
E::BinOp { E::BinOp {
left: E::Ident { id, .. }, left: E::Ident { id, last, .. },
op: T::Decl, op: T::Decl,
right, right,
} => { } => {
let val = self.expr(right)?; let val = self.expr(right)?;
let loc = self.make_loc_owned(val.loc, val.ty); let loc = self.make_loc_owned(val.loc, val.ty);
let loc = match loc { let loc = match loc {
Loc::Reg(r) => { Loc::Reg(r) if last.is_some_and(|l| l.get() & parser::REFERENCED != 0) => {
let size = self.size_of(val.ty); let size = self.size_of(val.ty);
let stack = self.alloc_stack(size); let stack = self.alloc_stack(size);
self.store_stack(r.0, stack.offset, size as _); self.store_stack(r.0, stack.offset, size as _);
@ -1033,14 +1033,20 @@ impl<'a> Codegen<'a> {
loc, loc,
}); });
} }
E::Ident { name, id, last } => { E::Ident {
let Some((index, var)) = self.vars.iter_mut().enumerate().find(|(_, v)| v.id == id) name,
id,
last,
index,
} => {
let Some((var_index, var)) =
self.vars.iter_mut().enumerate().find(|(_, v)| v.id == id)
else { 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(|l| parser::ident_flag_index(l.get()) == index)
&& !self.loops.last().is_some_and(|l| l.var_count > index) && !self.loops.last().is_some_and(|l| l.var_count > var_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(),

View file

@ -8,10 +8,19 @@ use crate::{
pub type Pos = u32; pub type Pos = u32;
pub type IdentFlags = u32;
pub const MUTABLE: IdentFlags = 1 << std::mem::size_of::<IdentFlags>() * 8 - 1;
pub const REFERENCED: IdentFlags = 1 << std::mem::size_of::<IdentFlags>() * 8 - 2;
pub fn ident_flag_index(flag: IdentFlags) -> u32 {
flag & !(MUTABLE | REFERENCED)
}
struct ScopeIdent<'a> { struct ScopeIdent<'a> {
ident: Ident, ident: Ident,
declared: bool, declared: bool,
last: &'a Cell<bool>, last: &'a Cell<IdentFlags>,
} }
pub struct Parser<'a, 'b> { pub struct Parser<'a, 'b> {
@ -20,6 +29,7 @@ pub struct Parser<'a, 'b> {
arena: &'b Arena<'a>, arena: &'b Arena<'a>,
token: Token, token: Token,
idents: Vec<ScopeIdent<'a>>, idents: Vec<ScopeIdent<'a>>,
referening: bool,
} }
impl<'a, 'b> Parser<'a, 'b> { impl<'a, 'b> Parser<'a, 'b> {
@ -32,6 +42,7 @@ impl<'a, 'b> Parser<'a, 'b> {
path: "", path: "",
arena, arena,
idents: Vec::new(), idents: Vec::new(),
referening: false,
} }
} }
@ -91,6 +102,7 @@ impl<'a, 'b> Parser<'a, 'b> {
let left = &*self.arena.alloc(fold); let left = &*self.arena.alloc(fold);
if let Some(op) = op.assign_op() { if let Some(op) = op.assign_op() {
fold.mark_mut();
let right = Expr::BinOp { left, op, right }; let right = Expr::BinOp { left, op, right };
fold = Expr::BinOp { fold = Expr::BinOp {
left, left,
@ -99,6 +111,9 @@ impl<'a, 'b> Parser<'a, 'b> {
}; };
} else { } else {
fold = Expr::BinOp { left, right, op }; fold = Expr::BinOp { left, right, op };
if op == TokenKind::Assign {
fold.mark_mut();
}
} }
} }
@ -122,14 +137,13 @@ impl<'a, 'b> Parser<'a, 'b> {
}) })
} }
fn resolve_ident(&mut self, token: Token, decl: bool) -> (Ident, Option<&'a Cell<bool>>) { fn resolve_ident(&mut self, token: Token, decl: bool) -> (Ident, Option<&'a Cell<IdentFlags>>) {
let name = self.lexer.slice(token.range()); let name = self.lexer.slice(token.range());
if let Some(builtin) = Self::try_resolve_builtin(name) { if let Some(builtin) = Self::try_resolve_builtin(name) {
return (builtin, None); return (builtin, None);
} }
let last = self.arena.alloc(Cell::new(false));
let id = match self let id = match self
.idents .idents
.iter_mut() .iter_mut()
@ -138,8 +152,12 @@ impl<'a, 'b> Parser<'a, 'b> {
Some(elem) if decl && elem.declared => { Some(elem) if decl && elem.declared => {
self.report(format_args!("redeclaration of identifier: {name}")) self.report(format_args!("redeclaration of identifier: {name}"))
} }
Some(elem) => elem, Some(elem) => {
elem.last.set(elem.last.get() + 1);
elem
}
None => { None => {
let last = self.arena.alloc(Cell::new(0));
let id = ident::new(token.start, name.len() as _); let id = ident::new(token.start, name.len() as _);
self.idents.push(ScopeIdent { self.idents.push(ScopeIdent {
ident: id, ident: id,
@ -150,10 +168,11 @@ impl<'a, 'b> Parser<'a, 'b> {
} }
}; };
id.last = last;
id.declared |= decl; id.declared |= decl;
id.last
.set(id.last.get() | (REFERENCED * self.referening as u32));
(id.ident, Some(last)) (id.ident, Some(id.last))
} }
fn unit_expr(&mut self) -> Expr<'a> { fn unit_expr(&mut self) -> Expr<'a> {
@ -187,8 +206,12 @@ impl<'a, 'b> Parser<'a, 'b> {
}, },
T::Ident => { T::Ident => {
let (id, last) = self.resolve_ident(token, self.token.kind == T::Decl); let (id, last) = self.resolve_ident(token, self.token.kind == T::Decl);
let name = self.lexer.slice(token.range()); E::Ident {
E::Ident { name, id, last } name: self.lexer.slice(token.range()),
id,
last,
index: last.map_or(0, |l| ident_flag_index(l.get())),
}
} }
T::If => E::If { T::If => E::If {
pos: token.start, pos: token.start,
@ -231,7 +254,10 @@ impl<'a, 'b> Parser<'a, 'b> {
T::Band | T::Mul => E::UnOp { T::Band | T::Mul => E::UnOp {
pos: token.start, pos: token.start,
op: token.kind, op: token.kind,
val: self.ptr_unit_expr(), val: match token.kind {
T::Band => self.referenced(Self::ptr_unit_expr),
_ => self.ptr_unit_expr(),
},
}, },
T::LBrace => E::Block { T::LBrace => E::Block {
pos: token.start, pos: token.start,
@ -261,7 +287,9 @@ impl<'a, 'b> Parser<'a, 'b> {
expr = match token.kind { expr = match token.kind {
T::LParen => Expr::Call { T::LParen => Expr::Call {
func: self.arena.alloc(expr), func: self.arena.alloc(expr),
args: self.collect_list(T::Comma, T::RParen, Self::expr), args: self
.calcel_ref()
.collect_list(T::Comma, T::RParen, Self::expr),
}, },
T::Ctor => E::Ctor { T::Ctor => E::Ctor {
pos: token.start, pos: token.start,
@ -300,6 +328,16 @@ impl<'a, 'b> Parser<'a, 'b> {
expr expr
} }
fn referenced<T>(&mut self, f: impl Fn(&mut Self) -> T) -> T {
if self.referening {
self.report("cannot take reference of reference, (souwy)");
}
self.referening = true;
let expr = f(self);
self.referening = false;
expr
}
fn pop_scope(&mut self, frame: usize) { fn pop_scope(&mut self, frame: usize) {
let mut undeclared_count = frame; let mut undeclared_count = frame;
for i in frame..self.idents.len() { for i in frame..self.idents.len() {
@ -309,9 +347,7 @@ impl<'a, 'b> Parser<'a, 'b> {
} }
} }
for id in self.idents.drain(undeclared_count..) { self.idents.drain(undeclared_count..);
id.last.set(true);
}
} }
fn ptr_unit_expr(&mut self) -> &'a Expr<'a> { fn ptr_unit_expr(&mut self) -> &'a Expr<'a> {
@ -362,13 +398,18 @@ impl<'a, 'b> Parser<'a, 'b> {
eprintln!("{}:{}:{} => {}", self.path, line, col, msg); eprintln!("{}:{}:{} => {}", self.path, line, col, msg);
unreachable!(); unreachable!();
} }
fn calcel_ref(&mut self) -> &mut Self {
self.referening = false;
self
}
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Arg<'a> { pub struct Arg<'a> {
pub name: &'a str, pub name: &'a str,
pub id: Ident, pub id: Ident,
pub last: Option<&'a Cell<bool>>, pub last: Option<&'a Cell<IdentFlags>>,
pub ty: Expr<'a>, pub ty: Expr<'a>,
} }
@ -397,7 +438,8 @@ pub enum Expr<'a> {
Ident { Ident {
name: &'a str, name: &'a str,
id: Ident, id: Ident,
last: Option<&'a Cell<bool>>, index: u32,
last: Option<&'a Cell<IdentFlags>>,
}, },
Block { Block {
pos: Pos, pos: Pos,
@ -473,6 +515,14 @@ impl<'a> Expr<'a> {
Self::Field { target, .. } => target.pos(), Self::Field { target, .. } => target.pos(),
} }
} }
fn mark_mut(&self) {
match self {
Self::Ident { last, .. } => _ = last.map(|l| l.set(l.get() | MUTABLE)),
Self::Field { target, .. } => target.mark_mut(),
_ => {}
}
}
} }
impl<'a> std::fmt::Display for Expr<'a> { impl<'a> std::fmt::Display for Expr<'a> {

View file

@ -1,3 +1,3 @@
code size: 997 code size: 758
ret: 0 ret: 0
status: Ok(()) status: Ok(())

View file

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

View file

@ -1,3 +1,3 @@
code size: 486 code size: 437
ret: 0 ret: 0
status: Ok(()) status: Ok(())

View file

@ -1,3 +1,3 @@
code size: 213 code size: 130
ret: 0 ret: 0
status: Ok(()) status: Ok(())