fixing small struct return
This commit is contained in:
parent
78ebc3292c
commit
e0d4955bd5
|
@ -527,6 +527,19 @@ main := fn(): int {
|
||||||
|
|
||||||
### Purely Testing Examples
|
### 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
|
#### wide_ret
|
||||||
```hb
|
```hb
|
||||||
OemIdent := struct {
|
OemIdent := struct {
|
||||||
|
|
|
@ -37,6 +37,7 @@ fn ensure_loaded(value: CtValue, derefed: bool, size: u32) -> u64 {
|
||||||
mod stack {
|
mod stack {
|
||||||
use {
|
use {
|
||||||
super::{Offset, Size},
|
super::{Offset, Size},
|
||||||
|
crate::debug,
|
||||||
alloc::vec::Vec,
|
alloc::vec::Vec,
|
||||||
core::num::NonZeroU32,
|
core::num::NonZeroU32,
|
||||||
};
|
};
|
||||||
|
@ -81,17 +82,7 @@ mod stack {
|
||||||
|
|
||||||
impl Drop for Id {
|
impl Drop for Id {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let is_panicking = {
|
if !debug::panicking() && !self.is_ref() {
|
||||||
#[cfg(feature = "std")]
|
|
||||||
{
|
|
||||||
std::thread::panicking()
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "std"))]
|
|
||||||
{
|
|
||||||
false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if !is_panicking && !self.is_ref() {
|
|
||||||
unreachable!("stack id leaked: {:?}", self.0);
|
unreachable!("stack id leaked: {:?}", self.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,7 +154,10 @@ mod stack {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod rall {
|
mod rall {
|
||||||
use {crate::reg::*, alloc::vec::Vec};
|
use {
|
||||||
|
crate::{debug, reg::*},
|
||||||
|
alloc::vec::Vec,
|
||||||
|
};
|
||||||
|
|
||||||
type Reg = u8;
|
type Reg = u8;
|
||||||
|
|
||||||
|
@ -208,17 +202,9 @@ mod rall {
|
||||||
#[cfg(all(debug_assertions, feature = "std"))]
|
#[cfg(all(debug_assertions, feature = "std"))]
|
||||||
impl Drop for Id {
|
impl Drop for Id {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let is_panicking = {
|
if !debug::panicking()
|
||||||
#[cfg(all(debug_assertions, feature = "std"))]
|
&& 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);
|
unreachable!("reg id leaked: {:?} {bt}", self.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,34 @@ pub mod lexer;
|
||||||
#[cfg(feature = "opts")]
|
#[cfg(feature = "opts")]
|
||||||
mod vc;
|
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 mod reg {
|
||||||
pub const STACK_PTR: Reg = 254;
|
pub const STACK_PTR: Reg = 254;
|
||||||
pub const ZERO: Reg = 0;
|
pub const ZERO: Reg = 0;
|
||||||
|
@ -252,7 +280,7 @@ mod ty {
|
||||||
parser::{self, Pos},
|
parser::{self, Pos},
|
||||||
Size, Types,
|
Size, Types,
|
||||||
},
|
},
|
||||||
core::{num::NonZeroU32, ops::Range, usize},
|
core::{num::NonZeroU32, ops::Range},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type ArrayLen = u32;
|
pub type ArrayLen = u32;
|
||||||
|
@ -1268,7 +1296,7 @@ impl Types {
|
||||||
})
|
})
|
||||||
.chain(self.ins.globals.iter().filter(|g| task::is_done(g.offset)).map(|g| {
|
.chain(self.ins.globals.iter().filter(|g| task::is_done(g.offset)).map(|g| {
|
||||||
let name = if g.file == u32::MAX {
|
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 {
|
} else {
|
||||||
let file = &files[g.file as usize];
|
let file = &files[g.file as usize];
|
||||||
file.ident_str(g.name)
|
file.ident_str(g.name)
|
||||||
|
|
|
@ -2,6 +2,7 @@ use {
|
||||||
self::var::{Scope, Variable},
|
self::var::{Scope, Variable},
|
||||||
crate::{
|
crate::{
|
||||||
ctx_map::CtxEntry,
|
ctx_map::CtxEntry,
|
||||||
|
debug,
|
||||||
ident::Ident,
|
ident::Ident,
|
||||||
instrs,
|
instrs,
|
||||||
lexer::{self, TokenKind},
|
lexer::{self, TokenKind},
|
||||||
|
@ -23,6 +24,7 @@ use {
|
||||||
fmt::{self, Debug, Display, Write},
|
fmt::{self, Debug, Display, Write},
|
||||||
format_args as fa, mem,
|
format_args as fa, mem,
|
||||||
ops::{self},
|
ops::{self},
|
||||||
|
u16,
|
||||||
},
|
},
|
||||||
hashbrown::hash_map,
|
hashbrown::hash_map,
|
||||||
hbbytecode::DisasmError,
|
hbbytecode::DisasmError,
|
||||||
|
@ -49,7 +51,7 @@ impl StoreId for Nid {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::ctx_map::CtxEntry 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);
|
type Key<'a> = (Kind, &'a [Nid], ty::Id);
|
||||||
|
|
||||||
fn key<'a>(&self, ctx: &'a Self::Ctx) -> Self::Key<'a> {
|
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)]
|
#[derive(Clone)]
|
||||||
struct Nodes {
|
struct Nodes {
|
||||||
values: Vec<Result<Node, (Nid, Trace)>>,
|
values: Vec<Result<Node, (Nid, debug::Trace)>>,
|
||||||
visited: BitSet,
|
visited: BitSet,
|
||||||
free: Nid,
|
free: Nid,
|
||||||
lookup: Lookup,
|
lookup: Lookup,
|
||||||
|
@ -165,15 +153,18 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn graphviz_in_browser(&self, tys: &Types, files: &[parser::Ast]) {
|
fn graphviz_in_browser(&self, tys: &Types, files: &[parser::Ast]) {
|
||||||
let out = &mut String::new();
|
#[cfg(all(debug_assertions, feature = "std"))]
|
||||||
_ = self.graphviz_low(tys, files, out);
|
|
||||||
if !std::process::Command::new("brave")
|
|
||||||
.arg(format!("https://dreampuf.github.io/GraphvizOnline/#{out}"))
|
|
||||||
.status()
|
|
||||||
.unwrap()
|
|
||||||
.success()
|
|
||||||
{
|
{
|
||||||
log::error!("{out}");
|
let out = &mut String::new();
|
||||||
|
_ = self.graphviz_low(tys, files, out);
|
||||||
|
if !std::process::Command::new("brave")
|
||||||
|
.arg(format!("https://dreampuf.github.io/GraphvizOnline/#{out}"))
|
||||||
|
.status()
|
||||||
|
.unwrap()
|
||||||
|
.success()
|
||||||
|
{
|
||||||
|
log::error!("{out}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,11 +179,12 @@ impl Nodes {
|
||||||
fn remove_low(&mut self, id: Nid) -> Node {
|
fn remove_low(&mut self, id: Nid) -> Node {
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
let value =
|
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;
|
self.free = id;
|
||||||
value
|
value
|
||||||
} else {
|
} 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 {
|
if self.free == Nid::MAX {
|
||||||
self.free = self.values.len() as _;
|
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;
|
let free = self.free;
|
||||||
|
@ -1132,7 +1124,7 @@ struct Loop {
|
||||||
mod var {
|
mod var {
|
||||||
use {
|
use {
|
||||||
super::{Kind, Nid, Nodes},
|
super::{Kind, Nid, Nodes},
|
||||||
crate::{ident::Ident, ty},
|
crate::{debug, ident::Ident, ty},
|
||||||
alloc::vec::Vec,
|
alloc::vec::Vec,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1189,7 +1181,7 @@ mod var {
|
||||||
|
|
||||||
impl Drop for Variable {
|
impl Drop for Variable {
|
||||||
fn drop(&mut self) {
|
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")
|
panic!("variable unproperly deinitialized")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1427,11 +1419,19 @@ impl ItemCtx {
|
||||||
self.emit(instrs::ld(r, atr(allocs[0]), 0, size))
|
self.emit(instrs::ld(r, atr(allocs[0]), 0, size))
|
||||||
}
|
}
|
||||||
Some(PLoc::Ref(_, size)) => {
|
Some(PLoc::Ref(_, size)) => {
|
||||||
self.emit(instrs::bmc(
|
let [src, dst] = [atr(allocs[0]), atr(allocs[1])];
|
||||||
atr(allocs[0]),
|
if let Ok(size) = u16::try_from(size) {
|
||||||
atr(allocs[1]),
|
self.emit(instrs::bmc(src, dst, size));
|
||||||
size.try_into().expect("TODO: handle huge copies"),
|
} 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;
|
let stck = fuc.nodes[*node.inputs.last().unwrap()].offset;
|
||||||
self.emit(instrs::st(r, reg::STACK_PTR, stck as _, size));
|
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 } => {
|
Kind::Global { global } => {
|
||||||
let reloc = Reloc::new(self.code.len(), 3, 4);
|
let reloc = Reloc::new(self.code.len(), 3, 4);
|
||||||
|
@ -2523,8 +2529,7 @@ impl<'a> Codegen<'a> {
|
||||||
Expr::Directive { name: "as", args: [ty, expr], .. } => {
|
Expr::Directive { name: "as", args: [ty, expr], .. } => {
|
||||||
let ty = self.ty(ty);
|
let ty = self.ty(ty);
|
||||||
let ctx = Ctx::default().with_ty(ty);
|
let ctx = Ctx::default().with_ty(ty);
|
||||||
let mut val = self.raw_expr_ctx(expr, ctx)?;
|
let mut val = self.expr_ctx(expr, ctx)?;
|
||||||
self.strip_var(&mut val);
|
|
||||||
self.assert_ty(expr.pos(), &mut val, ty, "hinted expr");
|
self.assert_ty(expr.pos(), &mut val, ty, "hinted expr");
|
||||||
Some(val)
|
Some(val)
|
||||||
}
|
}
|
||||||
|
@ -3230,11 +3235,18 @@ impl<'a> Codegen<'a> {
|
||||||
// FIXME: could fuck us
|
// FIXME: could fuck us
|
||||||
ty::Id::UNDECLARED
|
ty::Id::UNDECLARED
|
||||||
} else {
|
} else {
|
||||||
debug_assert_eq!(
|
if ty != ty::Id::TYPE {
|
||||||
ty,
|
self.report(
|
||||||
ty::Id::TYPE,
|
arg.pos(),
|
||||||
"TODO: we dont support anything except type generics"
|
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);
|
let ty = self.ty(arg);
|
||||||
self.tys.tmp.args.push(ty);
|
self.tys.tmp.args.push(ty);
|
||||||
ty
|
ty
|
||||||
|
@ -4437,6 +4449,7 @@ mod tests {
|
||||||
fb_driver;
|
fb_driver;
|
||||||
|
|
||||||
// Purely Testing Examples;
|
// Purely Testing Examples;
|
||||||
|
returning_global_struct;
|
||||||
wide_ret;
|
wide_ret;
|
||||||
comptime_min_reg_leak;
|
comptime_min_reg_leak;
|
||||||
different_types;
|
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
|
ST r31, r254, 32a, 16h
|
||||||
ADDI64 r32, r254, 28d
|
ADDI64 r32, r254, 28d
|
||||||
JAL r31, r0, :small_struct
|
JAL r31, r0, :small_struct
|
||||||
|
ST r1, r254, 28a, 4h
|
||||||
LI64 r2, 1d
|
LI64 r2, 1d
|
||||||
LI64 r4, 3d
|
LI64 r4, 3d
|
||||||
LI64 r1, 0d
|
LI64 r1, 0d
|
||||||
|
@ -51,6 +52,6 @@ small_struct:
|
||||||
LD r1, r3, 0a, 4h
|
LD r1, r3, 0a, 4h
|
||||||
ADDI64 r254, r254, 4d
|
ADDI64 r254, r254, 4d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 544
|
code size: 557
|
||||||
ret: 2
|
ret: 2
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
Loading…
Reference in a new issue