revise RC for function pointers

This commit is contained in:
Folkert 2021-02-11 15:27:46 +01:00
parent a1731518ad
commit 9d3db2f507
2 changed files with 64 additions and 41 deletions

View file

@ -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.
/// 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
@ -308,31 +318,33 @@ impl<'a> BorrowInfState<'a> {
} = e;
match call_type {
ByName {
name, arg_layouts, ..
}
| ByPointer {
name, arg_layouts, ..
} => {
ByName { name, .. } => {
// get the borrow signature of the applied function
let ps = match self.param_map.get_symbol(*name) {
Some(slice) => slice,
None => Vec::from_iter_in(
arg_layouts.iter().cloned().map(|layout| Param {
symbol: Symbol::UNDERSCORE,
borrow: false,
layout,
}),
self.arena,
)
.into_bump_slice(),
};
match self.param_map.get_symbol(*name) {
Some(ps) => {
// 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_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
self.own_var(z);
// 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 } => {

View file

@ -466,35 +466,46 @@ impl<'a> Context<'a> {
&*self.arena.alloc(Stmt::Let(z, v, l, b))
}
ByName {
name, arg_layouts, ..
}
| ByPointer {
name, arg_layouts, ..
} => {
ByName { name, .. } => {
// get the borrow signature
let ps = match self.param_map.get_symbol(*name) {
Some(slice) => slice,
None => Vec::from_iter_in(
arg_layouts.iter().cloned().map(|layout| Param {
symbol: Symbol::UNDERSCORE,
borrow: false,
layout,
}),
self.arena,
)
.into_bump_slice(),
};
match self.param_map.get_symbol(*name) {
Some(ps) => {
let v = Expr::Call(crate::ir::Call {
call_type,
arguments,
});
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 {
call_type,
arguments,
});
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)
self.add_inc_before_consume_all(
arguments,
self.arena.alloc(Stmt::Let(z, v, l, b)),
b_live_vars,
)
}
}
}