mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 14:54:47 +00:00
revise RC for function pointers
This commit is contained in:
parent
a1731518ad
commit
9d3db2f507
2 changed files with 64 additions and 41 deletions
|
@ -261,6 +261,16 @@ impl<'a> BorrowInfState<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn own_arg(&mut self, x: Symbol) {
|
||||||
|
self.own_var(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn own_args(&mut self, xs: &[Symbol]) {
|
||||||
|
for x in xs.iter() {
|
||||||
|
self.own_arg(*x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// For each xs[i], if xs[i] is owned, then mark ps[i] as owned.
|
/// For each xs[i], if xs[i] is owned, then mark ps[i] as owned.
|
||||||
/// We use this action to preserve tail calls. That is, if we have
|
/// We use this action to preserve tail calls. That is, if we have
|
||||||
/// a tail call `f xs`, if the i-th parameter is borrowed, but `xs[i]` is owned
|
/// a tail call `f xs`, if the i-th parameter is borrowed, but `xs[i]` is owned
|
||||||
|
@ -308,31 +318,33 @@ impl<'a> BorrowInfState<'a> {
|
||||||
} = e;
|
} = e;
|
||||||
|
|
||||||
match call_type {
|
match call_type {
|
||||||
ByName {
|
ByName { name, .. } => {
|
||||||
name, arg_layouts, ..
|
|
||||||
}
|
|
||||||
| ByPointer {
|
|
||||||
name, arg_layouts, ..
|
|
||||||
} => {
|
|
||||||
// get the borrow signature of the applied function
|
// get the borrow signature of the applied function
|
||||||
let ps = match self.param_map.get_symbol(*name) {
|
match self.param_map.get_symbol(*name) {
|
||||||
Some(slice) => slice,
|
Some(ps) => {
|
||||||
None => Vec::from_iter_in(
|
// the return value will be owned
|
||||||
arg_layouts.iter().cloned().map(|layout| Param {
|
self.own_var(z);
|
||||||
symbol: Symbol::UNDERSCORE,
|
|
||||||
borrow: false,
|
|
||||||
layout,
|
|
||||||
}),
|
|
||||||
self.arena,
|
|
||||||
)
|
|
||||||
.into_bump_slice(),
|
|
||||||
};
|
|
||||||
|
|
||||||
|
// if the function exects an owned argument (ps), the argument must be owned (args)
|
||||||
|
self.own_args_using_params(arguments, ps);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// this is really an indirect call, but the function was bound to a symbol
|
||||||
|
// the return value will be owned
|
||||||
|
self.own_var(z);
|
||||||
|
|
||||||
|
// if the function exects an owned argument (ps), the argument must be owned (args)
|
||||||
|
self.own_args(arguments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ByPointer { .. } => {
|
||||||
// the return value will be owned
|
// the return value will be owned
|
||||||
self.own_var(z);
|
self.own_var(z);
|
||||||
|
|
||||||
// if the function exects an owned argument (ps), the argument must be owned (args)
|
// if the function exects an owned argument (ps), the argument must be owned (args)
|
||||||
self.own_args_using_params(arguments, ps);
|
self.own_args(arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
LowLevel { op } => {
|
LowLevel { op } => {
|
||||||
|
|
|
@ -466,35 +466,46 @@ impl<'a> Context<'a> {
|
||||||
&*self.arena.alloc(Stmt::Let(z, v, l, b))
|
&*self.arena.alloc(Stmt::Let(z, v, l, b))
|
||||||
}
|
}
|
||||||
|
|
||||||
ByName {
|
ByName { name, .. } => {
|
||||||
name, arg_layouts, ..
|
|
||||||
}
|
|
||||||
| ByPointer {
|
|
||||||
name, arg_layouts, ..
|
|
||||||
} => {
|
|
||||||
// get the borrow signature
|
// get the borrow signature
|
||||||
let ps = match self.param_map.get_symbol(*name) {
|
match self.param_map.get_symbol(*name) {
|
||||||
Some(slice) => slice,
|
Some(ps) => {
|
||||||
None => Vec::from_iter_in(
|
let v = Expr::Call(crate::ir::Call {
|
||||||
arg_layouts.iter().cloned().map(|layout| Param {
|
call_type,
|
||||||
symbol: Symbol::UNDERSCORE,
|
arguments,
|
||||||
borrow: false,
|
});
|
||||||
layout,
|
|
||||||
}),
|
|
||||||
self.arena,
|
|
||||||
)
|
|
||||||
.into_bump_slice(),
|
|
||||||
};
|
|
||||||
|
|
||||||
|
let b = self.add_dec_after_application(arguments, ps, b, b_live_vars);
|
||||||
|
let b = self.arena.alloc(Stmt::Let(z, v, l, b));
|
||||||
|
|
||||||
|
self.add_inc_before(arguments, ps, b, b_live_vars)
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// an indirect call that was bound to a name
|
||||||
|
let v = Expr::Call(crate::ir::Call {
|
||||||
|
call_type,
|
||||||
|
arguments,
|
||||||
|
});
|
||||||
|
|
||||||
|
self.add_inc_before_consume_all(
|
||||||
|
arguments,
|
||||||
|
self.arena.alloc(Stmt::Let(z, v, l, b)),
|
||||||
|
b_live_vars,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ByPointer { .. } => {
|
||||||
let v = Expr::Call(crate::ir::Call {
|
let v = Expr::Call(crate::ir::Call {
|
||||||
call_type,
|
call_type,
|
||||||
arguments,
|
arguments,
|
||||||
});
|
});
|
||||||
|
|
||||||
let b = self.add_dec_after_application(arguments, ps, b, b_live_vars);
|
self.add_inc_before_consume_all(
|
||||||
let b = self.arena.alloc(Stmt::Let(z, v, l, b));
|
arguments,
|
||||||
|
self.arena.alloc(Stmt::Let(z, v, l, b)),
|
||||||
self.add_inc_before(arguments, ps, b, b_live_vars)
|
b_live_vars,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue