fixing function destinations

This commit is contained in:
Jakub Doka 2024-11-14 20:25:52 +01:00
parent d01e31b203
commit 981c17ff19
No known key found for this signature in database
GPG key ID: C6E9A89936B8C143
22 changed files with 340 additions and 174 deletions

View file

@ -646,6 +646,41 @@ main := fn(): uint {
### 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
```hb
opaque := fn(): uint {

View file

@ -1,4 +1,5 @@
#![feature(
iter_array_chunks,
assert_matches,
let_chains,
if_let_guard,

View file

@ -125,52 +125,34 @@ impl Default for Nodes {
impl Nodes {
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 {
Kind::Entry | Kind::Then | Kind::Else | Kind::Call { .. } | Kind::Return | Kind::If => {
let dpth = self.loop_depth(self[target].inputs[0]);
Kind::Region | Kind::Entry | Kind::Then | Kind::Else | Kind::Call { .. } | Kind::If => {
if self[target].loop_depth.get() != 0 {
return self[target].loop_depth.get();
}
dpth
}
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
self.loop_depth(self[target].inputs[0])
}
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);
let mut cursor = self[target].inputs[1];
while cursor != target {
self[cursor].loop_depth.set(depth);
let next = if self[cursor].kind == Kind::Region {
self.loop_depth(self[cursor].inputs[0]);
self[cursor].inputs[1]
} else {
self.idom(cursor)
};
debug_assert_ne!(next, VOID);
let next = self.idom(cursor);
debug_assert_ne!(next, 0);
if matches!(self[cursor].kind, Kind::Then | Kind::Else) {
let other = *self[next]
.outputs
.iter()
.find(|&&n| self[n].kind != self[cursor].kind)
.unwrap();
if self[other].loop_depth.get() == 0 {
self[other].loop_depth.set(depth - 1);
}
debug_assert_eq!(self[next].kind, Kind::If);
let other = self[next].outputs[(self[next].outputs[0] == cursor) as usize];
self[other].loop_depth.set(depth - 1);
}
cursor = next;
}
depth
}
Kind::Start | Kind::End | Kind::Die => 1,
Kind::Start | Kind::End | Kind::Die | Kind::Return => 1,
u => unreachable!("{u:?}"),
});
@ -194,21 +176,22 @@ impl Nodes {
self[target].depth.get()
}
fn fix_loops(&mut self) {
'o: for l in self[LOOPS].outputs.clone() {
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);
}
fn fix_loops(&mut self, stack: &mut Vec<Nid>, seen: &mut BitSet) {
debug_assert!(stack.is_empty());
self[l].outputs.push(NEVER);
self[NEVER].inputs.push(l);
stack.push(NEVER);
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) {
self.fix_loops();
visited.clear(self.values.len());
self.fix_loops(rpo, visited);
visited.clear(self.values.len());
self.push_up(rpo, visited);
visited.clear(self.values.len());
@ -947,6 +931,10 @@ impl Nodes {
}
}
K::If => {
if self[target].inputs[0] == NEVER {
return Some(NEVER);
}
if self[target].ty == ty::Id::VOID {
match self.try_opt_cond(target) {
CondOptRes::Unknown => {}
@ -962,6 +950,10 @@ impl Nodes {
}
}
K::Then => {
if self[target].inputs[0] == NEVER {
return Some(NEVER);
}
if self[self[target].inputs[0]].ty == ty::Id::LEFT_UNREACHABLE {
return Some(NEVER);
} else if self[self[target].inputs[0]].ty == ty::Id::RIGHT_UNREACHABLE {
@ -969,6 +961,10 @@ impl Nodes {
}
}
K::Else => {
if self[target].inputs[0] == NEVER {
return Some(NEVER);
}
if self[self[target].inputs[0]].ty == ty::Id::RIGHT_UNREACHABLE {
return Some(NEVER);
} else if self[self[target].inputs[0]].ty == ty::Id::LEFT_UNREACHABLE {
@ -1354,6 +1350,7 @@ impl Nodes {
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]) {
if var.value() != VOID {
return;
@ -1748,14 +1779,16 @@ impl Nodes {
}
}
fn is_data_dep(&self, nid: Nid, n: Nid) -> bool {
match self[n].kind {
Kind::Return => self[n].inputs[1] == nid,
_ if self.is_cfg(n) && !matches!(self[n].kind, Kind::Call { .. } | Kind::If) => false,
fn is_data_dep(&self, val: Nid, user: Nid) -> bool {
match self[user].kind {
Kind::Return => self[user].inputs[1] == val,
_ if self.is_cfg(user) && !matches!(self[user].kind, Kind::Call { .. } | Kind::If) => {
false
}
Kind::Join => false,
Kind::Stre => self[n].inputs[3] != nid,
Kind::Load => self[n].inputs[2] != nid,
_ => self[n].inputs[0] != nid || self[n].inputs[1..].contains(&nid),
Kind::Stre => self[user].inputs[3] != val,
Kind::Load => self[user].inputs[2] != val,
_ => 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.graphviz(self.ty_display(ty::Id::VOID));
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.graphviz(self.ty_display(ty::Id::VOID));
} else {
@ -4844,6 +4878,7 @@ mod tests {
fb_driver;
// Purely Testing Examples;
different_function_destinations;
triggering_store_in_divergent_branch;
wrong_dead_code_elimination;
memory_swap;

View file

@ -336,6 +336,18 @@ impl Backend for HbvmBackend {
}
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) {
// NOTE: this code is horible
let fromc = Some(&from);
@ -638,17 +650,10 @@ impl HbvmBackend {
self.emit(instrs::jal(reg::RET_ADDR, reg::ZERO, 0));
}
if let Some(PLoc::WideReg(r, size)) = ret {
debug_assert_eq!(nodes[*node.inputs.last().unwrap()].kind, Kind::Stck);
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
if node.ty.loc(tys) == Loc::Stack
&& let Some(PLoc::Reg(r, size) | PLoc::WideReg(r, size)) = ret
{
debug_assert_eq!(nodes[*node.inputs.last().unwrap()].kind, Kind::Stck);
let stck = self.offsets[*node.inputs.last().unwrap() as usize];
self.emit(instrs::st(r, reg::STACK_PTR, stck as _, size));
self.emit(instrs::st(r, *allocs.last().unwrap(), 0, size));
}
}
Kind::Global { global } => {
@ -662,14 +667,7 @@ impl HbvmBackend {
self.emit(instrs::addi64(allocs[0], base, offset as _));
}
Kind::Load => {
let mut region = node.inputs[1];
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 (region, offset) = nodes.strip_offset(node.inputs[1], node.ty, tys);
let size = tys.size_of(node.ty);
if node.ty.loc(tys) != Loc::Stack {
let (base, offset) = match nodes[region].kind {
@ -681,16 +679,8 @@ impl HbvmBackend {
}
Kind::Stre if node.inputs[1] == VOID => {}
Kind::Stre => {
let mut region = node.inputs[2];
let mut offset = 0;
let (region, offset) = nodes.strip_offset(node.inputs[2], node.ty, tys);
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 {
Kind::Stck if node.ty.loc(tys) == Loc::Reg => {
(reg::STACK_PTR, self.offsets[region as usize] + offset, allocs[0])

View file

@ -1,7 +1,6 @@
use {
super::{HbvmBackend, Nid, Nodes},
crate::{
lexer::TokenKind,
parser,
reg::{self, Reg},
son::{debug_assert_matches, Kind, ARG_START, MEM, VOID},
@ -10,7 +9,8 @@ use {
PLoc, Sig, Types,
},
alloc::{borrow::ToOwned, vec::Vec},
core::{mem, ops::Range},
core::{cell::RefCell, mem, ops::Range},
hashbrown::HashSet,
hbbytecode::{self as instrs},
};
@ -101,6 +101,28 @@ impl HbvmBackend {
let node = &fuc.nodes[nid];
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;
match node.kind {
Kind::If => {
@ -170,13 +192,14 @@ impl HbvmBackend {
}
Kind::Return => {
let &[_, ret, ..] = node.inputs.as_slice() else { unreachable!() };
alloc_buf.push(atr(ret));
match retl {
Some(PLoc::Reg(r, _)) if sig.ret.loc(tys) == Loc::Reg => {
alloc_buf.push(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()),
@ -224,12 +247,7 @@ impl HbvmBackend {
}
Kind::Stck | Kind::Global { .. } => alloc_buf.push(atr(nid)),
Kind::Load => {
let mut region = node.inputs[1];
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];
}
let (region, _) = fuc.nodes.strip_offset(node.inputs[1], node.ty, tys);
if node.ty.loc(tys) != Loc::Stack {
alloc_buf.push(atr(nid));
match fuc.nodes[region].kind {
@ -240,14 +258,7 @@ impl HbvmBackend {
}
Kind::Stre if node.inputs[1] == VOID => {}
Kind::Stre => {
let mut region = node.inputs[2];
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];
}
let (region, _) = fuc.nodes.strip_offset(node.inputs[2], node.ty, tys);
match fuc.nodes[region].kind {
Kind::Stck if node.ty.loc(tys) == Loc::Reg => {
alloc_buf.push(atr(node.inputs[1]))
@ -313,6 +324,7 @@ pub struct Function<'a> {
tys: &'a Types,
visited: BitSet,
func: Func,
marked: RefCell<HashSet<(Nid, Nid), crate::FnvBuildHasher>>,
}
impl Function<'_> {
@ -334,6 +346,7 @@ impl Function<'_> {
.filter(|&(o, &n)| self.nodes.is_data_dep(o, n))
.map(|(p, &n)| (self.use_block(p, n), n))
.inspect(|&(_, n)| debug_assert_eq!(self.nodes[n].lock_rc, 0))
.inspect(|&(_, n)| _ = self.marked.borrow_mut().insert((nid, n)))
.collect_into(buf);
}
@ -347,20 +360,11 @@ impl Function<'_> {
fn phi_inputs_of(&self, nid: Nid, buf: &mut Vec<Nid>) {
match self.nodes[nid].kind {
Kind::Region => {
Kind::Region | Kind::Loop => {
for &inp in self.nodes[nid].outputs.as_slice() {
if self.nodes[inp].is_data_phi() {
buf.push(inp);
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,
visited: Default::default(),
func: Default::default(),
marked: Default::default(),
};
s.visited.clear(s.nodes.values.len());
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 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);
for param in phi_input_buf.drain(..) {
if !visited.set(param) {
continue;
for [a, rest @ ..] in phi_input_buf.drain(..).array_chunks::<3>() {
if visited.set(a) {
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;
@ -595,13 +612,19 @@ impl<'a> Env<'a> {
if visited.get(inst) || inst == 0 {
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;
}
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);
self.ctx.uses_of(inst, use_buf);
for (cursor, uinst) in use_buf.drain(..) {
@ -611,7 +634,7 @@ impl<'a> Env<'a> {
range.start =
range.start.max(self.ctx.instr_of(inst).map_or(0, |n| n + 1) as usize);
debug_assert!(range.start < range.end, "{:?}", range);
range.end = range.end.min(
let new = range.end.min(
self.ctx
.instr_of(uinst)
.filter(|_| {
@ -621,6 +644,8 @@ impl<'a> Env<'a> {
})
.map_or(Nid::MAX, |n| n + 1) as usize,
);
range.end = new;
debug_assert!(range.start < range.end);
bundle.add(range);
@ -632,15 +657,25 @@ impl<'a> Env<'a> {
return;
}
match self.res.bundles.iter_mut().enumerate().find(|(_, b)| !b.overlaps(bundle)) {
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;
if let Some(prefered) = prefered
&& !self.res.bundles[prefered].overlaps(bundle)
{
self.res.bundles[prefered].merge(bundle);
bundle.clear();
self.res.node_to_reg[inst as usize] = prefered as Reg + 1;
} else {
match self.res.bundles.iter_mut().enumerate().find(|(_, b)| !b.overlaps(bundle)) {
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;
}
}
}
}

View file

@ -1,7 +1,6 @@
use {
super::{HbvmBackend, Nid, Nodes},
crate::{
lexer::TokenKind,
parser, reg,
son::{debug_assert_matches, Kind, ARG_START, MEM, NEVER, VOID},
ty::{self, Arg, Loc},
@ -540,6 +539,8 @@ impl<'a> Function<'a> {
self.rg(*node.inputs.last().unwrap()),
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);
@ -565,13 +566,7 @@ impl<'a> Function<'a> {
Kind::Assert { .. } => unreachable!(),
Kind::End | Kind::Phi | Kind::Arg | Kind::Mem | Kind::Loops | Kind::Join => {}
Kind::Load { .. } => {
let mut region = node.inputs[1];
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 (region, _) = self.nodes.strip_offset(node.inputs[1], node.ty, self.tys);
let ops = match self.nodes[region].kind {
Kind::Stck => vec![self.drg(nid)],
_ => vec![self.drg(nid), self.urg(region)],
@ -580,13 +575,7 @@ impl<'a> Function<'a> {
}
Kind::Stre => {
debug_assert_ne!(self.tys.size_of(node.ty), 0);
let mut region = node.inputs[2];
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 (region, _) = self.nodes.strip_offset(node.inputs[2], node.ty, self.tys);
let ops = match self.nodes[region].kind {
_ if node.ty.loc(self.tys) == Loc::Stack => {
if self.nodes[node.inputs[1]].kind == Kind::Arg {

View 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(())

View file

@ -1,16 +1,16 @@
continue_and_state_change:
LI64 r9, 3d
LI64 r10, 4d
LI64 r11, 2d
LI64 r12, 10d
6: JLTU r2, r12, :0
CP r1, r0
LI64 r10, 3d
LI64 r11, 4d
LI64 r12, 2d
LI64 r3, 10d
6: JLTU r2, r3, :0
CP r1, r2
JMP :1
0: JNE r2, r11, :2
CP r2, r10
0: JNE r2, r12, :2
CP r2, r11
JMP :3
2: JNE r2, r9, :4
CP r1, r0
2: JNE r2, r10, :4
1: JMP :5
4: ADDI64 r2, r2, 1d
3: JMP :6

View file

@ -3,7 +3,7 @@ main:
ST r31, r254, 6a, 24h
ADDI64 r32, r254, 0d
2: JAL r31, r0, :return_fn
ST r1, r254, 0a, 6h
ST r1, r32, 0a, 6h
LD r33, r254, 0a, 1h
ANDI r33, r33, 255d
ANDI r0, r0, 255d

View file

@ -4,7 +4,7 @@ foo:
ADDI64 r32, r254, 64d
LRA r3, r0, :some_file
JAL r31, r0, :get
ST r1, r254, 64a, 16h
ST r1, r32, 0a, 16h
LD r33, r254, 64a, 1h
ANDI r33, r33, 255d
ANDI r0, r0, 255d
@ -60,7 +60,7 @@ main:
ST r31, r254, 16a, 24h
ADDI64 r32, r254, 0d
JAL r31, r0, :foo
ST r1, r254, 0a, 16h
ST r1, r32, 0a, 16h
LD r33, r254, 0a, 1h
ANDI r33, r33, 255d
ANDI r0, r0, 255d

View file

@ -7,7 +7,7 @@ main:
JAL r31, r0, :returner_bn
ADDI64 r33, r254, 0d
JAL r31, r0, :returner_cn
ST r1, r254, 0a, 2h
ST r1, r33, 0a, 2h
LD r34, r254, 2a, 1h
CP r1, r32
CMPU r35, r1, r0

View file

@ -45,22 +45,21 @@ main:
JNE r40, r39, :9
LI64 r1, 69d
JMP :3
9: ADDI64 r3, r254, 40d
CP r41, r3
9: ADDI64 r41, r254, 40d
JAL r31, r0, :new_foo
ST r1, r254, 40a, 16h
ST r1, r41, 0a, 16h
CP r3, r41
LD r42, r254, 40a, 8h
JNE r42, r0, :10
LI64 r1, 999d
JMP :3
10: LRA r4, r0, :"foo\0"
CP r3, r41
CP r2, r3
LD r2, r2, 0a, 16h
JAL r31, r0, :use_foo
ADDI64 r43, r254, 0d
JAL r31, r0, :no_foo
ST r1, r254, 0a, 16h
ST r1, r43, 0a, 16h
JAL r31, r0, :decide
ANDI r1, r1, 255d
JNE r1, r0, :11
@ -126,6 +125,6 @@ use_foo:
ADDI64 r2, r254, 0d
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
code size: 1100
code size: 1097
ret: 0
status: Ok(())

View file

@ -1,12 +1,12 @@
main:
ADDI64 r254, r254, -16d
ADDI64 r4, r254, 0d
ADDI64 r7, r254, 0d
CP r3, r0
CP r4, r0
CP r5, r0
CP r6, r0
ECA
ST r1, r254, 0a, 16h
ST r1, r7, 0a, 16h
LD r7, r254, 0a, 1h
ANDI r7, r7, 255d
ANDI r0, r0, 255d

View file

@ -8,7 +8,7 @@ main:
ST r34, r254, 0a, 8h
ST r33, r254, 8a, 8h
JAL r31, r0, :opaque
ST r1, r254, 0a, 16h
ST r1, r32, 0a, 16h
LD r35, r254, 8a, 8h
LD r36, r254, 16a, 8h
ADD64 r37, r36, r35

View file

@ -3,7 +3,7 @@ main:
ST r31, r254, 4a, 96h
ADDI64 r32, r254, 0d
JAL r31, r0, :random_color
ST r1, r254, 0a, 4h
ST r1, r32, 0a, 4h
LD r33, r254, 0a, 1h
LD r34, r254, 1a, 1h
LD r35, r254, 2a, 1h

View file

@ -14,7 +14,7 @@ main:
ST r31, r254, 16a, 24h
ADDI64 r32, r254, 0d
JAL r31, r0, :get_format
ST r1, r254, 0a, 16h
ST r1, r32, 0a, 16h
LD r33, r254, 0a, 1h
ANDI r33, r33, 255d
ANDI r0, r0, 255d

View file

@ -16,7 +16,7 @@ main:
ADDI64 r32, r254, 0d
CP r3, r0
JAL r31, r0, :constructor
ST r1, r254, 0a, 16h
ST r1, r32, 0a, 16h
LD r31, r254, 16a, 16h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a

View file

@ -5,7 +5,7 @@ main:
ADDI64 r33, r254, 0d
LD r2, r32, 0a, 4h
JAL r31, r0, :u32_to_color
ST r1, r254, 0a, 4h
ST r1, r33, 0a, 4h
LD r34, r254, 0a, 1h
ANDI r1, r34, 255d
LD r31, r254, 4a, 32h

View file

@ -21,7 +21,7 @@ main:
CP r34, r1
ADDI64 r35, r254, 0d
JAL r31, r0, :optional
ST r1, r254, 0a, 16h
ST r1, r35, 0a, 16h
LD r36, r254, 0a, 1h
ANDI r36, r36, 255d
ANDI r0, r0, 255d

View file

@ -14,13 +14,13 @@ main:
ST r31, r254, 48a, 80h
ADDI64 r32, r254, 32d
JAL r31, r0, :foo
ST r1, r254, 32a, 16h
ST r1, r32, 0a, 16h
ADDI64 r33, r254, 16d
JAL r31, r0, :foo
ST r1, r254, 16a, 16h
ST r1, r33, 0a, 16h
ADDI64 r34, r254, 0d
JAL r31, r0, :foo
ST r1, r254, 0a, 16h
ST r1, r34, 0a, 16h
LD r35, r254, 24a, 4h
LD r36, r254, 12a, 4h
ANDI r37, r35, 4294967295d

View file

@ -10,7 +10,7 @@ main:
CP r3, r4
LD r3, r3, 0a, 16h
JAL r31, r0, :odher_pass
ST r1, r254, 0a, 16h
ST r1, r34, 0a, 16h
LD r35, r254, 8a, 8h
JNE r35, r33, :0
CP r2, r34

View file

@ -5,7 +5,7 @@ main:
CP r4, r0
CP r3, r4
JAL r31, r0, :maina
ST r1, r254, 0a, 16h
ST r1, r32, 0a, 16h
LD r33, r254, 12a, 1h
LD r34, r254, 3a, 1h
SUB8 r35, r34, r33
@ -18,7 +18,7 @@ maina:
ST r31, r254, 20a, 40h
ADDI64 r32, r254, 16d
JAL r31, r0, :small_struct
ST r1, r254, 16a, 4h
ST r1, r32, 0a, 4h
ADDI64 r33, r254, 0d
ST r0, r254, 0a, 1h
ST r0, r254, 1a, 1h