From bba3570788c487489a3632bc68f29c37dcb17a85 Mon Sep 17 00:00:00 2001 From: mlokr Date: Tue, 17 Sep 2024 15:47:23 +0200 Subject: [PATCH] adding wide return move for wider range of cases --- hblang/README.md | 13 +++++++++ hblang/src/codegen.rs | 36 +++++++++++++++++++------ hblang/tests/codegen_tests_wide_ret.txt | 0 3 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 hblang/tests/codegen_tests_wide_ret.txt diff --git a/hblang/README.md b/hblang/README.md index d58e63f..af15fe3 100644 --- a/hblang/README.md +++ b/hblang/README.md @@ -356,6 +356,19 @@ main := fn(): int { } ``` +#### wide_ret +```hb +OemIdent := struct { + dos_version: [u8; 8], + dos_version_name: [u8; 8], +} + +main := fn(major: int, minor: int): OemIdent { + ver := [u8].(0, 0, 0, 0, 0, 0, 0, 0) + return OemIdent.(ver, ver) +} +``` + ### Incomplete Examples #### comptime_pointers diff --git a/hblang/src/codegen.rs b/hblang/src/codegen.rs index 48d768c..2f4a8ec 100644 --- a/hblang/src/codegen.rs +++ b/hblang/src/codegen.rs @@ -1375,11 +1375,11 @@ impl Codegen { Some(self.ci.inline_ret_loc.as_ref()) } 0 => None, - 1..=8 => Some(Loc::reg(1)), - 9..=16 => None, + 1..=16 => Some(Loc::reg(1)), + //9..=16 => None, _ => Some(Loc::reg(self.ci.ret_reg.as_ref()).into_derefed()), }; - let loc_is_none = loc.is_none(); + //let loc_is_none = loc.is_none(); let value = if let Some(val) = val { self.expr_ctx(val, Ctx { ty: self.ci.ret, loc })? } else { @@ -1391,11 +1391,11 @@ impl Codegen { Some(ret) => _ = self.assert_ty(pos, value.ty, ret, "return type"), } - if let 9..=16 = size - && loc_is_none - { - self.store_sized(value.loc, Loc::reg(1), size); - } + //if let 9..=16 = size + // && loc_is_none + //{ + // self.store_sized(value.loc, Loc::reg(1), size); + //} self.ci.ret_relocs.push(Reloc::new(self.ci.code.len(), 1, 4)); self.ci.emit(jmp(0)); @@ -2286,6 +2286,25 @@ impl Codegen { self.ci.emit(cp(dst.get(), src.get())); } } + (lpat!(false, src, 0, None), lpat!(false, dst, off, None)) => { + assert!(size <= 8); + let off_rem = 8 * (off % 8); + let freg = dst.get() + (off / 8) as u8; + if size < 8 { + let mask = !(((1u64 << (8 * size)) - 1) << off_rem); + self.ci.emit(andi(freg, freg, mask)); + if off_rem == 0 { + self.ci.emit(or(freg, freg, src.get())); + } else { + let tmp = self.ci.regs.allocate(); + self.ci.emit(slui64(tmp.get(), src.get(), off_rem as _)); + self.ci.emit(or(freg, freg, src.get())); + self.ci.regs.free(tmp); + } + } else { + self.ci.emit(cp(freg, src.get())); + } + } (lpat!(true, src, soff, ref ssta), lpat!(false, dst, 0, None)) => { if size < 8 { self.ci.emit(cp(dst.get(), 0)); @@ -2748,5 +2767,6 @@ mod tests { writing_into_string => README; request_page => README; tests_ptr_to_ptr_copy => README; + wide_ret => README; } } diff --git a/hblang/tests/codegen_tests_wide_ret.txt b/hblang/tests/codegen_tests_wide_ret.txt new file mode 100644 index 0000000..e69de29