making the variables smarter (only putting then on stack when they get referenced)
This commit is contained in:
parent
8b81cfef37
commit
589a30c8a3
|
@ -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(),
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 997
|
code size: 758
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 475
|
code size: 347
|
||||||
ret: 55
|
ret: 55
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 486
|
code size: 437
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 213
|
code size: 130
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
Loading…
Reference in a new issue