forked from AbleOS/holey-bytes
making better use of parameter and return registers (use register 2 for arguments when possible)
This commit is contained in:
parent
4502a64514
commit
aae217dd00
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -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"
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
[workspace]
|
||||
resolver = "2"
|
||||
members = ["hbasm", "hbbytecode", "hbvm", "hbxrt", "xtask", "hblang"]
|
||||
members = ["hbasm", "hbbytecode", "hbvm", "hbxrt", "xtask", "hblang", "hbjit"]
|
||||
|
|
6
hbjit/Cargo.toml
Normal file
6
hbjit/Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "hbjit"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
3
hbjit/src/main.rs
Normal file
3
hbjit/src/main.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
14
hblang/examples/global_variables.hb
Normal file
14
hblang/examples/global_variables.hb
Normal file
|
@ -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;
|
||||
}
|
|
@ -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<u8>,
|
||||
}
|
||||
|
||||
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<T: Copy>(&mut self, addr: hbvm::mem::Address) -> T {
|
||||
debug_assert!(std::mem::align_of::<T>() == 1);
|
||||
*(self.code.add(addr.get() as usize) as *const T)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Codegen<'a> {
|
||||
path: &'a str,
|
||||
input: &'a [u8],
|
||||
|
||||
ret: Type,
|
||||
gpa: Rc<RefCell<RegAlloc>>,
|
||||
sa: Rc<RefCell<StackAlloc>>,
|
||||
|
@ -500,6 +555,8 @@ pub struct Codegen<'a> {
|
|||
pointers: Vec<Type>,
|
||||
globals: Vec<Global>,
|
||||
main: Option<LabelId>,
|
||||
|
||||
vm: Vm<CompileMem, 0>,
|
||||
}
|
||||
|
||||
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<u8>) -> Loc {
|
||||
fn load_arg(&mut self, flags: parser::IdentFlags, ty: Type, parama: &mut Range<u8>) -> 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<u8> {
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(..) {
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
code size: 483
|
||||
code size: 461
|
||||
ret: 3
|
||||
status: Ok(())
|
||||
|
|
|
@ -54,6 +54,18 @@ pub struct Vm<Mem, const TIMER_QUOTIENT: usize> {
|
|||
copier: Option<BlockCopier>,
|
||||
}
|
||||
|
||||
impl<Mem: Default, const TIMER_QUOTIENT: usize> Default for Vm<Mem, TIMER_QUOTIENT> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
registers: [Value::from(0_u64); 256],
|
||||
memory: Mem::default(),
|
||||
pc: Address::default(),
|
||||
timer: 0,
|
||||
copier: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Mem, const TIMER_QUOTIENT: usize> Vm<Mem, TIMER_QUOTIENT>
|
||||
where
|
||||
Mem: Memory,
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue