diff --git a/lang/README.md b/lang/README.md index 3328a231..0f92d7a3 100644 --- a/lang/README.md +++ b/lang/README.md @@ -273,7 +273,7 @@ main := fn(): int { align_of_Type_in_bytes := @alignof(foo.Type) hardcoded_pointer := @as(^u8, @bitcast(10)) ecall_that_returns_int := @as(int, @eca(1, foo.Type.(10, 20), 5, 6)) - embedded_array := @as(^[u8; 15], @embed("text.txt")) + embedded_array := @as([u8; 15], @embed("text.txt")) return @inline(foo.foo) } diff --git a/lang/src/son.rs b/lang/src/son.rs index d56b0fcb..cdeefb67 100644 --- a/lang/src/son.rs +++ b/lang/src/son.rs @@ -22,7 +22,6 @@ use { fmt::{self, Debug, Display, Write}, format_args as fa, mem, ops::{self}, - usize, }, hashbrown::hash_map, regalloc2::VReg, @@ -262,13 +261,6 @@ impl Nodes { changed = true; } - if let K::CInt { value } = self[lhs].kind - && op == T::Sub - { - let lhs = self.new_node_nop(ty, K::CInt { value: -value }, [ctrl]); - return Some(self.new_node(ty, K::BinOp { op: T::Add }, [ctrl, rhs, lhs])); - } - if let K::CInt { value } = self[rhs].kind { match (op, value) { (T::Add | T::Sub | T::Shl, 0) | (T::Mul | T::Div, 1) => return Some(lhs), @@ -1252,18 +1244,17 @@ impl ItemCtx { } } Kind::Call { argc, func } => { - std::dbg!(node.ty.simple_size()); let (ret, mut parama) = tys.parama(node.ty); - debug_assert_eq!( - allocs.len(), - argc as usize - + !matches!(ret, PLoc::Reg(..) | PLoc::None) as usize - + !matches!(ret, PLoc::None) as usize - ); - for (&i, &arg) in node.inputs[1..][..argc as usize].iter().zip(&allocs[1..]) - { + let has_ret = !matches!(ret, PLoc::None) as usize; + let mut iter = allocs[has_ret..].iter(); + for &i in node.inputs[1..][..argc as usize].iter() { let ty = fuc.nodes[i].ty; - let (rg, size) = match parama.next(ty, tys) { + let loc = parama.next(ty, tys); + if let PLoc::None = loc { + continue; + } + let &arg = iter.next().unwrap(); + let (rg, size) = match loc { PLoc::Reg(rg, size) if ty.loc(tys) == Loc::Stack => (rg, size), PLoc::WideReg(rg, size) => (rg, size), PLoc::None | PLoc::Ref(..) | PLoc::Reg(..) => continue, @@ -1271,6 +1262,8 @@ impl ItemCtx { self.emit(instrs::ld(rg, atr(arg), 0, size)); } + debug_assert!(!matches!(ret, PLoc::Ref(..)) || iter.next().is_some()); + if func == ty::ECA { self.emit(instrs::eca()); } else { @@ -1588,9 +1581,63 @@ impl TypeParser for Codegen<'_> { &mut self.tys } - #[expect(unused)] - fn eval_const(&mut self, file: FileId, expr: &Expr, ty: ty::Id) -> u64 { - todo!() + fn eval_const(&mut self, file: FileId, expr: &Expr, ret: ty::Id) -> u64 { + self.pool.push_ci(file, Some(ret), self.tasks.len(), &mut self.ci); + + let prev_err_len = self.errors.borrow().len(); + + self.expr(&Expr::Return { pos: expr.pos(), val: Some(expr) }); + + self.ci.finalize(); + + 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: 0, + expr: ExprRef::new(expr), + relocs: core::mem::take(&mut self.ci.relocs), + code: core::mem::take(&mut self.ci.code), + ..Default::default() + }; + + self.pool.pop_ci(&mut self.ci); + self.complete_call_graph(); + + // 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); + } + } + + 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); + 1 + } } fn infer_type(&mut self, expr: &Expr) -> ty::Id { @@ -2022,8 +2069,8 @@ impl<'a> Codegen<'a> { } Expr::Embed { id, .. } => { let glob = &self.tys.ins.globals[id as usize]; - let ty = self.tys.make_ptr(glob.ty); - Some(self.ci.nodes.new_node_lit(ty, Kind::Global { global: id }, [VOID])) + let g = self.ci.nodes.new_node(glob.ty, Kind::Global { global: id }, [VOID]); + Some(Value::ptr(g).ty(glob.ty)) } Expr::Directive { name: "sizeof", args: [ty], .. } => { let ty = self.ty(ty); @@ -2110,8 +2157,12 @@ impl<'a> Codegen<'a> { Some(self.ci.nodes.new_node_lit(ty, Kind::BinOp { op: TokenKind::Band }, inps)) } Expr::Directive { name: "as", args: [ty, expr], .. } => { - let ctx = Ctx::default().with_ty(self.ty(ty)); - self.raw_expr_ctx(expr, ctx) + let ty = self.ty(ty); + let ctx = Ctx::default().with_ty(ty); + let mut val = self.raw_expr_ctx(expr, ctx)?; + self.strip_var(&mut val); + self.assert_ty(expr.pos(), &mut val, ty, "hited expr"); + Some(val) } Expr::Directive { pos, name: "eca", args } => { let Some(ty) = ctx.ty else { @@ -3720,6 +3771,7 @@ mod tests { fn generate(ident: &'static str, input: &'static str, output: &mut String) { _ = log::set_logger(&crate::fs::Logger); log::set_max_level(log::LevelFilter::Info); + // log::set_max_level(log::LevelFilter::Trace); let (ref files, embeds) = crate::test_parse_files(ident, input); let mut codegen = super::Codegen { files, ..Default::default() }; @@ -3778,17 +3830,17 @@ mod tests { wide_ret; comptime_min_reg_leak; different_types; - //struct_return_from_module_function; + struct_return_from_module_function; sort_something_viredly; - //structs_in_registers; + structs_in_registers; comptime_function_from_another_file; inline_test; //inlined_generic_functions; //some_generic_code; - //integer_inference_issues; + integer_inference_issues; writing_into_string; - //request_page; - //tests_ptr_to_ptr_copy; + request_page; + tests_ptr_to_ptr_copy; // Just Testing Optimizations; const_folding_with_arg; diff --git a/lang/tests/son_tests_directives.txt b/lang/tests/son_tests_directives.txt index e69de29b..517c362f 100644 --- a/lang/tests/son_tests_directives.txt +++ b/lang/tests/son_tests_directives.txt @@ -0,0 +1,19 @@ +main: + ADDI64 r254, r254, -16d + LI64 r5, 5d + LI64 r7, 20d + LI64 r2, 1d + LI64 r4, 10d + LI64 r6, 6d + ADDI64 r8, r254, 0d + ST r4, r254, 0a, 8h + ST r7, r254, 8a, 8h + LD r3, r8, 0a, 16h + ECA + LI64 r1, 0d + ADDI64 r254, r254, 16d + JALA r0, r31, 0a +ev: Ecall +code size: 152 +ret: 0 +status: Ok(()) diff --git a/lang/tests/son_tests_inline_test.txt b/lang/tests/son_tests_inline_test.txt index 1220e09b..9e7159e1 100644 --- a/lang/tests/son_tests_inline_test.txt +++ b/lang/tests/son_tests_inline_test.txt @@ -30,13 +30,13 @@ line: JMP :0 0: JALA r0, r31, 0a main: - ADDI64 r254, r254, -112d - ST r31, r254, 96a, 16h + ADDI64 r254, r254, -160d + ST r31, r254, 96a, 64h LI64 r32, 10d LI64 r1, 0d - ADDI64 r7, r254, 48d - ADDI64 r5, r254, 64d - ADDI64 r3, r254, 80d + ADDI64 r33, r254, 48d + ADDI64 r34, r254, 64d + ADDI64 r35, r254, 80d ST r1, r254, 80a, 8h ST r1, r254, 88a, 8h ST r1, r254, 64a, 8h @@ -44,16 +44,13 @@ main: ST r1, r254, 48a, 8h ST r1, r254, 56a, 8h CP r8, r32 - CP r2, r3 - CP r4, r5 - CP r6, r7 - LD r2, r2, 0a, 16h - LD r4, r4, 0a, 16h - LD r6, r6, 0a, 16h + LD r2, r35, 0a, 16h + LD r4, r34, 0a, 16h + LD r6, r33, 0a, 16h JAL r31, r0, :line - ADDI64 r7, r254, 0d - ADDI64 r5, r254, 16d - ADDI64 r3, r254, 32d + ADDI64 r36, r254, 0d + ADDI64 r37, r254, 16d + ADDI64 r38, r254, 32d ST r1, r254, 32a, 8h ST r1, r254, 40a, 8h ST r1, r254, 16a, 8h @@ -61,16 +58,13 @@ main: ST r1, r254, 0a, 8h ST r1, r254, 8a, 8h CP r8, r32 - CP r2, r3 - CP r4, r5 - CP r6, r7 - LD r2, r2, 0a, 16h - LD r4, r4, 0a, 16h - LD r6, r6, 0a, 16h + LD r2, r38, 0a, 16h + LD r4, r37, 0a, 16h + LD r6, r36, 0a, 16h JAL r31, r0, :rect_line JAL r31, r0, :example - LD r31, r254, 96a, 16h - ADDI64 r254, r254, 112d + LD r31, r254, 96a, 64h + ADDI64 r254, r254, 160d JALA r0, r31, 0a rect_line: ST r2, r254, 0a, 16h @@ -92,6 +86,6 @@ rect_line: 2: ADDI64 r9, r9, 1d JMP :4 1: JALA r0, r31, 0a -code size: 875 +code size: 857 ret: 4 status: Ok(()) diff --git a/lang/tests/son_tests_integer_inference_issues.txt b/lang/tests/son_tests_integer_inference_issues.txt new file mode 100644 index 00000000..e5abe29a --- /dev/null +++ b/lang/tests/son_tests_integer_inference_issues.txt @@ -0,0 +1,29 @@ +integer_range: + ADDI64 r254, r254, -16d + ST r31, r254, 0a, 16h + CP r32, r2 + CP r33, r3 + LI64 r3, 4d + LI64 r2, 3d + ECA + CP r2, r32 + CP r3, r33 + SUB64 r11, r3, r2 + ADDI64 r3, r11, 1d + DIRU64 r0, r3, r1, r3 + ADD64 r1, r3, r2 + LD r31, r254, 0a, 16h + ADDI64 r254, r254, 16d + JALA r0, r31, 0a +main: + ADDI64 r254, r254, -8d + ST r31, r254, 0a, 8h + LI64 r3, 1000d + LI64 r2, 0d + JAL r31, r0, :integer_range + LD r31, r254, 0a, 8h + ADDI64 r254, r254, 8d + JALA r0, r31, 0a +code size: 210 +ret: 42 +status: Ok(()) diff --git a/lang/tests/son_tests_pointer_opts.txt b/lang/tests/son_tests_pointer_opts.txt index a4785962..d3454775 100644 --- a/lang/tests/son_tests_pointer_opts.txt +++ b/lang/tests/son_tests_pointer_opts.txt @@ -3,17 +3,18 @@ clobber: ST r3, r2, 0a, 8h JALA r0, r31, 0a main: - ADDI64 r254, r254, -32d - ST r31, r254, 8a, 24h + ADDI64 r254, r254, -40d + ST r31, r254, 8a, 32h LI64 r32, 2d ADDI64 r2, r254, 0d ST r32, r254, 0a, 8h JAL r31, r0, :clobber - LD r33, r254, 0a, 8h - ADDI64 r1, r33, -4d - LD r31, r254, 8a, 24h - ADDI64 r254, r254, 32d + LI64 r33, 4d + LD r34, r254, 0a, 8h + SUB64 r1, r33, r34 + LD r31, r254, 8a, 32h + ADDI64 r254, r254, 40d JALA r0, r31, 0a -code size: 166 +code size: 169 ret: 0 status: Ok(()) diff --git a/lang/tests/son_tests_request_page.txt b/lang/tests/son_tests_request_page.txt new file mode 100644 index 00000000..e69de29b diff --git a/lang/tests/son_tests_struct_return_from_module_function.txt b/lang/tests/son_tests_struct_return_from_module_function.txt index e69de29b..fedb7752 100644 --- a/lang/tests/son_tests_struct_return_from_module_function.txt +++ b/lang/tests/son_tests_struct_return_from_module_function.txt @@ -0,0 +1,38 @@ +foo: + ADDI64 r254, r254, -16d + LI64 r3, 2d + LI64 r5, 3d + ADDI64 r4, r254, 0d + ST r5, r254, 0a, 8h + ST r3, r254, 8a, 4h + ST r3, r254, 12a, 4h + LD r1, r4, 0a, 16h + ADDI64 r254, r254, 16d + JALA r0, r31, 0a +main: + ADDI64 r254, r254, -144d + ST r31, r254, 48a, 96h + ADDI64 r32, r254, 32d + JAL r31, r0, :foo + ST r1, r254, 32a, 16h + ADDI64 r33, r254, 16d + LD r34, r254, 32a, 8h + JAL r31, r0, :foo + ST r1, r254, 16a, 16h + ADDI64 r35, r254, 0d + LD r36, r254, 24a, 4h + JAL r31, r0, :foo + ST r1, r254, 0a, 16h + LI64 r37, 7d + LD r38, r254, 12a, 4h + ANDI r39, r38, 4294967295d + ANDI r40, r36, 4294967295d + ADD64 r41, r34, r40 + ADD64 r42, r41, r39 + SUB64 r1, r37, r42 + LD r31, r254, 48a, 96h + ADDI64 r254, r254, 144d + JALA r0, r31, 0a +code size: 359 +ret: 0 +status: Ok(()) diff --git a/lang/tests/son_tests_structs_in_registers.txt b/lang/tests/son_tests_structs_in_registers.txt new file mode 100644 index 00000000..3b6345d4 --- /dev/null +++ b/lang/tests/son_tests_structs_in_registers.txt @@ -0,0 +1,8 @@ +main: + LRA r1, r0, :MAGENTA + LD r3, r1, 2a, 1h + ANDI r1, r3, 255d + JALA r0, r31, 0a +code size: 54 +ret: 205 +status: Ok(()) diff --git a/lang/tests/son_tests_tests_ptr_to_ptr_copy.txt b/lang/tests/son_tests_tests_ptr_to_ptr_copy.txt new file mode 100644 index 00000000..798c58cc --- /dev/null +++ b/lang/tests/son_tests_tests_ptr_to_ptr_copy.txt @@ -0,0 +1,30 @@ +main: + ADDI64 r254, r254, -10240d + LI64 r7, 64d + LI64 r5, 1024d + LI64 r9, 1d + LI64 r8, 0d + ADDI64 r6, r254, 0d + 4: JLTU r8, r5, :0 + LI64 r7, 10d + CP r8, r9 + 3: JLTU r8, r7, :1 + LD r9, r254, 2048a, 1h + ANDI r1, r9, 255d + JMP :2 + 1: ADD64 r3, r8, r9 + MUL64 r2, r8, r5 + ADD64 r4, r2, r6 + BMC r6, r4, 1024h + CP r8, r3 + JMP :3 + 0: ADD64 r2, r8, r9 + ADD64 r12, r8, r6 + ST r7, r12, 0a, 1h + CP r8, r2 + JMP :4 + 2: ADDI64 r254, r254, 10240d + JALA r0, r31, 0a +code size: 198 +ret: 64 +status: Ok(())