diff --git a/Cargo.lock b/Cargo.lock index 98e05393..7698ffcd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -194,6 +194,10 @@ dependencies = [ name = "hbbytecode" version = "0.1.0" +[[package]] +name = "hbjit" +version = "0.1.0" + [[package]] name = "hblang" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index dd22930f..539119e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,3 @@ [workspace] resolver = "2" -members = ["hbasm", "hbbytecode", "hbvm", "hbxrt", "xtask", "hblang"] +members = ["hbasm", "hbbytecode", "hbvm", "hbxrt", "xtask", "hblang", "hbjit"] diff --git a/hbjit/Cargo.toml b/hbjit/Cargo.toml new file mode 100644 index 00000000..884ff16b --- /dev/null +++ b/hbjit/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "hbjit" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/hbjit/src/main.rs b/hbjit/src/main.rs new file mode 100644 index 00000000..e7a11a96 --- /dev/null +++ b/hbjit/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/hblang/examples/global_variables.hb b/hblang/examples/global_variables.hb new file mode 100644 index 00000000..503d6641 --- /dev/null +++ b/hblang/examples/global_variables.hb @@ -0,0 +1,14 @@ +global_var := 10; + +complex_global_var := fib(global_var) - 5; + +fib := fn(n: int): int { + if n <= 2 { + return n; + } + return fib(n - 1) + fib(n - 2); +} + +main := fn(): int { + return complex_global_var; +} diff --git a/hblang/src/codegen.rs b/hblang/src/codegen.rs index cd7c463a..17bab6f2 100644 --- a/hblang/src/codegen.rs +++ b/hblang/src/codegen.rs @@ -3,6 +3,8 @@ use std::{ ops::Range, }; +use hbvm::Vm; + use crate::ident::{self, Ident}; use { @@ -483,10 +485,63 @@ struct Global { ty: Type, } +struct CompileMem { + code: *mut u8, + mem: Vec, +} + +impl Default for CompileMem { + fn default() -> Self { + Self { + code: std::ptr::null_mut(), + mem: Vec::new(), + } + } +} + +impl hbvm::mem::Memory for CompileMem { + unsafe fn load( + &mut self, + addr: hbvm::mem::Address, + target: *mut u8, + count: usize, + ) -> Result<(), hbvm::mem::LoadError> { + let sub = self + .mem + .get(addr.get() as usize..addr.get() as usize + count) + .ok_or(hbvm::mem::LoadError(addr))?; + + target.copy_from(sub.as_ptr(), count); + + Ok(()) + } + + unsafe fn store( + &mut self, + addr: hbvm::mem::Address, + source: *const u8, + count: usize, + ) -> Result<(), hbvm::mem::StoreError> { + self.mem + .get_mut(addr.get() as usize..addr.get() as usize + count) + .ok_or(hbvm::mem::StoreError(addr))? + .as_mut_ptr() + .copy_from(source, count); + + Ok(()) + } + + unsafe fn prog_read(&mut self, addr: hbvm::mem::Address) -> T { + debug_assert!(std::mem::align_of::() == 1); + *(self.code.add(addr.get() as usize) as *const T) + } +} + #[derive(Default)] pub struct Codegen<'a> { - path: &'a str, - input: &'a [u8], + path: &'a str, + input: &'a [u8], + ret: Type, gpa: Rc>, sa: Rc>, @@ -500,6 +555,8 @@ pub struct Codegen<'a> { pointers: Vec, globals: Vec, main: Option, + + vm: Vm, } impl<'a> Codegen<'a> { @@ -573,9 +630,9 @@ impl<'a> Codegen<'a> { self.gpa.borrow_mut().init_callee(); log::dbg!("fn-args"); - let mut parama = 3..12; + let mut parama = self.param_alloc(fn_label.ret); for (arg, &ty) in args.iter().zip(fn_label.args.iter()) { - let refed = arg.last.is_some_and(|l| l.get() & parser::REFERENCED != 0); + let refed = arg.last.map_or(0, Cell::get); let loc = self.load_arg(refed, ty, &mut parama); self.vars.push(Variable { id: arg.id, @@ -772,7 +829,9 @@ impl<'a> Codegen<'a> { args: [ret_ty, args @ ..], .. } => { - let mut parama = 3..12; + let ty = self.ty(ret_ty); + + let mut parama = self.param_alloc(ty); let mut values = Vec::with_capacity(args.len()); for arg in args { let arg = self.expr(arg)?; @@ -781,7 +840,6 @@ impl<'a> Codegen<'a> { } drop(values); - let ty = self.ty(ret_ty); let loc = self.alloc_ret_loc(ty, ctx); self.code.encode(i::eca()); @@ -1019,7 +1077,7 @@ impl<'a> Codegen<'a> { let func = self.get_label(*id); let fn_label = self.labels[func as usize].clone(); - let mut parama = 3..12; + let mut parama = self.param_alloc(fn_label.ret); let mut values = Vec::with_capacity(args.len()); for (earg, &ty) in args.iter().zip(fn_label.args.iter()) { let arg = self.expr_ctx(earg, Ctx::Inferred(ty))?; @@ -1137,6 +1195,7 @@ impl<'a> Codegen<'a> { } E::Loop { body, .. } => 'a: { log::dbg!("loop"); + let loop_start = self.code.code.len() as u32; self.loops.push(Loop { var_count: self.vars.len() as _, @@ -1715,11 +1774,11 @@ impl<'a> Codegen<'a> { } } - fn load_arg(&mut self, referenced: bool, ty: Type, parama: &mut Range) -> Loc { + fn load_arg(&mut self, flags: parser::IdentFlags, ty: Type, parama: &mut Range) -> Loc { let size = self.size_of(ty); match size { 0 => Loc::Imm(0), - ..=8 if !referenced => { + ..=8 if flags & parser::REFERENCED == 0 => { let reg = self.alloc_reg(); self.code.encode(instrs::cp(reg.0, parama.next().unwrap())); Loc::Reg(reg) @@ -1735,7 +1794,13 @@ impl<'a> Codegen<'a> { parama.next().unwrap(); Loc::Stack(stack, 0) } - ..=u64::MAX => { + _ if flags & (parser::MUTABLE | parser::REFERENCED) == 0 => { + let ptr = parama.next().unwrap(); + let reg = self.alloc_reg(); + self.code.encode(instrs::cp(reg.0, ptr)); + Loc::Deref(reg, None, 0) + } + _ => { let ptr = parama.next().unwrap(); let stack = self.alloc_stack(size); self.assign( @@ -1802,6 +1867,10 @@ impl<'a> Codegen<'a> { ..=u64::MAX => {} } } + + fn param_alloc(&self, ret: Type) -> Range { + 2 + (9..=16).contains(&self.size_of(ret)) as u8..12 + } } #[derive(Debug)] @@ -1986,5 +2055,6 @@ mod tests { different_types => include_str!("../examples/different_types.hb"); struct_operators => include_str!("../examples/struct_operators.hb"); directives => include_str!("../examples/directives.hb"); + global_variables => include_str!("../examples/global_variables.hb"); } } diff --git a/hblang/src/parser.rs b/hblang/src/parser.rs index f3f6a072..b3e5aac9 100644 --- a/hblang/src/parser.rs +++ b/hblang/src/parser.rs @@ -51,7 +51,7 @@ impl<'a, 'b> Parser<'a, 'b> { self.lexer = Lexer::new(input); self.token = self.lexer.next(); - let f = self.collect(|s| (s.token.kind != TokenKind::Eof).then(|| s.expr())); + let f = self.collect_list(TokenKind::Semi, TokenKind::Eof, Self::expr); self.pop_scope(0); let has_undeclared = !self.idents.is_empty(); for id in self.idents.drain(..) { diff --git a/hblang/tests/codegen_tests_structs.txt b/hblang/tests/codegen_tests_structs.txt index e81084ab..00a0fbe4 100644 --- a/hblang/tests/codegen_tests_structs.txt +++ b/hblang/tests/codegen_tests_structs.txt @@ -1,3 +1,3 @@ -code size: 483 +code size: 461 ret: 3 status: Ok(()) diff --git a/hbvm/src/lib.rs b/hbvm/src/lib.rs index 33a9fe2d..565fc728 100644 --- a/hbvm/src/lib.rs +++ b/hbvm/src/lib.rs @@ -54,6 +54,18 @@ pub struct Vm { copier: Option, } +impl Default for Vm { + fn default() -> Self { + Self { + registers: [Value::from(0_u64); 256], + memory: Mem::default(), + pc: Address::default(), + timer: 0, + copier: None, + } + } +} + impl Vm where Mem: Memory, diff --git a/hbvm/src/mem/addr.rs b/hbvm/src/mem/addr.rs index d994a070..4a4ac8ed 100644 --- a/hbvm/src/mem/addr.rs +++ b/hbvm/src/mem/addr.rs @@ -6,7 +6,7 @@ use { }; /// Memory address -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub struct Address(u64); impl Address { /// A null address