diff --git a/lang/src/son.rs b/lang/src/son.rs index 2299482..b038b09 100644 --- a/lang/src/son.rs +++ b/lang/src/son.rs @@ -93,10 +93,6 @@ impl Nodes { _ => "white", }; - let dest = i; - //let mut index_override = None; - - //if !matches!(node.kind, Kind::Then | Kind::Else) { if node.ty != ty::Id::VOID { writeln!( out, @@ -107,24 +103,14 @@ impl Nodes { } else { writeln!(out, " node{i}[label=\"{i} {}\" color={color}]", node.kind,)?; } - //} else { - // dest = node.inputs[0]; - - // index_override = if node.kind == Kind::Then { Some(0) } else { Some(1) }; - //} - - //if node.kind == Kind::If { - // continue; - //} for (j, &o) in node.outputs.iter().enumerate() { - //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 { "" }; writeln!( out, - " node{o} -> node{dest}[color={color} taillabel={index} headlabel={j} {style}]", + " node{o} -> node{i}[color={color} taillabel={index} headlabel={j} {style}]", )?; } } @@ -141,19 +127,19 @@ impl Nodes { log::info!("{out}"); } - fn graphviz_in_browser(&self, _tys: &Types, _files: &[parser::Ast]) { + fn graphviz_in_browser(&self, tys: &Types, files: &[parser::Ast]) { #[cfg(all(debug_assertions, feature = "std"))] { - // let out = &mut String::new(); - // _ = self.graphviz_low(tys, files, out); - // if !std::process::Command::new("brave") - // .arg(format!("https://dreampuf.github.io/GraphvizOnline/#{out}")) - // .status() - // .unwrap() - // .success() - // { - // log::error!("{out}"); - // } + let out = &mut String::new(); + _ = self.graphviz_low(tys, files, out); + if !std::process::Command::new("brave") + .arg(format!("https://dreampuf.github.io/GraphvizOnline/#{out}")) + .status() + .unwrap() + .success() + { + log::error!("{out}"); + } } } @@ -290,8 +276,6 @@ impl Nodes { self.remove_node_lookup(target); self.remove_low(target); - //std::println!("{target} {}", trace()); - true } @@ -711,71 +695,14 @@ impl Nodes { log::error!("outputs are empry {id} {:?}", node.kind); failed = true; } - - // let mut allowed_cfgs = 1 + (node.kind == Kind::If) as usize; - // for &o in node.outputs.iter() { - // if self.is_cfg(i) { - // if allowed_cfgs == 0 && self.is_cfg(o) { - // log::err!( - // "multiple cfg outputs detected: {:?} -> {:?}", - // node.kind, - // self[o].kind - // ); - // failed = true; - // } else { - // allowed_cfgs += self.is_cfg(o) as usize; - // } - // } - - // let other = match &self.values[o as usize] { - // Ok(other) => other, - // Err(_) => { - // log::err!("the edge points to dropped node: {i} {:?} {o}", node.kind,); - // failed = true; - // continue; - // } - // }; - // let occurs = self[o].inputs.iter().filter(|&&el| el == i).count(); - // let self_occurs = self[i].outputs.iter().filter(|&&el| el == o).count(); - // if occurs != self_occurs { - // log::err!( - // "the edge is not bidirectional: {i} {:?} {self_occurs} {o} {:?} {occurs}", - // node.kind, - // other.kind - // ); - // failed = true; - // } - // } } + if failed { self.graphviz_in_browser(tys, files); panic!() } } - #[expect(dead_code)] - fn climb_expr(&mut self, from: Nid, mut for_each: impl FnMut(Nid, &Node) -> bool) -> bool { - fn climb_impl( - nodes: &mut Nodes, - from: Nid, - for_each: &mut impl FnMut(Nid, &Node) -> bool, - ) -> bool { - for i in 0..nodes[from].inputs.len() { - let n = nodes[from].inputs[i]; - if n != Nid::MAX - && nodes.visited.set(n) - && !nodes.is_cfg(n) - && (for_each(n, &nodes[n]) || climb_impl(nodes, n, for_each)) - { - return true; - } - } - false - } - self.visited.clear(self.values.len()); - climb_impl(self, from, &mut for_each) - } - fn late_peephole(&mut self, target: Nid) -> Nid { if let Some(id) = self.peephole(target) { self.replace(target, id); @@ -855,11 +782,6 @@ impl Nodes { } } - #[expect(dead_code)] - fn iter_mut(&mut self) -> impl Iterator { - self.values.iter_mut().flat_map(Result::as_mut) - } - #[allow(dead_code)] fn eliminate_stack_temporaries(&mut self) { 'o: for stack in self[MEM].outputs.clone() { @@ -1061,7 +983,6 @@ impl fmt::Display for Kind { } #[derive(Debug, Default, Clone)] -//#[repr(align(64))] pub struct Node { kind: Kind, inputs: Vc, @@ -1267,11 +1188,16 @@ impl ItemCtx { crate::emit(&mut self.code, instr); } - fn emit_body_code(&mut self, sig: Sig, tys: &Types, files: &[parser::Ast]) -> usize { + fn emit_body_code( + &mut self, + sig: Sig, + tys: &Types, + files: &[parser::Ast], + ralloc: &mut Regalloc, + ) -> usize { let mut nodes = core::mem::take(&mut self.nodes); let fuc = Function::new(&mut nodes, tys, sig); - let mut ralloc = Regalloc::default(); // TODO: reuse log::info!("{:?}", fuc); if self.call_count != 0 { core::mem::swap( @@ -1600,7 +1526,13 @@ impl ItemCtx { saved_regs.len() } - fn emit_body(&mut self, tys: &mut Types, files: &[parser::Ast], sig: Sig) { + fn emit_body( + &mut self, + tys: &mut Types, + files: &[parser::Ast], + sig: Sig, + ralloc: &mut Regalloc, + ) { self.nodes.check_final_integrity(tys, files); self.nodes.graphviz(tys, files); self.nodes.gcm(); @@ -1638,7 +1570,7 @@ impl ItemCtx { self.nodes[MEM].outputs = mems; } - let saved = self.emit_body_code(sig, tys, files); + let saved = self.emit_body_code(sig, tys, files, ralloc); if let Some(last_ret) = self.ret_relocs.last() && last_ret.offset as usize == self.code.len() - 5 @@ -1722,8 +1654,6 @@ impl Ctx { struct Pool { cis: Vec, used_cis: usize, - - #[expect(dead_code)] ralloc: Regalloc, } @@ -1889,7 +1819,12 @@ impl<'a> Codegen<'a> { return 1; } - self.ci.emit_body(self.tys, self.files, Sig { args: Tuple::empty(), ret }); + self.ci.emit_body( + self.tys, + self.files, + Sig { args: Tuple::empty(), ret }, + &mut self.pool.ralloc, + ); self.ci.code.truncate(self.ci.code.len() - instrs::jala(0, 0, 0).0); self.ci.emit(instrs::tx()); @@ -3425,7 +3360,7 @@ impl<'a> Codegen<'a> { self.ci.finalize(); if self.errors.borrow().len() == prev_err_len { - self.ci.emit_body(self.tys, self.files, sig); + self.ci.emit_body(self.tys, self.files, sig, &mut self.pool.ralloc); self.tys.ins.funcs[id as usize].code.append(&mut self.ci.code); self.tys.ins.funcs[id as usize].relocs.append(&mut self.ci.relocs); } diff --git a/pointers.hb b/pointers.hb deleted file mode 100644 index eafa8c2..0000000 --- a/pointers.hb +++ /dev/null @@ -1,51 +0,0 @@ -Point := struct { - x: int, - y: int, -} - -Rect := struct { - min: Point, - max: Point, -} - -main := fn(): void { - rect := Rect.(.(0, 0), .(0, 0)) - // eliminates initila 0 - rect.min.x = 1 - // here as well - rect.min.y = 2 - // eliminates previous 2 lines, intermidiate stack slot is created, and stores are - // delegated to the rect - rect.min = .(3, 4) - - // encompasses the previous two loads - ptr := &rect.min - // pointer escapes to a function -> rect.min now has unknown values - clobber(ptr) - - // this can not be folded but load can be reused - rect.max.x = rect.min.x * rect.min.x - - // this should invalidate the previous loads - clobber(ptr) - // now all stores are clobbered - clobber(&rect.max) - - // conslusion: pointers fundamentally dont do anything and are not registered anywhere, - // thay are just bound to the base memory and when you interact with them (store, load) - // they modity the memory state, they are literally a view trought which we look at the - // memory and remotely modify it, so in summary, pointers are not bound to a specific load - // or store, but they can invalidate them. - // - // The fact pointers are bound to the base memory also makes it easy to tell how aliasing works - // for the pointer, we prohibit pointer arithmetic on these pointers, instead this is delegated - // to special pointer type that can only be created when compiler can prove ist safe or explicitly - // with a directive - - return -} - -clobber := fn(p: ^Point): void { - *p = .(5, 6) - return -}