fixing function destinations
This commit is contained in:
parent
d01e31b203
commit
981c17ff19
|
@ -646,6 +646,41 @@ main := fn(): uint {
|
||||||
|
|
||||||
### Purely Testing Examples
|
### Purely Testing Examples
|
||||||
|
|
||||||
|
#### different_function_destinations
|
||||||
|
```hb
|
||||||
|
Stru := struct {a: uint, b: uint}
|
||||||
|
new_stru := fn(): Stru return .(0, 0)
|
||||||
|
|
||||||
|
glob_stru := Stru.(1, 1)
|
||||||
|
|
||||||
|
main := fn(): uint {
|
||||||
|
glob_stru = new_stru()
|
||||||
|
if glob_stru.a != 0 return 300
|
||||||
|
glob_stru = .(1, 1)
|
||||||
|
glob_stru = @inline(new_stru)
|
||||||
|
if glob_stru.a != 0 return 200
|
||||||
|
|
||||||
|
glob_stru = .(1, 1)
|
||||||
|
strus := [Stru].(glob_stru, glob_stru, glob_stru)
|
||||||
|
i := 0
|
||||||
|
loop if i == 3 break else {
|
||||||
|
strus[i] = new_stru()
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
if strus[2].a != 0 return 100
|
||||||
|
|
||||||
|
strus = [Stru].(glob_stru, glob_stru, glob_stru)
|
||||||
|
i = 0
|
||||||
|
loop if i == 3 break else {
|
||||||
|
strus[i] = @inline(new_stru)
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
if strus[2].a != 0 return 10
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
#### triggering_store_in_divergent_branch
|
#### triggering_store_in_divergent_branch
|
||||||
```hb
|
```hb
|
||||||
opaque := fn(): uint {
|
opaque := fn(): uint {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#![feature(
|
#![feature(
|
||||||
|
iter_array_chunks,
|
||||||
assert_matches,
|
assert_matches,
|
||||||
let_chains,
|
let_chains,
|
||||||
if_let_guard,
|
if_let_guard,
|
||||||
|
|
139
lang/src/son.rs
139
lang/src/son.rs
|
@ -125,52 +125,34 @@ impl Default for Nodes {
|
||||||
|
|
||||||
impl Nodes {
|
impl Nodes {
|
||||||
fn loop_depth(&self, target: Nid) -> LoopDepth {
|
fn loop_depth(&self, target: Nid) -> LoopDepth {
|
||||||
if self[target].loop_depth.get() != 0 {
|
|
||||||
return self[target].loop_depth.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
self[target].loop_depth.set(match self[target].kind {
|
self[target].loop_depth.set(match self[target].kind {
|
||||||
Kind::Entry | Kind::Then | Kind::Else | Kind::Call { .. } | Kind::Return | Kind::If => {
|
Kind::Region | Kind::Entry | Kind::Then | Kind::Else | Kind::Call { .. } | Kind::If => {
|
||||||
let dpth = self.loop_depth(self[target].inputs[0]);
|
|
||||||
if self[target].loop_depth.get() != 0 {
|
if self[target].loop_depth.get() != 0 {
|
||||||
return self[target].loop_depth.get();
|
return self[target].loop_depth.get();
|
||||||
}
|
}
|
||||||
dpth
|
self.loop_depth(self[target].inputs[0])
|
||||||
}
|
|
||||||
Kind::Region => {
|
|
||||||
let l = self.loop_depth(self[target].inputs[0]);
|
|
||||||
let r = self.loop_depth(self[target].inputs[1]);
|
|
||||||
debug_assert_eq!(l, r);
|
|
||||||
l
|
|
||||||
}
|
}
|
||||||
Kind::Loop => {
|
Kind::Loop => {
|
||||||
let depth = Self::loop_depth(self, self[target].inputs[0]) + 1;
|
if self[target].loop_depth.get() == self.loop_depth(self[target].inputs[0]) + 1 {
|
||||||
|
return self[target].loop_depth.get();
|
||||||
|
}
|
||||||
|
let depth = self.loop_depth(self[target].inputs[0]) + 1;
|
||||||
self[target].loop_depth.set(depth);
|
self[target].loop_depth.set(depth);
|
||||||
let mut cursor = self[target].inputs[1];
|
let mut cursor = self[target].inputs[1];
|
||||||
while cursor != target {
|
while cursor != target {
|
||||||
self[cursor].loop_depth.set(depth);
|
self[cursor].loop_depth.set(depth);
|
||||||
let next = if self[cursor].kind == Kind::Region {
|
let next = self.idom(cursor);
|
||||||
self.loop_depth(self[cursor].inputs[0]);
|
debug_assert_ne!(next, 0);
|
||||||
self[cursor].inputs[1]
|
|
||||||
} else {
|
|
||||||
self.idom(cursor)
|
|
||||||
};
|
|
||||||
debug_assert_ne!(next, VOID);
|
|
||||||
if matches!(self[cursor].kind, Kind::Then | Kind::Else) {
|
if matches!(self[cursor].kind, Kind::Then | Kind::Else) {
|
||||||
let other = *self[next]
|
debug_assert_eq!(self[next].kind, Kind::If);
|
||||||
.outputs
|
let other = self[next].outputs[(self[next].outputs[0] == cursor) as usize];
|
||||||
.iter()
|
self[other].loop_depth.set(depth - 1);
|
||||||
.find(|&&n| self[n].kind != self[cursor].kind)
|
|
||||||
.unwrap();
|
|
||||||
if self[other].loop_depth.get() == 0 {
|
|
||||||
self[other].loop_depth.set(depth - 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
cursor = next;
|
cursor = next;
|
||||||
}
|
}
|
||||||
depth
|
depth
|
||||||
}
|
}
|
||||||
Kind::Start | Kind::End | Kind::Die => 1,
|
Kind::Start | Kind::End | Kind::Die | Kind::Return => 1,
|
||||||
u => unreachable!("{u:?}"),
|
u => unreachable!("{u:?}"),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -194,21 +176,22 @@ impl Nodes {
|
||||||
self[target].depth.get()
|
self[target].depth.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fix_loops(&mut self) {
|
fn fix_loops(&mut self, stack: &mut Vec<Nid>, seen: &mut BitSet) {
|
||||||
'o: for l in self[LOOPS].outputs.clone() {
|
debug_assert!(stack.is_empty());
|
||||||
let mut cursor = self[l].inputs[1];
|
|
||||||
let depth = self.loop_depth(cursor);
|
|
||||||
while cursor != l {
|
|
||||||
if self[cursor].kind == Kind::If
|
|
||||||
&& self[cursor].outputs.iter().any(|&b| self.loop_depth(b) < depth)
|
|
||||||
{
|
|
||||||
continue 'o;
|
|
||||||
}
|
|
||||||
cursor = self.idom(cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
self[l].outputs.push(NEVER);
|
stack.push(NEVER);
|
||||||
self[NEVER].inputs.push(l);
|
|
||||||
|
while let Some(node) = stack.pop() {
|
||||||
|
if seen.set(node) && self.is_cfg(node) {
|
||||||
|
stack.extend(self[node].inputs.iter());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for l in self[LOOPS].outputs.clone() {
|
||||||
|
if !seen.get(l) {
|
||||||
|
self[l].outputs.push(NEVER);
|
||||||
|
self[NEVER].inputs.push(l);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,7 +582,8 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gcm(&mut self, rpo: &mut Vec<Nid>, visited: &mut BitSet) {
|
fn gcm(&mut self, rpo: &mut Vec<Nid>, visited: &mut BitSet) {
|
||||||
self.fix_loops();
|
visited.clear(self.values.len());
|
||||||
|
self.fix_loops(rpo, visited);
|
||||||
visited.clear(self.values.len());
|
visited.clear(self.values.len());
|
||||||
self.push_up(rpo, visited);
|
self.push_up(rpo, visited);
|
||||||
visited.clear(self.values.len());
|
visited.clear(self.values.len());
|
||||||
|
@ -947,6 +931,10 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
K::If => {
|
K::If => {
|
||||||
|
if self[target].inputs[0] == NEVER {
|
||||||
|
return Some(NEVER);
|
||||||
|
}
|
||||||
|
|
||||||
if self[target].ty == ty::Id::VOID {
|
if self[target].ty == ty::Id::VOID {
|
||||||
match self.try_opt_cond(target) {
|
match self.try_opt_cond(target) {
|
||||||
CondOptRes::Unknown => {}
|
CondOptRes::Unknown => {}
|
||||||
|
@ -962,6 +950,10 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
K::Then => {
|
K::Then => {
|
||||||
|
if self[target].inputs[0] == NEVER {
|
||||||
|
return Some(NEVER);
|
||||||
|
}
|
||||||
|
|
||||||
if self[self[target].inputs[0]].ty == ty::Id::LEFT_UNREACHABLE {
|
if self[self[target].inputs[0]].ty == ty::Id::LEFT_UNREACHABLE {
|
||||||
return Some(NEVER);
|
return Some(NEVER);
|
||||||
} else if self[self[target].inputs[0]].ty == ty::Id::RIGHT_UNREACHABLE {
|
} else if self[self[target].inputs[0]].ty == ty::Id::RIGHT_UNREACHABLE {
|
||||||
|
@ -969,6 +961,10 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
K::Else => {
|
K::Else => {
|
||||||
|
if self[target].inputs[0] == NEVER {
|
||||||
|
return Some(NEVER);
|
||||||
|
}
|
||||||
|
|
||||||
if self[self[target].inputs[0]].ty == ty::Id::RIGHT_UNREACHABLE {
|
if self[self[target].inputs[0]].ty == ty::Id::RIGHT_UNREACHABLE {
|
||||||
return Some(NEVER);
|
return Some(NEVER);
|
||||||
} else if self[self[target].inputs[0]].ty == ty::Id::LEFT_UNREACHABLE {
|
} else if self[self[target].inputs[0]].ty == ty::Id::LEFT_UNREACHABLE {
|
||||||
|
@ -1354,6 +1350,7 @@ impl Nodes {
|
||||||
return Some(self[target].inputs[0]);
|
return Some(self[target].inputs[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ if self.is_cfg(target) && self.idom(target) == NEVER => panic!(),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1665,6 +1662,40 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_loop_depth_integrity(&self, disp: ty::Display) {
|
||||||
|
if !cfg!(debug_assertions) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut failed = false;
|
||||||
|
for &loob in self[LOOPS].outputs.iter() {
|
||||||
|
let mut stack = vec![self[loob].inputs[1]];
|
||||||
|
let mut seen = BitSet::default();
|
||||||
|
seen.set(loob);
|
||||||
|
let depth = self.loop_depth(loob);
|
||||||
|
while let Some(nid) = stack.pop() {
|
||||||
|
if seen.set(nid) {
|
||||||
|
if depth > self.loop_depth(nid) {
|
||||||
|
failed = true;
|
||||||
|
log::error!("{depth} {} {nid} {:?}", self.loop_depth(nid), self[nid]);
|
||||||
|
}
|
||||||
|
|
||||||
|
match self[nid].kind {
|
||||||
|
Kind::Loop | Kind::Region => {
|
||||||
|
stack.extend(&self[nid].inputs[..2]);
|
||||||
|
}
|
||||||
|
_ => stack.push(self[nid].inputs[0]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if failed {
|
||||||
|
self.graphviz_in_browser(disp);
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn load_loop_var(&mut self, index: usize, var: &mut Variable, loops: &mut [Loop]) {
|
fn load_loop_var(&mut self, index: usize, var: &mut Variable, loops: &mut [Loop]) {
|
||||||
if var.value() != VOID {
|
if var.value() != VOID {
|
||||||
return;
|
return;
|
||||||
|
@ -1748,14 +1779,16 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_data_dep(&self, nid: Nid, n: Nid) -> bool {
|
fn is_data_dep(&self, val: Nid, user: Nid) -> bool {
|
||||||
match self[n].kind {
|
match self[user].kind {
|
||||||
Kind::Return => self[n].inputs[1] == nid,
|
Kind::Return => self[user].inputs[1] == val,
|
||||||
_ if self.is_cfg(n) && !matches!(self[n].kind, Kind::Call { .. } | Kind::If) => false,
|
_ if self.is_cfg(user) && !matches!(self[user].kind, Kind::Call { .. } | Kind::If) => {
|
||||||
|
false
|
||||||
|
}
|
||||||
Kind::Join => false,
|
Kind::Join => false,
|
||||||
Kind::Stre => self[n].inputs[3] != nid,
|
Kind::Stre => self[user].inputs[3] != val,
|
||||||
Kind::Load => self[n].inputs[2] != nid,
|
Kind::Load => self[user].inputs[2] != val,
|
||||||
_ => self[n].inputs[0] != nid || self[n].inputs[1..].contains(&nid),
|
_ => self[user].inputs[0] != val || self[user].inputs[1..].contains(&val),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4426,6 +4459,7 @@ impl<'a> Codegen<'a> {
|
||||||
self.ci.nodes.check_final_integrity(self.ty_display(ty::Id::VOID));
|
self.ci.nodes.check_final_integrity(self.ty_display(ty::Id::VOID));
|
||||||
self.ci.nodes.graphviz(self.ty_display(ty::Id::VOID));
|
self.ci.nodes.graphviz(self.ty_display(ty::Id::VOID));
|
||||||
self.ci.nodes.gcm(&mut self.pool.nid_stack, &mut self.pool.nid_set);
|
self.ci.nodes.gcm(&mut self.pool.nid_stack, &mut self.pool.nid_set);
|
||||||
|
self.ci.nodes.check_loop_depth_integrity(self.ty_display(ty::Id::VOID));
|
||||||
self.ci.nodes.basic_blocks();
|
self.ci.nodes.basic_blocks();
|
||||||
self.ci.nodes.graphviz(self.ty_display(ty::Id::VOID));
|
self.ci.nodes.graphviz(self.ty_display(ty::Id::VOID));
|
||||||
} else {
|
} else {
|
||||||
|
@ -4844,6 +4878,7 @@ mod tests {
|
||||||
fb_driver;
|
fb_driver;
|
||||||
|
|
||||||
// Purely Testing Examples;
|
// Purely Testing Examples;
|
||||||
|
different_function_destinations;
|
||||||
triggering_store_in_divergent_branch;
|
triggering_store_in_divergent_branch;
|
||||||
wrong_dead_code_elimination;
|
wrong_dead_code_elimination;
|
||||||
memory_swap;
|
memory_swap;
|
||||||
|
|
|
@ -336,6 +336,18 @@ impl Backend for HbvmBackend {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Nodes {
|
impl Nodes {
|
||||||
|
fn strip_offset(&self, region: Nid, ty: ty::Id, tys: &Types) -> (Nid, Offset) {
|
||||||
|
if matches!(self[region].kind, Kind::BinOp { op: TokenKind::Add | TokenKind::Sub })
|
||||||
|
&& self[region].lock_rc != 0
|
||||||
|
&& let Kind::CInt { value } = self[self[region].inputs[2]].kind
|
||||||
|
&& ty.loc(tys) == Loc::Reg
|
||||||
|
{
|
||||||
|
(self[region].inputs[1], value as _)
|
||||||
|
} else {
|
||||||
|
(region, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn reschedule_block(&mut self, from: Nid, outputs: &mut Vc) {
|
fn reschedule_block(&mut self, from: Nid, outputs: &mut Vc) {
|
||||||
// NOTE: this code is horible
|
// NOTE: this code is horible
|
||||||
let fromc = Some(&from);
|
let fromc = Some(&from);
|
||||||
|
@ -638,17 +650,10 @@ impl HbvmBackend {
|
||||||
self.emit(instrs::jal(reg::RET_ADDR, reg::ZERO, 0));
|
self.emit(instrs::jal(reg::RET_ADDR, reg::ZERO, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(PLoc::WideReg(r, size)) = ret {
|
if node.ty.loc(tys) == Loc::Stack
|
||||||
debug_assert_eq!(nodes[*node.inputs.last().unwrap()].kind, Kind::Stck);
|
&& let Some(PLoc::Reg(r, size) | PLoc::WideReg(r, size)) = ret
|
||||||
let stck = self.offsets[*node.inputs.last().unwrap() as usize];
|
|
||||||
self.emit(instrs::st(r, reg::STACK_PTR, stck as _, size));
|
|
||||||
}
|
|
||||||
if let Some(PLoc::Reg(r, size)) = ret
|
|
||||||
&& node.ty.loc(tys) == Loc::Stack
|
|
||||||
{
|
{
|
||||||
debug_assert_eq!(nodes[*node.inputs.last().unwrap()].kind, Kind::Stck);
|
self.emit(instrs::st(r, *allocs.last().unwrap(), 0, size));
|
||||||
let stck = self.offsets[*node.inputs.last().unwrap() as usize];
|
|
||||||
self.emit(instrs::st(r, reg::STACK_PTR, stck as _, size));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Kind::Global { global } => {
|
Kind::Global { global } => {
|
||||||
|
@ -662,14 +667,7 @@ impl HbvmBackend {
|
||||||
self.emit(instrs::addi64(allocs[0], base, offset as _));
|
self.emit(instrs::addi64(allocs[0], base, offset as _));
|
||||||
}
|
}
|
||||||
Kind::Load => {
|
Kind::Load => {
|
||||||
let mut region = node.inputs[1];
|
let (region, offset) = nodes.strip_offset(node.inputs[1], node.ty, tys);
|
||||||
let mut offset = 0;
|
|
||||||
if nodes[region].kind == (Kind::BinOp { op: TokenKind::Add })
|
|
||||||
&& let Kind::CInt { value } = nodes[nodes[region].inputs[2]].kind
|
|
||||||
{
|
|
||||||
region = nodes[region].inputs[1];
|
|
||||||
offset = value as Offset;
|
|
||||||
}
|
|
||||||
let size = tys.size_of(node.ty);
|
let size = tys.size_of(node.ty);
|
||||||
if node.ty.loc(tys) != Loc::Stack {
|
if node.ty.loc(tys) != Loc::Stack {
|
||||||
let (base, offset) = match nodes[region].kind {
|
let (base, offset) = match nodes[region].kind {
|
||||||
|
@ -681,16 +679,8 @@ impl HbvmBackend {
|
||||||
}
|
}
|
||||||
Kind::Stre if node.inputs[1] == VOID => {}
|
Kind::Stre if node.inputs[1] == VOID => {}
|
||||||
Kind::Stre => {
|
Kind::Stre => {
|
||||||
let mut region = node.inputs[2];
|
let (region, offset) = nodes.strip_offset(node.inputs[2], node.ty, tys);
|
||||||
let mut offset = 0;
|
|
||||||
let size = u16::try_from(tys.size_of(node.ty)).expect("TODO");
|
let size = u16::try_from(tys.size_of(node.ty)).expect("TODO");
|
||||||
if nodes[region].kind == (Kind::BinOp { op: TokenKind::Add })
|
|
||||||
&& let Kind::CInt { value } = nodes[nodes[region].inputs[2]].kind
|
|
||||||
&& node.ty.loc(tys) == Loc::Reg
|
|
||||||
{
|
|
||||||
region = nodes[region].inputs[1];
|
|
||||||
offset = value as Offset;
|
|
||||||
}
|
|
||||||
let (base, offset, src) = match nodes[region].kind {
|
let (base, offset, src) = match nodes[region].kind {
|
||||||
Kind::Stck if node.ty.loc(tys) == Loc::Reg => {
|
Kind::Stck if node.ty.loc(tys) == Loc::Reg => {
|
||||||
(reg::STACK_PTR, self.offsets[region as usize] + offset, allocs[0])
|
(reg::STACK_PTR, self.offsets[region as usize] + offset, allocs[0])
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use {
|
use {
|
||||||
super::{HbvmBackend, Nid, Nodes},
|
super::{HbvmBackend, Nid, Nodes},
|
||||||
crate::{
|
crate::{
|
||||||
lexer::TokenKind,
|
|
||||||
parser,
|
parser,
|
||||||
reg::{self, Reg},
|
reg::{self, Reg},
|
||||||
son::{debug_assert_matches, Kind, ARG_START, MEM, VOID},
|
son::{debug_assert_matches, Kind, ARG_START, MEM, VOID},
|
||||||
|
@ -10,7 +9,8 @@ use {
|
||||||
PLoc, Sig, Types,
|
PLoc, Sig, Types,
|
||||||
},
|
},
|
||||||
alloc::{borrow::ToOwned, vec::Vec},
|
alloc::{borrow::ToOwned, vec::Vec},
|
||||||
core::{mem, ops::Range},
|
core::{cell::RefCell, mem, ops::Range},
|
||||||
|
hashbrown::HashSet,
|
||||||
hbbytecode::{self as instrs},
|
hbbytecode::{self as instrs},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -101,6 +101,28 @@ impl HbvmBackend {
|
||||||
let node = &fuc.nodes[nid];
|
let node = &fuc.nodes[nid];
|
||||||
alloc_buf.clear();
|
alloc_buf.clear();
|
||||||
|
|
||||||
|
let atr = |allc: Nid| {
|
||||||
|
let allc = strip_load(allc);
|
||||||
|
debug_assert_eq!(
|
||||||
|
fuc.nodes[allc].lock_rc,
|
||||||
|
0,
|
||||||
|
"{:?} {}",
|
||||||
|
fuc.nodes[allc],
|
||||||
|
ty::Display::new(tys, files, fuc.nodes[allc].ty)
|
||||||
|
);
|
||||||
|
debug_assert!(
|
||||||
|
fuc.marked.borrow().contains(&(allc, nid))
|
||||||
|
|| nid == allc
|
||||||
|
|| fuc.nodes.is_hard_zero(allc)
|
||||||
|
|| allc == MEM
|
||||||
|
|| matches!(node.kind, Kind::Loop | Kind::Region),
|
||||||
|
"{nid} {:?}\n{allc} {:?}",
|
||||||
|
fuc.nodes[nid],
|
||||||
|
fuc.nodes[allc]
|
||||||
|
);
|
||||||
|
res.node_to_reg[allc as usize]
|
||||||
|
};
|
||||||
|
|
||||||
let mut is_next_block = false;
|
let mut is_next_block = false;
|
||||||
match node.kind {
|
match node.kind {
|
||||||
Kind::If => {
|
Kind::If => {
|
||||||
|
@ -170,13 +192,14 @@ impl HbvmBackend {
|
||||||
}
|
}
|
||||||
Kind::Return => {
|
Kind::Return => {
|
||||||
let &[_, ret, ..] = node.inputs.as_slice() else { unreachable!() };
|
let &[_, ret, ..] = node.inputs.as_slice() else { unreachable!() };
|
||||||
alloc_buf.push(atr(ret));
|
|
||||||
match retl {
|
match retl {
|
||||||
Some(PLoc::Reg(r, _)) if sig.ret.loc(tys) == Loc::Reg => {
|
Some(PLoc::Reg(r, _)) if sig.ret.loc(tys) == Loc::Reg => {
|
||||||
|
alloc_buf.push(atr(ret));
|
||||||
self.emit(instrs::cp(r, atr(ret)));
|
self.emit(instrs::cp(r, atr(ret)));
|
||||||
}
|
}
|
||||||
Some(PLoc::Ref(..)) => alloc_buf.push(atr(MEM)),
|
Some(PLoc::Ref(..)) => alloc_buf.extend([atr(ret), atr(MEM)]),
|
||||||
_ => {}
|
Some(_) => alloc_buf.push(atr(ret)),
|
||||||
|
None => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Kind::Die => self.emit(instrs::un()),
|
Kind::Die => self.emit(instrs::un()),
|
||||||
|
@ -224,12 +247,7 @@ impl HbvmBackend {
|
||||||
}
|
}
|
||||||
Kind::Stck | Kind::Global { .. } => alloc_buf.push(atr(nid)),
|
Kind::Stck | Kind::Global { .. } => alloc_buf.push(atr(nid)),
|
||||||
Kind::Load => {
|
Kind::Load => {
|
||||||
let mut region = node.inputs[1];
|
let (region, _) = fuc.nodes.strip_offset(node.inputs[1], node.ty, tys);
|
||||||
if fuc.nodes[region].kind == (Kind::BinOp { op: TokenKind::Add })
|
|
||||||
&& let Kind::CInt { .. } = fuc.nodes[fuc.nodes[region].inputs[2]].kind
|
|
||||||
{
|
|
||||||
region = fuc.nodes[region].inputs[1];
|
|
||||||
}
|
|
||||||
if node.ty.loc(tys) != Loc::Stack {
|
if node.ty.loc(tys) != Loc::Stack {
|
||||||
alloc_buf.push(atr(nid));
|
alloc_buf.push(atr(nid));
|
||||||
match fuc.nodes[region].kind {
|
match fuc.nodes[region].kind {
|
||||||
|
@ -240,14 +258,7 @@ impl HbvmBackend {
|
||||||
}
|
}
|
||||||
Kind::Stre if node.inputs[1] == VOID => {}
|
Kind::Stre if node.inputs[1] == VOID => {}
|
||||||
Kind::Stre => {
|
Kind::Stre => {
|
||||||
let mut region = node.inputs[2];
|
let (region, _) = fuc.nodes.strip_offset(node.inputs[2], node.ty, tys);
|
||||||
if matches!(fuc.nodes[region].kind, Kind::BinOp {
|
|
||||||
op: TokenKind::Add | TokenKind::Sub
|
|
||||||
}) && let Kind::CInt { .. } = fuc.nodes[fuc.nodes[region].inputs[2]].kind
|
|
||||||
&& node.ty.loc(tys) == Loc::Reg
|
|
||||||
{
|
|
||||||
region = fuc.nodes[region].inputs[1];
|
|
||||||
}
|
|
||||||
match fuc.nodes[region].kind {
|
match fuc.nodes[region].kind {
|
||||||
Kind::Stck if node.ty.loc(tys) == Loc::Reg => {
|
Kind::Stck if node.ty.loc(tys) == Loc::Reg => {
|
||||||
alloc_buf.push(atr(node.inputs[1]))
|
alloc_buf.push(atr(node.inputs[1]))
|
||||||
|
@ -313,6 +324,7 @@ pub struct Function<'a> {
|
||||||
tys: &'a Types,
|
tys: &'a Types,
|
||||||
visited: BitSet,
|
visited: BitSet,
|
||||||
func: Func,
|
func: Func,
|
||||||
|
marked: RefCell<HashSet<(Nid, Nid), crate::FnvBuildHasher>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Function<'_> {
|
impl Function<'_> {
|
||||||
|
@ -334,6 +346,7 @@ impl Function<'_> {
|
||||||
.filter(|&(o, &n)| self.nodes.is_data_dep(o, n))
|
.filter(|&(o, &n)| self.nodes.is_data_dep(o, n))
|
||||||
.map(|(p, &n)| (self.use_block(p, n), n))
|
.map(|(p, &n)| (self.use_block(p, n), n))
|
||||||
.inspect(|&(_, n)| debug_assert_eq!(self.nodes[n].lock_rc, 0))
|
.inspect(|&(_, n)| debug_assert_eq!(self.nodes[n].lock_rc, 0))
|
||||||
|
.inspect(|&(_, n)| _ = self.marked.borrow_mut().insert((nid, n)))
|
||||||
.collect_into(buf);
|
.collect_into(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,20 +360,11 @@ impl Function<'_> {
|
||||||
|
|
||||||
fn phi_inputs_of(&self, nid: Nid, buf: &mut Vec<Nid>) {
|
fn phi_inputs_of(&self, nid: Nid, buf: &mut Vec<Nid>) {
|
||||||
match self.nodes[nid].kind {
|
match self.nodes[nid].kind {
|
||||||
Kind::Region => {
|
Kind::Region | Kind::Loop => {
|
||||||
for &inp in self.nodes[nid].outputs.as_slice() {
|
for &inp in self.nodes[nid].outputs.as_slice() {
|
||||||
if self.nodes[inp].is_data_phi() {
|
if self.nodes[inp].is_data_phi() {
|
||||||
|
buf.push(inp);
|
||||||
buf.extend(&self.nodes[inp].inputs[1..]);
|
buf.extend(&self.nodes[inp].inputs[1..]);
|
||||||
buf.push(inp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Kind::Loop => {
|
|
||||||
for &inp in self.nodes[nid].outputs.as_slice() {
|
|
||||||
if self.nodes[inp].is_data_phi() {
|
|
||||||
buf.push(self.nodes[inp].inputs[1]);
|
|
||||||
buf.push(inp);
|
|
||||||
buf.push(self.nodes[inp].inputs[2]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,6 +416,7 @@ impl<'a> Function<'a> {
|
||||||
sig,
|
sig,
|
||||||
visited: Default::default(),
|
visited: Default::default(),
|
||||||
func: Default::default(),
|
func: Default::default(),
|
||||||
|
marked: Default::default(),
|
||||||
};
|
};
|
||||||
s.visited.clear(s.nodes.values.len());
|
s.visited.clear(s.nodes.values.len());
|
||||||
s.emit_node(VOID);
|
s.emit_node(VOID);
|
||||||
|
@ -580,13 +585,25 @@ impl<'a> Env<'a> {
|
||||||
let mut use_buf = mem::take(&mut self.res.use_buf);
|
let mut use_buf = mem::take(&mut self.res.use_buf);
|
||||||
|
|
||||||
let mut phi_input_buf = mem::take(&mut self.res.phi_input_buf);
|
let mut phi_input_buf = mem::take(&mut self.res.phi_input_buf);
|
||||||
for block in &self.func.blocks {
|
for block in self.func.blocks.iter().rev() {
|
||||||
self.ctx.phi_inputs_of(block.entry, &mut phi_input_buf);
|
self.ctx.phi_inputs_of(block.entry, &mut phi_input_buf);
|
||||||
for param in phi_input_buf.drain(..) {
|
for [a, rest @ ..] in phi_input_buf.drain(..).array_chunks::<3>() {
|
||||||
if !visited.set(param) {
|
if visited.set(a) {
|
||||||
continue;
|
self.append_bundle(a, &mut bundle, &mut use_buf, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
for r in rest {
|
||||||
|
if !visited.set(r) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.append_bundle(
|
||||||
|
r,
|
||||||
|
&mut bundle,
|
||||||
|
&mut use_buf,
|
||||||
|
Some(self.res.node_to_reg[a as usize] as usize - 1),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
self.append_bundle(param, &mut bundle, &mut use_buf);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.res.phi_input_buf = phi_input_buf;
|
self.res.phi_input_buf = phi_input_buf;
|
||||||
|
@ -595,13 +612,19 @@ impl<'a> Env<'a> {
|
||||||
if visited.get(inst) || inst == 0 {
|
if visited.get(inst) || inst == 0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
self.append_bundle(inst, &mut bundle, &mut use_buf);
|
self.append_bundle(inst, &mut bundle, &mut use_buf, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.res.use_buf = use_buf;
|
self.res.use_buf = use_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn append_bundle(&mut self, inst: Nid, bundle: &mut Bundle, use_buf: &mut Vec<(Nid, Nid)>) {
|
fn append_bundle(
|
||||||
|
&mut self,
|
||||||
|
inst: Nid,
|
||||||
|
bundle: &mut Bundle,
|
||||||
|
use_buf: &mut Vec<(Nid, Nid)>,
|
||||||
|
prefered: Option<usize>,
|
||||||
|
) {
|
||||||
let dom = self.ctx.idom_of(inst);
|
let dom = self.ctx.idom_of(inst);
|
||||||
self.ctx.uses_of(inst, use_buf);
|
self.ctx.uses_of(inst, use_buf);
|
||||||
for (cursor, uinst) in use_buf.drain(..) {
|
for (cursor, uinst) in use_buf.drain(..) {
|
||||||
|
@ -611,7 +634,7 @@ impl<'a> Env<'a> {
|
||||||
range.start =
|
range.start =
|
||||||
range.start.max(self.ctx.instr_of(inst).map_or(0, |n| n + 1) as usize);
|
range.start.max(self.ctx.instr_of(inst).map_or(0, |n| n + 1) as usize);
|
||||||
debug_assert!(range.start < range.end, "{:?}", range);
|
debug_assert!(range.start < range.end, "{:?}", range);
|
||||||
range.end = range.end.min(
|
let new = range.end.min(
|
||||||
self.ctx
|
self.ctx
|
||||||
.instr_of(uinst)
|
.instr_of(uinst)
|
||||||
.filter(|_| {
|
.filter(|_| {
|
||||||
|
@ -621,6 +644,8 @@ impl<'a> Env<'a> {
|
||||||
})
|
})
|
||||||
.map_or(Nid::MAX, |n| n + 1) as usize,
|
.map_or(Nid::MAX, |n| n + 1) as usize,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
range.end = new;
|
||||||
debug_assert!(range.start < range.end);
|
debug_assert!(range.start < range.end);
|
||||||
|
|
||||||
bundle.add(range);
|
bundle.add(range);
|
||||||
|
@ -632,15 +657,25 @@ impl<'a> Env<'a> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.res.bundles.iter_mut().enumerate().find(|(_, b)| !b.overlaps(bundle)) {
|
if let Some(prefered) = prefered
|
||||||
Some((i, other)) => {
|
&& !self.res.bundles[prefered].overlaps(bundle)
|
||||||
other.merge(bundle);
|
{
|
||||||
bundle.clear();
|
self.res.bundles[prefered].merge(bundle);
|
||||||
self.res.node_to_reg[inst as usize] = i as Reg + 1;
|
bundle.clear();
|
||||||
}
|
self.res.node_to_reg[inst as usize] = prefered as Reg + 1;
|
||||||
None => {
|
} else {
|
||||||
self.res.bundles.push(mem::replace(bundle, Bundle::new(self.func.instrs.len())));
|
match self.res.bundles.iter_mut().enumerate().find(|(_, b)| !b.overlaps(bundle)) {
|
||||||
self.res.node_to_reg[inst as usize] = self.res.bundles.len() as Reg;
|
Some((i, other)) => {
|
||||||
|
other.merge(bundle);
|
||||||
|
bundle.clear();
|
||||||
|
self.res.node_to_reg[inst as usize] = i as Reg + 1;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
self.res
|
||||||
|
.bundles
|
||||||
|
.push(mem::replace(bundle, Bundle::new(self.func.instrs.len())));
|
||||||
|
self.res.node_to_reg[inst as usize] = self.res.bundles.len() as Reg;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use {
|
use {
|
||||||
super::{HbvmBackend, Nid, Nodes},
|
super::{HbvmBackend, Nid, Nodes},
|
||||||
crate::{
|
crate::{
|
||||||
lexer::TokenKind,
|
|
||||||
parser, reg,
|
parser, reg,
|
||||||
son::{debug_assert_matches, Kind, ARG_START, MEM, NEVER, VOID},
|
son::{debug_assert_matches, Kind, ARG_START, MEM, NEVER, VOID},
|
||||||
ty::{self, Arg, Loc},
|
ty::{self, Arg, Loc},
|
||||||
|
@ -540,6 +539,8 @@ impl<'a> Function<'a> {
|
||||||
self.rg(*node.inputs.last().unwrap()),
|
self.rg(*node.inputs.last().unwrap()),
|
||||||
regalloc2::PReg::new(r as _, regalloc2::RegClass::Int),
|
regalloc2::PReg::new(r as _, regalloc2::RegClass::Int),
|
||||||
));
|
));
|
||||||
|
} else if node.ty.loc(self.tys) == Loc::Stack {
|
||||||
|
ops.push(self.urg(*node.inputs.last().unwrap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.add_instr(nid, ops);
|
self.add_instr(nid, ops);
|
||||||
|
@ -565,13 +566,7 @@ impl<'a> Function<'a> {
|
||||||
Kind::Assert { .. } => unreachable!(),
|
Kind::Assert { .. } => unreachable!(),
|
||||||
Kind::End | Kind::Phi | Kind::Arg | Kind::Mem | Kind::Loops | Kind::Join => {}
|
Kind::End | Kind::Phi | Kind::Arg | Kind::Mem | Kind::Loops | Kind::Join => {}
|
||||||
Kind::Load { .. } => {
|
Kind::Load { .. } => {
|
||||||
let mut region = node.inputs[1];
|
let (region, _) = self.nodes.strip_offset(node.inputs[1], node.ty, self.tys);
|
||||||
if self.nodes[region].kind == (Kind::BinOp { op: TokenKind::Add })
|
|
||||||
&& self.nodes.is_const(self.nodes[region].inputs[2])
|
|
||||||
&& node.ty.loc(self.tys) == Loc::Reg
|
|
||||||
{
|
|
||||||
region = self.nodes[region].inputs[1]
|
|
||||||
}
|
|
||||||
let ops = match self.nodes[region].kind {
|
let ops = match self.nodes[region].kind {
|
||||||
Kind::Stck => vec![self.drg(nid)],
|
Kind::Stck => vec![self.drg(nid)],
|
||||||
_ => vec![self.drg(nid), self.urg(region)],
|
_ => vec![self.drg(nid), self.urg(region)],
|
||||||
|
@ -580,13 +575,7 @@ impl<'a> Function<'a> {
|
||||||
}
|
}
|
||||||
Kind::Stre => {
|
Kind::Stre => {
|
||||||
debug_assert_ne!(self.tys.size_of(node.ty), 0);
|
debug_assert_ne!(self.tys.size_of(node.ty), 0);
|
||||||
let mut region = node.inputs[2];
|
let (region, _) = self.nodes.strip_offset(node.inputs[2], node.ty, self.tys);
|
||||||
if self.nodes[region].kind == (Kind::BinOp { op: TokenKind::Add })
|
|
||||||
&& self.nodes.is_const(self.nodes[region].inputs[2])
|
|
||||||
&& node.ty.loc(self.tys) == Loc::Reg
|
|
||||||
{
|
|
||||||
region = self.nodes[region].inputs[1]
|
|
||||||
}
|
|
||||||
let ops = match self.nodes[region].kind {
|
let ops = match self.nodes[region].kind {
|
||||||
_ if node.ty.loc(self.tys) == Loc::Stack => {
|
_ if node.ty.loc(self.tys) == Loc::Stack => {
|
||||||
if self.nodes[node.inputs[1]].kind == Kind::Arg {
|
if self.nodes[node.inputs[1]].kind == Kind::Arg {
|
||||||
|
|
82
lang/tests/son_tests_different_function_destinations.txt
Normal file
82
lang/tests/son_tests_different_function_destinations.txt
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
main:
|
||||||
|
ADDI64 r254, r254, -208d
|
||||||
|
ST r31, r254, 80a, 128h
|
||||||
|
LRA r32, r0, :glob_stru
|
||||||
|
JAL r31, r0, :new_stru
|
||||||
|
ST r1, r32, 0a, 16h
|
||||||
|
CP r1, r0
|
||||||
|
LD r33, r32, 0a, 8h
|
||||||
|
JEQ r33, r1, :0
|
||||||
|
LI64 r1, 300d
|
||||||
|
JMP :1
|
||||||
|
0: LI64 r34, 1d
|
||||||
|
ST r34, r32, 0a, 8h
|
||||||
|
ST r34, r32, 8a, 8h
|
||||||
|
ST r1, r32, 0a, 8h
|
||||||
|
LD r35, r32, 0a, 8h
|
||||||
|
JEQ r35, r1, :2
|
||||||
|
LI64 r1, 200d
|
||||||
|
JMP :1
|
||||||
|
2: CP r36, r1
|
||||||
|
LI64 r37, 3d
|
||||||
|
ST r34, r32, 0a, 8h
|
||||||
|
ST r34, r32, 8a, 8h
|
||||||
|
ADDI64 r38, r254, 16d
|
||||||
|
ST r34, r254, 16a, 8h
|
||||||
|
ST r34, r254, 24a, 8h
|
||||||
|
ST r34, r254, 32a, 8h
|
||||||
|
ST r34, r254, 40a, 8h
|
||||||
|
ST r34, r254, 48a, 8h
|
||||||
|
ST r34, r254, 56a, 8h
|
||||||
|
CP r39, r36
|
||||||
|
8: JNE r39, r37, :3
|
||||||
|
LD r40, r254, 48a, 8h
|
||||||
|
CP r1, r36
|
||||||
|
JEQ r40, r1, :4
|
||||||
|
LI64 r1, 100d
|
||||||
|
JMP :1
|
||||||
|
4: ST r1, r254, 0a, 8h
|
||||||
|
ST r1, r254, 8a, 8h
|
||||||
|
ST r1, r254, 64a, 8h
|
||||||
|
ST r1, r254, 72a, 8h
|
||||||
|
ST r34, r254, 16a, 8h
|
||||||
|
ST r34, r254, 24a, 8h
|
||||||
|
ST r34, r254, 32a, 8h
|
||||||
|
ST r34, r254, 40a, 8h
|
||||||
|
ST r34, r254, 48a, 8h
|
||||||
|
ST r34, r254, 56a, 8h
|
||||||
|
CP r41, r1
|
||||||
|
7: LD r42, r254, 48a, 8h
|
||||||
|
JNE r41, r37, :5
|
||||||
|
JEQ r42, r1, :6
|
||||||
|
LI64 r1, 10d
|
||||||
|
JMP :1
|
||||||
|
6: JMP :1
|
||||||
|
5: ADD64 r43, r41, r34
|
||||||
|
MULI64 r44, r41, 16d
|
||||||
|
ADD64 r45, r38, r44
|
||||||
|
ST r1, r45, 0a, 8h
|
||||||
|
ST r1, r45, 8a, 8h
|
||||||
|
CP r36, r1
|
||||||
|
CP r41, r43
|
||||||
|
JMP :7
|
||||||
|
3: MULI64 r46, r39, 16d
|
||||||
|
ADD64 r43, r38, r46
|
||||||
|
JAL r31, r0, :new_stru
|
||||||
|
ST r1, r43, 0a, 16h
|
||||||
|
ADD64 r39, r39, r34
|
||||||
|
JMP :8
|
||||||
|
1: LD r31, r254, 80a, 128h
|
||||||
|
ADDI64 r254, r254, 208d
|
||||||
|
JALA r0, r31, 0a
|
||||||
|
new_stru:
|
||||||
|
ADDI64 r254, r254, -16d
|
||||||
|
ADDI64 r3, r254, 0d
|
||||||
|
ST r0, r254, 0a, 8h
|
||||||
|
ST r0, r254, 8a, 8h
|
||||||
|
LD r1, r3, 0a, 16h
|
||||||
|
ADDI64 r254, r254, 16d
|
||||||
|
JALA r0, r31, 0a
|
||||||
|
code size: 759
|
||||||
|
ret: 0
|
||||||
|
status: Ok(())
|
|
@ -1,16 +1,16 @@
|
||||||
continue_and_state_change:
|
continue_and_state_change:
|
||||||
LI64 r9, 3d
|
CP r1, r0
|
||||||
LI64 r10, 4d
|
LI64 r10, 3d
|
||||||
LI64 r11, 2d
|
LI64 r11, 4d
|
||||||
LI64 r12, 10d
|
LI64 r12, 2d
|
||||||
6: JLTU r2, r12, :0
|
LI64 r3, 10d
|
||||||
|
6: JLTU r2, r3, :0
|
||||||
CP r1, r2
|
CP r1, r2
|
||||||
JMP :1
|
JMP :1
|
||||||
0: JNE r2, r11, :2
|
0: JNE r2, r12, :2
|
||||||
CP r2, r10
|
CP r2, r11
|
||||||
JMP :3
|
JMP :3
|
||||||
2: JNE r2, r9, :4
|
2: JNE r2, r10, :4
|
||||||
CP r1, r0
|
|
||||||
1: JMP :5
|
1: JMP :5
|
||||||
4: ADDI64 r2, r2, 1d
|
4: ADDI64 r2, r2, 1d
|
||||||
3: JMP :6
|
3: JMP :6
|
||||||
|
|
|
@ -3,7 +3,7 @@ main:
|
||||||
ST r31, r254, 6a, 24h
|
ST r31, r254, 6a, 24h
|
||||||
ADDI64 r32, r254, 0d
|
ADDI64 r32, r254, 0d
|
||||||
2: JAL r31, r0, :return_fn
|
2: JAL r31, r0, :return_fn
|
||||||
ST r1, r254, 0a, 6h
|
ST r1, r32, 0a, 6h
|
||||||
LD r33, r254, 0a, 1h
|
LD r33, r254, 0a, 1h
|
||||||
ANDI r33, r33, 255d
|
ANDI r33, r33, 255d
|
||||||
ANDI r0, r0, 255d
|
ANDI r0, r0, 255d
|
||||||
|
|
|
@ -4,7 +4,7 @@ foo:
|
||||||
ADDI64 r32, r254, 64d
|
ADDI64 r32, r254, 64d
|
||||||
LRA r3, r0, :some_file
|
LRA r3, r0, :some_file
|
||||||
JAL r31, r0, :get
|
JAL r31, r0, :get
|
||||||
ST r1, r254, 64a, 16h
|
ST r1, r32, 0a, 16h
|
||||||
LD r33, r254, 64a, 1h
|
LD r33, r254, 64a, 1h
|
||||||
ANDI r33, r33, 255d
|
ANDI r33, r33, 255d
|
||||||
ANDI r0, r0, 255d
|
ANDI r0, r0, 255d
|
||||||
|
@ -60,7 +60,7 @@ main:
|
||||||
ST r31, r254, 16a, 24h
|
ST r31, r254, 16a, 24h
|
||||||
ADDI64 r32, r254, 0d
|
ADDI64 r32, r254, 0d
|
||||||
JAL r31, r0, :foo
|
JAL r31, r0, :foo
|
||||||
ST r1, r254, 0a, 16h
|
ST r1, r32, 0a, 16h
|
||||||
LD r33, r254, 0a, 1h
|
LD r33, r254, 0a, 1h
|
||||||
ANDI r33, r33, 255d
|
ANDI r33, r33, 255d
|
||||||
ANDI r0, r0, 255d
|
ANDI r0, r0, 255d
|
||||||
|
|
|
@ -7,7 +7,7 @@ main:
|
||||||
JAL r31, r0, :returner_bn
|
JAL r31, r0, :returner_bn
|
||||||
ADDI64 r33, r254, 0d
|
ADDI64 r33, r254, 0d
|
||||||
JAL r31, r0, :returner_cn
|
JAL r31, r0, :returner_cn
|
||||||
ST r1, r254, 0a, 2h
|
ST r1, r33, 0a, 2h
|
||||||
LD r34, r254, 2a, 1h
|
LD r34, r254, 2a, 1h
|
||||||
CP r1, r32
|
CP r1, r32
|
||||||
CMPU r35, r1, r0
|
CMPU r35, r1, r0
|
||||||
|
|
|
@ -45,22 +45,21 @@ main:
|
||||||
JNE r40, r39, :9
|
JNE r40, r39, :9
|
||||||
LI64 r1, 69d
|
LI64 r1, 69d
|
||||||
JMP :3
|
JMP :3
|
||||||
9: ADDI64 r3, r254, 40d
|
9: ADDI64 r41, r254, 40d
|
||||||
CP r41, r3
|
|
||||||
JAL r31, r0, :new_foo
|
JAL r31, r0, :new_foo
|
||||||
ST r1, r254, 40a, 16h
|
ST r1, r41, 0a, 16h
|
||||||
|
CP r3, r41
|
||||||
LD r42, r254, 40a, 8h
|
LD r42, r254, 40a, 8h
|
||||||
JNE r42, r0, :10
|
JNE r42, r0, :10
|
||||||
LI64 r1, 999d
|
LI64 r1, 999d
|
||||||
JMP :3
|
JMP :3
|
||||||
10: LRA r4, r0, :"foo\0"
|
10: LRA r4, r0, :"foo\0"
|
||||||
CP r3, r41
|
|
||||||
CP r2, r3
|
CP r2, r3
|
||||||
LD r2, r2, 0a, 16h
|
LD r2, r2, 0a, 16h
|
||||||
JAL r31, r0, :use_foo
|
JAL r31, r0, :use_foo
|
||||||
ADDI64 r43, r254, 0d
|
ADDI64 r43, r254, 0d
|
||||||
JAL r31, r0, :no_foo
|
JAL r31, r0, :no_foo
|
||||||
ST r1, r254, 0a, 16h
|
ST r1, r43, 0a, 16h
|
||||||
JAL r31, r0, :decide
|
JAL r31, r0, :decide
|
||||||
ANDI r1, r1, 255d
|
ANDI r1, r1, 255d
|
||||||
JNE r1, r0, :11
|
JNE r1, r0, :11
|
||||||
|
@ -126,6 +125,6 @@ use_foo:
|
||||||
ADDI64 r2, r254, 0d
|
ADDI64 r2, r254, 0d
|
||||||
ADDI64 r254, r254, 16d
|
ADDI64 r254, r254, 16d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 1100
|
code size: 1097
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -16d
|
ADDI64 r254, r254, -16d
|
||||||
ADDI64 r4, r254, 0d
|
ADDI64 r7, r254, 0d
|
||||||
CP r3, r0
|
CP r3, r0
|
||||||
CP r4, r0
|
CP r4, r0
|
||||||
CP r5, r0
|
CP r5, r0
|
||||||
CP r6, r0
|
CP r6, r0
|
||||||
ECA
|
ECA
|
||||||
ST r1, r254, 0a, 16h
|
ST r1, r7, 0a, 16h
|
||||||
LD r7, r254, 0a, 1h
|
LD r7, r254, 0a, 1h
|
||||||
ANDI r7, r7, 255d
|
ANDI r7, r7, 255d
|
||||||
ANDI r0, r0, 255d
|
ANDI r0, r0, 255d
|
||||||
|
|
|
@ -8,7 +8,7 @@ main:
|
||||||
ST r34, r254, 0a, 8h
|
ST r34, r254, 0a, 8h
|
||||||
ST r33, r254, 8a, 8h
|
ST r33, r254, 8a, 8h
|
||||||
JAL r31, r0, :opaque
|
JAL r31, r0, :opaque
|
||||||
ST r1, r254, 0a, 16h
|
ST r1, r32, 0a, 16h
|
||||||
LD r35, r254, 8a, 8h
|
LD r35, r254, 8a, 8h
|
||||||
LD r36, r254, 16a, 8h
|
LD r36, r254, 16a, 8h
|
||||||
ADD64 r37, r36, r35
|
ADD64 r37, r36, r35
|
||||||
|
|
|
@ -3,7 +3,7 @@ main:
|
||||||
ST r31, r254, 4a, 96h
|
ST r31, r254, 4a, 96h
|
||||||
ADDI64 r32, r254, 0d
|
ADDI64 r32, r254, 0d
|
||||||
JAL r31, r0, :random_color
|
JAL r31, r0, :random_color
|
||||||
ST r1, r254, 0a, 4h
|
ST r1, r32, 0a, 4h
|
||||||
LD r33, r254, 0a, 1h
|
LD r33, r254, 0a, 1h
|
||||||
LD r34, r254, 1a, 1h
|
LD r34, r254, 1a, 1h
|
||||||
LD r35, r254, 2a, 1h
|
LD r35, r254, 2a, 1h
|
||||||
|
|
|
@ -14,7 +14,7 @@ main:
|
||||||
ST r31, r254, 16a, 24h
|
ST r31, r254, 16a, 24h
|
||||||
ADDI64 r32, r254, 0d
|
ADDI64 r32, r254, 0d
|
||||||
JAL r31, r0, :get_format
|
JAL r31, r0, :get_format
|
||||||
ST r1, r254, 0a, 16h
|
ST r1, r32, 0a, 16h
|
||||||
LD r33, r254, 0a, 1h
|
LD r33, r254, 0a, 1h
|
||||||
ANDI r33, r33, 255d
|
ANDI r33, r33, 255d
|
||||||
ANDI r0, r0, 255d
|
ANDI r0, r0, 255d
|
||||||
|
|
|
@ -16,7 +16,7 @@ main:
|
||||||
ADDI64 r32, r254, 0d
|
ADDI64 r32, r254, 0d
|
||||||
CP r3, r0
|
CP r3, r0
|
||||||
JAL r31, r0, :constructor
|
JAL r31, r0, :constructor
|
||||||
ST r1, r254, 0a, 16h
|
ST r1, r32, 0a, 16h
|
||||||
LD r31, r254, 16a, 16h
|
LD r31, r254, 16a, 16h
|
||||||
ADDI64 r254, r254, 32d
|
ADDI64 r254, r254, 32d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
|
|
|
@ -5,7 +5,7 @@ main:
|
||||||
ADDI64 r33, r254, 0d
|
ADDI64 r33, r254, 0d
|
||||||
LD r2, r32, 0a, 4h
|
LD r2, r32, 0a, 4h
|
||||||
JAL r31, r0, :u32_to_color
|
JAL r31, r0, :u32_to_color
|
||||||
ST r1, r254, 0a, 4h
|
ST r1, r33, 0a, 4h
|
||||||
LD r34, r254, 0a, 1h
|
LD r34, r254, 0a, 1h
|
||||||
ANDI r1, r34, 255d
|
ANDI r1, r34, 255d
|
||||||
LD r31, r254, 4a, 32h
|
LD r31, r254, 4a, 32h
|
||||||
|
|
|
@ -21,7 +21,7 @@ main:
|
||||||
CP r34, r1
|
CP r34, r1
|
||||||
ADDI64 r35, r254, 0d
|
ADDI64 r35, r254, 0d
|
||||||
JAL r31, r0, :optional
|
JAL r31, r0, :optional
|
||||||
ST r1, r254, 0a, 16h
|
ST r1, r35, 0a, 16h
|
||||||
LD r36, r254, 0a, 1h
|
LD r36, r254, 0a, 1h
|
||||||
ANDI r36, r36, 255d
|
ANDI r36, r36, 255d
|
||||||
ANDI r0, r0, 255d
|
ANDI r0, r0, 255d
|
||||||
|
|
|
@ -14,13 +14,13 @@ main:
|
||||||
ST r31, r254, 48a, 80h
|
ST r31, r254, 48a, 80h
|
||||||
ADDI64 r32, r254, 32d
|
ADDI64 r32, r254, 32d
|
||||||
JAL r31, r0, :foo
|
JAL r31, r0, :foo
|
||||||
ST r1, r254, 32a, 16h
|
ST r1, r32, 0a, 16h
|
||||||
ADDI64 r33, r254, 16d
|
ADDI64 r33, r254, 16d
|
||||||
JAL r31, r0, :foo
|
JAL r31, r0, :foo
|
||||||
ST r1, r254, 16a, 16h
|
ST r1, r33, 0a, 16h
|
||||||
ADDI64 r34, r254, 0d
|
ADDI64 r34, r254, 0d
|
||||||
JAL r31, r0, :foo
|
JAL r31, r0, :foo
|
||||||
ST r1, r254, 0a, 16h
|
ST r1, r34, 0a, 16h
|
||||||
LD r35, r254, 24a, 4h
|
LD r35, r254, 24a, 4h
|
||||||
LD r36, r254, 12a, 4h
|
LD r36, r254, 12a, 4h
|
||||||
ANDI r37, r35, 4294967295d
|
ANDI r37, r35, 4294967295d
|
||||||
|
|
|
@ -10,7 +10,7 @@ main:
|
||||||
CP r3, r4
|
CP r3, r4
|
||||||
LD r3, r3, 0a, 16h
|
LD r3, r3, 0a, 16h
|
||||||
JAL r31, r0, :odher_pass
|
JAL r31, r0, :odher_pass
|
||||||
ST r1, r254, 0a, 16h
|
ST r1, r34, 0a, 16h
|
||||||
LD r35, r254, 8a, 8h
|
LD r35, r254, 8a, 8h
|
||||||
JNE r35, r33, :0
|
JNE r35, r33, :0
|
||||||
CP r2, r34
|
CP r2, r34
|
||||||
|
|
|
@ -5,7 +5,7 @@ main:
|
||||||
CP r4, r0
|
CP r4, r0
|
||||||
CP r3, r4
|
CP r3, r4
|
||||||
JAL r31, r0, :maina
|
JAL r31, r0, :maina
|
||||||
ST r1, r254, 0a, 16h
|
ST r1, r32, 0a, 16h
|
||||||
LD r33, r254, 12a, 1h
|
LD r33, r254, 12a, 1h
|
||||||
LD r34, r254, 3a, 1h
|
LD r34, r254, 3a, 1h
|
||||||
SUB8 r35, r34, r33
|
SUB8 r35, r34, r33
|
||||||
|
@ -18,7 +18,7 @@ maina:
|
||||||
ST r31, r254, 20a, 40h
|
ST r31, r254, 20a, 40h
|
||||||
ADDI64 r32, r254, 16d
|
ADDI64 r32, r254, 16d
|
||||||
JAL r31, r0, :small_struct
|
JAL r31, r0, :small_struct
|
||||||
ST r1, r254, 16a, 4h
|
ST r1, r32, 0a, 4h
|
||||||
ADDI64 r33, r254, 0d
|
ADDI64 r33, r254, 0d
|
||||||
ST r0, r254, 0a, 1h
|
ST r0, r254, 0a, 1h
|
||||||
ST r0, r254, 1a, 1h
|
ST r0, r254, 1a, 1h
|
||||||
|
|
Loading…
Reference in a new issue