This commit is contained in:
Jakub Doka 2024-10-26 10:25:42 +02:00
parent af4d965b8c
commit b62413046d
No known key found for this signature in database
GPG key ID: C6E9A89936B8C143
2 changed files with 35 additions and 151 deletions

View file

@ -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<Item = &mut Node> {
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<ItemCtx>,
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);
}

View file

@ -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
}