forked from koniifer/ableos
fixing more bugs and also adding uninig memory and also optimizing cong jumps
This commit is contained in:
parent
391638d5b1
commit
601625e43f
|
@ -335,6 +335,19 @@ foo := fn(a: int, b: int, c: int): int {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### idk
|
||||||
|
```hb
|
||||||
|
main := fn(): int {
|
||||||
|
big_array := @as([u8; 128], idk)
|
||||||
|
i := 0
|
||||||
|
loop if i >= 128 break else {
|
||||||
|
big_array[i] = 69
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
return big_array[42]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Incomplete Examples
|
### Incomplete Examples
|
||||||
|
|
||||||
#### comptime_pointers
|
#### comptime_pointers
|
||||||
|
|
|
@ -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::{collections::BTreeMap, fmt::Display, ops::Range, rc::Rc},
|
std::{collections::BTreeMap, fmt::Display, ops::Range, rc::Rc, u32},
|
||||||
};
|
};
|
||||||
|
|
||||||
type Offset = u32;
|
type Offset = u32;
|
||||||
|
@ -688,6 +688,10 @@ impl Loc {
|
||||||
Self::Rt { .. } => None,
|
Self::Rt { .. } => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_stack(&self) -> bool {
|
||||||
|
matches!(self, Self::Rt { derefed: true, reg, stack: Some(_), offset: 0 } if reg.get() == STACK_PTR)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<reg::Id> for Loc {
|
impl From<reg::Id> for Loc {
|
||||||
|
@ -702,6 +706,7 @@ impl Default for Loc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
struct Loop {
|
struct Loop {
|
||||||
var_count: u32,
|
var_count: u32,
|
||||||
offset: u32,
|
offset: u32,
|
||||||
|
@ -710,6 +715,7 @@ struct Loop {
|
||||||
|
|
||||||
struct Variable {
|
struct Variable {
|
||||||
id: Ident,
|
id: Ident,
|
||||||
|
uses_left: u32,
|
||||||
value: Value,
|
value: Value,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1419,7 +1425,9 @@ impl Codegen {
|
||||||
// TODO: we need to check if index is in bounds on debug builds
|
// TODO: we need to check if index is in bounds on debug builds
|
||||||
|
|
||||||
let mut base_val = self.expr(base)?;
|
let mut base_val = self.expr(base)?;
|
||||||
|
if base_val.ty.is_pointer() {
|
||||||
base_val.loc = self.make_loc_owned(base_val.loc, base_val.ty);
|
base_val.loc = self.make_loc_owned(base_val.loc, base_val.ty);
|
||||||
|
}
|
||||||
let index_val = self.expr(index)?;
|
let index_val = self.expr(index)?;
|
||||||
_ = self.assert_ty(index.pos(), index_val.ty, ty::INT.into(), "subsctipt");
|
_ = self.assert_ty(index.pos(), index_val.ty, ty::INT.into(), "subsctipt");
|
||||||
|
|
||||||
|
@ -1449,7 +1457,9 @@ impl Codegen {
|
||||||
|
|
||||||
let idx = self.loc_to_reg(index_val.loc, 8);
|
let idx = self.loc_to_reg(index_val.loc, 8);
|
||||||
|
|
||||||
|
if item_size != 1 {
|
||||||
self.output.emit(muli64(idx.get(), idx.get(), item_size as _));
|
self.output.emit(muli64(idx.get(), idx.get(), item_size as _));
|
||||||
|
}
|
||||||
self.output.emit(add64(reg.get(), reg.get(), idx.get()));
|
self.output.emit(add64(reg.get(), reg.get(), idx.get()));
|
||||||
self.ci.regs.free(idx);
|
self.ci.regs.free(idx);
|
||||||
|
|
||||||
|
@ -1491,7 +1501,13 @@ impl Codegen {
|
||||||
args.iter().zip(sig.args.view(&self.tys.args).to_owned()).zip(cargs)
|
args.iter().zip(sig.args.view(&self.tys.args).to_owned()).zip(cargs)
|
||||||
{
|
{
|
||||||
let loc = self.expr_ctx(arg, Ctx::default().with_ty(ty))?.loc;
|
let loc = self.expr_ctx(arg, Ctx::default().with_ty(ty))?.loc;
|
||||||
self.ci.vars.push(Variable { id: carg.id, value: Value { ty, loc } });
|
|
||||||
|
let sym = parser::find_symbol(&fast.symbols, carg.id).flags;
|
||||||
|
self.ci.vars.push(Variable {
|
||||||
|
id: carg.id,
|
||||||
|
value: Value { ty, loc },
|
||||||
|
uses_left: idfl::count(sym) as u32,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1524,11 +1540,7 @@ impl Codegen {
|
||||||
return Some(Value { ty: sig.ret, loc });
|
return Some(Value { ty: sig.ret, loc });
|
||||||
}
|
}
|
||||||
E::Directive { name: "TypeOf", args: [expr], .. } => {
|
E::Directive { name: "TypeOf", args: [expr], .. } => {
|
||||||
let snap = self.output.snap();
|
Some(Value::ty(self.infer_type(expr)))
|
||||||
let value = self.expr(expr).unwrap();
|
|
||||||
self.ci.free_loc(value.loc);
|
|
||||||
self.output.trunc(&snap);
|
|
||||||
Some(Value::ty(value.ty))
|
|
||||||
}
|
}
|
||||||
E::Directive { name: "eca", args: [ret_ty, args @ ..], .. } => {
|
E::Directive { name: "eca", args: [ret_ty, args @ ..], .. } => {
|
||||||
let ty = self.ty(ret_ty);
|
let ty = self.ty(ret_ty);
|
||||||
|
@ -1585,7 +1597,7 @@ impl Codegen {
|
||||||
let Some(ty) = ctx.ty else {
|
let Some(ty) = ctx.ty else {
|
||||||
self.report(
|
self.report(
|
||||||
expr.pos(),
|
expr.pos(),
|
||||||
"type to cast to is unknown, use `@as(<type>, <expr>)`",
|
"type to cast to is unknown, use `@as(<type>, @bitcast(<expr>))`",
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1623,6 +1635,31 @@ impl Codegen {
|
||||||
E::Bool { value, .. } => {
|
E::Bool { value, .. } => {
|
||||||
Some(Value { ty: ty::BOOL.into(), loc: Loc::ct(value as u64) })
|
Some(Value { ty: ty::BOOL.into(), loc: Loc::ct(value as u64) })
|
||||||
}
|
}
|
||||||
|
E::Idk { pos } => {
|
||||||
|
let Some(ty) = ctx.ty else {
|
||||||
|
self.report(
|
||||||
|
pos,
|
||||||
|
"`idk` can be used only when type can be inferred, use @as(<type>, idk)",
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
if ctx.loc.is_some() {
|
||||||
|
self.report(
|
||||||
|
pos,
|
||||||
|
"`idk` would be written to an existing memory location \
|
||||||
|
which at ths point does notthing so its prohibited. TODO: make debug \
|
||||||
|
builds write 0xAA instead.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let loc = match self.tys.size_of(ty) {
|
||||||
|
0 => Loc::default(),
|
||||||
|
1..=8 => Loc::reg(self.ci.regs.allocate()),
|
||||||
|
size => Loc::stack(self.ci.stack.allocate(size)),
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(Value { ty, loc })
|
||||||
|
}
|
||||||
E::String { pos, mut literal } => {
|
E::String { pos, mut literal } => {
|
||||||
literal = literal.trim_matches('"');
|
literal = literal.trim_matches('"');
|
||||||
|
|
||||||
|
@ -1917,12 +1954,12 @@ impl Codegen {
|
||||||
return Some(Value { ty: sig.ret, loc });
|
return Some(Value { ty: sig.ret, loc });
|
||||||
}
|
}
|
||||||
E::Ident { id, .. } if ident::is_null(id) => Some(Value::ty(id.into())),
|
E::Ident { id, .. } if ident::is_null(id) => Some(Value::ty(id.into())),
|
||||||
E::Ident { id, index, .. }
|
E::Ident { id, .. }
|
||||||
if let Some((var_index, var)) =
|
if let Some((var_index, var)) =
|
||||||
self.ci.vars.iter_mut().enumerate().find(|(_, v)| v.id == id) =>
|
self.ci.vars.iter_mut().enumerate().find(|(_, v)| v.id == id) =>
|
||||||
{
|
{
|
||||||
let sym = parser::find_symbol(&self.files[self.ci.file as usize].symbols, id);
|
var.uses_left -= 1;
|
||||||
let loc = match idfl::index(sym.flags) == index
|
let loc = match var.uses_left == 0
|
||||||
&& !self.ci.loops.last().is_some_and(|l| l.var_count > var_index as u32)
|
&& !self.ci.loops.last().is_some_and(|l| l.var_count > var_index as u32)
|
||||||
{
|
{
|
||||||
true => std::mem::take(&mut var.value.loc),
|
true => std::mem::take(&mut var.value.loc),
|
||||||
|
@ -1990,15 +2027,59 @@ impl Codegen {
|
||||||
},
|
},
|
||||||
loc: Loc::ct(value as u64),
|
loc: Loc::ct(value as u64),
|
||||||
}),
|
}),
|
||||||
E::If { cond, then, else_, .. } => {
|
E::If { cond, then, mut else_, .. } => {
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
|
fn cond_op(
|
||||||
|
op: TokenKind,
|
||||||
|
signed: bool,
|
||||||
|
) -> Option<(fn(u8, u8, i16) -> (usize, [u8; instrs::MAX_SIZE]), bool)>
|
||||||
|
{
|
||||||
|
Some((
|
||||||
|
match op {
|
||||||
|
TokenKind::Le if signed => instrs::jgts,
|
||||||
|
TokenKind::Le => instrs::jgtu,
|
||||||
|
TokenKind::Lt if signed => instrs::jlts,
|
||||||
|
TokenKind::Lt => instrs::jltu,
|
||||||
|
TokenKind::Eq => instrs::jne,
|
||||||
|
TokenKind::Ne => instrs::jeq,
|
||||||
|
_ => return None,
|
||||||
|
},
|
||||||
|
matches!(op, TokenKind::Lt | TokenKind::Gt),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut then = Some(then);
|
||||||
|
let jump_offset;
|
||||||
|
if let &E::BinOp { left, op, right } = cond
|
||||||
|
&& let ty = self.infer_type(left)
|
||||||
|
&& let Some((op, swapped)) = cond_op(op, ty.is_signed())
|
||||||
|
{
|
||||||
|
let left = self.expr_ctx(left, Ctx::default())?;
|
||||||
|
let right = self.expr_ctx(right, Ctx::default())?;
|
||||||
|
let lsize = self.tys.size_of(left.ty);
|
||||||
|
let rsize = self.tys.size_of(right.ty);
|
||||||
|
let left_reg = self.loc_to_reg(&left.loc, lsize);
|
||||||
|
let right_reg = self.loc_to_reg(&right.loc, rsize);
|
||||||
|
jump_offset = self.local_offset();
|
||||||
|
self.output.emit(op(left_reg.get(), right_reg.get(), 0));
|
||||||
|
self.ci.free_loc(left.loc);
|
||||||
|
self.ci.free_loc(right.loc);
|
||||||
|
self.ci.regs.free(left_reg);
|
||||||
|
self.ci.regs.free(right_reg);
|
||||||
|
if swapped {
|
||||||
|
std::mem::swap(&mut then, &mut else_);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
let cond = self.expr_ctx(cond, Ctx::default().with_ty(ty::BOOL))?;
|
let cond = self.expr_ctx(cond, Ctx::default().with_ty(ty::BOOL))?;
|
||||||
let reg = self.loc_to_reg(&cond.loc, 1);
|
let reg = self.loc_to_reg(&cond.loc, 1);
|
||||||
let jump_offset = self.local_offset();
|
jump_offset = self.local_offset();
|
||||||
self.output.emit(jeq(reg.get(), 0, 0));
|
self.output.emit(jeq(reg.get(), 0, 0));
|
||||||
self.ci.free_loc(cond.loc);
|
self.ci.free_loc(cond.loc);
|
||||||
self.ci.regs.free(reg);
|
self.ci.regs.free(reg);
|
||||||
|
}
|
||||||
|
|
||||||
let then_unreachable = self.expr(then).is_none();
|
let then_unreachable =
|
||||||
|
if let Some(then) = then { self.expr(then).is_none() } else { false };
|
||||||
let mut else_unreachable = false;
|
let mut else_unreachable = false;
|
||||||
|
|
||||||
let mut jump = self.local_offset() as i64 - jump_offset as i64;
|
let mut jump = self.local_offset() as i64 - jump_offset as i64;
|
||||||
|
@ -2196,9 +2277,8 @@ impl Codegen {
|
||||||
|
|
||||||
Some(match ctx.loc {
|
Some(match ctx.loc {
|
||||||
Some(dest) => {
|
Some(dest) => {
|
||||||
let ty = ctx.ty.unwrap_or(value.ty);
|
self.store_typed(value.loc, dest, value.ty);
|
||||||
self.store_typed(value.loc, dest, ty);
|
Value { ty: value.ty, loc: Loc::ct(0) }
|
||||||
Value { ty, loc: Loc::ct(0) }
|
|
||||||
}
|
}
|
||||||
None => value,
|
None => value,
|
||||||
})
|
})
|
||||||
|
@ -2236,7 +2316,11 @@ impl Codegen {
|
||||||
arg.loc
|
arg.loc
|
||||||
};
|
};
|
||||||
|
|
||||||
self.ci.vars.push(Variable { id: carg.id, value: Value { ty, loc } });
|
self.ci.vars.push(Variable {
|
||||||
|
id: carg.id,
|
||||||
|
value: Value { ty, loc },
|
||||||
|
uses_left: idfl::count(sym.flags) as u32,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let args = self.pack_args(pos, arg_base);
|
let args = self.pack_args(pos, arg_base);
|
||||||
|
@ -2266,6 +2350,38 @@ impl Codegen {
|
||||||
expr.has_ct(&self.cfile().symbols)
|
expr.has_ct(&self.cfile().symbols)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn infer_type(&mut self, expr: &Expr) -> ty::Id {
|
||||||
|
let mut snap = self.output.snap();
|
||||||
|
snap._sub(&self.ci.snap);
|
||||||
|
let mut ci = ItemCtx {
|
||||||
|
file: self.ci.file,
|
||||||
|
id: self.ci.id,
|
||||||
|
ret: self.ci.ret,
|
||||||
|
task_base: self.ci.task_base,
|
||||||
|
snap: self.ci.snap,
|
||||||
|
loops: self.ci.loops.clone(),
|
||||||
|
vars: self
|
||||||
|
.ci
|
||||||
|
.vars
|
||||||
|
.iter()
|
||||||
|
.map(|v| Variable {
|
||||||
|
id: v.id,
|
||||||
|
value: Value { ty: v.value.ty, loc: v.value.loc.as_ref() },
|
||||||
|
uses_left: v.uses_left,
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
ci.regs.init();
|
||||||
|
std::mem::swap(&mut self.ci, &mut ci);
|
||||||
|
let value = self.expr(expr).unwrap();
|
||||||
|
self.ci.free_loc(value.loc);
|
||||||
|
std::mem::swap(&mut self.ci, &mut ci);
|
||||||
|
snap._add(&self.ci.snap);
|
||||||
|
self.output.trunc(&snap);
|
||||||
|
value.ty
|
||||||
|
}
|
||||||
|
|
||||||
fn eval_const(&mut self, expr: &Expr, ty: impl Into<ty::Id>) -> u64 {
|
fn eval_const(&mut self, expr: &Expr, ty: impl Into<ty::Id>) -> u64 {
|
||||||
self.eval_const_low(expr, Some(ty.into())).0
|
self.eval_const_low(expr, Some(ty.into())).0
|
||||||
}
|
}
|
||||||
|
@ -2321,11 +2437,15 @@ impl Codegen {
|
||||||
&& size <= 8 =>
|
&& size <= 8 =>
|
||||||
{
|
{
|
||||||
let loc = Loc::ct(load_value(offset, size));
|
let loc = Loc::ct(load_value(offset, size));
|
||||||
self.ci.vars.push(Variable { id, value: Value { ty, loc } });
|
self.ci.vars.push(Variable { id, value: Value { ty, loc }, uses_left: u32::MAX });
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
Expr::Ident { id, .. } => {
|
Expr::Ident { id, .. } => {
|
||||||
let var = Variable { id, value: Value { ty, loc: Loc::ct_ptr(offset as _) } };
|
let var = Variable {
|
||||||
|
id,
|
||||||
|
value: Value { ty, loc: Loc::ct_ptr(offset as _) },
|
||||||
|
uses_left: u32::MAX,
|
||||||
|
};
|
||||||
self.ci.vars.push(var);
|
self.ci.vars.push(var);
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -2337,11 +2457,15 @@ impl Codegen {
|
||||||
match *pat {
|
match *pat {
|
||||||
Expr::Ident { id, .. } => {
|
Expr::Ident { id, .. } => {
|
||||||
let mut loc = self.make_loc_owned(right.loc, right.ty);
|
let mut loc = self.make_loc_owned(right.loc, right.ty);
|
||||||
let sym = parser::find_symbol(&self.cfile().symbols, id);
|
let sym = parser::find_symbol(&self.cfile().symbols, id).flags;
|
||||||
if sym.flags & idfl::REFERENCED != 0 {
|
if sym & idfl::REFERENCED != 0 {
|
||||||
loc = self.spill(loc, self.tys.size_of(right.ty));
|
loc = self.spill(loc, self.tys.size_of(right.ty));
|
||||||
}
|
}
|
||||||
self.ci.vars.push(Variable { id, value: Value { ty: right.ty, loc } });
|
self.ci.vars.push(Variable {
|
||||||
|
id,
|
||||||
|
value: Value { ty: right.ty, loc },
|
||||||
|
uses_left: idfl::count(sym) as u32,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
Expr::Ctor { pos, fields, .. } => {
|
Expr::Ctor { pos, fields, .. } => {
|
||||||
let ty::Kind::Struct(idx) = right.ty.expand() else {
|
let ty::Kind::Struct(idx) = right.ty.expand() else {
|
||||||
|
@ -2553,9 +2677,13 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spill(&mut self, loc: Loc, size: Size) -> Loc {
|
fn spill(&mut self, loc: Loc, size: Size) -> Loc {
|
||||||
|
if loc.is_ref() || !loc.is_stack() {
|
||||||
let stack = Loc::stack(self.ci.stack.allocate(size));
|
let stack = Loc::stack(self.ci.stack.allocate(size));
|
||||||
self.store_sized(loc, &stack, size);
|
self.store_sized(loc, &stack, size);
|
||||||
stack
|
stack
|
||||||
|
} else {
|
||||||
|
loc
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_loc_owned(&mut self, loc: Loc, ty: ty::Id) -> Loc {
|
fn make_loc_owned(&mut self, loc: Loc, ty: ty::Id) -> Loc {
|
||||||
|
@ -2595,7 +2723,6 @@ impl Codegen {
|
||||||
self.output.code.append(&mut self.output.string_data);
|
self.output.code.append(&mut self.output.string_data);
|
||||||
// we drain these when linking
|
// we drain these when linking
|
||||||
for srel in self.output.strings.iter_mut().filter(|s| !s.shifted) {
|
for srel in self.output.strings.iter_mut().filter(|s| !s.shifted) {
|
||||||
dbg!(&srel.range);
|
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
srel.range.end <= prev_data_len as u32,
|
srel.range.end <= prev_data_len as u32,
|
||||||
"{} <= {}",
|
"{} <= {}",
|
||||||
|
@ -2628,7 +2755,7 @@ impl Codegen {
|
||||||
self.ci.snap = self.output.snap();
|
self.ci.snap = self.output.snap();
|
||||||
|
|
||||||
let Expr::BinOp {
|
let Expr::BinOp {
|
||||||
left: Expr::Ident { name, .. },
|
left: Expr::Ident { .. },
|
||||||
op: TokenKind::Decl,
|
op: TokenKind::Decl,
|
||||||
right: &Expr::Closure { body, args, .. },
|
right: &Expr::Closure { body, args, .. },
|
||||||
} = expr
|
} = expr
|
||||||
|
@ -2636,20 +2763,22 @@ impl Codegen {
|
||||||
unreachable!("{expr}")
|
unreachable!("{expr}")
|
||||||
};
|
};
|
||||||
|
|
||||||
log::dbg!(name);
|
|
||||||
|
|
||||||
self.output.emit_prelude();
|
self.output.emit_prelude();
|
||||||
|
|
||||||
let mut parama = self.tys.parama(sig.ret);
|
let mut parama = self.tys.parama(sig.ret);
|
||||||
let mut sig_args = sig.args.range();
|
let mut sig_args = sig.args.range();
|
||||||
for arg in args.iter() {
|
for arg in args.iter() {
|
||||||
let ty = self.tys.args[sig_args.next().unwrap()];
|
let ty = self.tys.args[sig_args.next().unwrap()];
|
||||||
let sym = parser::find_symbol(&ast.symbols, arg.id);
|
let sym = parser::find_symbol(&ast.symbols, arg.id).flags;
|
||||||
let loc = match sym.flags & idfl::COMPTIME != 0 {
|
let loc = match sym & idfl::COMPTIME != 0 {
|
||||||
true => Loc::ty(self.tys.args[sig_args.next().unwrap()]),
|
true => Loc::ty(self.tys.args[sig_args.next().unwrap()]),
|
||||||
false => self.load_arg(sym.flags, ty, &mut parama),
|
false => self.load_arg(sym, ty, &mut parama),
|
||||||
};
|
};
|
||||||
self.ci.vars.push(Variable { id: arg.id, value: Value { ty, loc } });
|
self.ci.vars.push(Variable {
|
||||||
|
id: arg.id,
|
||||||
|
value: Value { ty, loc },
|
||||||
|
uses_left: idfl::count(sym) as u32,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.tys.size_of(sig.ret) > 16 {
|
if self.tys.size_of(sig.ret) > 16 {
|
||||||
|
@ -2980,6 +3109,7 @@ impl Codegen {
|
||||||
self.ci.vars.push(Variable {
|
self.ci.vars.push(Variable {
|
||||||
id,
|
id,
|
||||||
value: Value::new(ty, Loc::ct(u64::from_ne_bytes(imm))),
|
value: Value::new(ty, Loc::ct(u64::from_ne_bytes(imm))),
|
||||||
|
uses_left: u32::MAX,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3555,6 +3685,7 @@ mod tests {
|
||||||
generic_types => README;
|
generic_types => README;
|
||||||
generic_functions => README;
|
generic_functions => README;
|
||||||
c_strings => README;
|
c_strings => README;
|
||||||
|
idk => README;
|
||||||
struct_patterns => README;
|
struct_patterns => README;
|
||||||
arrays => README;
|
arrays => README;
|
||||||
struct_return_from_module_function => README;
|
struct_return_from_module_function => README;
|
||||||
|
|
|
@ -44,19 +44,23 @@ macro_rules! gen_token_kind {
|
||||||
) => {
|
) => {
|
||||||
impl std::fmt::Display for $name {
|
impl std::fmt::Display for $name {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
let sf = *self as u8;
|
f.write_str(self.name())
|
||||||
f.write_str(match *self {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $name {
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
let sf = unsafe { &*(self as *const _ as *const u8) } ;
|
||||||
|
match *self {
|
||||||
$( Self::$pattern => concat!('<', stringify!($pattern), '>'), )*
|
$( Self::$pattern => concat!('<', stringify!($pattern), '>'), )*
|
||||||
$( Self::$keyword => stringify!($keyword_lit), )*
|
$( Self::$keyword => stringify!($keyword_lit), )*
|
||||||
$( Self::$punkt => stringify!($punkt_lit), )*
|
$( Self::$punkt => stringify!($punkt_lit), )*
|
||||||
$($( Self::$op => $op_lit,
|
$($( Self::$op => $op_lit,
|
||||||
$(Self::$assign => concat!($op_lit, "="),)?)*)*
|
$(Self::$assign => concat!($op_lit, "="),)?)*)*
|
||||||
_ => unsafe { std::str::from_utf8_unchecked(std::slice::from_ref(&sf)) },
|
_ => unsafe { std::str::from_utf8_unchecked(std::slice::from_ref(&sf)) },
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl $name {
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn precedence(&self) -> Option<u8> {
|
pub fn precedence(&self) -> Option<u8> {
|
||||||
Some(match self {
|
Some(match self {
|
||||||
|
@ -124,6 +128,8 @@ pub enum TokenKind {
|
||||||
Fn,
|
Fn,
|
||||||
Struct,
|
Struct,
|
||||||
True,
|
True,
|
||||||
|
False,
|
||||||
|
Idk,
|
||||||
|
|
||||||
Ctor,
|
Ctor,
|
||||||
Tupl,
|
Tupl,
|
||||||
|
@ -213,6 +219,8 @@ gen_token_kind! {
|
||||||
Fn = b"fn",
|
Fn = b"fn",
|
||||||
Struct = b"struct",
|
Struct = b"struct",
|
||||||
True = b"true",
|
True = b"true",
|
||||||
|
False = b"false",
|
||||||
|
Idk = b"idk",
|
||||||
#[punkt]
|
#[punkt]
|
||||||
Ctor = ".{",
|
Ctor = ".{",
|
||||||
Tupl = ".(",
|
Tupl = ".(",
|
||||||
|
|
|
@ -36,7 +36,7 @@ pub mod idfl {
|
||||||
COMPTIME,
|
COMPTIME,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn index(i: IdentFlags) -> IdentIndex {
|
pub fn count(i: IdentFlags) -> IdentIndex {
|
||||||
(i & !ALL) as _
|
(i & !ALL) as _
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -251,7 +251,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
self.captured.push(id.ident);
|
self.captured.push(id.ident);
|
||||||
}
|
}
|
||||||
|
|
||||||
(id.ident, idfl::index(id.flags))
|
(id.ident, idfl::count(id.flags))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_str(&mut self, range: Token) -> &'a str {
|
fn move_str(&mut self, range: Token) -> &'a str {
|
||||||
|
@ -261,11 +261,11 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
fn unit_expr(&mut self) -> Expr<'a> {
|
fn unit_expr(&mut self) -> Expr<'a> {
|
||||||
use {Expr as E, TokenKind as T};
|
use {Expr as E, TokenKind as T};
|
||||||
let frame = self.idents.len();
|
let frame = self.idents.len();
|
||||||
let token = self.next();
|
let token @ Token { start: pos, .. } = self.next();
|
||||||
let prev_boundary = self.ns_bound;
|
let prev_boundary = self.ns_bound;
|
||||||
let prev_captured = self.captured.len();
|
let prev_captured = self.captured.len();
|
||||||
let mut expr = match token.kind {
|
let mut expr = match token.kind {
|
||||||
T::Ct => E::Ct { pos: token.start, value: self.ptr_expr() },
|
T::Ct => E::Ct { pos, value: self.ptr_expr() },
|
||||||
T::Directive if self.lexer.slice(token.range()) == "use" => {
|
T::Directive if self.lexer.slice(token.range()) == "use" => {
|
||||||
self.expect_advance(TokenKind::LParen);
|
self.expect_advance(TokenKind::LParen);
|
||||||
let str = self.expect_advance(TokenKind::DQuote);
|
let str = self.expect_advance(TokenKind::DQuote);
|
||||||
|
@ -273,7 +273,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
let path = self.lexer.slice(str.range()).trim_matches('"');
|
let path = self.lexer.slice(str.range()).trim_matches('"');
|
||||||
|
|
||||||
E::Mod {
|
E::Mod {
|
||||||
pos: token.start,
|
pos,
|
||||||
path: self.arena.alloc_str(path),
|
path: self.arena.alloc_str(path),
|
||||||
id: match (self.loader)(path, self.path) {
|
id: match (self.loader)(path, self.path) {
|
||||||
Ok(id) => id,
|
Ok(id) => id,
|
||||||
|
@ -282,15 +282,17 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
T::Directive => E::Directive {
|
T::Directive => E::Directive {
|
||||||
pos: token.start,
|
pos,
|
||||||
name: self.move_str(token),
|
name: self.move_str(token),
|
||||||
args: {
|
args: {
|
||||||
self.expect_advance(T::LParen);
|
self.expect_advance(T::LParen);
|
||||||
self.collect_list(T::Comma, T::RParen, Self::expr)
|
self.collect_list(T::Comma, T::RParen, Self::expr)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
T::True => E::Bool { pos: token.start, value: true },
|
T::True => E::Bool { pos, value: true },
|
||||||
T::DQuote => E::String { pos: token.start, literal: self.move_str(token) },
|
T::False => E::Bool { pos, value: false },
|
||||||
|
T::Idk => E::Idk { pos },
|
||||||
|
T::DQuote => E::String { pos, literal: self.move_str(token) },
|
||||||
T::Struct => E::Struct {
|
T::Struct => E::Struct {
|
||||||
fields: {
|
fields: {
|
||||||
self.ns_bound = self.idents.len();
|
self.ns_bound = self.idents.len();
|
||||||
|
@ -313,26 +315,26 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
// we might save some memory
|
// we might save some memory
|
||||||
self.captured.clear();
|
self.captured.clear();
|
||||||
}
|
}
|
||||||
token.start
|
pos
|
||||||
},
|
},
|
||||||
trailing_comma: std::mem::take(&mut self.trailing_sep),
|
trailing_comma: std::mem::take(&mut self.trailing_sep),
|
||||||
},
|
},
|
||||||
T::Ident | T::CtIdent => {
|
T::Ident | T::CtIdent => {
|
||||||
let (id, index) = self.resolve_ident(token);
|
let (id, index) = self.resolve_ident(token);
|
||||||
let name = self.move_str(token);
|
let name = self.move_str(token);
|
||||||
E::Ident { pos: token.start, is_ct: token.kind == T::CtIdent, name, id, index }
|
E::Ident { pos, is_ct: token.kind == T::CtIdent, name, id, index }
|
||||||
}
|
}
|
||||||
T::If => E::If {
|
T::If => E::If {
|
||||||
pos: token.start,
|
pos,
|
||||||
cond: self.ptr_expr(),
|
cond: self.ptr_expr(),
|
||||||
then: self.ptr_expr(),
|
then: self.ptr_expr(),
|
||||||
else_: self.advance_if(T::Else).then(|| self.ptr_expr()),
|
else_: self.advance_if(T::Else).then(|| self.ptr_expr()),
|
||||||
},
|
},
|
||||||
T::Loop => E::Loop { pos: token.start, body: self.ptr_expr() },
|
T::Loop => E::Loop { pos, body: self.ptr_expr() },
|
||||||
T::Break => E::Break { pos: token.start },
|
T::Break => E::Break { pos },
|
||||||
T::Continue => E::Continue { pos: token.start },
|
T::Continue => E::Continue { pos },
|
||||||
T::Return => E::Return {
|
T::Return => E::Return {
|
||||||
pos: token.start,
|
pos,
|
||||||
val: (!matches!(
|
val: (!matches!(
|
||||||
self.token.kind,
|
self.token.kind,
|
||||||
T::Semi | T::RBrace | T::RBrack | T::RParen | T::Comma
|
T::Semi | T::RBrace | T::RBrack | T::RParen | T::Comma
|
||||||
|
@ -340,7 +342,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
.then(|| self.ptr_expr()),
|
.then(|| self.ptr_expr()),
|
||||||
},
|
},
|
||||||
T::Fn => E::Closure {
|
T::Fn => E::Closure {
|
||||||
pos: token.start,
|
pos,
|
||||||
args: {
|
args: {
|
||||||
self.expect_advance(T::LParen);
|
self.expect_advance(T::LParen);
|
||||||
self.collect_list(T::Comma, T::RParen, |s| {
|
self.collect_list(T::Comma, T::RParen, |s| {
|
||||||
|
@ -363,18 +365,18 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
},
|
},
|
||||||
body: self.ptr_expr(),
|
body: self.ptr_expr(),
|
||||||
},
|
},
|
||||||
T::Ctor => self.ctor(token.start, None),
|
T::Ctor => self.ctor(pos, None),
|
||||||
T::Tupl => self.tupl(token.start, None),
|
T::Tupl => self.tupl(pos, None),
|
||||||
T::LBrack => E::Slice {
|
T::LBrack => E::Slice {
|
||||||
item: self.ptr_unit_expr(),
|
item: self.ptr_unit_expr(),
|
||||||
size: self.advance_if(T::Semi).then(|| self.ptr_expr()),
|
size: self.advance_if(T::Semi).then(|| self.ptr_expr()),
|
||||||
pos: {
|
pos: {
|
||||||
self.expect_advance(T::RBrack);
|
self.expect_advance(T::RBrack);
|
||||||
token.start
|
pos
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
T::Band | T::Mul | T::Xor => E::UnOp {
|
T::Band | T::Mul | T::Xor => E::UnOp {
|
||||||
pos: token.start,
|
pos,
|
||||||
op: token.kind,
|
op: token.kind,
|
||||||
val: {
|
val: {
|
||||||
let expr = self.ptr_unit_expr();
|
let expr = self.ptr_unit_expr();
|
||||||
|
@ -384,10 +386,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
expr
|
expr
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
T::LBrace => E::Block {
|
T::LBrace => E::Block { pos, stmts: self.collect_list(T::Semi, T::RBrace, Self::expr) },
|
||||||
pos: token.start,
|
|
||||||
stmts: self.collect_list(T::Semi, T::RBrace, Self::expr),
|
|
||||||
},
|
|
||||||
T::Number => {
|
T::Number => {
|
||||||
let slice = self.lexer.slice(token.range());
|
let slice = self.lexer.slice(token.range());
|
||||||
let (slice, radix) = match &slice.get(0..2) {
|
let (slice, radix) = match &slice.get(0..2) {
|
||||||
|
@ -397,7 +396,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
_ => (slice, Radix::Decimal),
|
_ => (slice, Radix::Decimal),
|
||||||
};
|
};
|
||||||
E::Number {
|
E::Number {
|
||||||
pos: token.start,
|
pos,
|
||||||
value: match u64::from_str_radix(slice, radix as u32) {
|
value: match u64::from_str_radix(slice, radix as u32) {
|
||||||
Ok(value) => value,
|
Ok(value) => value,
|
||||||
Err(e) => self.report(format_args!("invalid number: {e}")),
|
Err(e) => self.report(format_args!("invalid number: {e}")),
|
||||||
|
@ -410,7 +409,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
self.expect_advance(T::RParen);
|
self.expect_advance(T::RParen);
|
||||||
expr
|
expr
|
||||||
}
|
}
|
||||||
T::Comment => Expr::Comment { pos: token.start, literal: self.move_str(token) },
|
T::Comment => Expr::Comment { pos, literal: self.move_str(token) },
|
||||||
tok => self.report(format_args!("unexpected token: {tok:?}")),
|
tok => self.report(format_args!("unexpected token: {tok:?}")),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -773,6 +772,10 @@ generate_expr! {
|
||||||
pos: Pos,
|
pos: Pos,
|
||||||
value: bool,
|
value: bool,
|
||||||
},
|
},
|
||||||
|
/// `'idk'`
|
||||||
|
Idk {
|
||||||
|
pos: Pos,
|
||||||
|
},
|
||||||
/// `'@' Ident List('(', ',', ')', Expr)`
|
/// `'@' Ident List('(', ',', ')', Expr)`
|
||||||
Directive {
|
Directive {
|
||||||
pos: u32,
|
pos: u32,
|
||||||
|
@ -1047,6 +1050,7 @@ impl<'a> std::fmt::Display for Expr<'a> {
|
||||||
Radix::Binary => write!(f, "{value:#b}"),
|
Radix::Binary => write!(f, "{value:#b}"),
|
||||||
},
|
},
|
||||||
Self::Bool { value, .. } => write!(f, "{value}"),
|
Self::Bool { value, .. } => write!(f, "{value}"),
|
||||||
|
Self::Idk { .. } => write!(f, "idk"),
|
||||||
Self::BinOp {
|
Self::BinOp {
|
||||||
left,
|
left,
|
||||||
op: TokenKind::Assign,
|
op: TokenKind::Assign,
|
||||||
|
|
|
@ -15,12 +15,14 @@ use {
|
||||||
core::fmt,
|
core::fmt,
|
||||||
std::{
|
std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
|
cmp,
|
||||||
collections::{hash_map, BTreeMap},
|
collections::{hash_map, BTreeMap},
|
||||||
fmt::Display,
|
fmt::{Display, Write},
|
||||||
hash::{Hash as _, Hasher},
|
hash::{Hash as _, Hasher},
|
||||||
mem,
|
mem,
|
||||||
ops::{self, Range},
|
ops::{self, Range},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
|
u32,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,6 +60,7 @@ impl BitSet {
|
||||||
self.data.resize(new_len, 0);
|
self.data.resize(new_len, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
pub fn set(&mut self, idx: usize) -> bool {
|
pub fn set(&mut self, idx: usize) -> bool {
|
||||||
let data_idx = idx / Self::ELEM_SIZE;
|
let data_idx = idx / Self::ELEM_SIZE;
|
||||||
let sub_idx = idx % Self::ELEM_SIZE;
|
let sub_idx = idx % Self::ELEM_SIZE;
|
||||||
|
@ -65,6 +68,12 @@ impl BitSet {
|
||||||
self.data[data_idx] |= 1 << sub_idx;
|
self.data[data_idx] |= 1 << sub_idx;
|
||||||
prev == 0
|
prev == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn unset(&mut self, idx: usize) {
|
||||||
|
let data_idx = idx / Self::ELEM_SIZE;
|
||||||
|
let sub_idx = idx % Self::ELEM_SIZE;
|
||||||
|
self.data[data_idx] &= !(1 << sub_idx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Nid = u32;
|
type Nid = u32;
|
||||||
|
@ -532,15 +541,8 @@ impl Nodes {
|
||||||
) -> Nid {
|
) -> Nid {
|
||||||
let ty = ty.into();
|
let ty = ty.into();
|
||||||
|
|
||||||
let node = Node {
|
let node =
|
||||||
inputs: inps.into(),
|
Node { inputs: inps.into(), kind, color: 0, depth: 0, lock_rc: 0, ty, outputs: vec![] };
|
||||||
kind,
|
|
||||||
color: 0,
|
|
||||||
depth: u32::MAX,
|
|
||||||
lock_rc: 0,
|
|
||||||
ty,
|
|
||||||
outputs: vec![],
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut lookup_meta = None;
|
let mut lookup_meta = None;
|
||||||
if !node.is_lazy_phi() {
|
if !node.is_lazy_phi() {
|
||||||
|
@ -689,14 +691,14 @@ impl Nodes {
|
||||||
let ty = self[target].ty;
|
let ty = self[target].ty;
|
||||||
|
|
||||||
if let (&K::CInt { value: a }, &K::CInt { value: b }) = (&self[lhs].kind, &self[rhs].kind) {
|
if let (&K::CInt { value: a }, &K::CInt { value: b }) = (&self[lhs].kind, &self[rhs].kind) {
|
||||||
return Some(self.new_node(ty, K::CInt { value: op.apply(a, b) }, []));
|
return Some(self.new_node(ty, K::CInt { value: op.apply(a, b) }, [ctrl]));
|
||||||
}
|
}
|
||||||
|
|
||||||
if lhs == rhs {
|
if lhs == rhs {
|
||||||
match op {
|
match op {
|
||||||
T::Sub => return Some(self.new_node(ty, K::CInt { value: 0 }, [])),
|
T::Sub => return Some(self.new_node(ty, K::CInt { value: 0 }, [ctrl])),
|
||||||
T::Add => {
|
T::Add => {
|
||||||
let rhs = self.new_node_nop(ty, K::CInt { value: 2 }, []);
|
let rhs = self.new_node_nop(ty, K::CInt { value: 2 }, [ctrl]);
|
||||||
return Some(self.new_node(ty, K::BinOp { op: T::Mul }, [ctrl, lhs, rhs]));
|
return Some(self.new_node(ty, K::BinOp { op: T::Mul }, [ctrl, lhs, rhs]));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -724,7 +726,7 @@ impl Nodes {
|
||||||
&& let K::CInt { value: bv } = self[rhs].kind
|
&& let K::CInt { value: bv } = self[rhs].kind
|
||||||
{
|
{
|
||||||
// (a op #b) op #c => a op (#b op #c)
|
// (a op #b) op #c => a op (#b op #c)
|
||||||
let new_rhs = self.new_node_nop(ty, K::CInt { value: op.apply(av, bv) }, []);
|
let new_rhs = self.new_node_nop(ty, K::CInt { value: op.apply(av, bv) }, [ctrl]);
|
||||||
return Some(self.new_node(ty, K::BinOp { op }, [ctrl, a, new_rhs]));
|
return Some(self.new_node(ty, K::BinOp { op }, [ctrl, a, new_rhs]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -741,7 +743,7 @@ impl Nodes {
|
||||||
&& let K::CInt { value } = self[self[lhs].inputs[2]].kind
|
&& let K::CInt { value } = self[self[lhs].inputs[2]].kind
|
||||||
{
|
{
|
||||||
// a * #n + a => a * (#n + 1)
|
// a * #n + a => a * (#n + 1)
|
||||||
let new_rhs = self.new_node_nop(ty, K::CInt { value: value + 1 }, []);
|
let new_rhs = self.new_node_nop(ty, K::CInt { value: value + 1 }, [ctrl]);
|
||||||
return Some(self.new_node(ty, K::BinOp { op: T::Mul }, [ctrl, rhs, new_rhs]));
|
return Some(self.new_node(ty, K::BinOp { op: T::Mul }, [ctrl, rhs, new_rhs]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -786,14 +788,12 @@ impl Nodes {
|
||||||
);
|
);
|
||||||
match entry {
|
match entry {
|
||||||
hash_map::RawEntryMut::Occupied(mut other) => {
|
hash_map::RawEntryMut::Occupied(mut other) => {
|
||||||
log::dbg!("rplc");
|
|
||||||
let rpl = other.get_key_value().0.nid;
|
let rpl = other.get_key_value().0.nid;
|
||||||
self[target].inputs[inp_index] = prev;
|
self[target].inputs[inp_index] = prev;
|
||||||
self.replace(target, rpl);
|
self.replace(target, rpl);
|
||||||
rpl
|
rpl
|
||||||
}
|
}
|
||||||
hash_map::RawEntryMut::Vacant(slot) => {
|
hash_map::RawEntryMut::Vacant(slot) => {
|
||||||
log::dbg!("mod");
|
|
||||||
slot.insert(LookupEntry { nid: target, hash }, ());
|
slot.insert(LookupEntry { nid: target, hash }, ());
|
||||||
let index = self[prev].outputs.iter().position(|&o| o == target).unwrap();
|
let index = self[prev].outputs.iter().position(|&o| o == target).unwrap();
|
||||||
self[prev].outputs.swap_remove(index);
|
self[prev].outputs.swap_remove(index);
|
||||||
|
@ -804,13 +804,6 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_deps(&mut self, id: Nid, deps: &[Nid]) {
|
|
||||||
for &d in deps {
|
|
||||||
debug_assert_ne!(d, id);
|
|
||||||
self[d].outputs.push(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn unlock_remove(&mut self, id: Nid) -> bool {
|
fn unlock_remove(&mut self, id: Nid) -> bool {
|
||||||
self[id].lock_rc -= 1;
|
self[id].lock_rc -= 1;
|
||||||
|
@ -909,15 +902,151 @@ impl Nodes {
|
||||||
for (i, node) in self.iter() {
|
for (i, node) in self.iter() {
|
||||||
let color = if self.is_cfg(i) { "yellow" } else { "white" };
|
let color = if self.is_cfg(i) { "yellow" } else { "white" };
|
||||||
writeln!(out, "node{i}[label=\"{}\" color={color}]", node.kind)?;
|
writeln!(out, "node{i}[label=\"{}\" color={color}]", node.kind)?;
|
||||||
for &o in &node.outputs {
|
for (j, &o) in node.outputs.iter().enumerate() {
|
||||||
let color = if self.is_cfg(i) && self.is_cfg(o) { "red" } else { "black" };
|
let color = if self.is_cfg(i) && self.is_cfg(o) { "red" } else { "lightgray" };
|
||||||
writeln!(out, "node{o} -> node{i}[color={color}]",)?;
|
let index = self[o].inputs.iter().position(|&inp| i == inp).unwrap();
|
||||||
|
let style = if index == 0 && !self.is_cfg(o) { "style=dotted" } else { "" };
|
||||||
|
writeln!(
|
||||||
|
out,
|
||||||
|
"node{o} -> node{i}[color={color} taillabel={index} headlabel={j} {style}]",
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::format_in_format_args)]
|
||||||
|
fn basic_blocks_instr(&mut self, out: &mut String, node: Nid) -> std::fmt::Result {
|
||||||
|
if !self.visited.set(node as _) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
write!(out, " {node:>2}: ")?;
|
||||||
|
match self[node].kind {
|
||||||
|
Kind::Start => unreachable!(),
|
||||||
|
Kind::End => unreachable!(),
|
||||||
|
Kind::If => write!(out, " if: "),
|
||||||
|
Kind::Region => unreachable!(),
|
||||||
|
Kind::Loop => unreachable!(),
|
||||||
|
Kind::Return => write!(out, " ret: "),
|
||||||
|
Kind::CInt { value } => write!(out, "cint: #{value:<4}"),
|
||||||
|
Kind::Phi => write!(out, " phi: "),
|
||||||
|
Kind::Tuple { index } => write!(out, " arg: {index:<5}"),
|
||||||
|
Kind::BinOp { op } => {
|
||||||
|
write!(out, "{:>4}: ", op.name())
|
||||||
|
}
|
||||||
|
Kind::Call { func } => {
|
||||||
|
write!(out, "call: {func} {}", self[node].depth)
|
||||||
|
}
|
||||||
|
}?;
|
||||||
|
|
||||||
|
writeln!(
|
||||||
|
out,
|
||||||
|
" {:<14} {}",
|
||||||
|
format!("{:?}", self[node].inputs),
|
||||||
|
format!("{:?}", self[node].outputs)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn basic_blocks_low(&mut self, out: &mut String, mut node: Nid) -> std::fmt::Result {
|
||||||
|
while self.visited.set(node as _) {
|
||||||
|
match dbg!(self[node].kind) {
|
||||||
|
Kind::Start => {
|
||||||
|
writeln!(out, "start: {}", self[node].depth)?;
|
||||||
|
let mut cfg_index = Nid::MAX;
|
||||||
|
for o in self[node].outputs.clone() {
|
||||||
|
if self[o].kind == (Kind::Tuple { index: 0 }) {
|
||||||
|
cfg_index = o;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
self.basic_blocks_instr(out, o)?;
|
||||||
|
}
|
||||||
|
node = cfg_index;
|
||||||
|
}
|
||||||
|
Kind::End => break,
|
||||||
|
Kind::If => {
|
||||||
|
self.visited.unset(node as _);
|
||||||
|
self.basic_blocks_instr(out, node)?;
|
||||||
|
self.basic_blocks_low(out, self[node].outputs[0])?;
|
||||||
|
node = self[node].outputs[1];
|
||||||
|
}
|
||||||
|
Kind::Region => {
|
||||||
|
let mut cfg_index = Nid::MAX;
|
||||||
|
for o in self[node].outputs.clone().into_iter() {
|
||||||
|
if self.is_cfg(o) {
|
||||||
|
cfg_index = o;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
self.basic_blocks_instr(out, o)?;
|
||||||
|
}
|
||||||
|
node = cfg_index;
|
||||||
|
}
|
||||||
|
Kind::Loop => {
|
||||||
|
writeln!(out, "loop{node} {}", self[node].depth)?;
|
||||||
|
let mut cfg_index = Nid::MAX;
|
||||||
|
for o in self[node].outputs.clone().into_iter() {
|
||||||
|
if self.is_cfg(o) {
|
||||||
|
cfg_index = o;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
self.basic_blocks_instr(out, o)?;
|
||||||
|
}
|
||||||
|
node = cfg_index;
|
||||||
|
}
|
||||||
|
Kind::Return => {
|
||||||
|
self.visited.unset(node as _);
|
||||||
|
self.basic_blocks_instr(out, node)?;
|
||||||
|
node = self[node].outputs[0];
|
||||||
|
}
|
||||||
|
Kind::CInt { .. } => unreachable!(),
|
||||||
|
Kind::Phi => unreachable!(),
|
||||||
|
Kind::Tuple { .. } => {
|
||||||
|
writeln!(out, "b{node}: {}", self[node].depth)?;
|
||||||
|
let mut cfg_index = Nid::MAX;
|
||||||
|
for o in self[node].outputs.clone().into_iter() {
|
||||||
|
if self.is_cfg(o) {
|
||||||
|
cfg_index = o;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
self.basic_blocks_instr(out, o)?;
|
||||||
|
}
|
||||||
|
if !self[cfg_index].kind.ends_basic_block()
|
||||||
|
&& !matches!(self[cfg_index].kind, Kind::Call { .. })
|
||||||
|
{
|
||||||
|
writeln!(out, " goto: {cfg_index}")?;
|
||||||
|
}
|
||||||
|
node = cfg_index;
|
||||||
|
}
|
||||||
|
Kind::BinOp { .. } => unreachable!(),
|
||||||
|
Kind::Call { .. } => {
|
||||||
|
self.visited.unset(node as _);
|
||||||
|
self.basic_blocks_instr(out, node)?;
|
||||||
|
|
||||||
|
let mut cfg_index = Nid::MAX;
|
||||||
|
for o in self[node].outputs.clone().into_iter() {
|
||||||
|
if self.is_cfg(o) {
|
||||||
|
cfg_index = o;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if self[o].inputs[0] == node {
|
||||||
|
self.basic_blocks_instr(out, o)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node = cfg_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn basic_blocks(&mut self) {
|
||||||
|
let mut out = String::new();
|
||||||
|
self.visited.clear(self.values.len());
|
||||||
|
self.basic_blocks_low(&mut out, 0).unwrap();
|
||||||
|
println!("{out}");
|
||||||
|
}
|
||||||
|
|
||||||
fn graphviz(&self) {
|
fn graphviz(&self) {
|
||||||
let out = &mut String::new();
|
let out = &mut String::new();
|
||||||
_ = self.graphviz_low(out);
|
_ = self.graphviz_low(out);
|
||||||
|
@ -925,17 +1054,7 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_cfg(&self, o: Nid) -> bool {
|
fn is_cfg(&self, o: Nid) -> bool {
|
||||||
matches!(
|
self[o].kind.is_cfg()
|
||||||
self[o].kind,
|
|
||||||
Kind::Start
|
|
||||||
| Kind::End
|
|
||||||
| Kind::Return
|
|
||||||
| Kind::Tuple { .. }
|
|
||||||
| Kind::Call { .. }
|
|
||||||
| Kind::If
|
|
||||||
| Kind::Region
|
|
||||||
| Kind::Loop
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_final_integrity(&self) {
|
fn check_final_integrity(&self) {
|
||||||
|
@ -1082,8 +1201,30 @@ pub enum Kind {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Kind {
|
impl Kind {
|
||||||
fn disc(&self) -> u8 {
|
fn is_pinned(&self) -> bool {
|
||||||
unsafe { *(self as *const _ as *const u8) }
|
self.is_cfg() || matches!(self, Kind::Phi)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_cfg(&self) -> bool {
|
||||||
|
matches!(
|
||||||
|
self,
|
||||||
|
Kind::Start
|
||||||
|
| Kind::End
|
||||||
|
| Kind::Return
|
||||||
|
| Kind::Tuple { .. }
|
||||||
|
| Kind::Call { .. }
|
||||||
|
| Kind::If
|
||||||
|
| Kind::Region
|
||||||
|
| Kind::Loop
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ends_basic_block(&self) -> bool {
|
||||||
|
matches!(self, Kind::Return | Kind::If | Kind::End)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn starts_basic_block(&self) -> bool {
|
||||||
|
matches!(self, Kind::Start | Kind::End | Kind::Tuple { .. } | Kind::Region | Kind::Loop)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1933,6 +2074,8 @@ impl Codegen {
|
||||||
return Some(self.ci.end);
|
return Some(self.ci.end);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.make_func_reachable(func);
|
||||||
|
|
||||||
let fuc = &self.tys.funcs[func as usize];
|
let fuc = &self.tys.funcs[func as usize];
|
||||||
let sig = fuc.sig.expect("TODO: generic functions");
|
let sig = fuc.sig.expect("TODO: generic functions");
|
||||||
let ast = self.files[fuc.file as usize].clone();
|
let ast = self.files[fuc.file as usize].clone();
|
||||||
|
@ -2107,7 +2250,7 @@ impl Codegen {
|
||||||
self.ci.ctrl = 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 { name, .. },
|
||||||
op: TokenKind::Decl,
|
op: TokenKind::Decl,
|
||||||
right: &Expr::Closure { body, args, .. },
|
right: &Expr::Closure { body, args, .. },
|
||||||
} = expr
|
} = expr
|
||||||
|
@ -2143,7 +2286,11 @@ impl Codegen {
|
||||||
if self.errors.borrow().is_empty() {
|
if self.errors.borrow().is_empty() {
|
||||||
self.gcm();
|
self.gcm();
|
||||||
|
|
||||||
self.ci.nodes.graphviz();
|
//self.ci.nodes.graphviz();
|
||||||
|
log::inf!("{id} {name}: ");
|
||||||
|
self.ci.nodes.basic_blocks();
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
{
|
{
|
||||||
|
@ -2470,7 +2617,6 @@ impl Codegen {
|
||||||
.relocs
|
.relocs
|
||||||
.push(TypedReloc { target: ty::Kind::Func(func).compress(), reloc });
|
.push(TypedReloc { target: ty::Kind::Func(func).compress(), reloc });
|
||||||
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.ci.call_count -= 1;
|
self.ci.call_count -= 1;
|
||||||
|
|
||||||
|
@ -2512,17 +2658,13 @@ impl Codegen {
|
||||||
let &[_, left, right] = self.ci.nodes[cond].inputs.as_slice() else {
|
let &[_, left, right] = self.ci.nodes[cond].inputs.as_slice() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
swapped = matches!(op, TokenKind::Lt | TokenKind::Gt);
|
|
||||||
let signed = self.ci.nodes[left].ty.is_signed();
|
let Some((op, swpd)) =
|
||||||
let op = match op {
|
Self::cond_op(op, self.ci.nodes[left].ty.is_signed())
|
||||||
TokenKind::Le if signed => instrs::jgts,
|
else {
|
||||||
TokenKind::Le => instrs::jgtu,
|
break 'optimize_cond;
|
||||||
TokenKind::Lt if signed => instrs::jlts,
|
|
||||||
TokenKind::Lt => instrs::jltu,
|
|
||||||
TokenKind::Eq => instrs::jne,
|
|
||||||
TokenKind::Ne => instrs::jeq,
|
|
||||||
_ => break 'optimize_cond,
|
|
||||||
};
|
};
|
||||||
|
swapped = swpd;
|
||||||
|
|
||||||
self.emit_expr_consume(left);
|
self.emit_expr_consume(left);
|
||||||
self.emit_expr_consume(right);
|
self.emit_expr_consume(right);
|
||||||
|
@ -2741,7 +2883,9 @@ impl Codegen {
|
||||||
Kind::BinOp { op } => {
|
Kind::BinOp { op } => {
|
||||||
_ = self.lazy_init(expr);
|
_ = self.lazy_init(expr);
|
||||||
let ty = self.tof(expr);
|
let ty = self.tof(expr);
|
||||||
let &[left, right] = self.ci.nodes[expr].inputs.as_slice() else { unreachable!() };
|
let &[_, left, right] = self.ci.nodes[expr].inputs.as_slice() else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
self.emit_expr_consume(left);
|
self.emit_expr_consume(left);
|
||||||
|
|
||||||
if let Kind::CInt { value } = self.ci.nodes[right].kind
|
if let Kind::CInt { value } = self.ci.nodes[right].kind
|
||||||
|
@ -2831,6 +2975,25 @@ impl Codegen {
|
||||||
Some(ops[size.ilog2() as usize])
|
Some(ops[size.ilog2() as usize])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
|
fn cond_op(
|
||||||
|
op: TokenKind,
|
||||||
|
signed: bool,
|
||||||
|
) -> Option<(fn(u8, u8, i16) -> (usize, [u8; instrs::MAX_SIZE]), bool)> {
|
||||||
|
Some((
|
||||||
|
match op {
|
||||||
|
TokenKind::Le if signed => instrs::jgts,
|
||||||
|
TokenKind::Le => instrs::jgtu,
|
||||||
|
TokenKind::Lt if signed => instrs::jlts,
|
||||||
|
TokenKind::Lt => instrs::jltu,
|
||||||
|
TokenKind::Eq => instrs::jne,
|
||||||
|
TokenKind::Ne => instrs::jeq,
|
||||||
|
_ => return None,
|
||||||
|
},
|
||||||
|
matches!(op, TokenKind::Lt | TokenKind::Gt),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
fn math_op(
|
fn math_op(
|
||||||
op: TokenKind,
|
op: TokenKind,
|
||||||
|
@ -2887,7 +3050,7 @@ impl Codegen {
|
||||||
match name.ok_or(lit_name) {
|
match name.ok_or(lit_name) {
|
||||||
Ok(name) => {
|
Ok(name) => {
|
||||||
let name = self.cfile().ident_str(name);
|
let name = self.cfile().ident_str(name);
|
||||||
self.report(pos, format_args!("undefined indentifier: {name}"))
|
self.report(pos, format_args!("idk indentifier: {name}"))
|
||||||
}
|
}
|
||||||
Err("main") => self.report(
|
Err("main") => self.report(
|
||||||
pos,
|
pos,
|
||||||
|
@ -2897,7 +3060,7 @@ impl Codegen {
|
||||||
f.path
|
f.path
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Err(name) => self.report(pos, format_args!("undefined indentifier: {name}")),
|
Err(name) => self.report(pos, format_args!("idk indentifier: {name}")),
|
||||||
}
|
}
|
||||||
return ty::Kind::Builtin(ty::NEVER);
|
return ty::Kind::Builtin(ty::NEVER);
|
||||||
};
|
};
|
||||||
|
@ -3093,7 +3256,105 @@ impl Codegen {
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gcm(&mut self) {}
|
fn gcm(&mut self) {
|
||||||
|
fn idepth(nodes: &mut Nodes, target: Nid) -> u32 {
|
||||||
|
if target == 0 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if nodes[target].depth == 0 {
|
||||||
|
let dm = idom(nodes, target);
|
||||||
|
nodes[target].depth = idepth(nodes, dm) + 1;
|
||||||
|
}
|
||||||
|
nodes[target].depth
|
||||||
|
}
|
||||||
|
|
||||||
|
fn idom(nodes: &mut Nodes, target: Nid) -> Nid {
|
||||||
|
match nodes[target].kind {
|
||||||
|
Kind::Start => 0,
|
||||||
|
Kind::End => unreachable!(),
|
||||||
|
Kind::Loop
|
||||||
|
| Kind::CInt { .. }
|
||||||
|
| Kind::BinOp { .. }
|
||||||
|
| Kind::Call { .. }
|
||||||
|
| Kind::Phi
|
||||||
|
| Kind::Tuple { .. }
|
||||||
|
| Kind::Return
|
||||||
|
| Kind::If => nodes[target].inputs[0],
|
||||||
|
Kind::Region => {
|
||||||
|
let &[mut lcfg, mut rcfg] = nodes[target].inputs.as_slice() else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
|
||||||
|
while lcfg != rcfg {
|
||||||
|
let [ldepth, rdepth] = [idepth(nodes, lcfg), idepth(nodes, rcfg)];
|
||||||
|
if ldepth >= rdepth {
|
||||||
|
lcfg = idom(nodes, lcfg);
|
||||||
|
}
|
||||||
|
if ldepth <= rdepth {
|
||||||
|
rcfg = idom(nodes, rcfg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lcfg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_up(nodes: &mut Nodes, node: Nid) {
|
||||||
|
if !nodes.visited.set(node as _) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if nodes[node].kind.is_pinned() {
|
||||||
|
for i in 0..nodes[node].inputs.len() {
|
||||||
|
let i = nodes[node].inputs[i];
|
||||||
|
push_up(nodes, i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let mut max = 0;
|
||||||
|
for i in 0..nodes[node].inputs.len() {
|
||||||
|
let i = nodes[node].inputs[i];
|
||||||
|
let is_call = matches!(nodes[i].kind, Kind::Call { .. });
|
||||||
|
if nodes.is_cfg(i) && !is_call {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
push_up(nodes, i);
|
||||||
|
if idepth(nodes, i) > idepth(nodes, max) {
|
||||||
|
max = if is_call { i } else { idom(nodes, i) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if max == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let index = nodes[0].outputs.iter().position(|&p| p == node).unwrap();
|
||||||
|
nodes[0].outputs.remove(index);
|
||||||
|
nodes[node].inputs[0] = max;
|
||||||
|
debug_assert!(
|
||||||
|
!nodes[max].outputs.contains(&node)
|
||||||
|
|| matches!(nodes[max].kind, Kind::Call { .. }),
|
||||||
|
"{node} {:?} {max} {:?}",
|
||||||
|
nodes[node],
|
||||||
|
nodes[max]
|
||||||
|
);
|
||||||
|
nodes[max].outputs.push(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_down(nodes: &mut Nodes, node: Nid) {
|
||||||
|
if !nodes.visited.set(node as _) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: handle memory nodes first
|
||||||
|
}
|
||||||
|
|
||||||
|
self.ci.nodes.visited.clear(self.ci.nodes.values.len());
|
||||||
|
push_up(&mut self.ci.nodes, self.ci.end);
|
||||||
|
// TODO: handle infinte loops
|
||||||
|
self.ci.nodes.visited.clear(self.ci.nodes.values.len());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -72d
|
ADDI64 r254, r254, -40d
|
||||||
ST r31, r254, 48a, 24h
|
ST r31, r254, 24a, 16h
|
||||||
LI64 r32, 1d
|
LI64 r32, 1d
|
||||||
ST r32, r254, 0a, 8h
|
ST r32, r254, 0a, 8h
|
||||||
LI64 r32, 2d
|
LI64 r32, 2d
|
||||||
|
@ -8,13 +8,10 @@ main:
|
||||||
LI64 r32, 4d
|
LI64 r32, 4d
|
||||||
ST r32, r254, 16a, 8h
|
ST r32, r254, 16a, 8h
|
||||||
ADDI64 r32, r254, 0d
|
ADDI64 r32, r254, 0d
|
||||||
ADDI64 r33, r254, 24d
|
CP r2, r32
|
||||||
BMC r32, r33, 24h
|
|
||||||
ADDI64 r33, r254, 24d
|
|
||||||
CP r2, r33
|
|
||||||
JAL r31, r0, :pass
|
JAL r31, r0, :pass
|
||||||
LD r31, r254, 48a, 24h
|
LD r31, r254, 24a, 16h
|
||||||
ADDI64 r254, r254, 72d
|
ADDI64 r254, r254, 40d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
pass:
|
pass:
|
||||||
ADDI64 r254, r254, -40d
|
ADDI64 r254, r254, -40d
|
||||||
|
@ -44,6 +41,6 @@ pass:
|
||||||
LD r31, r254, 0a, 40h
|
LD r31, r254, 0a, 40h
|
||||||
ADDI64 r254, r254, 40d
|
ADDI64 r254, r254, 40d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 408
|
code size: 381
|
||||||
ret: 7
|
ret: 7
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -16,30 +16,27 @@ main:
|
||||||
ADDI64 r254, r254, 24d
|
ADDI64 r254, r254, 24d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
str_len:
|
str_len:
|
||||||
ADDI64 r254, r254, -40d
|
ADDI64 r254, r254, -48d
|
||||||
ST r31, r254, 0a, 40h
|
ST r31, r254, 0a, 48h
|
||||||
CP r32, r2
|
CP r32, r2
|
||||||
LI64 r33, 0d
|
LI64 r33, 0d
|
||||||
2: CP r34, r32
|
2: CP r34, r32
|
||||||
CP r35, r0
|
CP r35, r0
|
||||||
LD r35, r34, 0a, 1h
|
LD r35, r34, 0a, 1h
|
||||||
LI64 r34, 0d
|
LI64 r36, 0d
|
||||||
CMPU r35, r35, r34
|
JNE r35, r36, :0
|
||||||
CMPUI r35, r35, 0d
|
|
||||||
NOT r35, r35
|
|
||||||
JEQ r35, r0, :0
|
|
||||||
JMP :1
|
JMP :1
|
||||||
0: CP r35, r33
|
0: CP r36, r33
|
||||||
ADDI64 r35, r35, 1d
|
ADDI64 r36, r36, 1d
|
||||||
CP r33, r35
|
CP r33, r36
|
||||||
CP r35, r32
|
CP r36, r32
|
||||||
ADDI64 r35, r35, 1d
|
ADDI64 r36, r36, 1d
|
||||||
CP r32, r35
|
CP r32, r36
|
||||||
JMP :2
|
JMP :2
|
||||||
1: CP r1, r33
|
1: CP r1, r33
|
||||||
LD r31, r254, 0a, 40h
|
LD r31, r254, 0a, 48h
|
||||||
ADDI64 r254, r254, 40d
|
ADDI64 r254, r254, 48d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 303
|
code size: 285
|
||||||
ret: 16
|
ret: 16
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -48d
|
ADDI64 r254, r254, -44d
|
||||||
ST r31, r254, 24a, 24h
|
ST r31, r254, 12a, 32h
|
||||||
LI64 r32, 255d
|
LI64 r32, 255d
|
||||||
ST r32, r254, 0a, 1h
|
ST r32, r254, 0a, 1h
|
||||||
LI64 r32, 0d
|
LI64 r32, 0d
|
||||||
|
@ -13,52 +13,45 @@ main:
|
||||||
ST r32, r254, 4a, 4h
|
ST r32, r254, 4a, 4h
|
||||||
LI64 r32, 2d
|
LI64 r32, 2d
|
||||||
ST r32, r254, 8a, 4h
|
ST r32, r254, 8a, 4h
|
||||||
ADDI64 r32, r254, 0d
|
LI64 r32, 1d
|
||||||
ADDI64 r33, r254, 12d
|
ADDI64 r33, r254, 4d
|
||||||
BMC r32, r33, 12h
|
MULI64 r32, r32, 4d
|
||||||
LI64 r33, 1d
|
ADD64 r33, r33, r32
|
||||||
ADDI64 r32, r254, 16d
|
|
||||||
MULI64 r33, r33, 4d
|
|
||||||
ADD64 r32, r32, r33
|
|
||||||
CP r33, r0
|
|
||||||
LD r33, r32, 0a, 4h
|
|
||||||
LI64 r32, 2d
|
|
||||||
CMPU r33, r33, r32
|
|
||||||
CMPUI r33, r33, 0d
|
|
||||||
JEQ r33, r0, :0
|
|
||||||
LI64 r1, 0d
|
|
||||||
JMP :1
|
|
||||||
0: ADDI64 r33, r254, 20d
|
|
||||||
ADDI64 r33, r33, -4d
|
|
||||||
CP r32, r0
|
CP r32, r0
|
||||||
LD r32, r33, 0a, 4h
|
LD r32, r33, 0a, 4h
|
||||||
|
LI64 r34, 2d
|
||||||
|
JEQ r32, r34, :0
|
||||||
|
LI64 r1, 0d
|
||||||
|
JMP :1
|
||||||
|
0: ADDI64 r34, r254, 8d
|
||||||
|
ADDI64 r34, r34, -4d
|
||||||
|
CP r32, r0
|
||||||
|
LD r32, r34, 0a, 4h
|
||||||
LI64 r33, 0d
|
LI64 r33, 0d
|
||||||
CMPU r32, r32, r33
|
JEQ r32, r33, :2
|
||||||
CMPUI r32, r32, 0d
|
|
||||||
JEQ r32, r0, :2
|
|
||||||
LI64 r1, 64d
|
LI64 r1, 64d
|
||||||
JMP :1
|
JMP :1
|
||||||
2: CP r32, r0
|
2: CP r33, r0
|
||||||
LD r32, r254, 16a, 4h
|
LD r33, r254, 4a, 4h
|
||||||
CP r33, r0
|
CP r32, r0
|
||||||
LD r33, r254, 20a, 4h
|
LD r32, r254, 8a, 4h
|
||||||
ADD32 r32, r32, r33
|
ADD32 r33, r33, r32
|
||||||
CP r33, r0
|
CP r32, r0
|
||||||
LD r33, r254, 12a, 1h
|
LD r32, r254, 0a, 1h
|
||||||
ADD32 r32, r32, r33
|
ADD32 r33, r33, r32
|
||||||
CP r33, r0
|
CP r32, r0
|
||||||
LD r33, r254, 13a, 1h
|
LD r32, r254, 1a, 1h
|
||||||
ADD32 r32, r32, r33
|
ADD32 r33, r33, r32
|
||||||
CP r33, r0
|
CP r32, r0
|
||||||
LD r33, r254, 14a, 1h
|
LD r32, r254, 2a, 1h
|
||||||
ADD32 r32, r32, r33
|
ADD32 r33, r33, r32
|
||||||
CP r33, r0
|
CP r32, r0
|
||||||
LD r33, r254, 15a, 1h
|
LD r32, r254, 3a, 1h
|
||||||
ADD32 r32, r32, r33
|
ADD32 r33, r33, r32
|
||||||
CP r1, r32
|
CP r1, r33
|
||||||
1: LD r31, r254, 24a, 24h
|
1: LD r31, r254, 12a, 32h
|
||||||
ADDI64 r254, r254, 48d
|
ADDI64 r254, r254, 44d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 531
|
code size: 474
|
||||||
ret: 512
|
ret: 512
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,23 +1,20 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -72d
|
ADDI64 r254, r254, -48d
|
||||||
ST r31, r254, 48a, 24h
|
ST r31, r254, 24a, 24h
|
||||||
ADDI64 r1, r254, 0d
|
ADDI64 r1, r254, 0d
|
||||||
JAL r31, r0, :new
|
JAL r31, r0, :new
|
||||||
ADDI64 r32, r254, 0d
|
ADDI64 r32, r254, 0d
|
||||||
ADDI64 r33, r254, 24d
|
CP r2, r32
|
||||||
BMC r32, r33, 24h
|
|
||||||
ADDI64 r33, r254, 24d
|
|
||||||
CP r2, r33
|
|
||||||
LI64 r3, 69d
|
LI64 r3, 69d
|
||||||
JAL r31, r0, :push
|
JAL r31, r0, :push
|
||||||
LD r33, r254, 24a, 8h
|
LD r32, r254, 0a, 8h
|
||||||
LD r32, r33, 0a, 8h
|
LD r33, r32, 0a, 8h
|
||||||
ADDI64 r33, r254, 24d
|
ADDI64 r32, r254, 0d
|
||||||
CP r2, r33
|
CP r2, r32
|
||||||
JAL r31, r0, :deinit
|
JAL r31, r0, :deinit
|
||||||
CP r1, r32
|
CP r1, r33
|
||||||
LD r31, r254, 48a, 24h
|
LD r31, r254, 24a, 24h
|
||||||
ADDI64 r254, r254, 72d
|
ADDI64 r254, r254, 48d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
deinit:
|
deinit:
|
||||||
ADDI64 r254, r254, -24d
|
ADDI64 r254, r254, -24d
|
||||||
|
@ -56,16 +53,10 @@ push:
|
||||||
CP r33, r3
|
CP r33, r3
|
||||||
LD r34, r32, 8a, 8h
|
LD r34, r32, 8a, 8h
|
||||||
LD r35, r32, 16a, 8h
|
LD r35, r32, 16a, 8h
|
||||||
CMPU r34, r34, r35
|
JNE r34, r35, :0
|
||||||
CMPUI r34, r34, 0d
|
LD r35, r32, 16a, 8h
|
||||||
NOT r34, r34
|
LI64 r34, 0d
|
||||||
JEQ r34, r0, :0
|
JNE r35, r34, :1
|
||||||
LD r34, r32, 16a, 8h
|
|
||||||
LI64 r35, 0d
|
|
||||||
CMPU r34, r34, r35
|
|
||||||
CMPUI r34, r34, 0d
|
|
||||||
NOT r34, r34
|
|
||||||
JEQ r34, r0, :1
|
|
||||||
LI64 r34, 1d
|
LI64 r34, 1d
|
||||||
ST r34, r32, 16a, 8h
|
ST r34, r32, 16a, 8h
|
||||||
JMP :2
|
JMP :2
|
||||||
|
@ -78,12 +69,8 @@ push:
|
||||||
LI64 r3, 8d
|
LI64 r3, 8d
|
||||||
JAL r31, r0, :malloc
|
JAL r31, r0, :malloc
|
||||||
CP r34, r1
|
CP r34, r1
|
||||||
CP r35, r34
|
LI64 r35, 0d
|
||||||
LI64 r36, 0d
|
JNE r34, r35, :3
|
||||||
CMPU r35, r35, r36
|
|
||||||
CMPUI r35, r35, 0d
|
|
||||||
NOT r35, r35
|
|
||||||
JEQ r35, r0, :3
|
|
||||||
LI64 r1, 0d
|
LI64 r1, 0d
|
||||||
JMP :4
|
JMP :4
|
||||||
3: LD r35, r32, 0a, 8h
|
3: LD r35, r32, 0a, 8h
|
||||||
|
@ -92,12 +79,7 @@ push:
|
||||||
LD r38, r32, 8a, 8h
|
LD r38, r32, 8a, 8h
|
||||||
MULI64 r38, r38, 8d
|
MULI64 r38, r38, 8d
|
||||||
ADD64 r37, r37, r38
|
ADD64 r37, r37, r38
|
||||||
7: CP r38, r35
|
7: JNE r35, r37, :5
|
||||||
CP r39, r37
|
|
||||||
CMPU r38, r38, r39
|
|
||||||
CMPUI r38, r38, 0d
|
|
||||||
NOT r38, r38
|
|
||||||
JEQ r38, r0, :5
|
|
||||||
JMP :6
|
JMP :6
|
||||||
5: CP r38, r36
|
5: CP r38, r36
|
||||||
CP r39, r35
|
CP r39, r35
|
||||||
|
@ -113,25 +95,23 @@ push:
|
||||||
JMP :7
|
JMP :7
|
||||||
6: LD r38, r32, 8a, 8h
|
6: LD r38, r32, 8a, 8h
|
||||||
LI64 r39, 0d
|
LI64 r39, 0d
|
||||||
CMPU r38, r38, r39
|
JEQ r38, r39, :8
|
||||||
CMPUI r38, r38, 0d
|
|
||||||
JEQ r38, r0, :8
|
|
||||||
LD r2, r32, 0a, 8h
|
LD r2, r32, 0a, 8h
|
||||||
LD r38, r32, 8a, 8h
|
LD r39, r32, 8a, 8h
|
||||||
MULI64 r38, r38, 8d
|
MULI64 r39, r39, 8d
|
||||||
CP r3, r38
|
CP r3, r39
|
||||||
LI64 r4, 8d
|
LI64 r4, 8d
|
||||||
JAL r31, r0, :free
|
JAL r31, r0, :free
|
||||||
8: ST r34, r32, 0a, 8h
|
8: ST r34, r32, 0a, 8h
|
||||||
0: LD r34, r32, 0a, 8h
|
0: LD r34, r32, 0a, 8h
|
||||||
LD r38, r32, 8a, 8h
|
LD r39, r32, 8a, 8h
|
||||||
MULI64 r38, r38, 8d
|
MULI64 r39, r39, 8d
|
||||||
ADD64 r34, r34, r38
|
ADD64 r34, r34, r39
|
||||||
CP r38, r34
|
CP r39, r34
|
||||||
ST r33, r38, 0a, 8h
|
ST r33, r39, 0a, 8h
|
||||||
LD r38, r32, 8a, 8h
|
LD r39, r32, 8a, 8h
|
||||||
ADDI64 r38, r38, 1d
|
ADDI64 r39, r39, 1d
|
||||||
ST r38, r32, 8a, 8h
|
ST r39, r32, 8a, 8h
|
||||||
CP r1, r34
|
CP r1, r34
|
||||||
4: LD r31, r254, 0a, 88h
|
4: LD r31, r254, 0a, 88h
|
||||||
ADDI64 r254, r254, 88d
|
ADDI64 r254, r254, 88d
|
||||||
|
@ -162,6 +142,6 @@ new:
|
||||||
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
|
||||||
code size: 1470
|
code size: 1347
|
||||||
ret: 69
|
ret: 69
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
30
hblang/tests/codegen_tests_idk.txt
Normal file
30
hblang/tests/codegen_tests_idk.txt
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
main:
|
||||||
|
ADDI64 r254, r254, -160d
|
||||||
|
ST r31, r254, 128a, 32h
|
||||||
|
LI64 r32, 0d
|
||||||
|
2: CP r33, r32
|
||||||
|
LI64 r34, 128d
|
||||||
|
CMPS r33, r33, r34
|
||||||
|
CMPUI r33, r33, -1d
|
||||||
|
JEQ r33, r0, :0
|
||||||
|
JMP :1
|
||||||
|
0: ADDI64 r33, r254, 0d
|
||||||
|
CP r34, r32
|
||||||
|
ADD64 r33, r33, r34
|
||||||
|
LI64 r34, 69d
|
||||||
|
ST r34, r33, 0a, 1h
|
||||||
|
CP r33, r32
|
||||||
|
ADDI64 r33, r33, 1d
|
||||||
|
CP r32, r33
|
||||||
|
JMP :2
|
||||||
|
1: ADDI64 r33, r254, 0d
|
||||||
|
LI64 r34, 42d
|
||||||
|
ADD64 r33, r33, r34
|
||||||
|
CP r1, r0
|
||||||
|
LD r1, r33, 0a, 1h
|
||||||
|
LD r31, r254, 128a, 32h
|
||||||
|
ADDI64 r254, r254, 160d
|
||||||
|
JALA r0, r31, 0a
|
||||||
|
code size: 219
|
||||||
|
ret: 69
|
||||||
|
status: Ok(())
|
|
@ -7,14 +7,11 @@ main:
|
||||||
ADDI64 r254, r254, 8d
|
ADDI64 r254, r254, 8d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
fib:
|
fib:
|
||||||
ADDI64 r254, r254, -32d
|
ADDI64 r254, r254, -24d
|
||||||
ST r31, r254, 0a, 32h
|
ST r31, r254, 0a, 24h
|
||||||
CP r32, r2
|
CP r32, r2
|
||||||
CP r33, r32
|
LI64 r33, 2d
|
||||||
LI64 r34, 2d
|
JGTS r32, r33, :0
|
||||||
CMPS r33, r33, r34
|
|
||||||
CMPUI r33, r33, 1d
|
|
||||||
JEQ r33, r0, :0
|
|
||||||
LI64 r1, 1d
|
LI64 r1, 1d
|
||||||
JMP :1
|
JMP :1
|
||||||
0: CP r33, r32
|
0: CP r33, r32
|
||||||
|
@ -28,9 +25,9 @@ fib:
|
||||||
CP r32, r1
|
CP r32, r1
|
||||||
ADD64 r33, r33, r32
|
ADD64 r33, r33, r32
|
||||||
CP r1, r33
|
CP r1, r33
|
||||||
1: LD r31, r254, 0a, 32h
|
1: LD r31, r254, 0a, 24h
|
||||||
ADDI64 r254, r254, 32d
|
ADDI64 r254, r254, 24d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 252
|
code size: 234
|
||||||
ret: 55
|
ret: 55
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -116,23 +116,14 @@ rect_line:
|
||||||
LI64 r33, 0d
|
LI64 r33, 0d
|
||||||
LI64 r34, 0d
|
LI64 r34, 0d
|
||||||
LI64 r35, 0d
|
LI64 r35, 0d
|
||||||
5: CP r36, r33
|
5: JNE r33, r32, :0
|
||||||
CP r37, r32
|
|
||||||
CMPS r36, r36, r37
|
|
||||||
CMPUI r36, r36, 0d
|
|
||||||
NOT r36, r36
|
|
||||||
JEQ r36, r0, :0
|
|
||||||
JMP :1
|
JMP :1
|
||||||
0: LD r34, r254, 8a, 8h
|
0: LD r34, r254, 8a, 8h
|
||||||
LD r35, r254, 0a, 8h
|
LD r35, r254, 0a, 8h
|
||||||
4: CP r36, r34
|
4: LD r36, r254, 8a, 8h
|
||||||
LD r37, r254, 8a, 8h
|
LD r37, r254, 16a, 8h
|
||||||
LD r38, r254, 16a, 8h
|
ADD64 r36, r36, r37
|
||||||
ADD64 r37, r37, r38
|
JNE r34, r36, :2
|
||||||
CMPS r36, r36, r37
|
|
||||||
CMPUI r36, r36, 0d
|
|
||||||
NOT r36, r36
|
|
||||||
JEQ r36, r0, :2
|
|
||||||
JMP :3
|
JMP :3
|
||||||
2: LI64 r36, 1d
|
2: LI64 r36, 1d
|
||||||
LI64 r37, 10d
|
LI64 r37, 10d
|
||||||
|
@ -179,6 +170,6 @@ line:
|
||||||
2: LD r31, r254, 48a, 32h
|
2: LD r31, r254, 48a, 32h
|
||||||
ADDI64 r254, r254, 80d
|
ADDI64 r254, r254, 80d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 1521
|
code size: 1476
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -12,12 +12,8 @@ fib:
|
||||||
CP r32, r2
|
CP r32, r2
|
||||||
LI64 r33, 0d
|
LI64 r33, 0d
|
||||||
LI64 r34, 1d
|
LI64 r34, 1d
|
||||||
2: CP r35, r32
|
2: LI64 r35, 0d
|
||||||
LI64 r36, 0d
|
JNE r32, r35, :0
|
||||||
CMPS r35, r35, r36
|
|
||||||
CMPUI r35, r35, 0d
|
|
||||||
NOT r35, r35
|
|
||||||
JEQ r35, r0, :0
|
|
||||||
JMP :1
|
JMP :1
|
||||||
0: CP r35, r33
|
0: CP r35, r33
|
||||||
CP r36, r34
|
CP r36, r34
|
||||||
|
@ -32,6 +28,6 @@ fib:
|
||||||
LD r31, r254, 0a, 48h
|
LD r31, r254, 0a, 48h
|
||||||
ADDI64 r254, r254, 48d
|
ADDI64 r254, r254, 48d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 248
|
code size: 227
|
||||||
ret: 55
|
ret: 55
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -26,12 +26,8 @@ fib_iter:
|
||||||
CP r32, r2
|
CP r32, r2
|
||||||
LI64 r33, 0d
|
LI64 r33, 0d
|
||||||
LI64 r34, 1d
|
LI64 r34, 1d
|
||||||
2: CP r35, r32
|
2: LI64 r35, 0d
|
||||||
LI64 r36, 0d
|
JNE r32, r35, :0
|
||||||
CMPS r35, r35, r36
|
|
||||||
CMPUI r35, r35, 0d
|
|
||||||
NOT r35, r35
|
|
||||||
JEQ r35, r0, :0
|
|
||||||
JMP :1
|
JMP :1
|
||||||
0: CP r35, r33
|
0: CP r35, r33
|
||||||
CP r36, r34
|
CP r36, r34
|
||||||
|
@ -50,28 +46,25 @@ fib:
|
||||||
ADDI64 r254, r254, -32d
|
ADDI64 r254, r254, -32d
|
||||||
ST r31, r254, 0a, 32h
|
ST r31, r254, 0a, 32h
|
||||||
CP r32, r2
|
CP r32, r2
|
||||||
|
LI64 r33, 2d
|
||||||
|
JLTS r32, r33, :0
|
||||||
CP r33, r32
|
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
|
ADDI64 r33, r33, -1d
|
||||||
CP r2, r33
|
CP r2, r33
|
||||||
JAL r31, r0, :fib
|
JAL r31, r0, :fib
|
||||||
CP r33, r1
|
CP r33, r1
|
||||||
ADDI64 r32, r32, -2d
|
CP r34, r32
|
||||||
CP r2, r32
|
ADDI64 r34, r34, -2d
|
||||||
|
CP r2, r34
|
||||||
JAL r31, r0, :fib
|
JAL r31, r0, :fib
|
||||||
CP r32, r1
|
CP r34, r1
|
||||||
ADD64 r33, r33, r32
|
ADD64 r33, r33, r34
|
||||||
CP r1, r33
|
CP r1, r33
|
||||||
|
JMP :1
|
||||||
|
0: CP r1, r32
|
||||||
1: LD r31, r254, 0a, 32h
|
1: LD r31, r254, 0a, 32h
|
||||||
ADDI64 r254, r254, 32d
|
ADDI64 r254, r254, 32d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 518
|
code size: 479
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,31 +1,25 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -72d
|
ADDI64 r254, r254, -48d
|
||||||
ST r31, r254, 48a, 24h
|
ST r31, r254, 24a, 24h
|
||||||
LI64 r32, 4d
|
LI64 r32, 4d
|
||||||
ST r32, r254, 24a, 8h
|
ST r32, r254, 0a, 8h
|
||||||
LI64 r32, 1d
|
LI64 r32, 1d
|
||||||
ST r32, r254, 32a, 8h
|
ST r32, r254, 8a, 8h
|
||||||
LI64 r32, 3d
|
LI64 r32, 3d
|
||||||
ST r32, r254, 40a, 8h
|
ST r32, r254, 16a, 8h
|
||||||
ADDI64 r2, r254, 24d
|
ADDI64 r2, r254, 0d
|
||||||
ADDI64 r1, r254, 0d
|
ADDI64 r1, r254, 0d
|
||||||
JAL r31, r0, :odher_pass
|
JAL r31, r0, :odher_pass
|
||||||
ADDI64 r32, r254, 0d
|
LD r32, r254, 16a, 8h
|
||||||
ADDI64 r33, r254, 24d
|
LI64 r33, 3d
|
||||||
BMC r32, r33, 24h
|
JNE r32, r33, :0
|
||||||
LD r33, r254, 40a, 8h
|
ADDI64 r33, r254, 0d
|
||||||
LI64 r32, 3d
|
|
||||||
CMPS r33, r33, r32
|
|
||||||
CMPUI r33, r33, 0d
|
|
||||||
NOT r33, r33
|
|
||||||
JEQ r33, r0, :0
|
|
||||||
ADDI64 r33, r254, 24d
|
|
||||||
CP r2, r33
|
CP r2, r33
|
||||||
JAL r31, r0, :pass
|
JAL r31, r0, :pass
|
||||||
JMP :1
|
JMP :1
|
||||||
0: LI64 r1, 0d
|
0: LI64 r1, 0d
|
||||||
1: LD r31, r254, 48a, 24h
|
1: LD r31, r254, 24a, 24h
|
||||||
ADDI64 r254, r254, 72d
|
ADDI64 r254, r254, 48d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
pass:
|
pass:
|
||||||
ADDI64 r254, r254, -32d
|
ADDI64 r254, r254, -32d
|
||||||
|
@ -49,6 +43,6 @@ odher_pass:
|
||||||
LD r31, r254, 0a, 40h
|
LD r31, r254, 0a, 40h
|
||||||
ADDI64 r254, r254, 40d
|
ADDI64 r254, r254, 40d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 445
|
code size: 400
|
||||||
ret: 3
|
ret: 3
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -22,7 +22,7 @@ fib:
|
||||||
SUB64 r35, r32, r33
|
SUB64 r35, r32, r33
|
||||||
CP r2, r35
|
CP r2, r35
|
||||||
JAL r31, r0, :fib
|
JAL r31, r0, :fib
|
||||||
ADD64 r1, r34, r1
|
ADD64 r1, r1, r34
|
||||||
1: LD r31, r254, 0a, 40h
|
1: LD r31, r254, 0a, 40h
|
||||||
ADDI64 r254, r254, 40d
|
ADDI64 r254, r254, 40d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
|
|
|
@ -1,31 +1,4 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -16d
|
code size: 8
|
||||||
ST r31, r254, 0a, 16h
|
ret: 0
|
||||||
LI64 r32, 10d
|
status: Err(Unreachable)
|
||||||
CP r2, r32
|
|
||||||
JAL r31, r0, :fib
|
|
||||||
LD r31, r254, 0a, 16h
|
|
||||||
ADDI64 r254, r254, 16d
|
|
||||||
JALA r0, r31, 0a
|
|
||||||
fib:
|
|
||||||
ADDI64 r254, r254, -56d
|
|
||||||
ST r31, r254, 0a, 56h
|
|
||||||
CP r32, r2
|
|
||||||
CP r33, r32
|
|
||||||
LI64 r34, 0d
|
|
||||||
CP r1, r34
|
|
||||||
LI64 r35, 1d
|
|
||||||
CP r36, r35
|
|
||||||
2: JNE r33, r34, :0
|
|
||||||
JMP :1
|
|
||||||
0: SUB64 r33, r33, r35
|
|
||||||
ADD64 r37, r1, r36
|
|
||||||
CP r1, r36
|
|
||||||
CP r36, r37
|
|
||||||
JMP :2
|
|
||||||
1: LD r31, r254, 0a, 56h
|
|
||||||
ADDI64 r254, r254, 56d
|
|
||||||
JALA r0, r31, 0a
|
|
||||||
code size: 207
|
|
||||||
ret: 55
|
|
||||||
status: Ok(())
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ use {
|
||||||
pub struct Vm<Mem, const TIMER_QUOTIENT: usize> {
|
pub struct Vm<Mem, const TIMER_QUOTIENT: usize> {
|
||||||
/// Holds 256 registers
|
/// Holds 256 registers
|
||||||
///
|
///
|
||||||
/// Writing to register 0 is considered undefined behaviour
|
/// Writing to register 0 is considered idk behaviour
|
||||||
/// in terms of HoleyBytes program execution
|
/// in terms of HoleyBytes program execution
|
||||||
pub registers: [Value; 256],
|
pub registers: [Value; 256],
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::utils::static_assert;
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// Its variants have to be sound to byte-reinterpretate
|
/// Its variants have to be sound to byte-reinterpretate
|
||||||
/// between each other. Otherwise the behaviour is undefined.
|
/// between each other. Otherwise the behaviour is idk.
|
||||||
macro_rules! value_def {
|
macro_rules! value_def {
|
||||||
($($ty:ident),* $(,)?) => {
|
($($ty:ident),* $(,)?) => {
|
||||||
/// HBVM register value
|
/// HBVM register value
|
||||||
|
|
Loading…
Reference in a new issue