forked from AbleOS/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
|
||||
|
||||
#### comptime_pointers
|
||||
|
|
|
@ -8,7 +8,7 @@ use {
|
|||
parser::{self, find_symbol, idfl, CtorField, Expr, ExprRef, FileId, Pos},
|
||||
HashMap,
|
||||
},
|
||||
std::{collections::BTreeMap, fmt::Display, ops::Range, rc::Rc},
|
||||
std::{collections::BTreeMap, fmt::Display, ops::Range, rc::Rc, u32},
|
||||
};
|
||||
|
||||
type Offset = u32;
|
||||
|
@ -688,6 +688,10 @@ impl Loc {
|
|||
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 {
|
||||
|
@ -702,6 +706,7 @@ impl Default for Loc {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Loop {
|
||||
var_count: u32,
|
||||
offset: u32,
|
||||
|
@ -710,6 +715,7 @@ struct Loop {
|
|||
|
||||
struct Variable {
|
||||
id: Ident,
|
||||
uses_left: u32,
|
||||
value: Value,
|
||||
}
|
||||
|
||||
|
@ -1419,7 +1425,9 @@ impl Codegen {
|
|||
// TODO: we need to check if index is in bounds on debug builds
|
||||
|
||||
let mut base_val = self.expr(base)?;
|
||||
base_val.loc = self.make_loc_owned(base_val.loc, base_val.ty);
|
||||
if base_val.ty.is_pointer() {
|
||||
base_val.loc = self.make_loc_owned(base_val.loc, base_val.ty);
|
||||
}
|
||||
let index_val = self.expr(index)?;
|
||||
_ = 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);
|
||||
|
||||
self.output.emit(muli64(idx.get(), idx.get(), item_size as _));
|
||||
if item_size != 1 {
|
||||
self.output.emit(muli64(idx.get(), idx.get(), item_size as _));
|
||||
}
|
||||
self.output.emit(add64(reg.get(), reg.get(), idx.get()));
|
||||
self.ci.regs.free(idx);
|
||||
|
||||
|
@ -1491,7 +1501,13 @@ impl Codegen {
|
|||
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;
|
||||
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 });
|
||||
}
|
||||
E::Directive { name: "TypeOf", args: [expr], .. } => {
|
||||
let snap = self.output.snap();
|
||||
let value = self.expr(expr).unwrap();
|
||||
self.ci.free_loc(value.loc);
|
||||
self.output.trunc(&snap);
|
||||
Some(Value::ty(value.ty))
|
||||
Some(Value::ty(self.infer_type(expr)))
|
||||
}
|
||||
E::Directive { name: "eca", args: [ret_ty, args @ ..], .. } => {
|
||||
let ty = self.ty(ret_ty);
|
||||
|
@ -1585,7 +1597,7 @@ impl Codegen {
|
|||
let Some(ty) = ctx.ty else {
|
||||
self.report(
|
||||
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, .. } => {
|
||||
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 } => {
|
||||
literal = literal.trim_matches('"');
|
||||
|
||||
|
@ -1917,12 +1954,12 @@ impl Codegen {
|
|||
return Some(Value { ty: sig.ret, loc });
|
||||
}
|
||||
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)) =
|
||||
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);
|
||||
let loc = match idfl::index(sym.flags) == index
|
||||
var.uses_left -= 1;
|
||||
let loc = match var.uses_left == 0
|
||||
&& !self.ci.loops.last().is_some_and(|l| l.var_count > var_index as u32)
|
||||
{
|
||||
true => std::mem::take(&mut var.value.loc),
|
||||
|
@ -1990,15 +2027,59 @@ impl Codegen {
|
|||
},
|
||||
loc: Loc::ct(value as u64),
|
||||
}),
|
||||
E::If { cond, then, else_, .. } => {
|
||||
let cond = self.expr_ctx(cond, Ctx::default().with_ty(ty::BOOL))?;
|
||||
let reg = self.loc_to_reg(&cond.loc, 1);
|
||||
let jump_offset = self.local_offset();
|
||||
self.output.emit(jeq(reg.get(), 0, 0));
|
||||
self.ci.free_loc(cond.loc);
|
||||
self.ci.regs.free(reg);
|
||||
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 then_unreachable = self.expr(then).is_none();
|
||||
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 reg = self.loc_to_reg(&cond.loc, 1);
|
||||
jump_offset = self.local_offset();
|
||||
self.output.emit(jeq(reg.get(), 0, 0));
|
||||
self.ci.free_loc(cond.loc);
|
||||
self.ci.regs.free(reg);
|
||||
}
|
||||
|
||||
let then_unreachable =
|
||||
if let Some(then) = then { self.expr(then).is_none() } else { false };
|
||||
let mut else_unreachable = false;
|
||||
|
||||
let mut jump = self.local_offset() as i64 - jump_offset as i64;
|
||||
|
@ -2196,9 +2277,8 @@ impl Codegen {
|
|||
|
||||
Some(match ctx.loc {
|
||||
Some(dest) => {
|
||||
let ty = ctx.ty.unwrap_or(value.ty);
|
||||
self.store_typed(value.loc, dest, ty);
|
||||
Value { ty, loc: Loc::ct(0) }
|
||||
self.store_typed(value.loc, dest, value.ty);
|
||||
Value { ty: value.ty, loc: Loc::ct(0) }
|
||||
}
|
||||
None => value,
|
||||
})
|
||||
|
@ -2236,7 +2316,11 @@ impl Codegen {
|
|||
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);
|
||||
|
@ -2266,6 +2350,38 @@ impl Codegen {
|
|||
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 {
|
||||
self.eval_const_low(expr, Some(ty.into())).0
|
||||
}
|
||||
|
@ -2321,11 +2437,15 @@ impl Codegen {
|
|||
&& size <= 8 =>
|
||||
{
|
||||
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
|
||||
}
|
||||
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);
|
||||
false
|
||||
}
|
||||
|
@ -2337,11 +2457,15 @@ impl Codegen {
|
|||
match *pat {
|
||||
Expr::Ident { id, .. } => {
|
||||
let mut loc = self.make_loc_owned(right.loc, right.ty);
|
||||
let sym = parser::find_symbol(&self.cfile().symbols, id);
|
||||
if sym.flags & idfl::REFERENCED != 0 {
|
||||
let sym = parser::find_symbol(&self.cfile().symbols, id).flags;
|
||||
if sym & idfl::REFERENCED != 0 {
|
||||
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, .. } => {
|
||||
let ty::Kind::Struct(idx) = right.ty.expand() else {
|
||||
|
@ -2553,9 +2677,13 @@ impl Codegen {
|
|||
}
|
||||
|
||||
fn spill(&mut self, loc: Loc, size: Size) -> Loc {
|
||||
let stack = Loc::stack(self.ci.stack.allocate(size));
|
||||
self.store_sized(loc, &stack, size);
|
||||
stack
|
||||
if loc.is_ref() || !loc.is_stack() {
|
||||
let stack = Loc::stack(self.ci.stack.allocate(size));
|
||||
self.store_sized(loc, &stack, size);
|
||||
stack
|
||||
} else {
|
||||
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);
|
||||
// we drain these when linking
|
||||
for srel in self.output.strings.iter_mut().filter(|s| !s.shifted) {
|
||||
dbg!(&srel.range);
|
||||
debug_assert!(
|
||||
srel.range.end <= prev_data_len as u32,
|
||||
"{} <= {}",
|
||||
|
@ -2628,7 +2755,7 @@ impl Codegen {
|
|||
self.ci.snap = self.output.snap();
|
||||
|
||||
let Expr::BinOp {
|
||||
left: Expr::Ident { name, .. },
|
||||
left: Expr::Ident { .. },
|
||||
op: TokenKind::Decl,
|
||||
right: &Expr::Closure { body, args, .. },
|
||||
} = expr
|
||||
|
@ -2636,20 +2763,22 @@ impl Codegen {
|
|||
unreachable!("{expr}")
|
||||
};
|
||||
|
||||
log::dbg!(name);
|
||||
|
||||
self.output.emit_prelude();
|
||||
|
||||
let mut parama = self.tys.parama(sig.ret);
|
||||
let mut sig_args = sig.args.range();
|
||||
for arg in args.iter() {
|
||||
let ty = self.tys.args[sig_args.next().unwrap()];
|
||||
let sym = parser::find_symbol(&ast.symbols, arg.id);
|
||||
let loc = match sym.flags & idfl::COMPTIME != 0 {
|
||||
let sym = parser::find_symbol(&ast.symbols, arg.id).flags;
|
||||
let loc = match sym & idfl::COMPTIME != 0 {
|
||||
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 {
|
||||
|
@ -2980,6 +3109,7 @@ impl Codegen {
|
|||
self.ci.vars.push(Variable {
|
||||
id,
|
||||
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_functions => README;
|
||||
c_strings => README;
|
||||
idk => README;
|
||||
struct_patterns => README;
|
||||
arrays => README;
|
||||
struct_return_from_module_function => README;
|
||||
|
@ -3562,7 +3693,7 @@ mod tests {
|
|||
sort_something_viredly => README;
|
||||
hex_octal_binary_literals => README;
|
||||
comptime_min_reg_leak => README;
|
||||
// structs_in_registers => README;
|
||||
// structs_in_registers => README;
|
||||
comptime_function_from_another_file => README;
|
||||
inline => README;
|
||||
inline_test => README;
|
||||
|
|
|
@ -44,19 +44,23 @@ macro_rules! gen_token_kind {
|
|||
) => {
|
||||
impl std::fmt::Display for $name {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let sf = *self as u8;
|
||||
f.write_str(match *self {
|
||||
f.write_str(self.name())
|
||||
}
|
||||
}
|
||||
|
||||
impl $name {
|
||||
pub fn name(&self) -> &str {
|
||||
let sf = unsafe { &*(self as *const _ as *const u8) } ;
|
||||
match *self {
|
||||
$( Self::$pattern => concat!('<', stringify!($pattern), '>'), )*
|
||||
$( Self::$keyword => stringify!($keyword_lit), )*
|
||||
$( Self::$punkt => stringify!($punkt_lit), )*
|
||||
$($( Self::$op => $op_lit,
|
||||
$(Self::$assign => concat!($op_lit, "="),)?)*)*
|
||||
_ => unsafe { std::str::from_utf8_unchecked(std::slice::from_ref(&sf)) },
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl $name {
|
||||
#[inline(always)]
|
||||
pub fn precedence(&self) -> Option<u8> {
|
||||
Some(match self {
|
||||
|
@ -124,6 +128,8 @@ pub enum TokenKind {
|
|||
Fn,
|
||||
Struct,
|
||||
True,
|
||||
False,
|
||||
Idk,
|
||||
|
||||
Ctor,
|
||||
Tupl,
|
||||
|
@ -204,15 +210,17 @@ gen_token_kind! {
|
|||
Eof,
|
||||
Directive,
|
||||
#[keywords]
|
||||
Return = b"return",
|
||||
If = b"if",
|
||||
Else = b"else",
|
||||
Loop = b"loop",
|
||||
Break = b"break",
|
||||
Continue = b"continue",
|
||||
Fn = b"fn",
|
||||
Struct = b"struct",
|
||||
True = b"true",
|
||||
Return = b"return",
|
||||
If = b"if",
|
||||
Else = b"else",
|
||||
Loop = b"loop",
|
||||
Break = b"break",
|
||||
Continue = b"continue",
|
||||
Fn = b"fn",
|
||||
Struct = b"struct",
|
||||
True = b"true",
|
||||
False = b"false",
|
||||
Idk = b"idk",
|
||||
#[punkt]
|
||||
Ctor = ".{",
|
||||
Tupl = ".(",
|
||||
|
|
|
@ -36,7 +36,7 @@ pub mod idfl {
|
|||
COMPTIME,
|
||||
}
|
||||
|
||||
pub fn index(i: IdentFlags) -> IdentIndex {
|
||||
pub fn count(i: IdentFlags) -> IdentIndex {
|
||||
(i & !ALL) as _
|
||||
}
|
||||
}
|
||||
|
@ -251,7 +251,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||
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 {
|
||||
|
@ -261,11 +261,11 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||
fn unit_expr(&mut self) -> Expr<'a> {
|
||||
use {Expr as E, TokenKind as T};
|
||||
let frame = self.idents.len();
|
||||
let token = self.next();
|
||||
let token @ Token { start: pos, .. } = self.next();
|
||||
let prev_boundary = self.ns_bound;
|
||||
let prev_captured = self.captured.len();
|
||||
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" => {
|
||||
self.expect_advance(TokenKind::LParen);
|
||||
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('"');
|
||||
|
||||
E::Mod {
|
||||
pos: token.start,
|
||||
pos,
|
||||
path: self.arena.alloc_str(path),
|
||||
id: match (self.loader)(path, self.path) {
|
||||
Ok(id) => id,
|
||||
|
@ -282,15 +282,17 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||
}
|
||||
}
|
||||
T::Directive => E::Directive {
|
||||
pos: token.start,
|
||||
pos,
|
||||
name: self.move_str(token),
|
||||
args: {
|
||||
self.expect_advance(T::LParen);
|
||||
self.collect_list(T::Comma, T::RParen, Self::expr)
|
||||
},
|
||||
},
|
||||
T::True => E::Bool { pos: token.start, value: true },
|
||||
T::DQuote => E::String { pos: token.start, literal: self.move_str(token) },
|
||||
T::True => E::Bool { pos, value: true },
|
||||
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 {
|
||||
fields: {
|
||||
self.ns_bound = self.idents.len();
|
||||
|
@ -313,26 +315,26 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||
// we might save some memory
|
||||
self.captured.clear();
|
||||
}
|
||||
token.start
|
||||
pos
|
||||
},
|
||||
trailing_comma: std::mem::take(&mut self.trailing_sep),
|
||||
},
|
||||
T::Ident | T::CtIdent => {
|
||||
let (id, index) = self.resolve_ident(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 {
|
||||
pos: token.start,
|
||||
pos,
|
||||
cond: self.ptr_expr(),
|
||||
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::Break => E::Break { pos: token.start },
|
||||
T::Continue => E::Continue { pos: token.start },
|
||||
T::Loop => E::Loop { pos, body: self.ptr_expr() },
|
||||
T::Break => E::Break { pos },
|
||||
T::Continue => E::Continue { pos },
|
||||
T::Return => E::Return {
|
||||
pos: token.start,
|
||||
pos,
|
||||
val: (!matches!(
|
||||
self.token.kind,
|
||||
T::Semi | T::RBrace | T::RBrack | T::RParen | T::Comma
|
||||
|
@ -340,7 +342,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||
.then(|| self.ptr_expr()),
|
||||
},
|
||||
T::Fn => E::Closure {
|
||||
pos: token.start,
|
||||
pos,
|
||||
args: {
|
||||
self.expect_advance(T::LParen);
|
||||
self.collect_list(T::Comma, T::RParen, |s| {
|
||||
|
@ -363,18 +365,18 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||
},
|
||||
body: self.ptr_expr(),
|
||||
},
|
||||
T::Ctor => self.ctor(token.start, None),
|
||||
T::Tupl => self.tupl(token.start, None),
|
||||
T::Ctor => self.ctor(pos, None),
|
||||
T::Tupl => self.tupl(pos, None),
|
||||
T::LBrack => E::Slice {
|
||||
item: self.ptr_unit_expr(),
|
||||
size: self.advance_if(T::Semi).then(|| self.ptr_expr()),
|
||||
pos: {
|
||||
self.expect_advance(T::RBrack);
|
||||
token.start
|
||||
pos
|
||||
},
|
||||
},
|
||||
T::Band | T::Mul | T::Xor => E::UnOp {
|
||||
pos: token.start,
|
||||
pos,
|
||||
op: token.kind,
|
||||
val: {
|
||||
let expr = self.ptr_unit_expr();
|
||||
|
@ -384,10 +386,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||
expr
|
||||
},
|
||||
},
|
||||
T::LBrace => E::Block {
|
||||
pos: token.start,
|
||||
stmts: self.collect_list(T::Semi, T::RBrace, Self::expr),
|
||||
},
|
||||
T::LBrace => E::Block { pos, stmts: self.collect_list(T::Semi, T::RBrace, Self::expr) },
|
||||
T::Number => {
|
||||
let slice = self.lexer.slice(token.range());
|
||||
let (slice, radix) = match &slice.get(0..2) {
|
||||
|
@ -397,7 +396,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||
_ => (slice, Radix::Decimal),
|
||||
};
|
||||
E::Number {
|
||||
pos: token.start,
|
||||
pos,
|
||||
value: match u64::from_str_radix(slice, radix as u32) {
|
||||
Ok(value) => value,
|
||||
Err(e) => self.report(format_args!("invalid number: {e}")),
|
||||
|
@ -410,7 +409,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||
self.expect_advance(T::RParen);
|
||||
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:?}")),
|
||||
};
|
||||
|
||||
|
@ -773,6 +772,10 @@ generate_expr! {
|
|||
pos: Pos,
|
||||
value: bool,
|
||||
},
|
||||
/// `'idk'`
|
||||
Idk {
|
||||
pos: Pos,
|
||||
},
|
||||
/// `'@' Ident List('(', ',', ')', Expr)`
|
||||
Directive {
|
||||
pos: u32,
|
||||
|
@ -1047,6 +1050,7 @@ impl<'a> std::fmt::Display for Expr<'a> {
|
|||
Radix::Binary => write!(f, "{value:#b}"),
|
||||
},
|
||||
Self::Bool { value, .. } => write!(f, "{value}"),
|
||||
Self::Idk { .. } => write!(f, "idk"),
|
||||
Self::BinOp {
|
||||
left,
|
||||
op: TokenKind::Assign,
|
||||
|
|
|
@ -15,12 +15,14 @@ use {
|
|||
core::fmt,
|
||||
std::{
|
||||
cell::RefCell,
|
||||
cmp,
|
||||
collections::{hash_map, BTreeMap},
|
||||
fmt::Display,
|
||||
fmt::{Display, Write},
|
||||
hash::{Hash as _, Hasher},
|
||||
mem,
|
||||
ops::{self, Range},
|
||||
rc::Rc,
|
||||
u32,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -58,6 +60,7 @@ impl BitSet {
|
|||
self.data.resize(new_len, 0);
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn set(&mut self, idx: usize) -> bool {
|
||||
let data_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;
|
||||
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;
|
||||
|
@ -532,15 +541,8 @@ impl Nodes {
|
|||
) -> Nid {
|
||||
let ty = ty.into();
|
||||
|
||||
let node = Node {
|
||||
inputs: inps.into(),
|
||||
kind,
|
||||
color: 0,
|
||||
depth: u32::MAX,
|
||||
lock_rc: 0,
|
||||
ty,
|
||||
outputs: vec![],
|
||||
};
|
||||
let node =
|
||||
Node { inputs: inps.into(), kind, color: 0, depth: 0, lock_rc: 0, ty, outputs: vec![] };
|
||||
|
||||
let mut lookup_meta = None;
|
||||
if !node.is_lazy_phi() {
|
||||
|
@ -689,14 +691,14 @@ impl Nodes {
|
|||
let ty = self[target].ty;
|
||||
|
||||
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 {
|
||||
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 => {
|
||||
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]));
|
||||
}
|
||||
_ => {}
|
||||
|
@ -724,7 +726,7 @@ impl Nodes {
|
|||
&& let K::CInt { value: bv } = self[rhs].kind
|
||||
{
|
||||
// (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]));
|
||||
}
|
||||
|
||||
|
@ -741,7 +743,7 @@ impl Nodes {
|
|||
&& let K::CInt { value } = self[self[lhs].inputs[2]].kind
|
||||
{
|
||||
// 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]));
|
||||
}
|
||||
|
||||
|
@ -786,14 +788,12 @@ impl Nodes {
|
|||
);
|
||||
match entry {
|
||||
hash_map::RawEntryMut::Occupied(mut other) => {
|
||||
log::dbg!("rplc");
|
||||
let rpl = other.get_key_value().0.nid;
|
||||
self[target].inputs[inp_index] = prev;
|
||||
self.replace(target, rpl);
|
||||
rpl
|
||||
}
|
||||
hash_map::RawEntryMut::Vacant(slot) => {
|
||||
log::dbg!("mod");
|
||||
slot.insert(LookupEntry { nid: target, hash }, ());
|
||||
let index = self[prev].outputs.iter().position(|&o| o == target).unwrap();
|
||||
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]
|
||||
fn unlock_remove(&mut self, id: Nid) -> bool {
|
||||
self[id].lock_rc -= 1;
|
||||
|
@ -909,15 +902,151 @@ impl Nodes {
|
|||
for (i, node) in self.iter() {
|
||||
let color = if self.is_cfg(i) { "yellow" } else { "white" };
|
||||
writeln!(out, "node{i}[label=\"{}\" color={color}]", node.kind)?;
|
||||
for &o in &node.outputs {
|
||||
let color = if self.is_cfg(i) && self.is_cfg(o) { "red" } else { "black" };
|
||||
writeln!(out, "node{o} -> node{i}[color={color}]",)?;
|
||||
for (j, &o) in node.outputs.iter().enumerate() {
|
||||
let color = if self.is_cfg(i) && self.is_cfg(o) { "red" } else { "lightgray" };
|
||||
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(())
|
||||
}
|
||||
|
||||
#[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) {
|
||||
let out = &mut String::new();
|
||||
_ = self.graphviz_low(out);
|
||||
|
@ -925,17 +1054,7 @@ impl Nodes {
|
|||
}
|
||||
|
||||
fn is_cfg(&self, o: Nid) -> bool {
|
||||
matches!(
|
||||
self[o].kind,
|
||||
Kind::Start
|
||||
| Kind::End
|
||||
| Kind::Return
|
||||
| Kind::Tuple { .. }
|
||||
| Kind::Call { .. }
|
||||
| Kind::If
|
||||
| Kind::Region
|
||||
| Kind::Loop
|
||||
)
|
||||
self[o].kind.is_cfg()
|
||||
}
|
||||
|
||||
fn check_final_integrity(&self) {
|
||||
|
@ -1082,8 +1201,30 @@ pub enum Kind {
|
|||
}
|
||||
|
||||
impl Kind {
|
||||
fn disc(&self) -> u8 {
|
||||
unsafe { *(self as *const _ as *const u8) }
|
||||
fn is_pinned(&self) -> bool {
|
||||
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);
|
||||
};
|
||||
|
||||
self.make_func_reachable(func);
|
||||
|
||||
let fuc = &self.tys.funcs[func as usize];
|
||||
let sig = fuc.sig.expect("TODO: generic functions");
|
||||
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]);
|
||||
|
||||
let Expr::BinOp {
|
||||
left: Expr::Ident { .. },
|
||||
left: Expr::Ident { name, .. },
|
||||
op: TokenKind::Decl,
|
||||
right: &Expr::Closure { body, args, .. },
|
||||
} = expr
|
||||
|
@ -2143,7 +2286,11 @@ impl Codegen {
|
|||
if self.errors.borrow().is_empty() {
|
||||
self.gcm();
|
||||
|
||||
self.ci.nodes.graphviz();
|
||||
//self.ci.nodes.graphviz();
|
||||
log::inf!("{id} {name}: ");
|
||||
self.ci.nodes.basic_blocks();
|
||||
|
||||
return;
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
|
@ -2470,7 +2617,6 @@ impl Codegen {
|
|||
.relocs
|
||||
.push(TypedReloc { target: ty::Kind::Func(func).compress(), reloc });
|
||||
self.ci.emit(instrs::jal(reg::RET_ADDR, reg::ZERO, 0));
|
||||
self.make_func_reachable(func);
|
||||
|
||||
self.ci.call_count -= 1;
|
||||
|
||||
|
@ -2512,17 +2658,13 @@ impl Codegen {
|
|||
let &[_, left, right] = self.ci.nodes[cond].inputs.as_slice() else {
|
||||
unreachable!()
|
||||
};
|
||||
swapped = matches!(op, TokenKind::Lt | TokenKind::Gt);
|
||||
let signed = self.ci.nodes[left].ty.is_signed();
|
||||
let op = 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,
|
||||
_ => break 'optimize_cond,
|
||||
|
||||
let Some((op, swpd)) =
|
||||
Self::cond_op(op, self.ci.nodes[left].ty.is_signed())
|
||||
else {
|
||||
break 'optimize_cond;
|
||||
};
|
||||
swapped = swpd;
|
||||
|
||||
self.emit_expr_consume(left);
|
||||
self.emit_expr_consume(right);
|
||||
|
@ -2741,7 +2883,9 @@ impl Codegen {
|
|||
Kind::BinOp { op } => {
|
||||
_ = self.lazy_init(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);
|
||||
|
||||
if let Kind::CInt { value } = self.ci.nodes[right].kind
|
||||
|
@ -2831,6 +2975,25 @@ impl Codegen {
|
|||
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)]
|
||||
fn math_op(
|
||||
op: TokenKind,
|
||||
|
@ -2887,7 +3050,7 @@ impl Codegen {
|
|||
match name.ok_or(lit_name) {
|
||||
Ok(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(
|
||||
pos,
|
||||
|
@ -2897,7 +3060,7 @@ impl Codegen {
|
|||
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);
|
||||
};
|
||||
|
@ -3093,7 +3256,105 @@ impl Codegen {
|
|||
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)]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
main:
|
||||
ADDI64 r254, r254, -72d
|
||||
ST r31, r254, 48a, 24h
|
||||
ADDI64 r254, r254, -40d
|
||||
ST r31, r254, 24a, 16h
|
||||
LI64 r32, 1d
|
||||
ST r32, r254, 0a, 8h
|
||||
LI64 r32, 2d
|
||||
|
@ -8,13 +8,10 @@ main:
|
|||
LI64 r32, 4d
|
||||
ST r32, r254, 16a, 8h
|
||||
ADDI64 r32, r254, 0d
|
||||
ADDI64 r33, r254, 24d
|
||||
BMC r32, r33, 24h
|
||||
ADDI64 r33, r254, 24d
|
||||
CP r2, r33
|
||||
CP r2, r32
|
||||
JAL r31, r0, :pass
|
||||
LD r31, r254, 48a, 24h
|
||||
ADDI64 r254, r254, 72d
|
||||
LD r31, r254, 24a, 16h
|
||||
ADDI64 r254, r254, 40d
|
||||
JALA r0, r31, 0a
|
||||
pass:
|
||||
ADDI64 r254, r254, -40d
|
||||
|
@ -44,6 +41,6 @@ pass:
|
|||
LD r31, r254, 0a, 40h
|
||||
ADDI64 r254, r254, 40d
|
||||
JALA r0, r31, 0a
|
||||
code size: 408
|
||||
code size: 381
|
||||
ret: 7
|
||||
status: Ok(())
|
||||
|
|
|
@ -16,30 +16,27 @@ main:
|
|||
ADDI64 r254, r254, 24d
|
||||
JALA r0, r31, 0a
|
||||
str_len:
|
||||
ADDI64 r254, r254, -40d
|
||||
ST r31, r254, 0a, 40h
|
||||
ADDI64 r254, r254, -48d
|
||||
ST r31, r254, 0a, 48h
|
||||
CP r32, r2
|
||||
LI64 r33, 0d
|
||||
2: CP r34, r32
|
||||
CP r35, r0
|
||||
LD r35, r34, 0a, 1h
|
||||
LI64 r34, 0d
|
||||
CMPU r35, r35, r34
|
||||
CMPUI r35, r35, 0d
|
||||
NOT r35, r35
|
||||
JEQ r35, r0, :0
|
||||
LI64 r36, 0d
|
||||
JNE r35, r36, :0
|
||||
JMP :1
|
||||
0: CP r35, r33
|
||||
ADDI64 r35, r35, 1d
|
||||
CP r33, r35
|
||||
CP r35, r32
|
||||
ADDI64 r35, r35, 1d
|
||||
CP r32, r35
|
||||
0: CP r36, r33
|
||||
ADDI64 r36, r36, 1d
|
||||
CP r33, r36
|
||||
CP r36, r32
|
||||
ADDI64 r36, r36, 1d
|
||||
CP r32, r36
|
||||
JMP :2
|
||||
1: CP r1, r33
|
||||
LD r31, r254, 0a, 40h
|
||||
ADDI64 r254, r254, 40d
|
||||
LD r31, r254, 0a, 48h
|
||||
ADDI64 r254, r254, 48d
|
||||
JALA r0, r31, 0a
|
||||
code size: 303
|
||||
code size: 285
|
||||
ret: 16
|
||||
status: Ok(())
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
main:
|
||||
ADDI64 r254, r254, -48d
|
||||
ST r31, r254, 24a, 24h
|
||||
ADDI64 r254, r254, -44d
|
||||
ST r31, r254, 12a, 32h
|
||||
LI64 r32, 255d
|
||||
ST r32, r254, 0a, 1h
|
||||
LI64 r32, 0d
|
||||
|
@ -13,52 +13,45 @@ main:
|
|||
ST r32, r254, 4a, 4h
|
||||
LI64 r32, 2d
|
||||
ST r32, r254, 8a, 4h
|
||||
ADDI64 r32, r254, 0d
|
||||
ADDI64 r33, r254, 12d
|
||||
BMC r32, r33, 12h
|
||||
LI64 r33, 1d
|
||||
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
|
||||
LI64 r32, 1d
|
||||
ADDI64 r33, r254, 4d
|
||||
MULI64 r32, r32, 4d
|
||||
ADD64 r33, r33, r32
|
||||
CP r32, r0
|
||||
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
|
||||
CMPU r32, r32, r33
|
||||
CMPUI r32, r32, 0d
|
||||
JEQ r32, r0, :2
|
||||
JEQ r32, r33, :2
|
||||
LI64 r1, 64d
|
||||
JMP :1
|
||||
2: CP r32, r0
|
||||
LD r32, r254, 16a, 4h
|
||||
CP r33, r0
|
||||
LD r33, r254, 20a, 4h
|
||||
ADD32 r32, r32, r33
|
||||
CP r33, r0
|
||||
LD r33, r254, 12a, 1h
|
||||
ADD32 r32, r32, r33
|
||||
CP r33, r0
|
||||
LD r33, r254, 13a, 1h
|
||||
ADD32 r32, r32, r33
|
||||
CP r33, r0
|
||||
LD r33, r254, 14a, 1h
|
||||
ADD32 r32, r32, r33
|
||||
CP r33, r0
|
||||
LD r33, r254, 15a, 1h
|
||||
ADD32 r32, r32, r33
|
||||
CP r1, r32
|
||||
1: LD r31, r254, 24a, 24h
|
||||
ADDI64 r254, r254, 48d
|
||||
2: CP r33, r0
|
||||
LD r33, r254, 4a, 4h
|
||||
CP r32, r0
|
||||
LD r32, r254, 8a, 4h
|
||||
ADD32 r33, r33, r32
|
||||
CP r32, r0
|
||||
LD r32, r254, 0a, 1h
|
||||
ADD32 r33, r33, r32
|
||||
CP r32, r0
|
||||
LD r32, r254, 1a, 1h
|
||||
ADD32 r33, r33, r32
|
||||
CP r32, r0
|
||||
LD r32, r254, 2a, 1h
|
||||
ADD32 r33, r33, r32
|
||||
CP r32, r0
|
||||
LD r32, r254, 3a, 1h
|
||||
ADD32 r33, r33, r32
|
||||
CP r1, r33
|
||||
1: LD r31, r254, 12a, 32h
|
||||
ADDI64 r254, r254, 44d
|
||||
JALA r0, r31, 0a
|
||||
code size: 531
|
||||
code size: 474
|
||||
ret: 512
|
||||
status: Ok(())
|
||||
|
|
|
@ -1,23 +1,20 @@
|
|||
main:
|
||||
ADDI64 r254, r254, -72d
|
||||
ST r31, r254, 48a, 24h
|
||||
ADDI64 r254, r254, -48d
|
||||
ST r31, r254, 24a, 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
|
||||
CP r2, r32
|
||||
LI64 r3, 69d
|
||||
JAL r31, r0, :push
|
||||
LD r33, r254, 24a, 8h
|
||||
LD r32, r33, 0a, 8h
|
||||
ADDI64 r33, r254, 24d
|
||||
CP r2, r33
|
||||
LD r32, r254, 0a, 8h
|
||||
LD r33, r32, 0a, 8h
|
||||
ADDI64 r32, r254, 0d
|
||||
CP r2, r32
|
||||
JAL r31, r0, :deinit
|
||||
CP r1, r32
|
||||
LD r31, r254, 48a, 24h
|
||||
ADDI64 r254, r254, 72d
|
||||
CP r1, r33
|
||||
LD r31, r254, 24a, 24h
|
||||
ADDI64 r254, r254, 48d
|
||||
JALA r0, r31, 0a
|
||||
deinit:
|
||||
ADDI64 r254, r254, -24d
|
||||
|
@ -56,16 +53,10 @@ push:
|
|||
CP r33, r3
|
||||
LD r34, r32, 8a, 8h
|
||||
LD r35, r32, 16a, 8h
|
||||
CMPU r34, r34, r35
|
||||
CMPUI r34, r34, 0d
|
||||
NOT r34, r34
|
||||
JEQ r34, r0, :0
|
||||
LD r34, r32, 16a, 8h
|
||||
LI64 r35, 0d
|
||||
CMPU r34, r34, r35
|
||||
CMPUI r34, r34, 0d
|
||||
NOT r34, r34
|
||||
JEQ r34, r0, :1
|
||||
JNE r34, r35, :0
|
||||
LD r35, r32, 16a, 8h
|
||||
LI64 r34, 0d
|
||||
JNE r35, r34, :1
|
||||
LI64 r34, 1d
|
||||
ST r34, r32, 16a, 8h
|
||||
JMP :2
|
||||
|
@ -78,12 +69,8 @@ push:
|
|||
LI64 r3, 8d
|
||||
JAL r31, r0, :malloc
|
||||
CP r34, r1
|
||||
CP r35, r34
|
||||
LI64 r36, 0d
|
||||
CMPU r35, r35, r36
|
||||
CMPUI r35, r35, 0d
|
||||
NOT r35, r35
|
||||
JEQ r35, r0, :3
|
||||
LI64 r35, 0d
|
||||
JNE r34, r35, :3
|
||||
LI64 r1, 0d
|
||||
JMP :4
|
||||
3: LD r35, r32, 0a, 8h
|
||||
|
@ -92,12 +79,7 @@ push:
|
|||
LD r38, r32, 8a, 8h
|
||||
MULI64 r38, r38, 8d
|
||||
ADD64 r37, r37, r38
|
||||
7: CP r38, r35
|
||||
CP r39, r37
|
||||
CMPU r38, r38, r39
|
||||
CMPUI r38, r38, 0d
|
||||
NOT r38, r38
|
||||
JEQ r38, r0, :5
|
||||
7: JNE r35, r37, :5
|
||||
JMP :6
|
||||
5: CP r38, r36
|
||||
CP r39, r35
|
||||
|
@ -113,25 +95,23 @@ push:
|
|||
JMP :7
|
||||
6: LD r38, r32, 8a, 8h
|
||||
LI64 r39, 0d
|
||||
CMPU r38, r38, r39
|
||||
CMPUI r38, r38, 0d
|
||||
JEQ r38, r0, :8
|
||||
JEQ r38, r39, :8
|
||||
LD r2, r32, 0a, 8h
|
||||
LD r38, r32, 8a, 8h
|
||||
MULI64 r38, r38, 8d
|
||||
CP r3, r38
|
||||
LD r39, r32, 8a, 8h
|
||||
MULI64 r39, r39, 8d
|
||||
CP r3, r39
|
||||
LI64 r4, 8d
|
||||
JAL r31, r0, :free
|
||||
8: ST r34, r32, 0a, 8h
|
||||
0: LD r34, r32, 0a, 8h
|
||||
LD r38, r32, 8a, 8h
|
||||
MULI64 r38, r38, 8d
|
||||
ADD64 r34, r34, r38
|
||||
CP r38, r34
|
||||
ST r33, r38, 0a, 8h
|
||||
LD r38, r32, 8a, 8h
|
||||
ADDI64 r38, r38, 1d
|
||||
ST r38, r32, 8a, 8h
|
||||
LD r39, r32, 8a, 8h
|
||||
MULI64 r39, r39, 8d
|
||||
ADD64 r34, r34, r39
|
||||
CP r39, r34
|
||||
ST r33, r39, 0a, 8h
|
||||
LD r39, r32, 8a, 8h
|
||||
ADDI64 r39, r39, 1d
|
||||
ST r39, r32, 8a, 8h
|
||||
CP r1, r34
|
||||
4: LD r31, r254, 0a, 88h
|
||||
ADDI64 r254, r254, 88d
|
||||
|
@ -162,6 +142,6 @@ new:
|
|||
LD r31, r254, 0a, 24h
|
||||
ADDI64 r254, r254, 24d
|
||||
JALA r0, r31, 0a
|
||||
code size: 1470
|
||||
code size: 1347
|
||||
ret: 69
|
||||
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
|
||||
JALA r0, r31, 0a
|
||||
fib:
|
||||
ADDI64 r254, r254, -32d
|
||||
ST r31, r254, 0a, 32h
|
||||
ADDI64 r254, r254, -24d
|
||||
ST r31, r254, 0a, 24h
|
||||
CP r32, r2
|
||||
CP r33, r32
|
||||
LI64 r34, 2d
|
||||
CMPS r33, r33, r34
|
||||
CMPUI r33, r33, 1d
|
||||
JEQ r33, r0, :0
|
||||
LI64 r33, 2d
|
||||
JGTS r32, r33, :0
|
||||
LI64 r1, 1d
|
||||
JMP :1
|
||||
0: CP r33, r32
|
||||
|
@ -28,9 +25,9 @@ fib:
|
|||
CP r32, r1
|
||||
ADD64 r33, r33, r32
|
||||
CP r1, r33
|
||||
1: LD r31, r254, 0a, 32h
|
||||
ADDI64 r254, r254, 32d
|
||||
1: LD r31, r254, 0a, 24h
|
||||
ADDI64 r254, r254, 24d
|
||||
JALA r0, r31, 0a
|
||||
code size: 252
|
||||
code size: 234
|
||||
ret: 55
|
||||
status: Ok(())
|
||||
|
|
|
@ -116,23 +116,14 @@ rect_line:
|
|||
LI64 r33, 0d
|
||||
LI64 r34, 0d
|
||||
LI64 r35, 0d
|
||||
5: CP r36, r33
|
||||
CP r37, r32
|
||||
CMPS r36, r36, r37
|
||||
CMPUI r36, r36, 0d
|
||||
NOT r36, r36
|
||||
JEQ r36, r0, :0
|
||||
5: JNE r33, r32, :0
|
||||
JMP :1
|
||||
0: LD r34, r254, 8a, 8h
|
||||
LD r35, r254, 0a, 8h
|
||||
4: CP r36, r34
|
||||
LD r37, r254, 8a, 8h
|
||||
LD r38, r254, 16a, 8h
|
||||
ADD64 r37, r37, r38
|
||||
CMPS r36, r36, r37
|
||||
CMPUI r36, r36, 0d
|
||||
NOT r36, r36
|
||||
JEQ r36, r0, :2
|
||||
4: LD r36, r254, 8a, 8h
|
||||
LD r37, r254, 16a, 8h
|
||||
ADD64 r36, r36, r37
|
||||
JNE r34, r36, :2
|
||||
JMP :3
|
||||
2: LI64 r36, 1d
|
||||
LI64 r37, 10d
|
||||
|
@ -179,6 +170,6 @@ line:
|
|||
2: LD r31, r254, 48a, 32h
|
||||
ADDI64 r254, r254, 80d
|
||||
JALA r0, r31, 0a
|
||||
code size: 1521
|
||||
code size: 1476
|
||||
ret: 0
|
||||
status: Ok(())
|
||||
|
|
|
@ -12,12 +12,8 @@ fib:
|
|||
CP r32, r2
|
||||
LI64 r33, 0d
|
||||
LI64 r34, 1d
|
||||
2: CP r35, r32
|
||||
LI64 r36, 0d
|
||||
CMPS r35, r35, r36
|
||||
CMPUI r35, r35, 0d
|
||||
NOT r35, r35
|
||||
JEQ r35, r0, :0
|
||||
2: LI64 r35, 0d
|
||||
JNE r32, r35, :0
|
||||
JMP :1
|
||||
0: CP r35, r33
|
||||
CP r36, r34
|
||||
|
@ -32,6 +28,6 @@ fib:
|
|||
LD r31, r254, 0a, 48h
|
||||
ADDI64 r254, r254, 48d
|
||||
JALA r0, r31, 0a
|
||||
code size: 248
|
||||
code size: 227
|
||||
ret: 55
|
||||
status: Ok(())
|
||||
|
|
|
@ -26,12 +26,8 @@ fib_iter:
|
|||
CP r32, r2
|
||||
LI64 r33, 0d
|
||||
LI64 r34, 1d
|
||||
2: CP r35, r32
|
||||
LI64 r36, 0d
|
||||
CMPS r35, r35, r36
|
||||
CMPUI r35, r35, 0d
|
||||
NOT r35, r35
|
||||
JEQ r35, r0, :0
|
||||
2: LI64 r35, 0d
|
||||
JNE r32, r35, :0
|
||||
JMP :1
|
||||
0: CP r35, r33
|
||||
CP r36, r34
|
||||
|
@ -50,28 +46,25 @@ fib:
|
|||
ADDI64 r254, r254, -32d
|
||||
ST r31, r254, 0a, 32h
|
||||
CP r32, r2
|
||||
LI64 r33, 2d
|
||||
JLTS r32, r33, :0
|
||||
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
|
||||
CP r34, r32
|
||||
ADDI64 r34, r34, -2d
|
||||
CP r2, r34
|
||||
JAL r31, r0, :fib
|
||||
CP r32, r1
|
||||
ADD64 r33, r33, r32
|
||||
CP r34, r1
|
||||
ADD64 r33, r33, r34
|
||||
CP r1, r33
|
||||
JMP :1
|
||||
0: CP r1, r32
|
||||
1: LD r31, r254, 0a, 32h
|
||||
ADDI64 r254, r254, 32d
|
||||
JALA r0, r31, 0a
|
||||
code size: 518
|
||||
code size: 479
|
||||
ret: 0
|
||||
status: Ok(())
|
||||
|
|
|
@ -1,31 +1,25 @@
|
|||
main:
|
||||
ADDI64 r254, r254, -72d
|
||||
ST r31, r254, 48a, 24h
|
||||
ADDI64 r254, r254, -48d
|
||||
ST r31, r254, 24a, 24h
|
||||
LI64 r32, 4d
|
||||
ST r32, r254, 24a, 8h
|
||||
ST r32, r254, 0a, 8h
|
||||
LI64 r32, 1d
|
||||
ST r32, r254, 32a, 8h
|
||||
ST r32, r254, 8a, 8h
|
||||
LI64 r32, 3d
|
||||
ST r32, r254, 40a, 8h
|
||||
ADDI64 r2, r254, 24d
|
||||
ST r32, r254, 16a, 8h
|
||||
ADDI64 r2, r254, 0d
|
||||
ADDI64 r1, r254, 0d
|
||||
JAL r31, r0, :odher_pass
|
||||
ADDI64 r32, r254, 0d
|
||||
ADDI64 r33, r254, 24d
|
||||
BMC r32, r33, 24h
|
||||
LD r33, r254, 40a, 8h
|
||||
LI64 r32, 3d
|
||||
CMPS r33, r33, r32
|
||||
CMPUI r33, r33, 0d
|
||||
NOT r33, r33
|
||||
JEQ r33, r0, :0
|
||||
ADDI64 r33, r254, 24d
|
||||
LD r32, r254, 16a, 8h
|
||||
LI64 r33, 3d
|
||||
JNE r32, r33, :0
|
||||
ADDI64 r33, r254, 0d
|
||||
CP r2, r33
|
||||
JAL r31, r0, :pass
|
||||
JMP :1
|
||||
0: LI64 r1, 0d
|
||||
1: LD r31, r254, 48a, 24h
|
||||
ADDI64 r254, r254, 72d
|
||||
1: LD r31, r254, 24a, 24h
|
||||
ADDI64 r254, r254, 48d
|
||||
JALA r0, r31, 0a
|
||||
pass:
|
||||
ADDI64 r254, r254, -32d
|
||||
|
@ -49,6 +43,6 @@ odher_pass:
|
|||
LD r31, r254, 0a, 40h
|
||||
ADDI64 r254, r254, 40d
|
||||
JALA r0, r31, 0a
|
||||
code size: 445
|
||||
code size: 400
|
||||
ret: 3
|
||||
status: Ok(())
|
||||
|
|
|
@ -22,7 +22,7 @@ fib:
|
|||
SUB64 r35, r32, r33
|
||||
CP r2, r35
|
||||
JAL r31, r0, :fib
|
||||
ADD64 r1, r34, r1
|
||||
ADD64 r1, r1, r34
|
||||
1: LD r31, r254, 0a, 40h
|
||||
ADDI64 r254, r254, 40d
|
||||
JALA r0, r31, 0a
|
||||
|
|
|
@ -1,31 +1,4 @@
|
|||
main:
|
||||
ADDI64 r254, r254, -16d
|
||||
ST r31, r254, 0a, 16h
|
||||
LI64 r32, 10d
|
||||
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(())
|
||||
code size: 8
|
||||
ret: 0
|
||||
status: Err(Unreachable)
|
||||
|
|
|
@ -36,7 +36,7 @@ use {
|
|||
pub struct Vm<Mem, const TIMER_QUOTIENT: usize> {
|
||||
/// 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
|
||||
pub registers: [Value; 256],
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::utils::static_assert;
|
|||
///
|
||||
/// # Safety
|
||||
/// 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 {
|
||||
($($ty:ident),* $(,)?) => {
|
||||
/// HBVM register value
|
||||
|
|
Loading…
Reference in a new issue