should work better

This commit is contained in:
Jakub Doka 2024-10-23 12:26:07 +02:00
parent f013e90936
commit 41b70bec43
No known key found for this signature in database
GPG key ID: C6E9A89936B8C143
6 changed files with 213 additions and 91 deletions

View file

@ -743,8 +743,8 @@ rect_line := fn(buffer: Buffer, pos: Point, tr: Transform, color: ColorBGRA, thi
y = pos.y
x = pos.x
loop if y == pos.y + tr.x break else {
a := 1 + @inline(screenidx, 10)
a = 1 + @inline(screenidx, 2)
//a := 1 + @inline(screenidx, 10)
//a = 1 + @inline(screenidx, 2)
y += 1
}
t += 1
@ -958,7 +958,15 @@ main := fn(): int {
return 6
}
f := 0
loop {
if f == 1 {
f = 0
} else {
f = 1
}
f = continue_and_state_change(0)
}
}

View file

@ -94,6 +94,12 @@ pub fn run_compiler(root_file: &str, options: Options, out: &mut Vec<u8>) -> std
codegen.push_embeds(parsed.embeds);
codegen.generate(0);
if !codegen.errors.borrow().is_empty() {
log::error!("{}", codegen.errors.borrow());
return Err(std::io::Error::other("compilation faoled"));
}
if options.dump_asm {
codegen
.disasm(unsafe { std::mem::transmute::<&mut Vec<u8>, &mut String>(out) })

View file

@ -3,7 +3,7 @@ fn main() -> std::io::Result<()> {
use std::io::Write;
log::set_logger(&hblang::Logger).unwrap();
log::set_max_level(log::LevelFilter::Error);
log::set_max_level(log::LevelFilter::Info);
let args = std::env::args().collect::<Vec<_>>();
let args = args.iter().map(String::as_str).collect::<Vec<_>>();

View file

@ -27,7 +27,7 @@ use {
hashbrown::hash_map,
hbbytecode::DisasmError,
regalloc2::VReg,
std::{borrow::ToOwned, panic},
std::borrow::ToOwned,
};
const VOID: Nid = 0;
@ -108,39 +108,41 @@ impl Nodes {
for (i, node) in self.iter() {
let color = match () {
_ if self[i].lock_rc != 0 => "red",
_ if self[i].outputs.is_empty() => "purple",
_ if self[i].is_mem() => "green",
_ if node.lock_rc == Nid::MAX => "orange",
_ if node.lock_rc == Nid::MAX - 1 => "blue",
_ if node.lock_rc != 0 => "red",
_ if node.outputs.is_empty() => "purple",
_ if node.is_mem() => "green",
_ if self.is_cfg(i) => "yellow",
_ => "white",
};
let mut dest = i;
let mut index_override = None;
let dest = i;
//let mut index_override = None;
if !matches!(node.kind, Kind::Then | Kind::Else) {
//if !matches!(node.kind, Kind::Then | Kind::Else) {
if node.ty != ty::Id::VOID {
writeln!(
out,
" node{i}[label=\"{} {}\" color={color}]",
" node{i}[label=\"{i} {} {}\" color={color}]",
node.kind,
ty::Display::new(tys, files, node.ty)
)?;
} else {
writeln!(out, " node{i}[label=\"{}\" color={color}]", node.kind,)?;
writeln!(out, " node{i}[label=\"{i} {}\" color={color}]", node.kind,)?;
}
} else {
dest = node.inputs[0];
//} else {
// dest = node.inputs[0];
index_override = if node.kind == Kind::Then { Some(0) } else { Some(1) };
}
// index_override = if node.kind == Kind::Then { Some(0) } else { Some(1) };
//}
if node.kind == Kind::If {
continue;
}
//if node.kind == Kind::If {
// continue;
//}
for (j, &o) in node.outputs.iter().enumerate() {
let j = index_override.unwrap_or(j);
//let j = index_override.unwrap_or(j);
let color = if self.is_cfg(i) && self.is_cfg(o) { "red" } else { "lightgray" };
let index = self[o].inputs.iter().position(|&inp| i == inp).unwrap();
let style = if index == 0 && !self.is_cfg(o) { "style=dotted" } else { "" };
@ -205,6 +207,26 @@ impl Nodes {
let node =
Node { ralloc_backref: u16::MAX, inputs: inps.into(), kind, ty, ..Default::default() };
if node.kind == Kind::Phi && node.ty != ty::Id::VOID {
debug_assert_ne!(
self[node.inputs[1]].ty,
ty::Id::VOID,
"{:?} {:?}",
self[node.inputs[1]],
node.ty.expand(),
);
if self[node.inputs[0]].kind != Kind::Loop {
debug_assert_ne!(
self[node.inputs[2]].ty,
ty::Id::VOID,
"{:?} {:?}",
self[node.inputs[2]],
node.ty.expand(),
);
}
}
let mut lookup_meta = None;
if !node.is_not_gvnd() {
let (raw_entry, hash) = self.lookup.entry(node.key(), &self.values);
@ -857,6 +879,7 @@ impl Nodes {
self.values.iter_mut().flat_map(Result::as_mut)
}
#[allow(dead_code)]
fn eliminate_stack_temporaries(&mut self) {
if !cfg!(debug_assertions) {
return;
@ -1192,7 +1215,7 @@ mod var {
impl Scope {
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Variable> {
self.vars.iter_mut().chain(core::iter::once(&mut self.store))
core::iter::once(&mut self.store).chain(self.vars.iter_mut())
}
pub fn dup(&self, nodes: &mut Nodes) -> Self {
@ -1216,8 +1239,9 @@ struct ItemCtx {
file: FileId,
ret: Option<ty::Id>,
task_base: usize,
inline_var_base: usize,
inline_depth: u16,
inline_ret: Option<(Value, Nid)>,
inline_ret: Option<(Value, Nid, Scope)>,
nodes: Nodes,
ctrl: Nid,
call_count: u16,
@ -1290,6 +1314,10 @@ impl ItemCtx {
};
regalloc2::run_with_ctx(&fuc, &ralloc.env, &options, &mut ralloc.ctx).unwrap_or_else(
|err| {
if let regalloc2::RegAllocError::SSA(vreg, inst) = err {
fuc.nodes[vreg.vreg() as Nid].lock_rc = Nid::MAX;
fuc.nodes[fuc.instrs[inst.index()].nid].lock_rc = Nid::MAX - 1;
}
fuc.nodes.graphviz_in_browser(tys, files);
panic!("{err}")
},
@ -1794,7 +1822,7 @@ pub struct Codegen<'a> {
#[expect(dead_code)]
ralloc: Regalloc,
ct: Comptime,
errors: RefCell<String>,
pub errors: RefCell<String>,
}
impl TypeParser for Codegen<'_> {
@ -2018,8 +2046,16 @@ impl<'a> Codegen<'a> {
fn load_mem(&mut self, region: Nid, ty: ty::Id) -> Nid {
debug_assert_ne!(region, VOID);
debug_assert_ne!({ self.ci.nodes[region].ty }, ty::Id::VOID, "{:?}", {
self.ci.nodes[region].lock_rc = Nid::MAX;
self.ci.nodes.graphviz_in_browser(&self.tys, self.files);
});
debug_assert!(
self.ci.nodes[region].kind != Kind::Load || self.ci.nodes[region].ty.is_pointer()
self.ci.nodes[region].kind != Kind::Load || self.ci.nodes[region].ty.is_pointer(),
"{:?} {} {}",
self.ci.nodes.graphviz_in_browser(&self.tys, self.files),
self.cfile().path,
self.ty_display(self.ci.nodes[region].ty)
);
debug_assert!(self.ci.nodes[region].kind != Kind::Stre);
let mut vc = Vc::from([VOID, region]);
@ -2095,7 +2131,7 @@ impl<'a> Codegen<'a> {
if let Some(index) = self.ci.scope.vars.iter().rposition(|v| v.id == id) =>
{
let var = &mut self.ci.scope.vars[index];
self.ci.nodes.load_loop_var(index, var, &mut self.ci.loops);
self.ci.nodes.load_loop_var(index + 1, var, &mut self.ci.loops);
Some(Value::var(index).ty(var.ty))
}
@ -2108,10 +2144,7 @@ impl<'a> Codegen<'a> {
let value = self.ci.nodes.new_node(gl.ty, Kind::Global { global }, [VOID]);
Some(Value::ptr(value).ty(gl.ty))
}
_ => self.report_unhandled_ast(
expr,
format_args!("identifier evaluated to '{}'", self.ty_display(decl)),
),
_ => Some(Value::new(Nid::MAX).ty(decl)),
}
}
Expr::Comment { .. } => Some(Value::VOID),
@ -2152,19 +2185,31 @@ impl<'a> Codegen<'a> {
self.ci.nodes[NEVER].inputs.push(self.ci.ctrl);
self.ci.nodes[self.ci.ctrl].outputs.push(NEVER);
} else if let Some((pv, ctrl)) = &mut self.ci.inline_ret {
} else if let Some((pv, ctrl, scope)) = &mut self.ci.inline_ret {
self.ci.nodes.unlock(*ctrl);
*ctrl =
self.ci.nodes.new_node(ty::Id::VOID, Kind::Region, [self.ci.ctrl, *ctrl]);
self.ci.nodes.lock(*ctrl);
self.ci.ctrl = *ctrl;
Self::merge_scopes(
&mut self.ci.nodes,
&mut self.ci.loops,
*ctrl,
scope,
&mut self.ci.scope,
);
self.ci.nodes.unlock(pv.id);
pv.id = self.ci.nodes.new_node(value.ty, Kind::Phi, [*ctrl, value.id, pv.id]);
self.ci.nodes.lock(pv.id);
self.ci.ctrl = *ctrl;
} else {
self.ci.nodes.lock(value.id);
self.ci.nodes.lock(self.ci.ctrl);
self.ci.inline_ret = Some((value, self.ci.ctrl));
let mut scope = self.ci.scope.dup(&mut self.ci.nodes);
scope
.vars
.drain(self.ci.inline_var_base..)
.for_each(|v| v.remove(&mut self.ci.nodes));
self.ci.inline_ret = Some((value, self.ci.ctrl, scope));
}
None
@ -2174,6 +2219,19 @@ impl<'a> Codegen<'a> {
self.strip_var(&mut vtarget);
let tty = vtarget.ty;
if let ty::Kind::Module(m) = tty.expand() {
return match self.find_type(pos, m, Err(name), self.files).expand() {
ty::Kind::Builtin(ty::NEVER) => Value::NEVER,
ty::Kind::Global(global) => {
let gl = &self.tys.ins.globals[global as usize];
let value =
self.ci.nodes.new_node(gl.ty, Kind::Global { global }, [VOID]);
Some(Value::ptr(value).ty(gl.ty))
}
v => Some(Value::new(Nid::MAX).ty(v.compress())),
};
}
let ty::Kind::Struct(s) = self.tys.base_of(tty).unwrap_or(tty).expand() else {
self.report(
pos,
@ -2296,7 +2354,7 @@ impl<'a> Codegen<'a> {
self.ci.nodes.unlock(lhs.id);
let mut rhs = rhs?;
self.strip_var(&mut rhs);
let ty = self.binop_ty(left.pos(), &mut rhs, &mut lhs, op);
let ty = self.binop_ty(left.pos(), &mut lhs, &mut rhs, op);
let inps = [VOID, lhs.id, rhs.id];
Some(self.ci.nodes.new_node_lit(
ty::bin_ret(ty, op),
@ -2463,7 +2521,7 @@ impl<'a> Codegen<'a> {
return Value::NEVER;
};
let mut inps = Vc::from([self.ci.ctrl]);
let mut inps = Vc::from([NEVER]);
for arg in args {
let value = self.expr(arg)?;
debug_assert_ne!(self.ci.nodes[value.id].kind, Kind::Stre);
@ -2500,6 +2558,7 @@ impl<'a> Codegen<'a> {
};
let argc = args.len() as u32;
inps[0] = self.ci.ctrl;
self.ci.ctrl = self.ci.nodes.new_node(ty, Kind::Call { func: ty::ECA, argc }, inps);
self.store_mem(VOID, VOID);
@ -2538,7 +2597,7 @@ impl<'a> Codegen<'a> {
);
}
let mut inps = Vc::from([self.ci.ctrl]);
let mut inps = Vc::from([NEVER]);
let mut tys = sig.args.range();
for (arg, carg) in args.iter().zip(cargs) {
let ty = self.tys.ins.args[tys.next().unwrap()];
@ -2546,6 +2605,7 @@ impl<'a> Codegen<'a> {
tys.next().unwrap();
continue;
}
std::println!("{}", self.ast_display(arg));
let mut value = self.expr_ctx(arg, Ctx::default().with_ty(ty))?;
debug_assert_ne!(self.ci.nodes[value.id].kind, Kind::Stre);
self.assert_ty(arg.pos(), &mut value, ty, fa!("argument {}", carg.name));
@ -2583,6 +2643,7 @@ impl<'a> Codegen<'a> {
}
};
inps[0] = self.ci.ctrl;
self.ci.ctrl = self.ci.nodes.new_node(sig.ret, Kind::Call { func: fu, argc }, inps);
self.store_mem(VOID, VOID);
@ -2626,7 +2687,8 @@ impl<'a> Codegen<'a> {
);
}
let arg_base = self.ci.scope.vars.len();
let prev_var_base =
std::mem::replace(&mut self.ci.inline_var_base, self.ci.scope.vars.len());
let mut sig_args = sig.args.range();
for (arg, carg) in args.iter().zip(cargs) {
let ty = self.tys.ins.args[sig_args.next().unwrap()];
@ -2641,7 +2703,8 @@ impl<'a> Codegen<'a> {
continue;
}
let mut value = self.expr_ctx(arg, Ctx::default().with_ty(ty))?;
let mut value = self.raw_expr_ctx(arg, Ctx::default().with_ty(ty))?;
self.strip_var(&mut value);
debug_assert_ne!(self.ci.nodes[value.id].kind, Kind::Stre);
debug_assert_ne!(value.id, 0);
self.assert_ty(arg.pos(), &mut value, ty, fa!("argument {}", carg.name));
@ -2671,15 +2734,22 @@ impl<'a> Codegen<'a> {
self.ci.ret = prev_ret;
self.ci.file = prev_file;
self.ci.inline_depth -= 1;
for var in self.ci.scope.vars.drain(arg_base..) {
for var in self.ci.scope.vars.drain(self.ci.inline_var_base..) {
var.remove(&mut self.ci.nodes);
}
self.ci.inline_var_base = prev_var_base;
core::mem::replace(&mut self.ci.inline_ret, prev_inline_ret).map(|(v, ctrl)| {
core::mem::replace(&mut self.ci.inline_ret, prev_inline_ret).map(
|(v, ctrl, scope)| {
self.ci.nodes.unlock(ctrl);
self.ci.nodes.unlock(v.id);
self.ci.scope.clear(&mut self.ci.nodes);
self.ci.scope = scope;
std::println!("{:?}", self.ci.nodes[ctrl]);
self.ci.ctrl = ctrl;
v
})
},
)
}
Expr::Tupl { pos, ty, fields, .. } => {
let Some(sty) = ty.map(|ty| self.ty(ty)).or(ctx.ty) else {
@ -2912,8 +2982,27 @@ impl<'a> Codegen<'a> {
}
if bre == Nid::MAX {
self.ci.ctrl = NEVER;
for (loop_var, scope_var) in self.ci.scope.iter_mut().zip(scope.iter_mut()) {
if self.ci.nodes[scope_var.value()].is_lazy_phi(node) {
if loop_var.value() != scope_var.value() {
scope_var.set_value(
self.ci.nodes.modify_input(
scope_var.value(),
2,
loop_var.value(),
),
&mut self.ci.nodes,
);
} else {
let phi = &self.ci.nodes[scope_var.value()];
let prev = phi.inputs[1];
self.ci.nodes.replace(scope_var.value(), prev);
scope_var.set_value(prev, &mut self.ci.nodes);
}
}
}
scope.clear(&mut self.ci.nodes);
self.ci.ctrl = NEVER;
return None;
}
self.ci.ctrl = bre;
@ -2954,6 +3043,7 @@ impl<'a> Codegen<'a> {
scope.clear(&mut self.ci.nodes);
bres.clear(&mut self.ci.nodes);
self.ci.scope.loads.drain(..).for_each(|l| _ = self.ci.nodes.unlock_remove(l));
self.ci.nodes.unlock(self.ci.ctrl);
self.ci.nodes.unlock(node);
@ -3253,6 +3343,7 @@ impl<'a> Codegen<'a> {
) {
nodes.lock(ctrl);
for (i, (to_value, from_value)) in to.iter_mut().zip(from.iter_mut()).enumerate() {
debug_assert_eq!(to_value.ty, from_value.ty);
if to_value.value() != from_value.value() {
nodes.load_loop_var(i, from_value, loops);
nodes.load_loop_var(i, to_value, loops);
@ -3298,6 +3389,8 @@ impl<'a> Codegen<'a> {
self.pool.push_ci(file, Some(sig.ret), 0, &mut self.ci);
log::info!("emmiting {}", self.ast_display(expr));
let &Expr::Closure { body, args, .. } = expr else {
unreachable!("{}", self.ast_display(expr))
};
@ -3546,6 +3639,9 @@ impl<'a> Function<'a> {
"{:?}",
self.nodes[nid]
);
debug_assert_eq!(self.nodes[nid].lock_rc, 0, "{:?}", self.nodes[nid]);
debug_assert_ne!(nid, MEM);
debug_assert!(self.nodes[nid].kind != Kind::Phi || self.nodes[nid].ty != ty::Id::VOID);
regalloc2::VReg::new(nid as _, regalloc2::RegClass::Int)
}
@ -3754,13 +3850,13 @@ impl<'a> Function<'a> {
let ty = self.nodes[i].ty;
match parama.next(ty, self.tys) {
PLoc::None => {}
PLoc::Reg(r, _) => {
PLoc::Reg(r, _) if ty.loc(self.tys) == Loc::Reg => {
ops.push(regalloc2::Operand::reg_fixed_use(
self.rg(i),
regalloc2::PReg::new(r as _, regalloc2::RegClass::Int),
));
}
PLoc::WideReg(..) => {
PLoc::WideReg(..) | PLoc::Reg(..) => {
loop {
match self.nodes[i].kind {
Kind::Stre { .. } => i = self.nodes[i].inputs[2],
@ -3774,6 +3870,7 @@ impl<'a> Function<'a> {
}
PLoc::Ref(r, _) => {
loop {
std::println!("{:?} {}", self.nodes[i], i);
match self.nodes[i].kind {
Kind::Stre { .. } => i = self.nodes[i].inputs[2],
Kind::Load { .. } => i = self.nodes[i].inputs[1],
@ -3860,8 +3957,12 @@ impl<'a> Function<'a> {
}
let ops = match self.nodes[region].kind {
_ if node.ty.loc(self.tys) == Loc::Stack => {
if self.nodes[node.inputs[1]].kind == Kind::Arg {
vec![self.urg(region), self.urg(node.inputs[1])]
} else {
vec![self.urg(region), self.urg(self.nodes[node.inputs[1]].inputs[1])]
}
}
Kind::Stck => vec![self.urg(node.inputs[1])],
_ => vec![self.urg(region), self.urg(node.inputs[1])],
};
@ -4222,7 +4323,7 @@ mod tests {
fn generate(ident: &'static str, input: &'static str, output: &mut String) {
_ = log::set_logger(&crate::fs::Logger);
//log::set_max_level(log::LevelFilter::Info);
log::set_max_level(log::LevelFilter::Info);
// log::set_max_level(log::LevelFilter::Trace);
let (ref files, embeds) = crate::test_parse_files(ident, input);

View file

@ -21,47 +21,49 @@ main:
LI64 r32, 0d
CP r2, r32
JAL r31, r0, :multiple_breaks
CP r33, r32
CP r34, r1
CP r33, r1
LI64 r1, 3d
JEQ r34, r1, :0
LI64 r1, 1d
LI64 r34, 1d
JEQ r33, r1, :0
CP r1, r34
JMP :1
0: CP r35, r1
LI64 r36, 4d
CP r2, r36
CP r36, r34
LI64 r37, 4d
CP r2, r37
JAL r31, r0, :multiple_breaks
CP r37, r36
LI64 r38, 10d
JEQ r1, r38, :2
CP r38, r37
LI64 r39, 10d
JEQ r1, r39, :2
LI64 r1, 2d
JMP :1
2: CP r2, r33
2: CP r2, r32
JAL r31, r0, :state_change_in_break
CP r39, r1
CP r1, r33
JEQ r39, r1, :3
JEQ r1, r32, :3
CP r1, r35
JMP :1
3: CP r33, r1
CP r2, r37
3: CP r2, r38
JAL r31, r0, :state_change_in_break
JEQ r1, r38, :4
CP r1, r37
JEQ r1, r39, :4
CP r1, r38
JMP :1
4: CP r2, r38
4: CP r2, r39
JAL r31, r0, :continue_and_state_change
JEQ r1, r38, :5
JEQ r1, r39, :5
LI64 r1, 5d
JMP :1
5: CP r2, r35
JAL r31, r0, :continue_and_state_change
CP r40, r1
CP r1, r33
JEQ r40, r1, :6
JEQ r1, r32, :6
LI64 r1, 6d
JMP :1
6: CP r1, r33
6: CP r1, r32
CP r40, r36
8: JNE r1, r40, :7
JMP :7
7: CP r2, r32
JAL r31, r0, :continue_and_state_change
JMP :8
1: LD r31, r254, 0a, 80h
ADDI64 r254, r254, 80d
JALA r0, r31, 0a
@ -89,6 +91,7 @@ state_change_in_break:
2: ADDI64 r2, r2, 1d
JMP :4
3: JALA r0, r31, 0a
code size: 569
ret: 0
timed out
code size: 585
ret: 10
status: Ok(())

View file

@ -18,17 +18,19 @@ integer:
JMP :0
0: JALA r0, r31, 0a
line:
ST r2, r254, 0a, 16h
ADDI64 r2, r254, 0d
ST r4, r254, 0a, 16h
ADDI64 r4, r254, 0d
ADDI64 r254, r254, -48d
ST r2, r254, 32a, 16h
ADDI64 r2, r254, 32d
ST r4, r254, 16a, 16h
ADDI64 r4, r254, 16d
ST r6, r254, 0a, 16h
ADDI64 r6, r254, 0d
LD r9, r4, 0a, 8h
LD r11, r2, 0a, 8h
JGTS r11, r9, :0
JMP :0
0: JALA r0, r31, 0a
0: ADDI64 r254, r254, 48d
JALA r0, r31, 0a
main:
ADDI64 r254, r254, -184d
ST r31, r254, 96a, 88h
@ -70,10 +72,11 @@ main:
ADDI64 r254, r254, 184d
JALA r0, r31, 0a
rect_line:
ST r2, r254, 0a, 16h
ADDI64 r2, r254, 0d
ST r4, r254, 0a, 16h
ADDI64 r4, r254, 0d
ADDI64 r254, r254, -48d
ST r2, r254, 32a, 16h
ADDI64 r2, r254, 32d
ST r4, r254, 16a, 16h
ADDI64 r4, r254, 16d
ST r6, r254, 0a, 16h
ADDI64 r6, r254, 0d
LI64 r10, 0d
@ -88,7 +91,8 @@ rect_line:
JMP :3
2: ADDI64 r9, r9, 1d
JMP :4
1: JALA r0, r31, 0a
code size: 886
1: ADDI64 r254, r254, 48d
JALA r0, r31, 0a
code size: 930
ret: 0
status: Ok(())