forked from AbleOS/holey-bytes
little cleanup and fixing error recovery
This commit is contained in:
parent
897e121eeb
commit
64e228450f
|
@ -1236,6 +1236,7 @@ impl Types {
|
||||||
for &func in &self.tmp.funcs {
|
for &func in &self.tmp.funcs {
|
||||||
let fuc = &mut self.ins.funcs[func as usize];
|
let fuc = &mut self.ins.funcs[func as usize];
|
||||||
fuc.offset = to.len() as _;
|
fuc.offset = to.len() as _;
|
||||||
|
debug_assert!(!fuc.code.is_empty());
|
||||||
to.extend(&fuc.code);
|
to.extend(&fuc.code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1520,6 +1521,26 @@ pub struct Comptime {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Comptime {
|
impl Comptime {
|
||||||
|
fn run(&mut self, ret_loc: &mut [u8], offset: u32) -> u64 {
|
||||||
|
self.vm.write_reg(reg::RET, ret_loc.as_mut_ptr() as u64);
|
||||||
|
let prev_pc = self.push_pc(offset);
|
||||||
|
loop {
|
||||||
|
match self.vm.run().expect("TODO") {
|
||||||
|
hbvm::VmRunOk::End => break,
|
||||||
|
hbvm::VmRunOk::Timer => todo!(),
|
||||||
|
hbvm::VmRunOk::Ecall => todo!(),
|
||||||
|
hbvm::VmRunOk::Breakpoint => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.pop_pc(prev_pc);
|
||||||
|
|
||||||
|
if let len @ 1..=8 = ret_loc.len() {
|
||||||
|
ret_loc.copy_from_slice(&self.vm.read_reg(reg::RET).0.to_ne_bytes()[..len])
|
||||||
|
}
|
||||||
|
|
||||||
|
self.vm.read_reg(reg::RET).0
|
||||||
|
}
|
||||||
|
|
||||||
fn reset(&mut self) {
|
fn reset(&mut self) {
|
||||||
let ptr = unsafe { self.stack.as_mut_ptr().cast::<u8>().add(VM_STACK_SIZE) as u64 };
|
let ptr = unsafe { self.stack.as_mut_ptr().cast::<u8>().add(VM_STACK_SIZE) as u64 };
|
||||||
self.vm.registers.fill(hbvm::value::Value(0));
|
self.vm.registers.fill(hbvm::value::Value(0));
|
||||||
|
|
165
lang/src/son.rs
165
lang/src/son.rs
|
@ -20,10 +20,12 @@ use {
|
||||||
alloc::{borrow::ToOwned, string::String, vec::Vec},
|
alloc::{borrow::ToOwned, string::String, vec::Vec},
|
||||||
core::{
|
core::{
|
||||||
assert_matches::debug_assert_matches,
|
assert_matches::debug_assert_matches,
|
||||||
|
borrow::Borrow,
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
fmt::{self, Debug, Display, Write},
|
fmt::{self, Debug, Display, Write},
|
||||||
format_args as fa, mem,
|
format_args as fa, mem,
|
||||||
ops::{self},
|
ops::{self},
|
||||||
|
usize,
|
||||||
},
|
},
|
||||||
hashbrown::hash_map,
|
hashbrown::hash_map,
|
||||||
hbbytecode::DisasmError,
|
hbbytecode::DisasmError,
|
||||||
|
@ -1826,6 +1828,7 @@ impl Value {
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Codegen<'a> {
|
pub struct Codegen<'a> {
|
||||||
pub files: &'a [parser::Ast],
|
pub files: &'a [parser::Ast],
|
||||||
|
pub errors: RefCell<String>,
|
||||||
|
|
||||||
tasks: Vec<Option<FTask>>,
|
tasks: Vec<Option<FTask>>,
|
||||||
tys: Types,
|
tys: Types,
|
||||||
|
@ -1834,7 +1837,6 @@ pub struct Codegen<'a> {
|
||||||
#[expect(dead_code)]
|
#[expect(dead_code)]
|
||||||
ralloc: Regalloc,
|
ralloc: Regalloc,
|
||||||
ct: Comptime,
|
ct: Comptime,
|
||||||
pub errors: RefCell<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeParser for Codegen<'_> {
|
impl TypeParser for Codegen<'_> {
|
||||||
|
@ -1854,56 +1856,16 @@ impl TypeParser for Codegen<'_> {
|
||||||
scope = core::mem::take(&mut self.ci.scope.vars);
|
scope = core::mem::take(&mut self.ci.scope.vars);
|
||||||
self.ci.finalize();
|
self.ci.finalize();
|
||||||
|
|
||||||
if self.errors.borrow().len() == prev_err_len {
|
let res = if self.errors.borrow().len() == prev_err_len {
|
||||||
self.ci.emit_body(&mut self.tys, self.files, Sig { args: Tuple::empty(), ret });
|
self.emit_and_eval(file, ret, &mut [])
|
||||||
self.ci.code.truncate(self.ci.code.len() - instrs::jala(0, 0, 0).0);
|
} else {
|
||||||
self.ci.emit(instrs::tx());
|
1
|
||||||
|
|
||||||
let func = Func {
|
|
||||||
file,
|
|
||||||
name: 0,
|
|
||||||
expr: ExprRef::new(expr),
|
|
||||||
relocs: core::mem::take(&mut self.ci.relocs),
|
|
||||||
code: core::mem::take(&mut self.ci.code),
|
|
||||||
..Default::default()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.complete_call_graph();
|
|
||||||
self.pool.pop_ci(&mut self.ci);
|
self.pool.pop_ci(&mut self.ci);
|
||||||
self.ci.scope.vars = scope;
|
self.ci.scope.vars = scope;
|
||||||
|
|
||||||
// TODO: return them back
|
res
|
||||||
let fuc = self.tys.ins.funcs.len() as ty::Func;
|
|
||||||
self.tys.ins.funcs.push(func);
|
|
||||||
|
|
||||||
self.tys.dump_reachable(fuc, &mut self.ct.code);
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
{
|
|
||||||
let mut vc = String::new();
|
|
||||||
if let Err(e) = self.tys.disasm(&self.ct.code, self.files, &mut vc, |_| {}) {
|
|
||||||
panic!("{e} {}", vc);
|
|
||||||
} else {
|
|
||||||
log::trace!("{}", vc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let prev_pc = self.ct.push_pc(self.tys.ins.funcs[fuc as usize].offset);
|
|
||||||
loop {
|
|
||||||
match self.ct.vm.run().expect("TODO") {
|
|
||||||
hbvm::VmRunOk::End => break,
|
|
||||||
hbvm::VmRunOk::Timer => todo!(),
|
|
||||||
hbvm::VmRunOk::Ecall => todo!(),
|
|
||||||
hbvm::VmRunOk::Breakpoint => todo!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.ct.pop_pc(prev_pc);
|
|
||||||
self.ct.vm.read_reg(reg::RET).0
|
|
||||||
} else {
|
|
||||||
self.pool.pop_ci(&mut self.ci);
|
|
||||||
self.ci.scope.vars = scope;
|
|
||||||
1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn infer_type(&mut self, expr: &Expr) -> ty::Id {
|
fn infer_type(&mut self, expr: &Expr) -> ty::Id {
|
||||||
|
@ -1931,73 +1893,20 @@ impl TypeParser for Codegen<'_> {
|
||||||
|
|
||||||
let ty = ty::Kind::Global(gid);
|
let ty = ty::Kind::Global(gid);
|
||||||
self.pool.push_ci(file, None, self.tasks.len(), &mut self.ci);
|
self.pool.push_ci(file, None, self.tasks.len(), &mut self.ci);
|
||||||
|
let prev_err_len = self.errors.borrow().len();
|
||||||
|
|
||||||
let ret = Expr::Return { pos: expr.pos(), val: Some(expr) };
|
self.expr(&(Expr::Return { pos: expr.pos(), val: Some(expr) }));
|
||||||
self.expr(&ret);
|
|
||||||
|
|
||||||
self.ci.finalize();
|
self.ci.finalize();
|
||||||
|
|
||||||
let ret = self.ci.ret.expect("for return type to be infered");
|
let ret = self.ci.ret.expect("for return type to be infered");
|
||||||
if self.errors.borrow().is_empty() {
|
if self.errors.borrow().len() == prev_err_len {
|
||||||
self.ci.emit_body(&mut self.tys, self.files, Sig { args: Tuple::empty(), ret });
|
|
||||||
self.ci.code.truncate(self.ci.code.len() - instrs::jala(0, 0, 0).0);
|
|
||||||
self.ci.emit(instrs::tx());
|
|
||||||
|
|
||||||
let func = Func {
|
|
||||||
file,
|
|
||||||
name,
|
|
||||||
expr: ExprRef::new(expr),
|
|
||||||
relocs: core::mem::take(&mut self.ci.relocs),
|
|
||||||
code: core::mem::take(&mut self.ci.code),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
self.complete_call_graph();
|
|
||||||
self.pool.pop_ci(&mut self.ci);
|
|
||||||
|
|
||||||
let mut mem = vec![0u8; self.tys.size_of(ret) as usize];
|
let mut mem = vec![0u8; self.tys.size_of(ret) as usize];
|
||||||
|
self.emit_and_eval(file, ret, &mut mem);
|
||||||
// TODO: return them back
|
|
||||||
let fuc = self.tys.ins.funcs.len() as ty::Func;
|
|
||||||
self.tys.ins.funcs.push(func);
|
|
||||||
|
|
||||||
self.tys.dump_reachable(fuc, &mut self.ct.code);
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
{
|
|
||||||
let mut vc = String::new();
|
|
||||||
if let Err(e) = self.tys.disasm(&self.ct.code, self.files, &mut vc, |_| {}) {
|
|
||||||
panic!("{e} {}", vc);
|
|
||||||
} else {
|
|
||||||
log::trace!("{}", vc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.ct.vm.write_reg(reg::RET, mem.as_mut_ptr() as u64);
|
|
||||||
let prev_pc = self.ct.push_pc(self.tys.ins.funcs[fuc as usize].offset);
|
|
||||||
loop {
|
|
||||||
match self.ct.vm.run().expect("TODO") {
|
|
||||||
hbvm::VmRunOk::End => break,
|
|
||||||
hbvm::VmRunOk::Timer => todo!(),
|
|
||||||
hbvm::VmRunOk::Ecall => todo!(),
|
|
||||||
hbvm::VmRunOk::Breakpoint => todo!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.ct.pop_pc(prev_pc);
|
|
||||||
|
|
||||||
match mem.len() {
|
|
||||||
0 => unreachable!(),
|
|
||||||
len @ 1..=8 => {
|
|
||||||
mem.copy_from_slice(&self.ct.vm.read_reg(reg::RET).0.to_ne_bytes()[..len])
|
|
||||||
}
|
|
||||||
9..=16 => todo!(),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.tys.ins.globals[gid as usize].data = mem;
|
self.tys.ins.globals[gid as usize].data = mem;
|
||||||
} else {
|
|
||||||
self.pool.pop_ci(&mut self.ci);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.pool.pop_ci(&mut self.ci);
|
||||||
self.tys.ins.globals[gid as usize].ty = ret;
|
self.tys.ins.globals[gid as usize].ty = ret;
|
||||||
|
|
||||||
ty.compress()
|
ty.compress()
|
||||||
|
@ -2014,6 +1923,45 @@ impl TypeParser for Codegen<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Codegen<'a> {
|
impl<'a> Codegen<'a> {
|
||||||
|
fn emit_and_eval(&mut self, file: FileId, ret: ty::Id, ret_loc: &mut [u8]) -> u64 {
|
||||||
|
if !self.complete_call_graph() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.ci.emit_body(&mut self.tys, self.files, Sig { args: Tuple::empty(), ret });
|
||||||
|
self.ci.code.truncate(self.ci.code.len() - instrs::jala(0, 0, 0).0);
|
||||||
|
self.ci.emit(instrs::tx());
|
||||||
|
|
||||||
|
let func = Func {
|
||||||
|
file,
|
||||||
|
name: 0,
|
||||||
|
relocs: core::mem::take(&mut self.ci.relocs),
|
||||||
|
code: core::mem::take(&mut self.ci.code),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: return them back
|
||||||
|
let fuc = self.tys.ins.funcs.len() as ty::Func;
|
||||||
|
self.tys.ins.funcs.push(func);
|
||||||
|
|
||||||
|
self.tys.dump_reachable(fuc, &mut self.ct.code);
|
||||||
|
self.dump_ct_asm();
|
||||||
|
|
||||||
|
self.ct.run(ret_loc, self.tys.ins.funcs[fuc as usize].offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dump_ct_asm(&self) {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
{
|
||||||
|
let mut vc = String::new();
|
||||||
|
if let Err(e) = self.tys.disasm(&self.ct.code, self.files, &mut vc, |_| {}) {
|
||||||
|
panic!("{e} {}", vc);
|
||||||
|
} else {
|
||||||
|
log::trace!("{}", vc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn push_embeds(&mut self, embeds: Vec<Vec<u8>>) {
|
pub fn push_embeds(&mut self, embeds: Vec<Vec<u8>>) {
|
||||||
self.tys.ins.globals = embeds
|
self.tys.ins.globals = embeds
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -3414,13 +3362,15 @@ impl<'a> Codegen<'a> {
|
||||||
self.ci.nodes[id].ty
|
self.ci.nodes[id].ty
|
||||||
}
|
}
|
||||||
|
|
||||||
fn complete_call_graph(&mut self) {
|
fn complete_call_graph(&mut self) -> bool {
|
||||||
|
let prev_err_len = self.errors.borrow().len();
|
||||||
while self.ci.task_base < self.tasks.len()
|
while self.ci.task_base < self.tasks.len()
|
||||||
&& let Some(task_slot) = self.tasks.pop()
|
&& let Some(task_slot) = self.tasks.pop()
|
||||||
{
|
{
|
||||||
let Some(task) = task_slot else { continue };
|
let Some(task) = task_slot else { continue };
|
||||||
self.emit_func(task);
|
self.emit_func(task);
|
||||||
}
|
}
|
||||||
|
self.errors.borrow().len() == prev_err_len
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_func(&mut self, FTask { file, id }: FTask) {
|
fn emit_func(&mut self, FTask { file, id }: FTask) {
|
||||||
|
@ -3432,6 +3382,7 @@ impl<'a> Codegen<'a> {
|
||||||
let expr = func.expr.get(ast);
|
let expr = func.expr.get(ast);
|
||||||
|
|
||||||
self.pool.push_ci(file, Some(sig.ret), 0, &mut self.ci);
|
self.pool.push_ci(file, Some(sig.ret), 0, &mut self.ci);
|
||||||
|
let prev_err_len = self.errors.borrow().len();
|
||||||
|
|
||||||
let &Expr::Closure { body, args, .. } = expr else {
|
let &Expr::Closure { body, args, .. } = expr else {
|
||||||
unreachable!("{}", self.ast_display(expr))
|
unreachable!("{}", self.ast_display(expr))
|
||||||
|
@ -3482,7 +3433,7 @@ impl<'a> Codegen<'a> {
|
||||||
|
|
||||||
self.ci.finalize();
|
self.ci.finalize();
|
||||||
|
|
||||||
if self.errors.borrow().is_empty() {
|
if self.errors.borrow().len() == prev_err_len {
|
||||||
self.ci.emit_body(&mut self.tys, self.files, sig);
|
self.ci.emit_body(&mut self.tys, self.files, sig);
|
||||||
self.tys.ins.funcs[id as usize].code.append(&mut self.ci.code);
|
self.tys.ins.funcs[id as usize].code.append(&mut self.ci.code);
|
||||||
self.tys.ins.funcs[id as usize].relocs.append(&mut self.ci.relocs);
|
self.tys.ins.funcs[id as usize].relocs.append(&mut self.ci.relocs);
|
||||||
|
|
Loading…
Reference in a new issue