implementing optimizations up to is statements

This commit is contained in:
mlokr 2024-09-05 11:16:11 +02:00
parent 955e4a5c7a
commit 1a3b0c2eec
No known key found for this signature in database
GPG key ID: DEA147DDEE644993
14 changed files with 623 additions and 304 deletions

View file

@ -8,7 +8,7 @@ use {
parser::{self, find_symbol, idfl, CtorField, Expr, ExprRef, FileId, Pos}, parser::{self, find_symbol, idfl, CtorField, Expr, ExprRef, FileId, Pos},
HashMap, HashMap,
}, },
std::{fmt::Display, ops::Range, rc::Rc}, std::{collections::BTreeMap, fmt::Display, ops::Range, rc::Rc},
}; };
type Offset = u32; type Offset = u32;
@ -3294,7 +3294,7 @@ impl Codegen {
), ),
) )
})) }))
.collect::<HashMap<_, _>>(); .collect::<BTreeMap<_, _>>();
crate::disasm(&mut sluce, &functions, output, |bin| { crate::disasm(&mut sluce, &functions, output, |bin| {
if self.ct.active() if self.ct.active()
&& let Some(trap) = Self::read_trap(bin.as_ptr() as u64) && let Some(trap) = Self::read_trap(bin.as_ptr() as u64)

View file

@ -20,7 +20,7 @@
use { use {
parser::Ast, parser::Ast,
std::{ std::{
collections::{hash_map, VecDeque}, collections::{hash_map, BTreeMap, VecDeque},
io::{self, Read}, io::{self, Read},
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::Mutex, sync::Mutex,
@ -146,7 +146,7 @@ enum DisasmItem {
fn disasm( fn disasm(
binary: &mut &[u8], binary: &mut &[u8],
functions: &HashMap<u32, (&str, u32, DisasmItem)>, functions: &BTreeMap<u32, (&str, u32, DisasmItem)>,
out: &mut impl std::io::Write, out: &mut impl std::io::Write,
mut eca_handler: impl FnMut(&mut &[u8]), mut eca_handler: impl FnMut(&mut &[u8]),
) -> std::io::Result<()> { ) -> std::io::Result<()> {

View file

@ -14,9 +14,11 @@ use {
}, },
core::fmt, core::fmt,
std::{ std::{
collections::BTreeMap,
mem, mem,
ops::{self, Range}, ops::{self, Range},
rc::Rc, rc::{self, Rc},
u32,
}, },
}; };
@ -24,6 +26,8 @@ type Nid = u32;
const NILL: u32 = u32::MAX; const NILL: u32 = u32::MAX;
mod reg { mod reg {
use crate::log;
pub const STACK_PTR: Reg = 254; pub const STACK_PTR: Reg = 254;
pub const ZERO: Reg = 0; pub const ZERO: Reg = 0;
pub const RET: Reg = 1; pub const RET: Reg = 1;
@ -59,7 +63,7 @@ mod reg {
impl Drop for Id { impl Drop for Id {
fn drop(&mut self) { fn drop(&mut self) {
if !std::thread::panicking() && self.1 { if !std::thread::panicking() && self.1 {
panic!("reg id leaked: {:?}", self.0); log::err!("reg id leaked: {:?}", self.0);
} }
} }
} }
@ -279,6 +283,8 @@ mod ty {
I16; I16;
I32; I32;
INT; INT;
LEFT_UNREACHABLE;
RIGHT_UNREACHABLE;
} }
macro_rules! type_kind { macro_rules! type_kind {
@ -526,6 +532,9 @@ impl Nodes {
Kind::Tuple { .. } => {} Kind::Tuple { .. } => {}
Kind::ConstInt { .. } => {} Kind::ConstInt { .. } => {}
Kind::Call { .. } => {} Kind::Call { .. } => {}
Kind::If => {}
Kind::Region => {}
Kind::Phi => {}
} }
None None
} }
@ -692,10 +701,12 @@ impl Nodes {
} }
Kind::Return => { Kind::Return => {
write!(f, "{}: return [{:?}] ", node, self[node].inputs[0])?; write!(f, "{}: return [{:?}] ", node, self[node].inputs[0])?;
self.fmt(f, self[node].inputs[1], rcs)?; if self[node].inputs[2] != NILL {
writeln!(f)?;
self.fmt(f, self[node].inputs[2], rcs)?; self.fmt(f, self[node].inputs[2], rcs)?;
} }
writeln!(f)?;
self.fmt(f, self[node].inputs[1], rcs)?;
}
Kind::ConstInt { value } => write!(f, "{}", value)?, Kind::ConstInt { value } => write!(f, "{}", value)?,
Kind::End => { Kind::End => {
if is_ready() { if is_ready() {
@ -744,6 +755,9 @@ impl Nodes {
write!(f, "call{node}")?; write!(f, "call{node}")?;
} }
} }
Kind::If => todo!(),
Kind::Region => todo!(),
Kind::Phi => todo!(),
} }
Ok(()) Ok(())
@ -799,8 +813,11 @@ enum PoolSlot {
pub enum Kind { pub enum Kind {
Start, Start,
End, End,
If,
Region,
Return, Return,
ConstInt { value: i64 }, ConstInt { value: i64 },
Phi,
Tuple { index: u32 }, Tuple { index: u32 },
BinOp { op: lexer::TokenKind }, BinOp { op: lexer::TokenKind },
Call { func: ty::Func, args: Vec<Nid> }, Call { func: ty::Func, args: Vec<Nid> },
@ -871,6 +888,7 @@ struct Loop {
break_relocs: Vec<Reloc>, break_relocs: Vec<Reloc>,
} }
#[derive(Clone, Copy)]
struct Variable { struct Variable {
id: Ident, id: Ident,
value: Nid, value: Nid,
@ -887,7 +905,9 @@ struct ItemCtx {
nodes: Nodes, nodes: Nodes,
start: Nid, start: Nid,
end: Nid, end: Nid,
cfg: Nid, ctrl: Nid,
call_count: usize,
loops: Vec<Loop>, loops: Vec<Loop>,
vars: Vec<Variable>, vars: Vec<Variable>,
@ -1313,7 +1333,7 @@ impl Codegen {
(g.offset, (file.ident_str(g.name), self.tys.size_of(g.ty), DisasmItem::Global)) (g.offset, (file.ident_str(g.name), self.tys.size_of(g.ty), DisasmItem::Global))
})) }))
.collect::<HashMap<_, _>>(); .collect::<BTreeMap<_, _>>();
crate::disasm(&mut sluce, &functions, output, |_| {}) crate::disasm(&mut sluce, &functions, output, |_| {})
} }
@ -1380,7 +1400,74 @@ impl Codegen {
self.ci.nodes.new_node(ty::bin_ret(ty, op), Kind::BinOp { op }, [lhs, rhs]); self.ci.nodes.new_node(ty::bin_ret(ty, op), Kind::BinOp { op }, [lhs, rhs]);
Some(id) Some(id)
} }
Expr::If { pos, cond, then, else_ } => {
let cond = self.expr_ctx(cond, Ctx::default().with_ty(ty::BOOL))?;
let if_node = self.ci.nodes.new_node(ty::VOID, Kind::If, [self.ci.ctrl, cond]);
'b: {
let branch = match self.tof(if_node).expand().inner() {
ty::LEFT_UNREACHABLE => else_,
ty::RIGHT_UNREACHABLE => Some(then),
_ => break 'b,
};
self.ci.nodes.lock(self.ci.ctrl);
self.ci.nodes.remove(if_node);
self.ci.nodes.unlock(self.ci.ctrl);
if let Some(branch) = branch {
return self.expr(branch);
} else {
return Some(NILL);
}
}
let else_scope = self.ci.vars.clone();
self.ci.ctrl =
self.ci.nodes.new_node(ty::VOID, Kind::Tuple { index: 0 }, [if_node]);
let lcntrl = self.expr(then).map_or(NILL, |_| self.ci.ctrl);
let then_scope = std::mem::replace(&mut self.ci.vars, else_scope);
self.ci.ctrl =
self.ci.nodes.new_node(ty::VOID, Kind::Tuple { index: 1 }, [if_node]);
let rcntrl = if let Some(else_) = else_ {
self.expr(else_).map_or(NILL, |_| self.ci.ctrl)
} else {
self.ci.ctrl
};
if lcntrl == NILL && rcntrl == NILL {
return None;
} else if lcntrl == NILL {
return Some(NILL);
} else if rcntrl == NILL {
self.ci.vars = then_scope;
return Some(NILL);
}
let region = self.ci.nodes.new_node(ty::VOID, Kind::Region, [lcntrl, rcntrl]);
for (else_var, then_var) in self.ci.vars.iter_mut().zip(then_scope) {
if else_var.value == then_var.value {
continue;
}
let ty = self.ci.nodes[else_var.value].ty;
debug_assert_eq!(
ty, self.ci.nodes[then_var.value].ty,
"TODO: typecheck properly"
);
let inps = [region, then_var.value, else_var.value];
else_var.value = self.ci.nodes.new_node(ty, Kind::Phi, inps);
}
Some(NILL)
}
Expr::Call { func: &Expr::Ident { pos, id, name, .. }, args, .. } => { Expr::Call { func: &Expr::Ident { pos, id, name, .. }, args, .. } => {
self.ci.call_count += 1;
let func = self.find_or_declare(pos, self.ci.file, Some(id), name); let func = self.find_or_declare(pos, self.ci.file, Some(id), name);
let ty::Kind::Func(func) = func else { let ty::Kind::Func(func) = func else {
self.report( self.report(
@ -1416,28 +1503,38 @@ impl Codegen {
let mut inps = vec![]; let mut inps = vec![];
for ((arg, _carg), tyx) in args.iter().zip(cargs).zip(sig.args.range()) { for ((arg, _carg), tyx) in args.iter().zip(cargs).zip(sig.args.range()) {
let ty = self.tys.args[tyx]; let ty = self.tys.args[tyx];
if self.tys.size_of(ty) == 0 {
continue;
}
let value = self.expr_ctx(arg, Ctx::default().with_ty(ty))?; let value = self.expr_ctx(arg, Ctx::default().with_ty(ty))?;
_ = self.assert_ty(arg.pos(), self.tof(value), ty, true); _ = self.assert_ty(arg.pos(), self.tof(value), ty, true);
inps.push(value); inps.push(value);
} }
self.ci.cfg = self.ci.ctrl =
self.ci self.ci
.nodes .nodes
.new_node(sig.ret, Kind::Call { func, args: inps.clone() }, [self.ci.cfg]); .new_node(sig.ret, Kind::Call { func, args: inps.clone() }, [self.ci.ctrl]);
self.ci.nodes.add_deps(self.ci.cfg, &inps); self.ci.nodes.add_deps(self.ci.ctrl, &inps);
Some(self.ci.cfg) Some(self.ci.ctrl)
} }
Expr::Return { pos, val } => { Expr::Return { pos, val } => {
let ty = if let Some(val) = val { let (ty, value) = if let Some(val) = val {
let value = self.expr_ctx(val, Ctx { ty: self.ci.ret })?; let value = self.expr_ctx(val, Ctx { ty: self.ci.ret })?;
let inps = [self.ci.cfg, value, self.ci.end];
self.ci.cfg = self.ci.nodes.new_node(ty::VOID, Kind::Return, inps); (self.tof(value), value)
self.tof(value)
} else { } else {
ty::VOID.into() (ty::VOID.into(), NILL)
}; };
if value == NILL {
let inps = [self.ci.ctrl, self.ci.end];
self.ci.ctrl = self.ci.nodes.new_node(ty::VOID, Kind::Return, inps);
} else {
let inps = [self.ci.ctrl, self.ci.end, value];
self.ci.ctrl = self.ci.nodes.new_node(ty::VOID, Kind::Return, inps);
}
let expected = *self.ci.ret.get_or_insert(ty); let expected = *self.ci.ret.get_or_insert(ty);
_ = self.assert_ty(pos, ty, expected, true); _ = self.assert_ty(pos, ty, expected, true);
@ -1494,7 +1591,8 @@ impl Codegen {
} }
fn handle_task(&mut self, FTask { file, id }: FTask) { fn handle_task(&mut self, FTask { file, id }: FTask) {
let func = &self.tys.funcs[id as usize]; let func = &mut self.tys.funcs[id as usize];
func.offset = u32::MAX - 1;
debug_assert!(func.file == file); debug_assert!(func.file == file);
let sig = func.sig.unwrap(); let sig = func.sig.unwrap();
let ast = self.files[file as usize].clone(); let ast = self.files[file as usize].clone();
@ -1510,7 +1608,7 @@ impl Codegen {
self.ci.start = self.ci.nodes.new_node(ty::VOID, Kind::Start, []); self.ci.start = self.ci.nodes.new_node(ty::VOID, Kind::Start, []);
self.ci.end = self.ci.nodes.new_node(ty::VOID, Kind::End, []); self.ci.end = self.ci.nodes.new_node(ty::VOID, Kind::End, []);
self.ci.cfg = self.ci.nodes.new_node(ty::VOID, Kind::Tuple { index: 0 }, [self.ci.start]); self.ci.ctrl = self.ci.nodes.new_node(ty::VOID, Kind::Tuple { index: 0 }, [self.ci.start]);
let Expr::BinOp { let Expr::BinOp {
left: Expr::Ident { .. }, left: Expr::Ident { .. },
@ -1574,6 +1672,18 @@ impl Codegen {
self.emit_control(self.ci.nodes[self.ci.start].outputs[0]); self.emit_control(self.ci.nodes[self.ci.start].outputs[0]);
if let Some(last_ret) = self.ci.ret_relocs.last()
&& last_ret.offset as usize == self.ci.code.len() - 5
{
self.ci.code.truncate(self.ci.code.len() - 5);
self.ci.ret_relocs.pop();
}
let end = self.ci.code.len();
for ret_rel in self.ci.ret_relocs.drain(..) {
ret_rel.apply_jump(&mut self.ci.code, end as _, 0);
}
'_close_function: { '_close_function: {
let pushed = self.ci.regs.pushed_size() as i64; let pushed = self.ci.regs.pushed_size() as i64;
let stack = 0; let stack = 0;
@ -1593,29 +1703,27 @@ impl Codegen {
self.pool.cis.push(std::mem::replace(&mut self.ci, prev_ci)); self.pool.cis.push(std::mem::replace(&mut self.ci, prev_ci));
} }
fn emit_control(&mut self, mut ctrl: Nid) { fn emit_control(&mut self, mut ctrl: Nid) -> Option<Nid> {
loop { loop {
match self.ci.nodes[ctrl].kind.clone() { match self.ci.nodes[ctrl].kind.clone() {
Kind::Start => unreachable!(), Kind::Start => unreachable!(),
Kind::End => unreachable!(), Kind::End => unreachable!(),
Kind::Return => { Kind::Return => {
if let Some(&ret) = self.ci.nodes[ctrl].inputs().get(2) {
let ret_loc = match self.tys.size_of(self.ci.ret.expect("TODO")) { let ret_loc = match self.tys.size_of(self.ci.ret.expect("TODO")) {
0 => Loc::default(), 0 => Loc::default(),
1..=8 => Loc { reg: 1u8.into() }, 1..=8 => Loc { reg: 1u8.into() },
s => todo!("{s}"), s => todo!("{s}"),
}; };
let dst = self.emit_expr(ret, GenCtx::default().with_loc(ret_loc));
let dst = self.emit_expr(
self.ci.nodes[ctrl].inputs[1],
GenCtx::default().with_loc(ret_loc),
);
self.ci.free_loc(dst); self.ci.free_loc(dst);
}
break; self.ci.ret_relocs.push(Reloc::new(self.ci.code.len(), 1, 4));
self.ci.emit(instrs::jmp(0));
break None;
} }
Kind::ConstInt { .. } => unreachable!(), Kind::ConstInt { .. } => unreachable!(),
Kind::Tuple { index } => { Kind::Tuple { .. } => {
debug_assert!(index == 0);
ctrl = self.ci.nodes[ctrl].outputs[0]; ctrl = self.ci.nodes[ctrl].outputs[0];
} }
Kind::BinOp { .. } => unreachable!(), Kind::BinOp { .. } => unreachable!(),
@ -1633,12 +1741,6 @@ impl Codegen {
self.ci.free_loc(dst); self.ci.free_loc(dst);
} }
let ret_loc = match self.tys.size_of(ret) {
0 => Loc::default(),
1..=8 => Loc { reg: 1u8.into() },
s => todo!("{s}"),
};
let reloc = Reloc::new(self.ci.code.len(), 3, 4); let reloc = Reloc::new(self.ci.code.len(), 3, 4);
self.ci self.ci
.relocs .relocs
@ -1646,12 +1748,30 @@ impl Codegen {
self.ci.emit(instrs::jal(reg::RET_ADDR, reg::ZERO, 0)); self.ci.emit(instrs::jal(reg::RET_ADDR, reg::ZERO, 0));
self.make_func_reachable(func); self.make_func_reachable(func);
// TODO: allocate return register self.ci.call_count -= 1;
let loc = Loc { reg: self.ci.regs.allocate() };
'b: {
let ret_loc = match self.tys.size_of(ret) {
0 => break 'b,
1..=8 => Loc { reg: 1u8.into() },
s => todo!("{s}"),
};
if self.ci.nodes[ctrl].outputs.len() == 1 {
break 'b;
}
let loc;
if self.ci.call_count != 0 {
loc = Loc { reg: self.ci.regs.allocate() };
self.ci.emit(instrs::cp(loc.reg.get(), ret_loc.reg.get())); self.ci.emit(instrs::cp(loc.reg.get(), ret_loc.reg.get()));
} else {
loc = ret_loc;
}
self.ci.nodes[ctrl].loc = loc; self.ci.nodes[ctrl].loc = loc;
self.ci.nodes[ctrl].lock_rc += 1; self.ci.nodes[ctrl].lock_rc += 1;
}
ctrl = *self.ci.nodes[ctrl] ctrl = *self.ci.nodes[ctrl]
.outputs .outputs
@ -1659,6 +1779,106 @@ impl Codegen {
.find(|&&o| self.ci.nodes.is_cfg(o)) .find(|&&o| self.ci.nodes.is_cfg(o))
.unwrap(); .unwrap();
} }
Kind::If => {
let cond = self.ci.nodes[ctrl].inputs[1];
let jump_offset: i64;
match self.ci.nodes[cond].kind {
Kind::BinOp { op: TokenKind::Le } => {
let [left, right, ..] = self.ci.nodes[cond].inputs;
let ldst = self.emit_expr(left, GenCtx::default());
let rdst = self.emit_expr(right, GenCtx::default());
jump_offset = self.ci.code.len() as _;
let op = if self.ci.nodes[left].ty.is_signed() {
instrs::jgts
} else {
instrs::jgtu
};
self.ci.emit(op(
self.ci.nodes[left].loc.reg.get(),
self.ci.nodes[right].loc.reg.get(),
0,
));
self.ci.free_loc(ldst);
self.ci.free_loc(rdst);
}
_ => {
let cdst = self.emit_expr(cond, GenCtx::default());
let cond = self.ci.nodes[cond].loc.reg.get();
jump_offset = self.ci.code.len() as _;
self.ci.emit(instrs::jeq(cond, reg::ZERO, 0));
self.ci.free_loc(cdst);
}
}
let left_unreachable = self.emit_control(self.ci.nodes[ctrl].outputs[0]);
let mut skip_then_offset = self.ci.code.len() as i64;
if let Some(region) = left_unreachable {
for i in 0..self.ci.nodes[region].outputs.len() {
let o = self.ci.nodes[region].outputs[i];
if self.ci.nodes[o].kind != Kind::Phi {
continue;
}
let out = self.ci.nodes[o].inputs[1];
let dst = self.emit_expr(out, GenCtx::default());
self.ci.nodes[o].loc = dst.unwrap_or_else(|| {
let reg = self.ci.regs.allocate();
self.ci
.emit(instrs::cp(reg.get(), self.ci.nodes[out].loc.reg.get()));
Loc { reg }
});
}
self.ci.emit(instrs::jmp(0));
}
let right_base = self.ci.code.len();
let right_unreachable = self.emit_control(self.ci.nodes[ctrl].outputs[1]);
if let Some(region) = left_unreachable {
for i in 0..self.ci.nodes[region].outputs.len() {
let o = self.ci.nodes[region].outputs[i];
if self.ci.nodes[o].kind != Kind::Phi {
continue;
}
let out = self.ci.nodes[o].inputs[2];
// TODO: this can be improved if we juggle ownership of the Phi inputs
let dst = self.emit_expr(out, GenCtx::default());
self.ci.free_loc(dst);
self.ci.emit(instrs::cp(
self.ci.nodes[o].loc.reg.get(),
self.ci.nodes[out].loc.reg.get(),
));
}
let right_end = self.ci.code.len();
if right_base == right_end {
self.ci.code.truncate(skip_then_offset as _);
} else {
write_reloc(
&mut self.ci.code,
skip_then_offset as usize + 1,
right_end as i64 - skip_then_offset,
4,
);
skip_then_offset += instrs::jmp(69).0 as i64;
}
}
write_reloc(
&mut self.ci.code,
jump_offset as usize + 3,
skip_then_offset - jump_offset,
2,
);
if left_unreachable.is_none() && right_unreachable.is_none() {
break None;
}
debug_assert_eq!(left_unreachable, right_unreachable);
}
Kind::Region => break Some(ctrl),
Kind::Phi => todo!(),
} }
} }
} }
@ -1685,6 +1905,20 @@ impl Codegen {
let ty = self.tof(expr); let ty = self.tof(expr);
let [left, right, ..] = self.ci.nodes[expr].inputs; let [left, right, ..] = self.ci.nodes[expr].inputs;
let mut ldst = self.emit_expr(left, GenCtx::default()); let mut ldst = self.emit_expr(left, GenCtx::default());
if let Kind::ConstInt { value } = self.ci.nodes[right].kind
&& let Some(op) = Self::imm_math_op(op, ty.is_signed(), self.tys.size_of(ty))
{
let loc = ctx
.loc
.or_else(|| ldst.take())
.unwrap_or_else(|| Loc { reg: self.ci.regs.allocate() });
self.ci.free_loc(ldst);
self.ci.emit(op(loc.reg.get(), self.ci.nodes[left].loc.reg.get(), value as _));
self.ci.nodes[expr].loc = loc;
} else {
let mut rdst = self.emit_expr(right, GenCtx::default()); let mut rdst = self.emit_expr(right, GenCtx::default());
let op = Self::math_op(op, ty.is_signed(), self.tys.size_of(ty)) let op = Self::math_op(op, ty.is_signed(), self.tys.size_of(ty))
@ -1706,7 +1940,11 @@ impl Codegen {
)); ));
self.ci.nodes[expr].loc = loc; self.ci.nodes[expr].loc = loc;
} }
}
Kind::Call { .. } => {} Kind::Call { .. } => {}
Kind::If => todo!(),
Kind::Region => todo!(),
Kind::Phi => todo!(),
} }
self.ci.nodes[expr].lock_rc += 1; self.ci.nodes[expr].lock_rc += 1;
@ -1718,6 +1956,45 @@ impl Codegen {
None None
} }
#[allow(clippy::type_complexity)]
fn imm_math_op(
op: TokenKind,
signed: bool,
size: u32,
) -> Option<fn(u8, u8, u64) -> (usize, [u8; instrs::MAX_SIZE])> {
use {instrs::*, TokenKind as T};
macro_rules! def_op {
($name:ident |$a:ident, $b:ident, $c:ident| $($tt:tt)*) => {
macro_rules! $name {
($$($$op:ident),*) => {
[$$(
|$a, $b, $c: u64| $$op($($tt)*),
)*]
}
}
};
}
def_op!(basic_op | a, b, c | a, b, c as _);
def_op!(sub_op | a, b, c | a, b, c.wrapping_neg() as _);
let ops = match op {
T::Add => basic_op!(addi8, addi16, addi32, addi64),
T::Sub => sub_op!(addi8, addi16, addi32, addi64),
T::Mul => basic_op!(muli8, muli16, muli32, muli64),
T::Band => return Some(andi),
T::Bor => return Some(ori),
T::Xor => return Some(xori),
T::Shr if signed => basic_op!(srui8, srui16, srui32, srui64),
T::Shr => basic_op!(srui8, srui16, srui32, srui64),
T::Shl => basic_op!(slui8, slui16, slui32, slui64),
_ => return None,
};
Some(ops[size.ilog2() as usize])
}
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
fn math_op( fn math_op(
op: TokenKind, op: TokenKind,
@ -1788,8 +2065,8 @@ impl Codegen {
if let Some(existing) = self.tys.syms.get(&SymKey { file, ident }) { if let Some(existing) = self.tys.syms.get(&SymKey { file, ident }) {
if let ty::Kind::Func(id) = existing.expand() if let ty::Kind::Func(id) = existing.expand()
&& let func = &mut self.tys.funcs[id as usize] && let func = &mut self.tys.funcs[id as usize]
&& func.offset != u32::MAX
&& let Err(idx) = task::unpack(func.offset) && let Err(idx) = task::unpack(func.offset)
&& idx < self.tasks.len()
{ {
func.offset = task::id(self.tasks.len()); func.offset = task::id(self.tasks.len());
let task = self.tasks[idx].take(); let task = self.tasks[idx].take();
@ -2104,8 +2381,8 @@ mod tests {
const_folding_with_arg => README; const_folding_with_arg => README;
variables => README; variables => README;
functions => README; functions => README;
//comments => README; comments => README;
//if_statements => README; if_statements => README;
//loops => README; //loops => README;
//fb_driver => README; //fb_driver => README;
//pointers => README; //pointers => README;

View file

@ -1,10 +1,3 @@
check_platform:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
JAL r31, r0, :x86_fb_ptr
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
main: main:
ADDI64 r254, r254, -64d ADDI64 r254, r254, -64d
ST r31, r254, 0a, 64h ST r31, r254, 0a, 64h
@ -60,6 +53,13 @@ set_pixel:
LD r31, r254, 0a, 32h LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d ADDI64 r254, r254, 32d
JALA r0, r31, 0a JALA r0, r31, 0a
check_platform:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
JAL r31, r0, :x86_fb_ptr
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
x86_fb_ptr: x86_fb_ptr:
ADDI64 r254, r254, -8d ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h ST r31, r254, 0a, 8h

View file

@ -1,12 +1,3 @@
add_two:
ADDI64 r254, r254, -16d
ST r31, r254, 0a, 16h
CP r32, r2
ADDI64 r32, r32, 2d
CP r1, r32
LD r31, r254, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
main: main:
ADDI64 r254, r254, -24d ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h ST r31, r254, 0a, 24h
@ -21,6 +12,15 @@ main:
LD r31, r254, 0a, 24h LD r31, r254, 0a, 24h
ADDI64 r254, r254, 24d ADDI64 r254, r254, 24d
JALA r0, r31, 0a JALA r0, r31, 0a
add_two:
ADDI64 r254, r254, -16d
ST r31, r254, 0a, 16h
CP r32, r2
ADDI64 r32, r32, 2d
CP r1, r32
LD r31, r254, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
add_one: add_one:
ADDI64 r254, r254, -16d ADDI64 r254, r254, -16d
ST r31, r254, 0a, 16h ST r31, r254, 0a, 16h

View file

@ -1,13 +1,3 @@
add:
ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h
CP r32, r2
CP r33, r3
ADD32 r32, r32, r33
CP r1, r32
LD r31, r254, 0a, 24h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
main: main:
ADDI64 r254, r254, -24d ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h ST r31, r254, 0a, 24h
@ -35,6 +25,16 @@ add:
LD r31, r254, 0a, 24h LD r31, r254, 0a, 24h
ADDI64 r254, r254, 24d ADDI64 r254, r254, 24d
JALA r0, r31, 0a JALA r0, r31, 0a
add:
ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h
CP r32, r2
CP r33, r3
ADD32 r32, r32, r33
CP r1, r32
LD r31, r254, 0a, 24h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
code size: 281 code size: 281
ret: 0 ret: 0
status: Ok(()) status: Ok(())

View file

@ -1,3 +1,39 @@
main:
ADDI64 r254, r254, -72d
ST r31, r254, 48a, 24h
ADDI64 r1, r254, 0d
JAL r31, r0, :new
ADDI64 r32, r254, 0d
ADDI64 r33, r254, 24d
BMC r32, r33, 24h
ADDI64 r33, r254, 24d
CP r2, r33
LI64 r3, 69d
JAL r31, r0, :push
LD r33, r254, 24a, 8h
LD r32, r33, 0a, 8h
ADDI64 r33, r254, 24d
CP r2, r33
JAL r31, r0, :deinit
CP r1, r32
LD r31, r254, 48a, 24h
ADDI64 r254, r254, 72d
JALA r0, r31, 0a
deinit:
ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h
CP r32, r2
LD r2, r32, 0a, 8h
LD r33, r32, 16a, 8h
MULI64 r33, r33, 8d
CP r3, r33
LI64 r4, 8d
JAL r31, r0, :free
CP r1, r32
JAL r31, r0, :new
LD r31, r254, 0a, 24h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
free: free:
ADDI64 r254, r254, -40d ADDI64 r254, r254, -40d
ST r31, r254, 0a, 40h ST r31, r254, 0a, 40h
@ -100,34 +136,6 @@ push:
4: LD r31, r254, 0a, 88h 4: LD r31, r254, 0a, 88h
ADDI64 r254, r254, 88d ADDI64 r254, r254, 88d
JALA r0, r31, 0a JALA r0, r31, 0a
new:
ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h
CP r32, r1
LI64 r33, 0d
ST r33, r32, 0a, 8h
LI64 r33, 0d
ST r33, r32, 8a, 8h
LI64 r33, 0d
ST r33, r32, 16a, 8h
LD r31, r254, 0a, 24h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
deinit:
ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h
CP r32, r2
LD r2, r32, 0a, 8h
LD r33, r32, 16a, 8h
MULI64 r33, r33, 8d
CP r3, r33
LI64 r4, 8d
JAL r31, r0, :free
CP r1, r32
JAL r31, r0, :new
LD r31, r254, 0a, 24h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
malloc: malloc:
ADDI64 r254, r254, -32d ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h ST r31, r254, 0a, 32h
@ -141,26 +149,18 @@ malloc:
LD r31, r254, 0a, 32h LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d ADDI64 r254, r254, 32d
JALA r0, r31, 0a JALA r0, r31, 0a
main: new:
ADDI64 r254, r254, -72d ADDI64 r254, r254, -24d
ST r31, r254, 48a, 24h ST r31, r254, 0a, 24h
ADDI64 r1, r254, 0d CP r32, r1
JAL r31, r0, :new LI64 r33, 0d
ADDI64 r32, r254, 0d ST r33, r32, 0a, 8h
ADDI64 r33, r254, 24d LI64 r33, 0d
BMC r32, r33, 24h ST r33, r32, 8a, 8h
ADDI64 r33, r254, 24d LI64 r33, 0d
CP r2, r33 ST r33, r32, 16a, 8h
LI64 r3, 69d LD r31, r254, 0a, 24h
JAL r31, r0, :push ADDI64 r254, r254, 24d
LD r33, r254, 24a, 8h
LD r32, r33, 0a, 8h
ADDI64 r33, r254, 24d
CP r2, r33
JAL r31, r0, :deinit
CP r1, r32
LD r31, r254, 48a, 24h
ADDI64 r254, r254, 72d
JALA r0, r31, 0a JALA r0, r31, 0a
code size: 1470 code size: 1470
ret: 69 ret: 69

View file

@ -1,96 +1,3 @@
integer:
ADDI64 r254, r254, -56d
ST r31, r254, 0a, 56h
CP r32, r2
CP r33, r3
LI64 r2, 3d
LI64 r3, 4d
ECA
CP r34, r1
CP r35, r32
LI64 r36, 0d
CMPS r35, r35, r36
CMPUI r35, r35, 0d
CP r36, r33
LI64 r37, 0d
CMPS r36, r36, r37
CMPUI r36, r36, 0d
OR r35, r35, r36
JEQ r35, r0, :0
CP r35, r34
CP r36, r32
SUB64 r33, r33, r36
ADDI64 r33, r33, 1d
DIRS64 r0, r35, r35, r33
ADD64 r35, r35, r32
CP r1, r35
JMP :1
0: CP r1, r34
1: LD r31, r254, 0a, 56h
ADDI64 r254, r254, 56d
JALA r0, r31, 0a
line:
ADDI64 r254, r254, -80d
ST r31, r254, 48a, 32h
ST r2, r254, 0a, 16h
ST r4, r254, 16a, 16h
ST r6, r254, 32a, 16h
CP r32, r8
LI64 r33, 1d
JEQ r33, r0, :0
LD r33, r254, 0a, 8h
LD r34, r254, 16a, 8h
CMPS r33, r33, r34
CMPUI r33, r33, 1d
NOT r33, r33
JEQ r33, r0, :1
JMP :1
1: JMP :2
0: LD r33, r254, 8a, 8h
LD r34, r254, 24a, 8h
CMPS r33, r33, r34
CMPUI r33, r33, 1d
NOT r33, r33
JEQ r33, r0, :2
JMP :2
2: LD r31, r254, 48a, 32h
ADDI64 r254, r254, 80d
JALA r0, r31, 0a
example:
ADDI64 r254, r254, -48d
ST r31, r254, 0a, 48h
LI64 r2, 3d
LI64 r3, 4d
ECA
CP r33, r1
LI64 r34, 0d
LI64 r35, 0d
CMPS r34, r34, r35
CMPUI r34, r34, 0d
LI64 r35, 1024d
LI64 r36, 0d
CMPS r35, r35, r36
CMPUI r35, r35, 0d
OR r34, r34, r35
JEQ r34, r0, :0
CP r34, r33
LI64 r35, 1024d
ADDI64 r35, r35, 0d
ADDI64 r35, r35, 1d
DIRS64 r0, r34, r34, r35
ADDI64 r34, r34, 0d
CP r32, r34
JMP :1
0: CP r32, r33
1: LI64 r2, 0d
LI64 r3, 768d
JAL r31, r0, :integer
CP r33, r1
CP r34, r32
JMP :2
2: LD r31, r254, 0a, 48h
ADDI64 r254, r254, 48d
JALA r0, r31, 0a
main: main:
ADDI64 r254, r254, -64d ADDI64 r254, r254, -64d
ST r31, r254, 48a, 16h ST r31, r254, 48a, 16h
@ -133,6 +40,72 @@ main:
LD r31, r254, 48a, 16h LD r31, r254, 48a, 16h
ADDI64 r254, r254, 64d ADDI64 r254, r254, 64d
JALA r0, r31, 0a JALA r0, r31, 0a
example:
ADDI64 r254, r254, -48d
ST r31, r254, 0a, 48h
LI64 r2, 3d
LI64 r3, 4d
ECA
CP r33, r1
LI64 r34, 0d
LI64 r35, 0d
CMPS r34, r34, r35
CMPUI r34, r34, 0d
LI64 r35, 1024d
LI64 r36, 0d
CMPS r35, r35, r36
CMPUI r35, r35, 0d
OR r34, r34, r35
JEQ r34, r0, :0
CP r34, r33
LI64 r35, 1024d
ADDI64 r35, r35, 0d
ADDI64 r35, r35, 1d
DIRS64 r0, r34, r34, r35
ADDI64 r34, r34, 0d
CP r32, r34
JMP :1
0: CP r32, r33
1: LI64 r2, 0d
LI64 r3, 768d
JAL r31, r0, :integer
CP r33, r1
CP r34, r32
JMP :2
2: LD r31, r254, 0a, 48h
ADDI64 r254, r254, 48d
JALA r0, r31, 0a
integer:
ADDI64 r254, r254, -56d
ST r31, r254, 0a, 56h
CP r32, r2
CP r33, r3
LI64 r2, 3d
LI64 r3, 4d
ECA
CP r34, r1
CP r35, r32
LI64 r36, 0d
CMPS r35, r35, r36
CMPUI r35, r35, 0d
CP r36, r33
LI64 r37, 0d
CMPS r36, r36, r37
CMPUI r36, r36, 0d
OR r35, r35, r36
JEQ r35, r0, :0
CP r35, r34
CP r36, r32
SUB64 r33, r33, r36
ADDI64 r33, r33, 1d
DIRS64 r0, r35, r35, r33
ADD64 r35, r35, r32
CP r1, r35
JMP :1
0: CP r1, r34
1: LD r31, r254, 0a, 56h
ADDI64 r254, r254, 56d
JALA r0, r31, 0a
rect_line: rect_line:
ADDI64 r254, r254, -112d ADDI64 r254, r254, -112d
ST r31, r254, 48a, 64h ST r31, r254, 48a, 64h
@ -179,6 +152,33 @@ rect_line:
1: LD r31, r254, 48a, 64h 1: LD r31, r254, 48a, 64h
ADDI64 r254, r254, 112d ADDI64 r254, r254, 112d
JALA r0, r31, 0a JALA r0, r31, 0a
line:
ADDI64 r254, r254, -80d
ST r31, r254, 48a, 32h
ST r2, r254, 0a, 16h
ST r4, r254, 16a, 16h
ST r6, r254, 32a, 16h
CP r32, r8
LI64 r33, 1d
JEQ r33, r0, :0
LD r33, r254, 0a, 8h
LD r34, r254, 16a, 8h
CMPS r33, r33, r34
CMPUI r33, r33, 1d
NOT r33, r33
JEQ r33, r0, :1
JMP :1
1: JMP :2
0: LD r33, r254, 8a, 8h
LD r34, r254, 24a, 8h
CMPS r33, r33, r34
CMPUI r33, r33, 1d
NOT r33, r33
JEQ r33, r0, :2
JMP :2
2: LD r31, r254, 48a, 32h
ADDI64 r254, r254, 80d
JALA r0, r31, 0a
code size: 1521 code size: 1521
ret: 0 ret: 0
status: Ok(()) status: Ok(())

View file

@ -1,29 +1,3 @@
fib:
ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h
CP r32, r2
CP r33, r32
LI64 r34, 2d
CMPS r33, r33, r34
CMPUI r33, r33, -1d
NOT r33, r33
JEQ r33, r0, :0
CP r1, r32
JMP :1
0: CP r33, r32
ADDI64 r33, r33, -1d
CP r2, r33
JAL r31, r0, :fib
CP r33, r1
ADDI64 r32, r32, -2d
CP r2, r32
JAL r31, r0, :fib
CP r32, r1
ADD64 r33, r33, r32
CP r1, r33
1: LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a
main: main:
ADDI64 r254, r254, -26d ADDI64 r254, r254, -26d
ST r31, r254, 2a, 24h ST r31, r254, 2a, 24h
@ -72,6 +46,32 @@ fib_iter:
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
fib:
ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h
CP r32, r2
CP r33, r32
LI64 r34, 2d
CMPS r33, r33, r34
CMPUI r33, r33, -1d
NOT r33, r33
JEQ r33, r0, :0
CP r1, r32
JMP :1
0: CP r33, r32
ADDI64 r33, r33, -1d
CP r2, r33
JAL r31, r0, :fib
CP r33, r1
ADDI64 r32, r32, -2d
CP r2, r32
JAL r31, r0, :fib
CP r32, r1
ADD64 r33, r33, r32
CP r1, r33
1: LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a
code size: 518 code size: 518
ret: 0 ret: 0
status: Ok(()) status: Ok(())

View file

@ -1,3 +1,14 @@
foo:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
LI64 r1, 3d
ANDI r2, r2, -4294967296d
ORI r2, r2, 2d
ANDI r2, r2, 4294967295d
ORI r2, r2, 8589934592d
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
main: main:
ADDI64 r254, r254, -40d ADDI64 r254, r254, -40d
ST r31, r254, 16a, 24h ST r31, r254, 16a, 24h
@ -22,17 +33,6 @@ main:
LD r31, r254, 16a, 24h LD r31, r254, 16a, 24h
ADDI64 r254, r254, 40d ADDI64 r254, r254, 40d
JALA r0, r31, 0a JALA r0, r31, 0a
foo:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
LI64 r1, 3d
ANDI r2, r2, -4294967296d
ORI r2, r2, 2d
ANDI r2, r2, 4294967295d
ORI r2, r2, 8589934592d
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
code size: 320 code size: 320
ret: 0 ret: 0
status: Ok(()) status: Ok(())

View file

@ -1,14 +1,3 @@
pass:
ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h
CP r32, r2
LD r33, r32, 0a, 8h
LD r34, r32, 8a, 8h
SUB64 r33, r33, r34
CP r1, r33
LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a
main: main:
ADDI64 r254, r254, -72d ADDI64 r254, r254, -72d
ST r31, r254, 48a, 24h ST r31, r254, 48a, 24h
@ -38,6 +27,17 @@ main:
1: LD r31, r254, 48a, 24h 1: LD r31, r254, 48a, 24h
ADDI64 r254, r254, 72d ADDI64 r254, r254, 72d
JALA r0, r31, 0a JALA r0, r31, 0a
pass:
ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h
CP r32, r2
LD r33, r32, 0a, 8h
LD r34, r32, 8a, 8h
SUB64 r33, r33, r34
CP r1, r33
LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a
odher_pass: odher_pass:
ADDI64 r254, r254, -40d ADDI64 r254, r254, -40d
ST r31, r254, 0a, 40h ST r31, r254, 0a, 40h

View file

@ -0,0 +1,17 @@
main:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
JAL r31, r0, :foo
LI64 r1, 0d
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
foo:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
code size: 143
ret: 0
status: Ok(())

View file

@ -1,34 +1,31 @@
main: main:
ADDI64 r254, r254, -24d ADDI64 r254, r254, -16d
ST r31, r254, 0a, 24h ST r31, r254, 0a, 16h
LI64 r2, 10d LI64 r2, 10d
JAL r31, r0, :add_one JAL r31, r0, :add_one
CP r32, r1 CP r32, r1
LI64 r2, 20d LI64 r2, 20d
JAL r31, r0, :add_two JAL r31, r0, :add_two
CP r33, r1 ADD64 r1, r1, r32
ADD64 r1, r33, r32 LD r31, r254, 0a, 16h
LD r31, r254, 0a, 24h ADDI64 r254, r254, 16d
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
add_one:
ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h
CP r32, r2
LI64 r33, 1d
ADD64 r1, r32, r33
LD r31, r254, 0a, 24h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a JALA r0, r31, 0a
add_two: add_two:
ADDI64 r254, r254, -24d ADDI64 r254, r254, -16d
ST r31, r254, 0a, 24h ST r31, r254, 0a, 16h
CP r32, r2 CP r32, r2
LI64 r33, 2d ADDI64 r1, r32, 2d
ADD64 r1, r32, r33 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
code size: 263 add_one:
ADDI64 r254, r254, -16d
ST r31, r254, 0a, 16h
CP r32, r2
ADDI64 r1, r32, 1d
LD r31, r254, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
code size: 254
ret: 33 ret: 33
status: Ok(()) status: Ok(())

View file

@ -0,0 +1,28 @@
main:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
LI64 r2, 10d
JAL r31, r0, :fib
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
fib:
ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h
CP r32, r2
LI64 r33, 2d
JGTS r32, r33, :0
LI64 r1, 1d
JMP :1
0: ADDI64 r2, r32, -1d
JAL r31, r0, :fib
CP r34, r1
ADDI64 r2, r32, -2d
JAL r31, r0, :fib
ADD64 r1, r1, r34
1: LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a
code size: 219
ret: 55
status: Ok(())