From 0aec47e985eb52094203da6a6b35c96d11c03494 Mon Sep 17 00:00:00 2001 From: mlokr Date: Mon, 13 May 2024 09:38:33 +0200 Subject: [PATCH] fixing struct regurns --- hblang/examples/structs.hb | 7 +- hblang/src/codegen.rs | 83 +++++++++++++++---- hblang/src/main.rs | 6 +- hblang/src/parser.rs | 16 ++-- .../tests/hblang_codegen_tests_fb_driver.txt | 2 +- .../tests/hblang_codegen_tests_pointers.txt | 2 +- hblang/tests/hblang_codegen_tests_structs.txt | 2 +- tests/hblang_codegen_tests_arithmetic.txt | 0 tests/hblang_codegen_tests_example.txt | 0 tests/hblang_codegen_tests_functions.txt | 0 tests/hblang_codegen_tests_variables.txt | 0 11 files changed, 88 insertions(+), 30 deletions(-) create mode 100644 tests/hblang_codegen_tests_arithmetic.txt create mode 100644 tests/hblang_codegen_tests_example.txt create mode 100644 tests/hblang_codegen_tests_functions.txt create mode 100644 tests/hblang_codegen_tests_variables.txt diff --git a/hblang/examples/structs.hb b/hblang/examples/structs.hb index 29ef52f..d0aea8a 100644 --- a/hblang/examples/structs.hb +++ b/hblang/examples/structs.hb @@ -9,7 +9,8 @@ Ty2 := struct { } main := fn(): int { - inst := Ty2.{ ty: Ty.{ a: 4, b: 1 }, c: 3 }; + finst := Ty2.{ ty: Ty.{ a: 4, b: 1 }, c: 3 }; + inst := odher_pass(finst); if inst.c == 3 { return pass(&inst.ty); } @@ -19,3 +20,7 @@ main := fn(): int { pass := fn(t: *Ty): int { return t.a - t.b; } + +odher_pass := fn(t: Ty2): Ty2 { + return t; +} diff --git a/hblang/src/codegen.rs b/hblang/src/codegen.rs index 854ce97..026ae26 100644 --- a/hblang/src/codegen.rs +++ b/hblang/src/codegen.rs @@ -388,7 +388,7 @@ impl<'a> Codegen<'a> { let fn_label = self.labels[frame.label as usize].clone(); log::dbg!("fn-args"); - let mut parama = 2..12; + let mut parama = 3..12; for (arg, &ty) in args.iter().zip(fn_label.args.iter()) { let loc = self.load_arg(ty, &mut parama); self.vars.push(Variable { @@ -694,18 +694,50 @@ impl<'a> Codegen<'a> { } => { let func = self.get_label(*id); let fn_label = self.labels[func as usize].clone(); - let mut parama = 2..12; + let mut parama = 3..12; for (earg, &ty) in args.iter().zip(fn_label.args.iter()) { let arg = self.expr(earg, Some(ty))?; self.assert_ty(earg.pos(), ty, arg.ty); self.pass_arg(arg, &mut parama); } + + let size = self.size_of(fn_label.ret); + let loc = match size { + 0 => Loc::Imm(0), + 8 => Loc::RegRef(1), + 16 => { + let stack = self.alloc_stack(16); + Loc::Stack(stack) + } + 24..=u64::MAX => { + let stack = self.alloc_stack(size as u32); + let reg = self.gpa.allocate(); + self.code + .encode(instrs::addi64(reg.0, STACK_PTR, stack as u64)); + self.code.encode(instrs::cp(1, reg.0)); + self.gpa.free(reg); + Loc::Stack(stack) + } + s => todo!("call return size: {}", s), + }; + self.code.call(func); - let reg = self.gpa.allocate(); - self.code.encode(instrs::cp(reg.0, 1)); + + match size { + 0 => {} + 8 => {} + 16 => { + if let Loc::Stack(stack) = loc { + self.store_stack(1, stack, 16); + } + } + 24..=u64::MAX => {} + s => todo!("call return size: {}", s), + } + Some(Value { - ty: self.ret, - loc: Loc::Reg(reg), + ty: fn_label.ret, + loc, }) } E::Ident { name, id, .. } => { @@ -721,13 +753,27 @@ impl<'a> Codegen<'a> { if let Some(val) = val { let val = self.expr(val, Some(self.ret))?; self.assert_ty(pos, self.ret, val.ty); - self.assign( - Value { - ty: self.ret, - loc: Loc::RegRef(1), - }, - val, - ); + let size = self.size_of(val.ty); + match size { + 8 => { + let val = self.loc_to_reg(val.loc); + self.code.encode(instrs::cp(1, val.0)); + self.gpa.free(val); + } + 16 => { + let (ptr, off) = self.loc_to_ptr(val.loc); + self.code.encode(instrs::ld(1, ptr.0, off, 16)); + self.gpa.free(ptr); + } + 24..=u64::MAX => { + let (ptr, off) = self.loc_to_ptr(val.loc); + self.code.encode(instrs::addi64(ptr.0, ptr.0, off)); + self.code + .encode(instrs::bmc(ptr.0, 1, size.try_into().unwrap())); + self.gpa.free(ptr); + } + s => todo!("return size: {}", s), + }; } self.ret_relocs.push(RetReloc { offset: self.code.code.len() as u32, @@ -847,13 +893,15 @@ impl<'a> Codegen<'a> { None } E::BinOp { left, op, right } => { - let left = self.expr(left, expeted)?; - let right = self.expr(right, Some(left.ty))?; if op == T::Assign { + let left = self.expr(left, expeted)?; + let right = self.expr(right, Some(left.ty))?; return self.assign(left, right); } + let left = self.expr(left, expeted)?; let lhs = self.loc_to_reg(left.loc); + let right = self.expr(right, Some(left.ty))?; let rhs = self.loc_to_reg(right.loc); let op = match op { @@ -1062,6 +1110,7 @@ impl<'a> Codegen<'a> { todo!("expected stack location, got {:?}", value.loc); }; self.code.encode(instrs::addi64(p, STACK_PTR, stack)); + return; } match value.loc { @@ -1254,8 +1303,8 @@ mod tests { fn generate(input: &'static str, output: &mut String) { let path = "test"; let arena = crate::parser::Arena::default(); - let mut parser = super::parser::Parser::new(input, path, &arena); - let exprs = parser.file(); + let mut parser = super::parser::Parser::new(&arena); + let exprs = parser.file(input, path); let mut codegen = super::Codegen::default(); codegen.file(path, input.as_bytes(), &exprs); let mut out = Vec::new(); diff --git a/hblang/src/main.rs b/hblang/src/main.rs index 2e9fd70..26ba0dc 100644 --- a/hblang/src/main.rs +++ b/hblang/src/main.rs @@ -14,12 +14,12 @@ fn main() -> io::Result<()> { .skip(1) .map(|path| std::fs::read_to_string(&path).map(|src| (path, src))) .collect::>>()?; - let mut arena = parser::Arena::default(); + let arena = parser::Arena::default(); + let mut parser = parser::Parser::new(&arena); let mut codegen = codegen::Codegen::default(); for (path, content) in files.iter() { - let file = parser::Parser::new(content, path, &arena).file(); + let file = parser.file(&path, content.as_str()); codegen.file(path, content.as_bytes(), file); - arena.clear(); } codegen.dump(&mut std::io::stdout()) } diff --git a/hblang/src/parser.rs b/hblang/src/parser.rs index a12b11c..d0baa7a 100644 --- a/hblang/src/parser.rs +++ b/hblang/src/parser.rs @@ -23,19 +23,23 @@ pub struct Parser<'a, 'b> { } impl<'a, 'b> Parser<'a, 'b> { - pub fn new(input: &'a str, path: &'a str, arena: &'b Arena<'a>) -> Self { - let mut lexer = Lexer::new(input); + pub fn new(arena: &'b Arena<'a>) -> Self { + let mut lexer = Lexer::new(""); let token = lexer.next(); Self { lexer, token, - path, + path: "", arena, idents: Vec::new(), } } - pub fn file(&mut self) -> &'a [Expr<'a>] { + pub fn file(&mut self, input: &'a str, path: &'a str) -> &'a [Expr<'a>] { + self.path = path; + self.lexer = Lexer::new(input); + self.token = self.lexer.next(); + let f = self.collect(|s| (s.token.kind != TokenKind::Eof).then(|| s.expr())); self.pop_scope(0); let has_undeclared = !self.idents.is_empty(); @@ -717,8 +721,8 @@ mod tests { fn parse(input: &'static str, output: &mut String) { use std::fmt::Write; let mut arena = super::Arena::default(); - let mut parser = super::Parser::new(input, "test", &arena); - for expr in parser.file() { + let mut parser = super::Parser::new(&arena); + for expr in parser.file(input, "test") { writeln!(output, "{}", expr).unwrap(); } arena.clear(); diff --git a/hblang/tests/hblang_codegen_tests_fb_driver.txt b/hblang/tests/hblang_codegen_tests_fb_driver.txt index 97e8939..0846bb8 100644 --- a/hblang/tests/hblang_codegen_tests_fb_driver.txt +++ b/hblang/tests/hblang_codegen_tests_fb_driver.txt @@ -1,3 +1,3 @@ -code size: 1120 +code size: 1114 ret: 0 status: Ok(()) diff --git a/hblang/tests/hblang_codegen_tests_pointers.txt b/hblang/tests/hblang_codegen_tests_pointers.txt index 86e7655..b6c62e4 100644 --- a/hblang/tests/hblang_codegen_tests_pointers.txt +++ b/hblang/tests/hblang_codegen_tests_pointers.txt @@ -1,3 +1,3 @@ -code size: 342 +code size: 339 ret: 0 status: Ok(()) diff --git a/hblang/tests/hblang_codegen_tests_structs.txt b/hblang/tests/hblang_codegen_tests_structs.txt index 808624a..b559783 100644 --- a/hblang/tests/hblang_codegen_tests_structs.txt +++ b/hblang/tests/hblang_codegen_tests_structs.txt @@ -1,3 +1,3 @@ -code size: 470 +code size: 691 ret: 3 status: Ok(()) diff --git a/tests/hblang_codegen_tests_arithmetic.txt b/tests/hblang_codegen_tests_arithmetic.txt new file mode 100644 index 0000000..e69de29 diff --git a/tests/hblang_codegen_tests_example.txt b/tests/hblang_codegen_tests_example.txt new file mode 100644 index 0000000..e69de29 diff --git a/tests/hblang_codegen_tests_functions.txt b/tests/hblang_codegen_tests_functions.txt new file mode 100644 index 0000000..e69de29 diff --git a/tests/hblang_codegen_tests_variables.txt b/tests/hblang_codegen_tests_variables.txt new file mode 100644 index 0000000..e69de29