more tests work now
This commit is contained in:
parent
4bcab25231
commit
b404e5b86d
|
@ -452,10 +452,10 @@ main := fn(): int {
|
|||
|
||||
loop {
|
||||
if x <= height + 1 {
|
||||
set_pixel(x, y, width)
|
||||
_d := set_pixel(x, y, width)
|
||||
x += 1
|
||||
} else {
|
||||
set_pixel(x, y, width)
|
||||
_d := set_pixel(x, y, width)
|
||||
x = 0
|
||||
y += 1
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use {
|
|||
parser::{self, find_symbol, idfl, CtorField, Expr, ExprRef, FileId, Pos},
|
||||
HashMap,
|
||||
},
|
||||
std::{collections::BTreeMap, fmt::Display, ops::Range, rc::Rc, usize},
|
||||
std::{collections::BTreeMap, fmt::Display, ops::Range, rc::Rc},
|
||||
};
|
||||
|
||||
type Offset = u32;
|
||||
|
@ -3429,6 +3429,7 @@ mod tests {
|
|||
use {
|
||||
super::parser,
|
||||
crate::{codegen::LoggedMem, log, parser::FileId},
|
||||
core::panic,
|
||||
std::io,
|
||||
};
|
||||
|
||||
|
@ -3536,6 +3537,10 @@ mod tests {
|
|||
3 => vm.write_reg(1, 42),
|
||||
unknown => unreachable!("unknown ecall: {unknown:?}"),
|
||||
},
|
||||
Ok(hbvm::VmRunOk::Timer) => {
|
||||
writeln!(output, "timed out").unwrap();
|
||||
break Ok(());
|
||||
}
|
||||
Ok(ev) => writeln!(output, "ev: {:?}", ev).unwrap(),
|
||||
Err(e) => break Err(e),
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
ptr_metadata,
|
||||
slice_ptr_get,
|
||||
slice_take,
|
||||
map_try_insert
|
||||
map_try_insert,
|
||||
extract_if
|
||||
)]
|
||||
#![allow(internal_features, clippy::format_collect)]
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ use {
|
|||
mem,
|
||||
ops::{self, Range},
|
||||
rc::Rc,
|
||||
usize,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -98,6 +97,10 @@ mod reg {
|
|||
pub fn pushed_size(&self) -> usize {
|
||||
((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 {
|
||||
matches!(
|
||||
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 {
|
||||
rc: u32,
|
||||
depth: u32,
|
||||
loc: Loc,
|
||||
}
|
||||
|
||||
|
@ -968,6 +978,7 @@ struct ItemCtx {
|
|||
colors: Vec<ColorMeta>,
|
||||
call_count: usize,
|
||||
filled: Vec<Nid>,
|
||||
delayed_frees: Vec<u32>,
|
||||
|
||||
loops: Vec<Loop>,
|
||||
vars: Vec<Variable>,
|
||||
|
@ -979,11 +990,21 @@ struct ItemCtx {
|
|||
|
||||
impl ItemCtx {
|
||||
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)
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -996,16 +1017,38 @@ impl ItemCtx {
|
|||
return;
|
||||
}
|
||||
|
||||
self.nodes[node].color = to;
|
||||
// TODO:
|
||||
// self.colors[to as usize - 1].rc -= 1;
|
||||
// self.colors[from as usize - 1].rc -= 1;
|
||||
self.set_color(node, to);
|
||||
|
||||
for i in 0..self.nodes[node].inputs().len() {
|
||||
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])) {
|
||||
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..) {
|
||||
self.ci.nodes.unlock_remove(var.value);
|
||||
}
|
||||
self.ci.nodes.unlock(self.ci.ctrl);
|
||||
|
||||
ret
|
||||
}
|
||||
|
@ -1836,11 +1881,15 @@ impl Codegen {
|
|||
'_color_args: {
|
||||
for var in &orig_vars {
|
||||
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]);
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
self.ci.check_color_integrity();
|
||||
}
|
||||
|
||||
self.ci.vars = orig_vars;
|
||||
self.emit_control(self.ci.nodes[self.ci.start].outputs[0]);
|
||||
|
@ -1892,6 +1941,7 @@ impl Codegen {
|
|||
1..=8 => Loc { reg: 1 },
|
||||
s => todo!("{s}"),
|
||||
};
|
||||
self.ci.regs.mark_leaked(1);
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
@ -1903,10 +1953,10 @@ impl Codegen {
|
|||
Kind::Call { args, .. } => {
|
||||
for &arg in args.iter() {
|
||||
_ = 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]
|
||||
.outputs
|
||||
|
@ -1958,7 +2008,7 @@ impl Codegen {
|
|||
|
||||
_ = self.color_expr_consume(left);
|
||||
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 _;
|
||||
|
@ -2004,7 +2054,7 @@ impl Codegen {
|
|||
// self.ci.recolor(right, c, self.ci.nodes[maybe_phy].color);
|
||||
//}
|
||||
} else {
|
||||
self.ci.nodes[maybe_phy].color = match (lcolor, rcolor) {
|
||||
let color = match (lcolor, rcolor) {
|
||||
(None, None) => self.ci.next_color(),
|
||||
(None, Some(c)) | (Some(c), None) => c,
|
||||
(Some(lc), Some(rc)) => {
|
||||
|
@ -2012,6 +2062,7 @@ impl Codegen {
|
|||
lc
|
||||
}
|
||||
};
|
||||
self.ci.set_color(maybe_phy, color);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2029,17 +2080,16 @@ impl Codegen {
|
|||
Kind::Start => unreachable!(),
|
||||
Kind::End => 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 } => {
|
||||
debug_assert!(index != 0);
|
||||
}
|
||||
Kind::BinOp { op } => {
|
||||
Kind::BinOp { .. } => {
|
||||
let [left, right, ..] = self.ci.nodes[expr].inputs;
|
||||
let lcolor = self.color_expr_consume(left);
|
||||
let rcolor = self.color_expr_consume(right);
|
||||
|
||||
self.ci.nodes[expr].color =
|
||||
lcolor.or(rcolor).unwrap_or_else(|| self.ci.next_color());
|
||||
let color = lcolor.or(rcolor).unwrap_or_else(|| self.ci.next_color());
|
||||
self.ci.set_color(expr, color);
|
||||
}
|
||||
Kind::Call { .. } => {}
|
||||
Kind::If => todo!(),
|
||||
|
@ -2086,6 +2136,7 @@ impl Codegen {
|
|||
1..=8 => Loc { reg: parama.next() },
|
||||
s => todo!("{s}"),
|
||||
};
|
||||
self.ci.regs.mark_leaked(node_loc!(self, arg).reg);
|
||||
self.emit_expr_consume(arg);
|
||||
}
|
||||
|
||||
|
@ -2156,7 +2207,7 @@ impl Codegen {
|
|||
let filled_base = self.ci.filled.len();
|
||||
let left_unreachable = self.emit_control(self.ci.nodes[ctrl].outputs[0]);
|
||||
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;
|
||||
if let Some(region) = left_unreachable {
|
||||
|
@ -2179,7 +2230,7 @@ impl Codegen {
|
|||
let right_unreachable = self.emit_control(self.ci.nodes[ctrl].outputs[1]);
|
||||
|
||||
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 {
|
||||
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.loop_depth += 1;
|
||||
|
||||
let end = self.emit_control(
|
||||
*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.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;
|
||||
}
|
||||
}
|
||||
|
@ -2290,13 +2351,14 @@ impl Codegen {
|
|||
|
||||
fn emit_expr_consume(&mut self, expr: Nid) {
|
||||
self.emit_expr(expr);
|
||||
self.use_expr(expr)
|
||||
self.use_expr(expr);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
self.ci.nodes[expr].depth = u32::MAX;
|
||||
self.ci.filled.push(expr);
|
||||
|
||||
match self.ci.nodes[expr].kind {
|
||||
|
@ -2344,7 +2406,7 @@ impl Codegen {
|
|||
|
||||
if let Kind::ConstInt { value } = self.ci.nodes[right].kind
|
||||
&& (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 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)]
|
||||
fn imm_math_op(
|
||||
|
@ -2564,13 +2643,15 @@ impl Codegen {
|
|||
|
||||
fn report_log(&self, pos: Pos, msg: impl std::fmt::Display) {
|
||||
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);
|
||||
|
||||
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())]
|
||||
.replace("\t", " ");
|
||||
println!("{line}");
|
||||
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()) + pos as usize];
|
||||
col += line.matches('\t').count() * 3;
|
||||
|
||||
println!("{}", line.replace("\t", " "));
|
||||
println!("{}^", " ".repeat(col - 1))
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
|
@ -2837,7 +2918,7 @@ mod tests {
|
|||
comments => README;
|
||||
if_statements => README;
|
||||
loops => README;
|
||||
//fb_driver => README;
|
||||
fb_driver => README;
|
||||
//pointers => README;
|
||||
//structs => README;
|
||||
//different_types => README;
|
||||
|
|
58
hblang/tests/son_tests_fb_driver.txt
Normal file
58
hblang/tests/son_tests_fb_driver.txt
Normal 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(())
|
Loading…
Reference in a new issue