fixing small struct return

This commit is contained in:
Jakub Doka 2024-10-24 13:25:30 +02:00
parent 78ebc3292c
commit e0d4955bd5
No known key found for this signature in database
GPG key ID: C6E9A89936B8C143
6 changed files with 137 additions and 67 deletions

View file

@ -527,6 +527,19 @@ main := fn(): int {
### Purely Testing Examples
#### returning_global_struct
```hb
Color := struct {r: u8, g: u8, b: u8, a: u8}
white := Color.(255, 255, 255, 255)
random_color := fn(): Color {
return white
}
main := fn(): int {
val := random_color()
return @as(int, val.r) + val.g + val.b + val.a
}
```
#### wide_ret
```hb
OemIdent := struct {

View file

@ -37,6 +37,7 @@ fn ensure_loaded(value: CtValue, derefed: bool, size: u32) -> u64 {
mod stack {
use {
super::{Offset, Size},
crate::debug,
alloc::vec::Vec,
core::num::NonZeroU32,
};
@ -81,17 +82,7 @@ mod stack {
impl Drop for Id {
fn drop(&mut self) {
let is_panicking = {
#[cfg(feature = "std")]
{
std::thread::panicking()
}
#[cfg(not(feature = "std"))]
{
false
}
};
if !is_panicking && !self.is_ref() {
if !debug::panicking() && !self.is_ref() {
unreachable!("stack id leaked: {:?}", self.0);
}
}
@ -163,7 +154,10 @@ mod stack {
}
mod rall {
use {crate::reg::*, alloc::vec::Vec};
use {
crate::{debug, reg::*},
alloc::vec::Vec,
};
type Reg = u8;
@ -208,17 +202,9 @@ mod rall {
#[cfg(all(debug_assertions, feature = "std"))]
impl Drop for Id {
fn drop(&mut self) {
let is_panicking = {
#[cfg(all(debug_assertions, feature = "std"))]
if !debug::panicking()
&& let Some(bt) = self.1.take()
{
std::thread::panicking()
}
#[cfg(not(all(debug_assertions, feature = "std")))]
{
false
}
};
if !is_panicking && let Some(bt) = self.1.take() {
unreachable!("reg id leaked: {:?} {bt}", self.0);
}
}

View file

@ -75,6 +75,34 @@ pub mod lexer;
#[cfg(feature = "opts")]
mod vc;
mod debug {
pub fn panicking() -> bool {
#[cfg(feature = "std")]
{
std::thread::panicking()
}
#[cfg(not(feature = "std"))]
{
false
}
}
#[cfg(all(debug_assertions, feature = "std"))]
pub type Trace = std::rc::Rc<std::backtrace::Backtrace>;
#[cfg(not(all(debug_assertions, feature = "std")))]
pub type Trace = ();
pub fn trace() -> Trace {
#[cfg(all(debug_assertions, feature = "std"))]
{
std::rc::Rc::new(std::backtrace::Backtrace::capture())
}
#[cfg(not(all(debug_assertions, feature = "std")))]
{}
}
}
pub mod reg {
pub const STACK_PTR: Reg = 254;
pub const ZERO: Reg = 0;
@ -252,7 +280,7 @@ mod ty {
parser::{self, Pos},
Size, Types,
},
core::{num::NonZeroU32, ops::Range, usize},
core::{num::NonZeroU32, ops::Range},
};
pub type ArrayLen = u32;
@ -1268,7 +1296,7 @@ impl Types {
})
.chain(self.ins.globals.iter().filter(|g| task::is_done(g.offset)).map(|g| {
let name = if g.file == u32::MAX {
core::str::from_utf8(&g.data).unwrap()
core::str::from_utf8(&g.data).unwrap_or("invalid utf-8")
} else {
let file = &files[g.file as usize];
file.ident_str(g.name)

View file

@ -2,6 +2,7 @@ use {
self::var::{Scope, Variable},
crate::{
ctx_map::CtxEntry,
debug,
ident::Ident,
instrs,
lexer::{self, TokenKind},
@ -23,6 +24,7 @@ use {
fmt::{self, Debug, Display, Write},
format_args as fa, mem,
ops::{self},
u16,
},
hashbrown::hash_map,
hbbytecode::DisasmError,
@ -49,7 +51,7 @@ impl StoreId for Nid {
}
impl crate::ctx_map::CtxEntry for Nid {
type Ctx = [Result<Node, (Nid, Trace)>];
type Ctx = [Result<Node, (Nid, debug::Trace)>];
type Key<'a> = (Kind, &'a [Nid], ty::Id);
fn key<'a>(&self, ctx: &'a Self::Ctx) -> Self::Key<'a> {
@ -57,23 +59,9 @@ impl crate::ctx_map::CtxEntry for Nid {
}
}
#[cfg(debug_assertions)]
type Trace = std::rc::Rc<std::backtrace::Backtrace>;
#[cfg(not(debug_assertions))]
type Trace = ();
fn trace() -> Trace {
#[cfg(debug_assertions)]
{
std::rc::Rc::new(std::backtrace::Backtrace::capture())
}
#[cfg(not(debug_assertions))]
{}
}
#[derive(Clone)]
struct Nodes {
values: Vec<Result<Node, (Nid, Trace)>>,
values: Vec<Result<Node, (Nid, debug::Trace)>>,
visited: BitSet,
free: Nid,
lookup: Lookup,
@ -165,6 +153,8 @@ impl Nodes {
}
fn graphviz_in_browser(&self, tys: &Types, files: &[parser::Ast]) {
#[cfg(all(debug_assertions, feature = "std"))]
{
let out = &mut String::new();
_ = self.graphviz_low(tys, files, out);
if !std::process::Command::new("brave")
@ -176,6 +166,7 @@ impl Nodes {
log::error!("{out}");
}
}
}
fn gcm(&mut self) {
self.visited.clear(self.values.len());
@ -188,11 +179,12 @@ impl Nodes {
fn remove_low(&mut self, id: Nid) -> Node {
if cfg!(debug_assertions) {
let value =
mem::replace(&mut self.values[id as usize], Err((self.free, trace()))).unwrap();
mem::replace(&mut self.values[id as usize], Err((self.free, debug::trace())))
.unwrap();
self.free = id;
value
} else {
mem::replace(&mut self.values[id as usize], Err((Nid::MAX, trace()))).unwrap()
mem::replace(&mut self.values[id as usize], Err((Nid::MAX, debug::trace()))).unwrap()
}
}
@ -240,7 +232,7 @@ impl Nodes {
if self.free == Nid::MAX {
self.free = self.values.len() as _;
self.values.push(Err((Nid::MAX, trace())));
self.values.push(Err((Nid::MAX, debug::trace())));
}
let free = self.free;
@ -1132,7 +1124,7 @@ struct Loop {
mod var {
use {
super::{Kind, Nid, Nodes},
crate::{ident::Ident, ty},
crate::{debug, ident::Ident, ty},
alloc::vec::Vec,
};
@ -1189,7 +1181,7 @@ mod var {
impl Drop for Variable {
fn drop(&mut self) {
if self.ty != ty::Id::UNDECLARED && !std::thread::panicking() {
if self.ty != ty::Id::UNDECLARED && !debug::panicking() {
panic!("variable unproperly deinitialized")
}
}
@ -1427,11 +1419,19 @@ impl ItemCtx {
self.emit(instrs::ld(r, atr(allocs[0]), 0, size))
}
Some(PLoc::Ref(_, size)) => {
self.emit(instrs::bmc(
atr(allocs[0]),
atr(allocs[1]),
size.try_into().expect("TODO: handle huge copies"),
));
let [src, dst] = [atr(allocs[0]), atr(allocs[1])];
if let Ok(size) = u16::try_from(size) {
self.emit(instrs::bmc(src, dst, size));
} else {
for _ in 0..size / u16::MAX as u32 {
self.emit(instrs::bmc(src, dst, u16::MAX));
self.emit(instrs::addi64(src, src, u16::MAX as _));
self.emit(instrs::addi64(dst, dst, u16::MAX as _));
}
self.emit(instrs::bmc(src, dst, size as u16));
self.emit(instrs::addi64(src, src, size.wrapping_neg() as _));
self.emit(instrs::addi64(dst, dst, size.wrapping_neg() as _));
}
}
}
@ -1522,6 +1522,12 @@ impl ItemCtx {
let stck = fuc.nodes[*node.inputs.last().unwrap()].offset;
self.emit(instrs::st(r, reg::STACK_PTR, stck as _, size));
}
if let Some(PLoc::Reg(r, size)) = ret
&& node.ty.loc(tys) == Loc::Stack
{
let stck = fuc.nodes[*node.inputs.last().unwrap()].offset;
self.emit(instrs::st(r, reg::STACK_PTR, stck as _, size));
}
}
Kind::Global { global } => {
let reloc = Reloc::new(self.code.len(), 3, 4);
@ -2523,8 +2529,7 @@ impl<'a> Codegen<'a> {
Expr::Directive { name: "as", args: [ty, expr], .. } => {
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);
let mut val = self.expr_ctx(expr, ctx)?;
self.assert_ty(expr.pos(), &mut val, ty, "hinted expr");
Some(val)
}
@ -3230,11 +3235,18 @@ impl<'a> Codegen<'a> {
// FIXME: could fuck us
ty::Id::UNDECLARED
} else {
debug_assert_eq!(
ty,
ty::Id::TYPE,
"TODO: we dont support anything except type generics"
if ty != ty::Id::TYPE {
self.report(
arg.pos(),
fa!(
"arbitrary comptime types are not supported yet \
(expected '{}' got '{}')",
self.ty_display(ty::Id::TYPE),
self.ty_display(ty)
),
);
return None;
}
let ty = self.ty(arg);
self.tys.tmp.args.push(ty);
ty
@ -4437,6 +4449,7 @@ mod tests {
fb_driver;
// Purely Testing Examples;
returning_global_struct;
wide_ret;
comptime_min_reg_leak;
different_types;

View file

@ -0,0 +1,29 @@
main:
ADDI64 r254, r254, -24d
ST r31, r254, 8a, 16h
ADDI64 r32, r254, 4d
JAL r31, r0, :random_color
ST r1, r254, 4a, 4h
ADDI64 r5, r254, 0d
BMC r32, r5, 4h
LD r4, r254, 3a, 1h
ANDI r6, r4, 255d
LD r3, r254, 2a, 1h
ANDI r5, r3, 255d
LD r2, r254, 1a, 1h
ANDI r4, r2, 255d
LD r2, r254, 0a, 1h
ANDI r7, r2, 255d
ADD64 r8, r4, r7
ADD64 r12, r8, r5
ADD64 r1, r12, r6
LD r31, r254, 8a, 16h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
random_color:
LRA r1, r0, :white
LD r1, r1, 0a, 4h
JALA r0, r31, 0a
code size: 257
ret: 1020
status: Ok(())

View file

@ -20,6 +20,7 @@ maina:
ST r31, r254, 32a, 16h
ADDI64 r32, r254, 28d
JAL r31, r0, :small_struct
ST r1, r254, 28a, 4h
LI64 r2, 1d
LI64 r4, 3d
LI64 r1, 0d
@ -51,6 +52,6 @@ small_struct:
LD r1, r3, 0a, 4h
ADDI64 r254, r254, 4d
JALA r0, r31, 0a
code size: 544
code size: 557
ret: 2
status: Ok(())