holey-bytes/depell/wasm-hbc/src/lib.rs

129 lines
4 KiB
Rust
Raw Normal View History

2024-10-10 12:01:12 -05:00
#![feature(alloc_error_handler)]
2024-10-12 06:07:49 -05:00
#![feature(slice_take)]
2024-10-10 12:01:12 -05:00
#![no_std]
use {
2024-10-12 06:07:49 -05:00
alloc::{string::String, vec::Vec},
2024-11-23 04:14:03 -06:00
core::ffi::CStr,
2024-10-27 07:57:00 -05:00
hblang::{
backend::hbvm::HbvmBackend,
son::{Codegen, CodegenCtx},
2024-11-08 03:25:34 -06:00
ty::Module,
Ent,
2024-10-27 07:57:00 -05:00
},
2024-10-10 12:01:12 -05:00
};
extern crate alloc;
const ARENA_CAP: usize = 128 * 16 * 1024;
wasm_rt::decl_runtime!(ARENA_CAP, 1024 * 4);
2024-10-10 12:01:12 -05:00
2024-10-12 06:07:49 -05:00
const MAX_INPUT_SIZE: usize = 32 * 4 * 1024;
wasm_rt::decl_buffer!(MAX_INPUT_SIZE, MAX_INPUT, INPUT, INPUT_LEN);
2024-10-10 12:01:12 -05:00
#[no_mangle]
2024-10-12 06:07:49 -05:00
unsafe fn compile_and_run(mut fuel: usize) {
2024-10-10 12:01:12 -05:00
ALLOCATOR.reset();
2024-10-12 14:25:37 -05:00
_ = log::set_logger(&wasm_rt::Logger);
2024-10-12 06:07:49 -05:00
log::set_max_level(log::LevelFilter::Error);
2024-10-10 12:01:12 -05:00
struct File<'a> {
path: &'a str,
code: &'a mut str,
}
2024-10-10 12:01:12 -05:00
let mut root = 0;
2024-10-10 12:01:12 -05:00
let files = {
let mut input_bytes =
core::slice::from_raw_parts_mut(core::ptr::addr_of_mut!(INPUT).cast::<u8>(), INPUT_LEN);
let mut files = Vec::with_capacity(32);
while let Some((&mut path_len, rest)) = input_bytes.split_first_chunk_mut() {
let (path, rest) = rest.split_at_mut(u16::from_le_bytes(path_len) as usize);
let (&mut code_len, rest) = rest.split_first_chunk_mut().unwrap();
let (code, rest) = rest.split_at_mut(u16::from_le_bytes(code_len) as usize);
files.push(File {
path: core::str::from_utf8_unchecked(path),
code: core::str::from_utf8_unchecked_mut(code),
});
input_bytes = rest;
}
2024-10-12 06:07:49 -05:00
let root_path = files[root].path;
2024-10-12 06:07:49 -05:00
hblang::quad_sort(&mut files, |a, b| a.path.cmp(b.path));
root = files.binary_search_by_key(&root_path, |p| p.path).unwrap();
2024-10-10 12:01:12 -05:00
files
};
let mut ctx = CodegenCtx::default();
2024-10-10 12:01:12 -05:00
let files = {
let paths = files.iter().map(|f| f.path).collect::<Vec<_>>();
2024-10-13 08:22:16 -05:00
let mut loader = |path: &str, _: &str, kind| match kind {
2024-11-08 03:25:34 -06:00
hblang::parser::FileKind::Module => Ok(paths.binary_search(&path).unwrap()),
2024-10-13 08:22:16 -05:00
hblang::parser::FileKind::Embed => Err("embeds are not supported".into()),
};
2024-10-10 12:01:12 -05:00
files
.into_iter()
.map(|f| {
hblang::parser::Ast::new(
f.path,
// since 'free' does nothing this is fine
String::from_raw_parts(f.code.as_mut_ptr(), f.code.len(), f.code.len()),
&mut ctx.parser,
2024-10-10 12:01:12 -05:00
&mut loader,
)
})
.collect::<Vec<_>>()
};
2024-10-12 06:07:49 -05:00
let mut ct = {
let mut backend = HbvmBackend::default();
2024-11-08 03:25:34 -06:00
Codegen::new(&mut backend, &files, &mut ctx).generate(Module::new(root));
if !ctx.parser.errors.borrow().is_empty() {
log::error!("{}", ctx.parser.errors.borrow());
return;
}
let mut c = Codegen::new(&mut backend, &files, &mut ctx);
2024-10-12 06:07:49 -05:00
c.assemble_comptime()
2024-10-10 12:01:12 -05:00
};
2024-10-12 06:07:49 -05:00
while fuel != 0 {
match ct.vm.run() {
Ok(hbvm::VmRunOk::End) => {
2024-10-14 15:04:18 -05:00
log::error!("exit code: {}", ct.vm.read_reg(1).0 as i64);
2024-10-12 06:07:49 -05:00
break;
}
Ok(hbvm::VmRunOk::Ecall) => {
2024-11-23 04:14:03 -06:00
let kind = ct.vm.read_reg(2).0;
match kind {
0 => {
let str = ct.vm.read_reg(3).0;
let str = unsafe { CStr::from_ptr(str as _) };
log::error!("{}", str.to_str().unwrap());
}
unknown => log::error!("unknown ecall: {unknown}"),
}
2024-10-12 06:07:49 -05:00
}
2024-10-12 14:25:37 -05:00
Ok(hbvm::VmRunOk::Timer) => {
fuel -= 1;
if fuel == 0 {
log::error!("program timed out");
}
}
2024-10-12 06:07:49 -05:00
Ok(hbvm::VmRunOk::Breakpoint) => todo!(),
Err(e) => {
log::error!("vm error: {e}");
break;
}
}
}
2024-10-13 13:01:18 -05:00
//log::error!("memory consumption: {}b / {}b", ALLOCATOR.used(), ARENA_CAP);
}