more tests work now

This commit is contained in:
mlokr 2024-09-06 16:11:57 +02:00
parent 4bcab25231
commit b404e5b86d
No known key found for this signature in database
GPG key ID: DEA147DDEE644993
5 changed files with 179 additions and 34 deletions

View file

@ -452,10 +452,10 @@ main := fn(): int {
loop { loop {
if x <= height + 1 { if x <= height + 1 {
set_pixel(x, y, width) _d := set_pixel(x, y, width)
x += 1 x += 1
} else { } else {
set_pixel(x, y, width) _d := set_pixel(x, y, width)
x = 0 x = 0
y += 1 y += 1
} }

View file

@ -8,7 +8,7 @@ use {
parser::{self, find_symbol, idfl, CtorField, Expr, ExprRef, FileId, Pos}, parser::{self, find_symbol, idfl, CtorField, Expr, ExprRef, FileId, Pos},
HashMap, HashMap,
}, },
std::{collections::BTreeMap, fmt::Display, ops::Range, rc::Rc, usize}, std::{collections::BTreeMap, fmt::Display, ops::Range, rc::Rc},
}; };
type Offset = u32; type Offset = u32;
@ -3429,6 +3429,7 @@ mod tests {
use { use {
super::parser, super::parser,
crate::{codegen::LoggedMem, log, parser::FileId}, crate::{codegen::LoggedMem, log, parser::FileId},
core::panic,
std::io, std::io,
}; };
@ -3536,6 +3537,10 @@ mod tests {
3 => vm.write_reg(1, 42), 3 => vm.write_reg(1, 42),
unknown => unreachable!("unknown ecall: {unknown:?}"), unknown => unreachable!("unknown ecall: {unknown:?}"),
}, },
Ok(hbvm::VmRunOk::Timer) => {
writeln!(output, "timed out").unwrap();
break Ok(());
}
Ok(ev) => writeln!(output, "ev: {:?}", ev).unwrap(), Ok(ev) => writeln!(output, "ev: {:?}", ev).unwrap(),
Err(e) => break Err(e), Err(e) => break Err(e),
} }

View file

@ -13,7 +13,8 @@
ptr_metadata, ptr_metadata,
slice_ptr_get, slice_ptr_get,
slice_take, slice_take,
map_try_insert map_try_insert,
extract_if
)] )]
#![allow(internal_features, clippy::format_collect)] #![allow(internal_features, clippy::format_collect)]

View file

@ -18,7 +18,6 @@ use {
mem, mem,
ops::{self, Range}, ops::{self, Range},
rc::Rc, rc::Rc,
usize,
}, },
}; };
@ -98,6 +97,10 @@ mod reg {
pub fn pushed_size(&self) -> usize { pub fn pushed_size(&self) -> usize {
((self.max_used as usize).saturating_sub(RET_ADDR as usize) + 1) * 8 ((self.max_used as usize).saturating_sub(RET_ADDR as usize) + 1) * 8
} }
pub fn mark_leaked(&mut self, reg: u8) {
self.meta.0[reg as usize].rc = u16::MAX;
}
} }
} }
@ -780,7 +783,13 @@ impl Nodes {
fn is_cfg(&self, o: Nid) -> bool { fn is_cfg(&self, o: Nid) -> bool {
matches!( matches!(
self[o].kind, self[o].kind,
Kind::Start | Kind::End | Kind::Return | Kind::Tuple { .. } | Kind::Call { .. } Kind::Start
| Kind::End
| Kind::Return
| Kind::Tuple { .. }
| Kind::Call { .. }
| Kind::Region
| Kind::Loop
) )
} }
@ -948,6 +957,7 @@ struct Variable {
struct ColorMeta { struct ColorMeta {
rc: u32, rc: u32,
depth: u32,
loc: Loc, loc: Loc,
} }
@ -968,6 +978,7 @@ struct ItemCtx {
colors: Vec<ColorMeta>, colors: Vec<ColorMeta>,
call_count: usize, call_count: usize,
filled: Vec<Nid>, filled: Vec<Nid>,
delayed_frees: Vec<u32>,
loops: Vec<Loop>, loops: Vec<Loop>,
vars: Vec<Variable>, vars: Vec<Variable>,
@ -979,11 +990,21 @@ struct ItemCtx {
impl ItemCtx { impl ItemCtx {
fn next_color(&mut self) -> u32 { fn next_color(&mut self) -> u32 {
self.colors.push(ColorMeta { rc: 0, loc: Default::default() }); self.colors.push(ColorMeta { rc: 0, depth: self.loop_depth, loc: Default::default() });
self.colors.len() as _ // leave out 0 (sentinel) self.colors.len() as _ // leave out 0 (sentinel)
} }
fn extend_color(&mut self, color: u32) { fn set_next_color(&mut self, node: Nid) {
let color = self.next_color();
self.set_color(node, color);
}
fn set_color(&mut self, node: Nid, color: u32) {
if self.nodes[node].color != 0 {
debug_assert_ne!(self.nodes[node].color, color);
self.colors[self.nodes[node].color as usize - 1].rc -= 1;
}
self.nodes[node].color = color;
self.colors[color as usize - 1].rc += 1; self.colors[color as usize - 1].rc += 1;
} }
@ -996,16 +1017,38 @@ impl ItemCtx {
return; return;
} }
self.nodes[node].color = to; self.set_color(node, to);
// TODO:
// self.colors[to as usize - 1].rc -= 1;
// self.colors[from as usize - 1].rc -= 1;
for i in 0..self.nodes[node].inputs().len() { for i in 0..self.nodes[node].inputs().len() {
self.recolor(self.nodes[node].inputs[i], from, to); self.recolor(self.nodes[node].inputs[i], from, to);
} }
} }
fn check_color_integrity(&self) {
let node_count = self
.nodes
.values
.iter()
.filter(|v| {
matches!(
v,
PoolSlot::Value(Node {
kind: Kind::BinOp { .. }
| Kind::Call { .. }
| Kind::Phi
| Kind::ConstInt { .. },
..
})
) || matches!(
v,
PoolSlot::Value(Node { kind: Kind::Tuple { index: 1.. }, inputs: [0, ..], .. })
)
})
.count();
let color_count = self.colors.iter().map(|c| c.rc).sum::<u32>();
debug_assert_eq!(node_count, color_count as usize);
}
fn emit(&mut self, instr: (usize, [u8; instrs::MAX_SIZE])) { fn emit(&mut self, instr: (usize, [u8; instrs::MAX_SIZE])) {
emit(&mut self.code, instr); emit(&mut self.code, instr);
} }
@ -1728,9 +1771,11 @@ impl Codegen {
} }
} }
self.ci.nodes.lock(self.ci.ctrl);
for var in self.ci.vars.drain(base..) { for var in self.ci.vars.drain(base..) {
self.ci.nodes.unlock_remove(var.value); self.ci.nodes.unlock_remove(var.value);
} }
self.ci.nodes.unlock(self.ci.ctrl);
ret ret
} }
@ -1836,11 +1881,15 @@ impl Codegen {
'_color_args: { '_color_args: {
for var in &orig_vars { for var in &orig_vars {
if var.id != u32::MAX { if var.id != u32::MAX {
self.ci.nodes[var.value].color = self.ci.next_color(); self.ci.set_next_color(var.value);
} }
} }
} }
self.color_control(self.ci.nodes[self.ci.start].outputs[0]); self.color_control(self.ci.nodes[self.ci.start].outputs[0]);
#[cfg(debug_assertions)]
{
self.ci.check_color_integrity();
}
self.ci.vars = orig_vars; self.ci.vars = orig_vars;
self.emit_control(self.ci.nodes[self.ci.start].outputs[0]); self.emit_control(self.ci.nodes[self.ci.start].outputs[0]);
@ -1892,6 +1941,7 @@ impl Codegen {
1..=8 => Loc { reg: 1 }, 1..=8 => Loc { reg: 1 },
s => todo!("{s}"), s => todo!("{s}"),
}; };
self.ci.regs.mark_leaked(1);
} }
return None; return None;
} }
@ -1903,10 +1953,10 @@ impl Codegen {
Kind::Call { args, .. } => { Kind::Call { args, .. } => {
for &arg in args.iter() { for &arg in args.iter() {
_ = self.color_expr_consume(arg); _ = self.color_expr_consume(arg);
self.ci.nodes[arg].color = self.ci.next_color(); // hack? self.ci.set_next_color(arg);
} }
self.ci.nodes[ctrl].color = self.ci.next_color(); self.ci.set_next_color(ctrl);
ctrl = *self.ci.nodes[ctrl] ctrl = *self.ci.nodes[ctrl]
.outputs .outputs
@ -1958,7 +2008,7 @@ impl Codegen {
_ = self.color_expr_consume(left); _ = self.color_expr_consume(left);
self.ci.nodes[maybe_phy].depth = self.ci.loop_depth; self.ci.nodes[maybe_phy].depth = self.ci.loop_depth;
self.ci.nodes[maybe_phy].color = self.ci.next_color(); self.ci.set_next_color(maybe_phy);
} }
self.ci.nodes[ctrl].lock_rc = self.ci.code.len() as _; self.ci.nodes[ctrl].lock_rc = self.ci.code.len() as _;
@ -2004,7 +2054,7 @@ impl Codegen {
// self.ci.recolor(right, c, self.ci.nodes[maybe_phy].color); // self.ci.recolor(right, c, self.ci.nodes[maybe_phy].color);
//} //}
} else { } else {
self.ci.nodes[maybe_phy].color = match (lcolor, rcolor) { let color = match (lcolor, rcolor) {
(None, None) => self.ci.next_color(), (None, None) => self.ci.next_color(),
(None, Some(c)) | (Some(c), None) => c, (None, Some(c)) | (Some(c), None) => c,
(Some(lc), Some(rc)) => { (Some(lc), Some(rc)) => {
@ -2012,6 +2062,7 @@ impl Codegen {
lc lc
} }
}; };
self.ci.set_color(maybe_phy, color);
} }
} }
@ -2029,17 +2080,16 @@ impl Codegen {
Kind::Start => unreachable!(), Kind::Start => unreachable!(),
Kind::End => unreachable!(), Kind::End => unreachable!(),
Kind::Return => unreachable!(), Kind::Return => unreachable!(),
Kind::ConstInt { .. } => self.ci.nodes[expr].color = self.ci.next_color(), Kind::ConstInt { .. } => self.ci.set_next_color(expr),
Kind::Tuple { index } => { Kind::Tuple { index } => {
debug_assert!(index != 0); debug_assert!(index != 0);
} }
Kind::BinOp { op } => { Kind::BinOp { .. } => {
let [left, right, ..] = self.ci.nodes[expr].inputs; let [left, right, ..] = self.ci.nodes[expr].inputs;
let lcolor = self.color_expr_consume(left); let lcolor = self.color_expr_consume(left);
let rcolor = self.color_expr_consume(right); let rcolor = self.color_expr_consume(right);
let color = lcolor.or(rcolor).unwrap_or_else(|| self.ci.next_color());
self.ci.nodes[expr].color = self.ci.set_color(expr, color);
lcolor.or(rcolor).unwrap_or_else(|| self.ci.next_color());
} }
Kind::Call { .. } => {} Kind::Call { .. } => {}
Kind::If => todo!(), Kind::If => todo!(),
@ -2086,6 +2136,7 @@ impl Codegen {
1..=8 => Loc { reg: parama.next() }, 1..=8 => Loc { reg: parama.next() },
s => todo!("{s}"), s => todo!("{s}"),
}; };
self.ci.regs.mark_leaked(node_loc!(self, arg).reg);
self.emit_expr_consume(arg); self.emit_expr_consume(arg);
} }
@ -2156,7 +2207,7 @@ impl Codegen {
let filled_base = self.ci.filled.len(); let filled_base = self.ci.filled.len();
let left_unreachable = self.emit_control(self.ci.nodes[ctrl].outputs[0]); let left_unreachable = self.emit_control(self.ci.nodes[ctrl].outputs[0]);
for fld in self.ci.filled.drain(filled_base..) { for fld in self.ci.filled.drain(filled_base..) {
self.ci.nodes[fld].lock_rc = 1; self.ci.nodes[fld].depth = 0;
} }
let mut skip_then_offset = self.ci.code.len() as i64; let mut skip_then_offset = self.ci.code.len() as i64;
if let Some(region) = left_unreachable { if let Some(region) = left_unreachable {
@ -2179,7 +2230,7 @@ impl Codegen {
let right_unreachable = self.emit_control(self.ci.nodes[ctrl].outputs[1]); let right_unreachable = self.emit_control(self.ci.nodes[ctrl].outputs[1]);
for fld in self.ci.filled.drain(filled_base..) { for fld in self.ci.filled.drain(filled_base..) {
self.ci.nodes[fld].lock_rc = 1; self.ci.nodes[fld].depth = 0;
} }
if let Some(region) = left_unreachable { if let Some(region) = left_unreachable {
for i in 0..self.ci.nodes[region].outputs.len() { for i in 0..self.ci.nodes[region].outputs.len() {
@ -2245,6 +2296,7 @@ impl Codegen {
} }
self.ci.nodes[ctrl].lock_rc = self.ci.code.len() as _; self.ci.nodes[ctrl].lock_rc = self.ci.code.len() as _;
self.ci.loop_depth += 1;
let end = self.emit_control( let end = self.emit_control(
*self.ci.nodes[ctrl] *self.ci.nodes[ctrl]
@ -2280,6 +2332,15 @@ impl Codegen {
self.ci.nodes[ctrl].lock_rc as i32 - self.ci.code.len() as i32, self.ci.nodes[ctrl].lock_rc as i32 - self.ci.code.len() as i32,
)); ));
self.ci.loop_depth -= 1;
for free in self.ci.delayed_frees.extract_if(|&mut color| {
self.ci.colors[color as usize].depth == self.ci.loop_depth
}) {
let color = &self.ci.colors[free as usize];
debug_assert_ne!(color.loc, Loc::default());
self.ci.regs.free(color.loc.reg);
}
return None; return None;
} }
} }
@ -2290,13 +2351,14 @@ impl Codegen {
fn emit_expr_consume(&mut self, expr: Nid) { fn emit_expr_consume(&mut self, expr: Nid) {
self.emit_expr(expr); self.emit_expr(expr);
self.use_expr(expr) self.use_expr(expr);
} }
fn emit_expr(&mut self, expr: Nid) { fn emit_expr(&mut self, expr: Nid) {
if std::mem::take(&mut self.ci.nodes[expr].lock_rc) == 0 { if self.ci.nodes[expr].depth == u32::MAX {
return; return;
} }
self.ci.nodes[expr].depth = u32::MAX;
self.ci.filled.push(expr); self.ci.filled.push(expr);
match self.ci.nodes[expr].kind { match self.ci.nodes[expr].kind {
@ -2344,7 +2406,7 @@ impl Codegen {
if let Kind::ConstInt { value } = self.ci.nodes[right].kind if let Kind::ConstInt { value } = self.ci.nodes[right].kind
&& (node_loc!(self, right) == Loc::default() && (node_loc!(self, right) == Loc::default()
|| self.ci.nodes[right].lock_rc != 0) || self.ci.nodes[right].depth != u32::MAX)
&& let Some(op) = Self::imm_math_op(op, ty.is_signed(), self.tys.size_of(ty)) && let Some(op) = Self::imm_math_op(op, ty.is_signed(), self.tys.size_of(ty))
{ {
let instr = let instr =
@ -2372,7 +2434,24 @@ impl Codegen {
} }
} }
fn use_expr(&mut self, _expr: Nid) {} fn use_expr(&mut self, expr: Nid) {
let node = &mut self.ci.nodes[expr];
node.lock_rc = node.lock_rc.saturating_sub(1);
if node.lock_rc != 0 {
return;
}
let color = &mut self.ci.colors[node.color as usize - 1];
color.rc -= 1;
if color.rc == 0 {
if color.depth != self.ci.loop_depth {
self.ci.delayed_frees.push(node.color);
} else {
debug_assert_ne!(color.loc, Loc::default(), "{:?}", node);
self.ci.regs.free(color.loc.reg);
}
}
}
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
fn imm_math_op( fn imm_math_op(
@ -2564,13 +2643,15 @@ impl Codegen {
fn report_log(&self, pos: Pos, msg: impl std::fmt::Display) { fn report_log(&self, pos: Pos, msg: impl std::fmt::Display) {
let str = &self.cfile().file; let str = &self.cfile().file;
let (line, col) = lexer::line_col(str.as_bytes(), pos); let (line, mut col) = lexer::line_col(str.as_bytes(), pos);
println!("{}:{}:{}: {}", self.cfile().path, line, col, msg); println!("{}:{}:{}: {}", self.cfile().path, line, col, msg);
let line = str[str[..pos as usize].rfind('\n').map_or(0, |i| i + 1) let line = &str[str[..pos as usize].rfind('\n').map_or(0, |i| i + 1)
..str[pos as usize..].find('\n').unwrap_or(str.len())] ..str[pos as usize..].find('\n').unwrap_or(str.len()) + pos as usize];
.replace("\t", " "); col += line.matches('\t').count() * 3;
println!("{line}");
println!("{}", line.replace("\t", " "));
println!("{}^", " ".repeat(col - 1))
} }
#[track_caller] #[track_caller]
@ -2837,7 +2918,7 @@ mod tests {
comments => README; comments => README;
if_statements => README; if_statements => README;
loops => README; loops => README;
//fb_driver => README; fb_driver => README;
//pointers => README; //pointers => README;
//structs => README; //structs => README;
//different_types => README; //different_types => README;

View file

@ -0,0 +1,58 @@
main:
ADDI64 r254, r254, -96d
ST r31, r254, 0a, 96h
JAL r31, r0, :check_platform
LI64 r1, 0d
CP r32, r1
LI64 r33, 30d
CP r34, r33
LI64 r35, 100d
CP r36, r35
CP r37, r32
CP r38, r36
4: ADDI64 r39, r34, 1d
JGTS r32, r39, :0
JAL r31, r0, :set_pixel
CP r40, r4
ADDI64 r41, r3, 1d
CP r42, r3
JMP :1
0: JAL r31, r0, :set_pixel
CP r40, r4
CP r41, r1
ADDI64 r42, r3, 1d
1: JNE r42, r40, :2
JMP :3
2: CP r2, r41
CP r34, r33
CP r4, r35
CP r3, r42
CP r4, r40
JMP :4
3: LD r31, r254, 0a, 96h
ADDI64 r254, r254, 96d
JALA r0, r31, 0a
set_pixel:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
LI64 r1, 0d
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
check_platform:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
JAL r31, r0, :x86_fb_ptr
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
x86_fb_ptr:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
LI64 r1, 100d
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
code size: 422
ret: 0
status: Ok(())