forked from AbleOS/holey-bytes
adding global mutatuon to the test
This commit is contained in:
parent
ee30069195
commit
bb41da484f
|
@ -217,6 +217,7 @@ fib := fn(n: int): int {
|
||||||
}
|
}
|
||||||
|
|
||||||
main := fn(): int {
|
main := fn(): int {
|
||||||
|
complex_global_var += 5
|
||||||
return complex_global_var
|
return complex_global_var
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -2106,7 +2106,7 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
E::BinOp { left, op, right } if op != T::Decl => 'ops: {
|
E::BinOp { left, op, right } if op != T::Decl => 'ops: {
|
||||||
let left = self.expr_ctx(left, Ctx {
|
let left = self.expr_ctx(left, Ctx {
|
||||||
ty: ctx.ty.filter(|_| dbg!(dbg!(op).is_homogenous())),
|
ty: ctx.ty.filter(|_| op.is_homogenous()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
|
|
@ -13,16 +13,17 @@ use {
|
||||||
HashMap,
|
HashMap,
|
||||||
},
|
},
|
||||||
core::fmt,
|
core::fmt,
|
||||||
|
hbvm::mem::softpaging::lookup,
|
||||||
std::{
|
std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
collections::{hash_map, BTreeMap},
|
collections::{hash_map, BTreeMap},
|
||||||
|
default,
|
||||||
fmt::Display,
|
fmt::Display,
|
||||||
hash::{Hash as _, Hasher},
|
hash::{Hash as _, Hasher},
|
||||||
intrinsics::unreachable,
|
|
||||||
mem,
|
mem,
|
||||||
ops::{self, Range},
|
ops::{self, Range},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
usize,
|
u32, usize,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -463,11 +464,43 @@ mod ty {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct LookupEntry {
|
||||||
|
nid: u32,
|
||||||
|
hash: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct IdentityHash(u64);
|
||||||
|
|
||||||
|
impl std::hash::Hasher for IdentityHash {
|
||||||
|
fn finish(&self) -> u64 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&mut self, _: &[u8]) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_u64(&mut self, i: u64) {
|
||||||
|
self.0 = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::hash::Hash for LookupEntry {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
state.write_u64(self.hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct Nodes {
|
struct Nodes {
|
||||||
values: Vec<Result<Node, u32>>,
|
values: Vec<Result<Node, u32>>,
|
||||||
visited: BitSet,
|
visited: BitSet,
|
||||||
free: u32,
|
free: u32,
|
||||||
lookup: HashMap<Nid, ()>,
|
lookup: std::collections::hash_map::HashMap<
|
||||||
|
LookupEntry,
|
||||||
|
(),
|
||||||
|
std::hash::BuildHasherDefault<IdentityHash>,
|
||||||
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Nodes {
|
impl Default for Nodes {
|
||||||
|
@ -504,7 +537,7 @@ impl Nodes {
|
||||||
|
|
||||||
let node = Node {
|
let node = Node {
|
||||||
inputs: inps.into(),
|
inputs: inps.into(),
|
||||||
kind: kind.clone(),
|
kind,
|
||||||
color: 0,
|
color: 0,
|
||||||
depth: u32::MAX,
|
depth: u32::MAX,
|
||||||
lock_rc: 0,
|
lock_rc: 0,
|
||||||
|
@ -512,15 +545,17 @@ impl Nodes {
|
||||||
outputs: vec![],
|
outputs: vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut hasher = crate::FnvHasher::default();
|
let mut lookup_meta = None;
|
||||||
node.key().hash(&mut hasher);
|
if node.kind != Kind::Phi || node.inputs[2] != 0 {
|
||||||
|
let (raw_entry, hash) = Self::find_node(&mut self.lookup, &self.values, &node);
|
||||||
|
|
||||||
let (raw_entry, _) = Self::find_node(&mut self.lookup, &self.values, &node);
|
let entry = match raw_entry {
|
||||||
|
hash_map::RawEntryMut::Occupied(mut o) => return o.get_key_value().0.nid,
|
||||||
|
hash_map::RawEntryMut::Vacant(v) => v,
|
||||||
|
};
|
||||||
|
|
||||||
let entry = match raw_entry {
|
lookup_meta = Some((entry, hash));
|
||||||
hash_map::RawEntryMut::Occupied(mut o) => return *o.get_key_value().0,
|
}
|
||||||
hash_map::RawEntryMut::Vacant(v) => v,
|
|
||||||
};
|
|
||||||
|
|
||||||
if self.free == u32::MAX {
|
if self.free == u32::MAX {
|
||||||
self.free = self.values.len() as _;
|
self.free = self.values.len() as _;
|
||||||
|
@ -532,40 +567,48 @@ impl Nodes {
|
||||||
debug_assert_ne!(d, free);
|
debug_assert_ne!(d, free);
|
||||||
self.values[d as usize].as_mut().unwrap().outputs.push(free);
|
self.values[d as usize].as_mut().unwrap().outputs.push(free);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.free = mem::replace(&mut self.values[free as usize], Ok(node)).unwrap_err();
|
self.free = mem::replace(&mut self.values[free as usize], Ok(node)).unwrap_err();
|
||||||
*entry.insert(free, ()).0
|
|
||||||
|
if let Some((entry, hash)) = lookup_meta {
|
||||||
|
entry.insert(LookupEntry { nid: free, hash }, ());
|
||||||
|
}
|
||||||
|
free
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_node<'a>(
|
fn find_node<'a>(
|
||||||
lookup: &'a mut HashMap<Nid, ()>,
|
lookup: &'a mut std::collections::hash_map::HashMap<
|
||||||
|
LookupEntry,
|
||||||
|
(),
|
||||||
|
std::hash::BuildHasherDefault<IdentityHash>,
|
||||||
|
>,
|
||||||
values: &[Result<Node, u32>],
|
values: &[Result<Node, u32>],
|
||||||
node: &Node,
|
node: &Node,
|
||||||
) -> (hash_map::RawEntryMut<'a, u32, (), std::hash::BuildHasherDefault<crate::FnvHasher>>, u64)
|
) -> (
|
||||||
{
|
hash_map::RawEntryMut<'a, LookupEntry, (), std::hash::BuildHasherDefault<IdentityHash>>,
|
||||||
|
u64,
|
||||||
|
) {
|
||||||
let mut hasher = crate::FnvHasher::default();
|
let mut hasher = crate::FnvHasher::default();
|
||||||
node.key().hash(&mut hasher);
|
node.key().hash(&mut hasher);
|
||||||
let hash = hasher.finish();
|
let hash = hasher.finish();
|
||||||
|
let entry = lookup
|
||||||
(
|
.raw_entry_mut()
|
||||||
lookup
|
.from_hash(hash, |n| values[n.nid as usize].as_ref().unwrap().key() == node.key());
|
||||||
.raw_entry_mut()
|
(entry, hash)
|
||||||
.from_hash(hash, |&n| values[n as usize].as_ref().unwrap().key() == node.key()),
|
|
||||||
hash,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_node_lookup(&mut self, target: Nid) {
|
fn remove_node_lookup(&mut self, target: Nid) {
|
||||||
match Self::find_node(
|
if self[target].kind != Kind::Phi || self[target].inputs[2] != 0 {
|
||||||
&mut self.lookup,
|
match Self::find_node(
|
||||||
&self.values,
|
&mut self.lookup,
|
||||||
&self.values[target as usize].as_ref().unwrap(),
|
&self.values,
|
||||||
)
|
self.values[target as usize].as_ref().unwrap(),
|
||||||
.0
|
)
|
||||||
{
|
.0
|
||||||
hash_map::RawEntryMut::Occupied(o) => o.remove(),
|
{
|
||||||
hash_map::RawEntryMut::Vacant(_) => unreachable!(),
|
hash_map::RawEntryMut::Occupied(o) => o.remove(),
|
||||||
};
|
hash_map::RawEntryMut::Vacant(_) => unreachable!(),
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_node(&mut self, ty: impl Into<ty::Id>, kind: Kind, inps: impl Into<Vec<u32>>) -> Nid {
|
fn new_node(&mut self, ty: impl Into<ty::Id>, kind: Kind, inps: impl Into<Vec<u32>>) -> Nid {
|
||||||
|
@ -619,12 +662,20 @@ impl Nodes {
|
||||||
Kind::Call { .. } => {}
|
Kind::Call { .. } => {}
|
||||||
Kind::If => return self.peephole_if(target),
|
Kind::If => return self.peephole_if(target),
|
||||||
Kind::Region => {}
|
Kind::Region => {}
|
||||||
Kind::Phi => {}
|
Kind::Phi => return self.peephole_phi(target),
|
||||||
Kind::Loop => {}
|
Kind::Loop => {}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn peephole_phi(&mut self, target: Nid) -> Option<Nid> {
|
||||||
|
if self[target].inputs[1] == self[target].inputs[2] {
|
||||||
|
return Some(self[target].inputs[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
fn peephole_if(&mut self, target: Nid) -> Option<Nid> {
|
fn peephole_if(&mut self, target: Nid) -> Option<Nid> {
|
||||||
let cond = self[target].inputs[1];
|
let cond = self[target].inputs[1];
|
||||||
if let Kind::ConstInt { value } = self[cond].kind {
|
if let Kind::ConstInt { value } = self[cond].kind {
|
||||||
|
@ -720,7 +771,7 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
|
|
||||||
if changed {
|
if changed {
|
||||||
return Some(self.new_node(self[target].ty, self[target].kind.clone(), [lhs, rhs]));
|
return Some(self.new_node(self[target].ty, self[target].kind, [lhs, rhs]));
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
|
@ -731,11 +782,13 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn replace(&mut self, target: Nid, with: Nid) {
|
fn replace(&mut self, target: Nid, with: Nid) {
|
||||||
|
let mut back_press = 0;
|
||||||
for i in 0..self[target].outputs.len() {
|
for i in 0..self[target].outputs.len() {
|
||||||
let out = self[target].outputs[i];
|
let out = self[target].outputs[i - back_press];
|
||||||
let index = self[out].inputs.iter().position(|&p| p == target).unwrap();
|
let index = self[out].inputs.iter().position(|&p| p == target).unwrap();
|
||||||
let rpl = self.modify_input(out, index, with);
|
let prev_len = self[target].outputs.len();
|
||||||
self[with].outputs.push(rpl);
|
self.modify_input(out, index, with);
|
||||||
|
back_press += (self[target].outputs.len() != prev_len) as usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.remove(target);
|
self.remove(target);
|
||||||
|
@ -750,17 +803,19 @@ impl Nodes {
|
||||||
let (entry, hash) = Self::find_node(
|
let (entry, hash) = Self::find_node(
|
||||||
&mut self.lookup,
|
&mut self.lookup,
|
||||||
&self.values,
|
&self.values,
|
||||||
&self.values[target as usize].as_ref().unwrap(),
|
self.values[target as usize].as_ref().unwrap(),
|
||||||
);
|
);
|
||||||
match entry {
|
match entry {
|
||||||
hash_map::RawEntryMut::Occupied(mut other) => {
|
hash_map::RawEntryMut::Occupied(mut other) => {
|
||||||
let rpl = *other.get_key_value().0;
|
log::dbg!("rplc");
|
||||||
|
let rpl = other.get_key_value().0.nid;
|
||||||
self[target].inputs[inp_index] = prev;
|
self[target].inputs[inp_index] = prev;
|
||||||
self.replace(target, rpl);
|
self.replace(target, rpl);
|
||||||
rpl
|
rpl
|
||||||
}
|
}
|
||||||
hash_map::RawEntryMut::Vacant(slot) => {
|
hash_map::RawEntryMut::Vacant(slot) => {
|
||||||
slot.insert_hashed_nocheck(hash, target, ());
|
log::dbg!("mod");
|
||||||
|
slot.insert(LookupEntry { nid: target, hash }, ());
|
||||||
let index = self[prev].outputs.iter().position(|&o| o == target).unwrap();
|
let index = self[prev].outputs.iter().position(|&o| o == target).unwrap();
|
||||||
self[prev].outputs.swap_remove(index);
|
self[prev].outputs.swap_remove(index);
|
||||||
self[with].outputs.push(target);
|
self[with].outputs.push(target);
|
||||||
|
@ -913,8 +968,28 @@ impl Nodes {
|
||||||
failed = true;
|
failed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut allowed_cfgs = 1 + (node.kind == Kind::If) as usize;
|
||||||
for &o in &node.outputs {
|
for &o in &node.outputs {
|
||||||
let mut occurs = 0;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if matches!(node.kind, Kind::Region | Kind::Loop)
|
||||||
|
&& !self.is_cfg(o)
|
||||||
|
&& self[o].kind != Kind::Phi
|
||||||
|
{
|
||||||
|
log::err!("unexpected output node on region: {:?}", self[o].kind);
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
|
||||||
let other = match &self.values[o as usize] {
|
let other = match &self.values[o as usize] {
|
||||||
Ok(other) => other,
|
Ok(other) => other,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
|
@ -923,10 +998,11 @@ impl Nodes {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
occurs += self[o].inputs.iter().filter(|&&el| el == i).count();
|
let occurs = self[o].inputs.iter().filter(|&&el| el == i).count();
|
||||||
if occurs == 0 {
|
let self_occurs = self[i].outputs.iter().filter(|&&el| el == o).count();
|
||||||
|
if occurs != self_occurs {
|
||||||
log::err!(
|
log::err!(
|
||||||
"the edge is not bidirectional: {i} {:?} {o} {:?}",
|
"the edge is not bidirectional: {i} {:?} {self_occurs} {o} {:?} {occurs}",
|
||||||
node.kind,
|
node.kind,
|
||||||
other.kind
|
other.kind
|
||||||
);
|
);
|
||||||
|
@ -961,11 +1037,19 @@ impl Nodes {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
false
|
||||||
}
|
}
|
||||||
self.visited.clear(self.values.len());
|
self.visited.clear(self.values.len());
|
||||||
climb_impl(self, from, &mut for_each)
|
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);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
target
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Index<u32> for Nodes {
|
impl ops::Index<u32> for Nodes {
|
||||||
|
@ -1625,16 +1709,23 @@ impl Codegen {
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.ci.vars[index].value == 0 {
|
if self.ci.vars[index].value == 0 {
|
||||||
self.ci.nodes.unlock(self.ci.vars[index].value);
|
|
||||||
let loob = self.ci.loops.last_mut().unwrap();
|
let loob = self.ci.loops.last_mut().unwrap();
|
||||||
let inps = [loob.node, loob.scope[index].value, loob.scope[index].value];
|
if self.ci.nodes[loob.scope[index].value].kind != Kind::Phi
|
||||||
self.ci.nodes.unlock(inps[1]);
|
|| self.ci.nodes[loob.scope[index].value].inputs[0] != loob.node
|
||||||
let ty = self.ci.nodes[inps[1]].ty;
|
{
|
||||||
// TODO: dont apply peepholes here
|
self.ci.nodes.unlock(self.ci.vars[index].value);
|
||||||
let phy = self.ci.nodes.new_node(ty, Kind::Phi, inps);
|
let inps = [loob.node, loob.scope[index].value, 0];
|
||||||
self.ci.nodes[phy].lock_rc += 2;
|
self.ci.nodes.unlock(inps[1]);
|
||||||
self.ci.vars[index].value = phy;
|
let ty = self.ci.nodes[inps[1]].ty;
|
||||||
loob.scope[index].value = phy;
|
let phi = self.ci.nodes.new_node_nop(ty, Kind::Phi, inps);
|
||||||
|
self.ci.nodes[phi].lock_rc += 2;
|
||||||
|
self.ci.vars[index].value = phi;
|
||||||
|
loob.scope[index].value = phi;
|
||||||
|
} else {
|
||||||
|
self.ci.nodes.unlock_remove(self.ci.vars[index].value);
|
||||||
|
self.ci.vars[index].value = loob.scope[index].value;
|
||||||
|
self.ci.nodes.lock(self.ci.vars[index].value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.ci.nodes.check_scope_integrity(&self.ci.vars);
|
self.ci.nodes.check_scope_integrity(&self.ci.vars);
|
||||||
|
@ -1751,8 +1842,12 @@ impl Codegen {
|
||||||
|
|
||||||
let ty = self.ci.nodes[else_var.value].ty;
|
let ty = self.ci.nodes[else_var.value].ty;
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(
|
||||||
ty, self.ci.nodes[then_var.value].ty,
|
ty,
|
||||||
"TODO: typecheck properly"
|
self.ci.nodes[then_var.value].ty,
|
||||||
|
"TODO: typecheck properly: {} != {}\n{}",
|
||||||
|
self.ty_display(ty),
|
||||||
|
self.ty_display(self.ci.nodes[then_var.value].ty),
|
||||||
|
self.errors.borrow()
|
||||||
);
|
);
|
||||||
|
|
||||||
let inps = [self.ci.ctrl, then_var.value, else_var.value];
|
let inps = [self.ci.ctrl, then_var.value, else_var.value];
|
||||||
|
@ -1826,33 +1921,35 @@ impl Codegen {
|
||||||
self.ci.nodes.check_scope_integrity(&self.ci.vars);
|
self.ci.nodes.check_scope_integrity(&self.ci.vars);
|
||||||
self.ci.nodes.check_scope_integrity(&break_scope);
|
self.ci.nodes.check_scope_integrity(&break_scope);
|
||||||
self.ci.nodes.check_scope_integrity(&scope);
|
self.ci.nodes.check_scope_integrity(&scope);
|
||||||
for ((dest_var, scope_var), loop_var) in
|
for ((dest_var, mut scope_var), loop_var) in
|
||||||
self.ci.vars.iter_mut().zip(scope).zip(break_scope)
|
self.ci.vars.iter_mut().zip(scope).zip(break_scope)
|
||||||
{
|
{
|
||||||
if loop_var.value == 0 {
|
|
||||||
self.ci.nodes.unlock(loop_var.value);
|
|
||||||
debug_assert!(loop_var.value == dest_var.value);
|
|
||||||
self.ci.nodes.unlock(dest_var.value);
|
|
||||||
dest_var.value = scope_var.value;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
debug_assert_eq!(self.ci.nodes[scope_var.value].kind, Kind::Phi);
|
|
||||||
|
|
||||||
if scope_var.value == loop_var.value {
|
|
||||||
let orig = self.ci.nodes[scope_var.value].inputs[1];
|
|
||||||
self.ci.nodes.lock(orig);
|
|
||||||
self.ci.nodes.unlock(loop_var.value);
|
|
||||||
self.ci.nodes.unlock_remove(scope_var.value);
|
|
||||||
self.ci.nodes.unlock_remove(dest_var.value);
|
|
||||||
dest_var.value = orig;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.ci.nodes.unlock(loop_var.value);
|
self.ci.nodes.unlock(loop_var.value);
|
||||||
let phy = self.ci.nodes.modify_input(scope_var.value, 2, loop_var.value);
|
|
||||||
self.ci.nodes.unlock_remove(dest_var.value);
|
if loop_var.value != 0 {
|
||||||
dest_var.value = phy;
|
self.ci.nodes.unlock(scope_var.value);
|
||||||
|
if loop_var.value != scope_var.value {
|
||||||
|
scope_var.value =
|
||||||
|
self.ci.nodes.modify_input(scope_var.value, 2, loop_var.value);
|
||||||
|
self.ci.nodes.lock(scope_var.value);
|
||||||
|
} else {
|
||||||
|
let phi = &self.ci.nodes[scope_var.value];
|
||||||
|
debug_assert_eq!(phi.kind, Kind::Phi);
|
||||||
|
debug_assert_eq!(phi.inputs[2], 0);
|
||||||
|
let prev = phi.inputs[1];
|
||||||
|
self.ci.nodes.replace(scope_var.value, prev);
|
||||||
|
scope_var.value = prev;
|
||||||
|
self.ci.nodes.lock(prev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if dest_var.value == 0 {
|
||||||
|
self.ci.nodes.unlock_remove(dest_var.value);
|
||||||
|
dest_var.value = scope_var.value;
|
||||||
|
self.ci.nodes.lock(dest_var.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.ci.nodes.unlock_remove(scope_var.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.ci.nodes.unlock(self.ci.ctrl);
|
self.ci.nodes.unlock(self.ci.ctrl);
|
||||||
|
@ -2198,7 +2295,7 @@ impl Codegen {
|
||||||
|
|
||||||
fn color_control(&mut self, mut ctrl: Nid) -> Option<Nid> {
|
fn color_control(&mut self, mut ctrl: Nid) -> Option<Nid> {
|
||||||
for _ in 0..30 {
|
for _ in 0..30 {
|
||||||
match self.ci.nodes[ctrl].kind.clone() {
|
match self.ci.nodes[ctrl].kind {
|
||||||
Kind::Start => unreachable!(),
|
Kind::Start => unreachable!(),
|
||||||
Kind::End => unreachable!(),
|
Kind::End => unreachable!(),
|
||||||
Kind::Return => {
|
Kind::Return => {
|
||||||
|
@ -2250,7 +2347,7 @@ impl Codegen {
|
||||||
(None, Some(n)) | (Some(n), None) => n,
|
(None, Some(n)) | (Some(n), None) => n,
|
||||||
(Some(l), Some(r)) if l == r => l,
|
(Some(l), Some(r)) if l == r => l,
|
||||||
(Some(left), Some(right)) => {
|
(Some(left), Some(right)) => {
|
||||||
todo!()
|
todo!("{:?} {:?}", self.ci.nodes[left], self.ci.nodes[right]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2258,14 +2355,12 @@ impl Codegen {
|
||||||
return Some(dest);
|
return Some(dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_assert!(left_unreachable.is_none() || right_unreachable.is_none());
|
|
||||||
|
|
||||||
debug_assert_eq!(self.ci.nodes[dest].kind, Kind::Region);
|
debug_assert_eq!(self.ci.nodes[dest].kind, Kind::Region);
|
||||||
|
|
||||||
for i in 0..self.ci.nodes[dest].outputs.len() {
|
for i in 0..self.ci.nodes[dest].outputs.len() {
|
||||||
let o = self.ci.nodes[dest].outputs[i];
|
let o = self.ci.nodes[dest].outputs[i];
|
||||||
if self.ci.nodes[o].kind == Kind::Phi {
|
if self.ci.nodes[o].kind == Kind::Phi {
|
||||||
self.color_phy(o);
|
self.color_phi(o);
|
||||||
self.ci.nodes[o].depth = self.ci.loop_depth;
|
self.ci.nodes[o].depth = self.ci.loop_depth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2284,15 +2379,15 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 0..self.ci.nodes[ctrl].outputs.len() {
|
for i in 0..self.ci.nodes[ctrl].outputs.len() {
|
||||||
let maybe_phy = self.ci.nodes[ctrl].outputs[i];
|
let maybe_phi = self.ci.nodes[ctrl].outputs[i];
|
||||||
let Node { kind: Kind::Phi, ref inputs, .. } = self.ci.nodes[maybe_phy]
|
let Node { kind: Kind::Phi, ref inputs, .. } = self.ci.nodes[maybe_phi]
|
||||||
else {
|
else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
_ = self.color_expr_consume(inputs[1]);
|
_ = self.color_expr_consume(inputs[1]);
|
||||||
self.ci.nodes[maybe_phy].depth = self.ci.loop_depth;
|
self.ci.nodes[maybe_phi].depth = self.ci.loop_depth;
|
||||||
self.ci.set_next_color(maybe_phy);
|
self.ci.set_next_color(maybe_phi);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.ci.nodes[ctrl].lock_rc = self.ci.code.len() as _;
|
self.ci.nodes[ctrl].lock_rc = self.ci.code.len() as _;
|
||||||
|
@ -2307,7 +2402,7 @@ impl Codegen {
|
||||||
);
|
);
|
||||||
|
|
||||||
for i in 0..self.ci.nodes[ctrl].outputs.len() {
|
for i in 0..self.ci.nodes[ctrl].outputs.len() {
|
||||||
self.color_phy(self.ci.nodes[ctrl].outputs[i]);
|
self.color_phi(self.ci.nodes[ctrl].outputs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.ci.loop_depth -= 1;
|
self.ci.loop_depth -= 1;
|
||||||
|
@ -2321,8 +2416,8 @@ impl Codegen {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn color_phy(&mut self, maybe_phy: Nid) {
|
fn color_phi(&mut self, maybe_phi: Nid) {
|
||||||
let Node { kind: Kind::Phi, ref inputs, .. } = self.ci.nodes[maybe_phy] else {
|
let Node { kind: Kind::Phi, ref inputs, .. } = self.ci.nodes[maybe_phi] else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let &[region, left, right] = inputs.as_slice() else { unreachable!() };
|
let &[region, left, right] = inputs.as_slice() else { unreachable!() };
|
||||||
|
@ -2330,14 +2425,14 @@ impl Codegen {
|
||||||
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);
|
||||||
|
|
||||||
if self.ci.nodes[maybe_phy].color != 0 {
|
if self.ci.nodes[maybe_phi].color != 0 {
|
||||||
// loop phy
|
// loop phi
|
||||||
if let Some(c) = rcolor
|
if let Some(c) = rcolor
|
||||||
&& !self.ci.nodes.climb_expr(right, |i, n| {
|
&& !self.ci.nodes.climb_expr(right, |i, n| {
|
||||||
matches!(n.kind, Kind::Phi) && n.inputs[0] == region && i != maybe_phy
|
matches!(n.kind, Kind::Phi) && n.inputs[0] == region && i != maybe_phi
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
self.ci.recolor(right, c, self.ci.nodes[maybe_phy].color);
|
self.ci.recolor(right, c, self.ci.nodes[maybe_phi].color);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let color = match (lcolor, rcolor) {
|
let color = match (lcolor, rcolor) {
|
||||||
|
@ -2348,7 +2443,7 @@ impl Codegen {
|
||||||
lc
|
lc
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.ci.set_color(maybe_phy, color);
|
self.ci.set_color(maybe_phi, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2396,7 +2491,7 @@ impl Codegen {
|
||||||
|
|
||||||
fn emit_control(&mut self, mut ctrl: Nid) -> Option<Nid> {
|
fn emit_control(&mut self, mut ctrl: Nid) -> Option<Nid> {
|
||||||
for _ in 0..30 {
|
for _ in 0..30 {
|
||||||
match self.ci.nodes[ctrl].kind.clone() {
|
match self.ci.nodes[ctrl].kind {
|
||||||
Kind::Start => unreachable!(),
|
Kind::Start => unreachable!(),
|
||||||
Kind::End => unreachable!(),
|
Kind::End => unreachable!(),
|
||||||
Kind::Return => {
|
Kind::Return => {
|
||||||
|
@ -2439,14 +2534,14 @@ impl Codegen {
|
||||||
let mut parama = self.tys.parama(ret);
|
let mut parama = self.tys.parama(ret);
|
||||||
for i in 1..self.ci.nodes[ctrl].inputs.len() {
|
for i in 1..self.ci.nodes[ctrl].inputs.len() {
|
||||||
let arg = self.ci.nodes[ctrl].inputs[i];
|
let arg = self.ci.nodes[ctrl].inputs[i];
|
||||||
node_loc!(self, arg) = match self.tys.size_of(self.tof(arg)) {
|
|
||||||
|
let dst = match self.tys.size_of(self.tof(arg)) {
|
||||||
0 => continue,
|
0 => continue,
|
||||||
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);
|
||||||
self.ci.nodes[arg].depth = 0;
|
self.ci.emit(instrs::cp(dst.reg, node_loc!(self, arg).reg));
|
||||||
}
|
}
|
||||||
|
|
||||||
let reloc = Reloc::new(self.ci.code.len(), 3, 4);
|
let reloc = Reloc::new(self.ci.code.len(), 3, 4);
|
||||||
|
@ -2770,8 +2865,7 @@ impl Codegen {
|
||||||
if color.rc == 0 {
|
if color.rc == 0 {
|
||||||
if color.depth != self.ci.loop_depth {
|
if color.depth != self.ci.loop_depth {
|
||||||
self.ci.delayed_frees.push(node.color);
|
self.ci.delayed_frees.push(node.color);
|
||||||
} else {
|
} else if color.loc != Loc::default() {
|
||||||
debug_assert_ne!(color.loc, Loc::default(), "{:?}", node);
|
|
||||||
self.ci.regs.free(color.loc.reg);
|
self.ci.regs.free(color.loc.reg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -64d
|
ADDI64 r254, r254, -80d
|
||||||
ST r31, r254, 0a, 64h
|
ST r31, r254, 0a, 80h
|
||||||
JAL r31, r0, :check_platform
|
JAL r31, r0, :check_platform
|
||||||
CP r32, r1
|
CP r32, r1
|
||||||
LI64 r33, 100d
|
LI64 r33, 100d
|
||||||
|
@ -17,29 +17,31 @@ main:
|
||||||
CP r3, r36
|
CP r3, r36
|
||||||
CP r4, r33
|
CP r4, r33
|
||||||
JAL r31, r0, :set_pixel
|
JAL r31, r0, :set_pixel
|
||||||
CP r37, r35
|
CP r37, r1
|
||||||
ADDI64 r37, r37, 1d
|
CP r38, r35
|
||||||
CP r35, r37
|
ADDI64 r38, r38, 1d
|
||||||
|
CP r35, r38
|
||||||
JMP :1
|
JMP :1
|
||||||
0: CP r2, r35
|
0: CP r2, r35
|
||||||
CP r3, r36
|
CP r3, r36
|
||||||
CP r4, r33
|
CP r4, r33
|
||||||
JAL r31, r0, :set_pixel
|
JAL r31, r0, :set_pixel
|
||||||
|
CP r38, r1
|
||||||
LI64 r35, 0d
|
LI64 r35, 0d
|
||||||
CP r37, r36
|
CP r39, r36
|
||||||
ADDI64 r37, r37, 1d
|
ADDI64 r39, r39, 1d
|
||||||
CP r36, r37
|
CP r36, r39
|
||||||
1: CP r37, r36
|
1: CP r39, r36
|
||||||
CP r38, r33
|
CP r40, r33
|
||||||
CMPS r37, r37, r38
|
CMPS r39, r39, r40
|
||||||
CMPUI r37, r37, 0d
|
CMPUI r39, r39, 0d
|
||||||
NOT r37, r37
|
NOT r39, r39
|
||||||
JEQ r37, r0, :2
|
JEQ r39, r0, :2
|
||||||
JMP :3
|
JMP :3
|
||||||
2: JMP :4
|
2: JMP :4
|
||||||
3: LI64 r1, 0d
|
3: LI64 r1, 0d
|
||||||
LD r31, r254, 0a, 64h
|
LD r31, r254, 0a, 80h
|
||||||
ADDI64 r254, r254, 64d
|
ADDI64 r254, r254, 80d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
set_pixel:
|
set_pixel:
|
||||||
ADDI64 r254, r254, -32d
|
ADDI64 r254, r254, -32d
|
||||||
|
@ -67,6 +69,6 @@ x86_fb_ptr:
|
||||||
LD r31, r254, 0a, 8h
|
LD r31, r254, 0a, 8h
|
||||||
ADDI64 r254, r254, 8d
|
ADDI64 r254, r254, 8d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 505
|
code size: 511
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -16d
|
ADDI64 r254, r254, -32d
|
||||||
ST r31, r254, 0a, 16h
|
ST r31, r254, 0a, 32h
|
||||||
|
LRA r32, r0, :complex_global_var
|
||||||
|
LRA r33, r0, :complex_global_var
|
||||||
|
LD r34, r33, 0a, 8h
|
||||||
|
ADDI64 r34, r34, 5d
|
||||||
|
ST r34, r32, 0a, 8h
|
||||||
LRA r32, r0, :complex_global_var
|
LRA r32, r0, :complex_global_var
|
||||||
LD r1, r32, 0a, 8h
|
LD r1, r32, 0a, 8h
|
||||||
LD r31, r254, 0a, 16h
|
LD r31, r254, 0a, 32h
|
||||||
ADDI64 r254, r254, 16d
|
ADDI64 r254, r254, 32d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 267
|
code size: 318
|
||||||
ret: 50
|
ret: 55
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -27,12 +27,11 @@ fib:
|
||||||
CP r35, r32
|
CP r35, r32
|
||||||
ADDI64 r35, r35, -1d
|
ADDI64 r35, r35, -1d
|
||||||
CP r32, r35
|
CP r32, r35
|
||||||
LI64 r35, 0d
|
|
||||||
JMP :2
|
JMP :2
|
||||||
1: CP r1, r33
|
1: CP r1, r33
|
||||||
LD r31, r254, 0a, 48h
|
LD r31, r254, 0a, 48h
|
||||||
ADDI64 r254, r254, 48d
|
ADDI64 r254, r254, 48d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 258
|
code size: 248
|
||||||
ret: 55
|
ret: 55
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -104d
|
ADDI64 r254, r254, -96d
|
||||||
ST r31, r254, 0a, 104h
|
ST r31, r254, 0a, 96h
|
||||||
JAL r31, r0, :check_platform
|
JAL r31, r0, :check_platform
|
||||||
LI64 r32, 0d
|
LI64 r32, 0d
|
||||||
CP r33, r32
|
CP r33, r32
|
||||||
|
@ -12,25 +12,30 @@ main:
|
||||||
CP r39, r37
|
CP r39, r37
|
||||||
4: ADDI64 r40, r35, 1d
|
4: ADDI64 r40, r35, 1d
|
||||||
JGTS r33, r40, :0
|
JGTS r33, r40, :0
|
||||||
|
CP r2, r33
|
||||||
|
CP r3, r33
|
||||||
|
CP r4, r37
|
||||||
JAL r31, r0, :set_pixel
|
JAL r31, r0, :set_pixel
|
||||||
CP r41, r4
|
CP r41, r37
|
||||||
ADDI64 r42, r3, 1d
|
ADDI64 r33, r33, 1d
|
||||||
CP r43, r3
|
CP r42, r33
|
||||||
JMP :1
|
JMP :1
|
||||||
0: JAL r31, r0, :set_pixel
|
0: CP r2, r33
|
||||||
CP r41, r4
|
CP r3, r38
|
||||||
CP r42, r32
|
CP r4, r39
|
||||||
ADDI64 r43, r3, 1d
|
JAL r31, r0, :set_pixel
|
||||||
1: JNE r43, r41, :2
|
CP r41, r39
|
||||||
|
CP r33, r32
|
||||||
|
ADDI64 r42, r38, 1d
|
||||||
|
1: JNE r42, r41, :2
|
||||||
JMP :3
|
JMP :3
|
||||||
2: CP r2, r42
|
2: CP r35, r34
|
||||||
CP r35, r34
|
CP r37, r36
|
||||||
CP r4, r36
|
CP r38, r42
|
||||||
CP r3, r43
|
CP r39, r41
|
||||||
CP r4, r41
|
|
||||||
JMP :4
|
JMP :4
|
||||||
3: LD r31, r254, 0a, 104h
|
3: LD r31, r254, 0a, 96h
|
||||||
ADDI64 r254, r254, 104d
|
ADDI64 r254, r254, 96d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
set_pixel:
|
set_pixel:
|
||||||
ADDI64 r254, r254, -8d
|
ADDI64 r254, r254, -8d
|
||||||
|
@ -53,6 +58,7 @@ x86_fb_ptr:
|
||||||
LD r31, r254, 0a, 8h
|
LD r31, r254, 0a, 8h
|
||||||
ADDI64 r254, r254, 8d
|
ADDI64 r254, r254, 8d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 422
|
timed out
|
||||||
|
code size: 437
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -16d
|
ADDI64 r254, r254, -24d
|
||||||
ST r31, r254, 0a, 16h
|
ST r31, r254, 0a, 24h
|
||||||
LI64 r2, 10d
|
LI64 r32, 10d
|
||||||
|
CP r2, r32
|
||||||
JAL r31, r0, :add_one
|
JAL r31, r0, :add_one
|
||||||
CP r32, r1
|
CP r32, r1
|
||||||
LI64 r2, 20d
|
LI64 r33, 20d
|
||||||
|
CP r2, r33
|
||||||
JAL r31, r0, :add_two
|
JAL r31, r0, :add_two
|
||||||
ADD64 r1, r1, r32
|
ADD64 r1, r1, r32
|
||||||
LD r31, r254, 0a, 16h
|
LD r31, r254, 0a, 24h
|
||||||
ADDI64 r254, r254, 16d
|
ADDI64 r254, r254, 24d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
add_two:
|
add_two:
|
||||||
ADDI64 r254, r254, -8d
|
ADDI64 r254, r254, -8d
|
||||||
|
@ -26,6 +28,6 @@ add_one:
|
||||||
LD r31, r254, 0a, 8h
|
LD r31, r254, 0a, 8h
|
||||||
ADDI64 r254, r254, 8d
|
ADDI64 r254, r254, 8d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 254
|
code size: 260
|
||||||
ret: 33
|
ret: 33
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,28 +1,31 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -8d
|
ADDI64 r254, r254, -16d
|
||||||
ST r31, r254, 0a, 8h
|
ST r31, r254, 0a, 16h
|
||||||
LI64 r2, 10d
|
LI64 r32, 10d
|
||||||
|
CP r2, r32
|
||||||
JAL r31, r0, :fib
|
JAL r31, r0, :fib
|
||||||
LD r31, r254, 0a, 8h
|
LD r31, r254, 0a, 16h
|
||||||
ADDI64 r254, r254, 8d
|
ADDI64 r254, r254, 16d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
fib:
|
fib:
|
||||||
ADDI64 r254, r254, -32d
|
ADDI64 r254, r254, -40d
|
||||||
ST r31, r254, 0a, 32h
|
ST r31, r254, 0a, 40h
|
||||||
CP r32, r2
|
CP r32, r2
|
||||||
LI64 r33, 2d
|
LI64 r33, 2d
|
||||||
JGTS r32, r33, :0
|
JGTS r32, r33, :0
|
||||||
LI64 r1, 1d
|
LI64 r1, 1d
|
||||||
JMP :1
|
JMP :1
|
||||||
0: ADDI64 r2, r32, -1d
|
0: ADDI64 r34, r32, -1d
|
||||||
|
CP r2, r34
|
||||||
JAL r31, r0, :fib
|
JAL r31, r0, :fib
|
||||||
CP r34, r1
|
CP r34, r1
|
||||||
SUB64 r2, r32, r33
|
SUB64 r35, r32, r33
|
||||||
|
CP r2, r35
|
||||||
JAL r31, r0, :fib
|
JAL r31, r0, :fib
|
||||||
ADD64 r1, r1, r34
|
ADD64 r1, r34, r1
|
||||||
1: LD r31, r254, 0a, 32h
|
1: LD r31, r254, 0a, 40h
|
||||||
ADDI64 r254, r254, 32d
|
ADDI64 r254, r254, 40d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 212
|
code size: 221
|
||||||
ret: 55
|
ret: 55
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -8d
|
ADDI64 r254, r254, -16d
|
||||||
ST r31, r254, 0a, 8h
|
ST r31, r254, 0a, 16h
|
||||||
LI64 r2, 10d
|
LI64 r32, 10d
|
||||||
|
CP r2, r32
|
||||||
JAL r31, r0, :fib
|
JAL r31, r0, :fib
|
||||||
LD r31, r254, 0a, 8h
|
LD r31, r254, 0a, 16h
|
||||||
ADDI64 r254, r254, 8d
|
ADDI64 r254, r254, 16d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
fib:
|
fib:
|
||||||
ADDI64 r254, r254, -56d
|
ADDI64 r254, r254, -56d
|
||||||
|
@ -25,6 +26,6 @@ fib:
|
||||||
1: LD r31, r254, 0a, 56h
|
1: LD r31, r254, 0a, 56h
|
||||||
ADDI64 r254, r254, 56d
|
ADDI64 r254, r254, 56d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 204
|
code size: 207
|
||||||
ret: 55
|
ret: 55
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
Loading…
Reference in a new issue