fixing stack return values

This commit is contained in:
Jakub Doka 2024-11-13 16:18:21 +01:00
parent 9cb273a04b
commit d01e31b203
No known key found for this signature in database
GPG key ID: C6E9A89936B8C143
3 changed files with 41 additions and 5 deletions

View file

@ -283,6 +283,19 @@ main := fn(): void {
} }
``` ```
#### inline_return_stack
```hb
$fun := fn(): [uint; 3] {
res := [uint].(0, 1, 2)
return res
}
main := fn(): uint {
vl := fun()
return vl[0]
}
```
#### struct_operators #### struct_operators
```hb ```hb
Point := struct { Point := struct {

View file

@ -2158,7 +2158,7 @@ pub struct ItemCtx {
inline_var_base: usize, inline_var_base: usize,
inline_aclass_base: usize, inline_aclass_base: usize,
inline_depth: u16, inline_depth: u16,
inline_ret: Option<(Value, StrongRef, Scope)>, inline_ret: Option<(Value, StrongRef, Scope, Option<AClass>)>,
nodes: Nodes, nodes: Nodes,
ctrl: StrongRef, ctrl: StrongRef,
loops: Vec<Loop>, loops: Vec<Loop>,
@ -2683,7 +2683,11 @@ impl<'a> Codegen<'a> {
self.ci.ctrl.set(NEVER, &mut self.ci.nodes); self.ci.ctrl.set(NEVER, &mut self.ci.nodes);
self.ci.nodes[ret].pos = pos; self.ci.nodes[ret].pos = pos;
self.ci.nodes.bind(ret, NEVER); self.ci.nodes.bind(ret, NEVER);
} else if let Some((pv, ctrl, scope)) = &mut self.ci.inline_ret { } else if let Some((pv, ctrl, scope, aclass)) = &mut self.ci.inline_ret {
debug_assert!(
aclass.is_none(),
"TODO: oh no, we cant return structs from divergent branches"
);
ctrl.set( ctrl.set(
self.ci.nodes.new_node( self.ci.nodes.new_node(
ty::Id::VOID, ty::Id::VOID,
@ -2726,8 +2730,14 @@ impl<'a> Codegen<'a> {
.for_each(|v| v.remove(&mut self.ci.nodes)); .for_each(|v| v.remove(&mut self.ci.nodes));
let repl = StrongRef::new(NEVER, &mut self.ci.nodes); let repl = StrongRef::new(NEVER, &mut self.ci.nodes);
let (index, _) = self
.ci
.nodes
.aclass_index(*self.ci.nodes[value.id].inputs.get(1).unwrap_or(&VOID));
let aclass = (self.ci.inline_aclass_base <= index)
.then(|| self.ci.scope.aclasses[index].dup(&mut self.ci.nodes));
self.ci.inline_ret = self.ci.inline_ret =
Some((value, mem::replace(&mut self.ci.ctrl, repl), scope)); Some((value, mem::replace(&mut self.ci.ctrl, repl), scope, aclass));
} }
None None
@ -3871,7 +3881,8 @@ impl<'a> Codegen<'a> {
var.remove(&mut self.ci.nodes); var.remove(&mut self.ci.nodes);
} }
let (v, ctrl, mut scope) = mem::replace(&mut self.ci.inline_ret, prev_inline_ret)?; let (v, ctrl, mut scope, aclass) =
mem::replace(&mut self.ci.inline_ret, prev_inline_ret)?;
if is_inline if is_inline
&& ctrl.get() != prev_ctrl && ctrl.get() != prev_ctrl
&& (!self.ci.nodes[ctrl.get()].kind.is_eca() && (!self.ci.nodes[ctrl.get()].kind.is_eca()
@ -3882,11 +3893,16 @@ impl<'a> Codegen<'a> {
scope.vars.drain(var_base..).for_each(|v| v.remove(&mut self.ci.nodes)); scope.vars.drain(var_base..).for_each(|v| v.remove(&mut self.ci.nodes));
scope.aclasses.drain(aclass_base..).for_each(|v| v.remove(&mut self.ci.nodes)); scope.aclasses.drain(aclass_base..).for_each(|v| v.remove(&mut self.ci.nodes));
scope.aclasses.extend(self.ci.scope.aclasses.drain(aclass_base..));
self.ci.nodes.unlock(v.id); self.ci.nodes.unlock(v.id);
self.ci.scope.clear(&mut self.ci.nodes); self.ci.scope.clear(&mut self.ci.nodes);
self.ci.scope = scope; self.ci.scope = scope;
if let Some(aclass) = aclass {
let (_, reg) = self.ci.nodes.aclass_index(v.id);
self.ci.nodes[reg].aclass = self.ci.scope.aclasses.len() as _;
self.ci.scope.aclasses.push(aclass);
}
mem::replace(&mut self.ci.ctrl, ctrl).remove(&mut self.ci.nodes); mem::replace(&mut self.ci.ctrl, ctrl).remove(&mut self.ci.nodes);
Some(v) Some(v)
@ -4868,6 +4884,7 @@ mod tests {
request_page; request_page;
tests_ptr_to_ptr_copy; tests_ptr_to_ptr_copy;
global_variable_wiredness; global_variable_wiredness;
inline_return_stack;
// Just Testing Optimizations; // Just Testing Optimizations;
const_folding_with_arg; const_folding_with_arg;

View file

@ -0,0 +1,6 @@
main:
CP r1, r0
JALA r0, r31, 0a
code size: 22
ret: 0
status: Ok(())