mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
indirec inc/dec generation in mono helpers
This commit is contained in:
parent
04081ae8b3
commit
6ed899d8be
6 changed files with 219 additions and 65 deletions
|
@ -31,6 +31,8 @@ pub const REFCOUNT_MAX: usize = 0;
|
|||
pub enum HelperOp {
|
||||
Inc,
|
||||
Dec,
|
||||
IndirectInc,
|
||||
IndirectDec,
|
||||
DecRef(JoinPointId),
|
||||
Reset,
|
||||
ResetRef,
|
||||
|
@ -293,14 +295,19 @@ impl<'a> CodeGenHelp<'a> {
|
|||
};
|
||||
|
||||
if layout_needs_helper_proc(layout_interner, layout, ctx.op) {
|
||||
let arena = self.arena;
|
||||
let proc_name = self.find_or_create_proc(ident_ids, ctx, layout_interner, layout);
|
||||
|
||||
let (ret_layout, arg_layouts): (InLayout<'a>, &'a [InLayout<'a>]) = {
|
||||
let arg = self.replace_rec_ptr(ctx, layout_interner, layout);
|
||||
let box_arg = layout_interner.insert(Layout::Boxed(arg));
|
||||
|
||||
match ctx.op {
|
||||
Dec | DecRef(_) => (LAYOUT_UNIT, self.arena.alloc([arg])),
|
||||
Reset | ResetRef => (layout, self.arena.alloc([layout])),
|
||||
Inc => (LAYOUT_UNIT, self.arena.alloc([arg, self.layout_isize])),
|
||||
IndirectDec => (LAYOUT_UNIT, arena.alloc([box_arg])),
|
||||
IndirectInc => (LAYOUT_UNIT, arena.alloc([box_arg, self.layout_isize])),
|
||||
Eq => (LAYOUT_BOOL, self.arena.alloc([arg, arg])),
|
||||
}
|
||||
};
|
||||
|
@ -350,7 +357,8 @@ impl<'a> CodeGenHelp<'a> {
|
|||
// Procs can be recursive, so we need to create the symbol before the body is complete
|
||||
// But with nested recursion, that means Symbols and Procs can end up in different orders.
|
||||
// We want the same order, especially for function indices in Wasm. So create an empty slot and fill it in later.
|
||||
let (proc_symbol, proc_layout) = self.create_proc_symbol(ident_ids, ctx, layout);
|
||||
let (proc_symbol, proc_layout) =
|
||||
self.create_proc_symbol(ident_ids, layout_interner, ctx, layout);
|
||||
ctx.new_linker_data.push((proc_symbol, proc_layout));
|
||||
let spec_index = self.specializations.len();
|
||||
self.specializations.push(Specialization {
|
||||
|
@ -373,6 +381,17 @@ impl<'a> CodeGenHelp<'a> {
|
|||
Symbol::ARG_1,
|
||||
),
|
||||
),
|
||||
IndirectInc | IndirectDec => (
|
||||
LAYOUT_UNIT,
|
||||
refcount::refcount_indirect(
|
||||
self,
|
||||
ident_ids,
|
||||
ctx,
|
||||
layout_interner,
|
||||
layout,
|
||||
Symbol::ARG_1,
|
||||
),
|
||||
),
|
||||
Reset => (
|
||||
layout,
|
||||
refcount::refcount_reset_proc_body(
|
||||
|
@ -409,6 +428,15 @@ impl<'a> CodeGenHelp<'a> {
|
|||
self.arena.alloc([roc_value, inc_amount])
|
||||
}
|
||||
Dec | DecRef(_) | Reset | ResetRef => self.arena.alloc([roc_value]),
|
||||
IndirectInc => {
|
||||
let box_layout = layout_interner.insert(Layout::Boxed(layout));
|
||||
let inc_amount = (self.layout_isize, ARG_2);
|
||||
self.arena.alloc([(box_layout, ARG_1), inc_amount])
|
||||
}
|
||||
IndirectDec => {
|
||||
let box_layout = layout_interner.insert(Layout::Boxed(layout));
|
||||
self.arena.alloc([(box_layout, ARG_1)])
|
||||
}
|
||||
Eq => self.arena.alloc([roc_value, (layout, ARG_2)]),
|
||||
}
|
||||
};
|
||||
|
@ -429,6 +457,7 @@ impl<'a> CodeGenHelp<'a> {
|
|||
fn create_proc_symbol(
|
||||
&self,
|
||||
ident_ids: &mut IdentIds,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
ctx: &mut Context<'a>,
|
||||
layout: InLayout<'a>,
|
||||
) -> (Symbol, ProcLayout<'a>) {
|
||||
|
@ -452,6 +481,24 @@ impl<'a> CodeGenHelp<'a> {
|
|||
result: LAYOUT_UNIT,
|
||||
niche: Niche::NONE,
|
||||
},
|
||||
HelperOp::IndirectInc => {
|
||||
let box_layout = layout_interner.insert(Layout::Boxed(layout));
|
||||
|
||||
ProcLayout {
|
||||
arguments: self.arena.alloc([box_layout, self.layout_isize]),
|
||||
result: LAYOUT_UNIT,
|
||||
niche: Niche::NONE,
|
||||
}
|
||||
}
|
||||
HelperOp::IndirectDec => {
|
||||
let box_layout = layout_interner.insert(Layout::Boxed(layout));
|
||||
|
||||
ProcLayout {
|
||||
arguments: self.arena.alloc([box_layout]),
|
||||
result: LAYOUT_UNIT,
|
||||
niche: Niche::NONE,
|
||||
}
|
||||
}
|
||||
HelperOp::Reset => ProcLayout {
|
||||
arguments: self.arena.alloc([layout]),
|
||||
result: layout,
|
||||
|
|
|
@ -120,6 +120,59 @@ pub fn refcount_stmt<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn refcount_indirect<'a>(
|
||||
root: &mut CodeGenHelp<'a>,
|
||||
ident_ids: &mut IdentIds,
|
||||
ctx: &mut Context<'a>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
element_layout: InLayout<'a>,
|
||||
structure: Symbol,
|
||||
) -> Stmt<'a> {
|
||||
let arena = root.arena;
|
||||
|
||||
let unit = root.create_symbol(ident_ids, "unit");
|
||||
let unboxed = root.create_symbol(ident_ids, "unboxed");
|
||||
|
||||
let indirect_op = ctx.op;
|
||||
let direct_op = match ctx.op {
|
||||
HelperOp::IndirectInc => HelperOp::Inc,
|
||||
HelperOp::IndirectDec => HelperOp::Dec,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
// we've done the indirection, the inner value shoud be inc- or decremented directly
|
||||
ctx.op = direct_op;
|
||||
|
||||
let mod_args = refcount_args(root, ctx, unboxed);
|
||||
let opt_mod_expr =
|
||||
root.call_specialized_op(ident_ids, ctx, layout_interner, element_layout, mod_args);
|
||||
|
||||
// set the op back to indirect ; this is important for correct layout generation
|
||||
ctx.op = indirect_op;
|
||||
|
||||
if let Some(mod_expr) = opt_mod_expr {
|
||||
Stmt::Let(
|
||||
unboxed,
|
||||
Expr::ExprUnbox { symbol: structure },
|
||||
element_layout,
|
||||
arena.alloc(
|
||||
//
|
||||
Stmt::Let(
|
||||
unit,
|
||||
mod_expr,
|
||||
Layout::UNIT,
|
||||
arena.alloc(
|
||||
//
|
||||
Stmt::Ret(unit),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
rc_return_stmt(root, ident_ids, ctx)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn refcount_generic<'a>(
|
||||
root: &mut CodeGenHelp<'a>,
|
||||
ident_ids: &mut IdentIds,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue