fixing small struct return
This commit is contained in:
parent
78ebc3292c
commit
e0d4955bd5
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
29
lang/tests/son_tests_returning_global_struct.txt
Normal file
29
lang/tests/son_tests_returning_global_struct.txt
Normal 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(())
|
|
@ -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(())
|
||||
|
|
Loading…
Reference in a new issue