generate elem refcount function and pass it into decref lowlevel

This commit is contained in:
Brendan Hansknecht 2024-07-10 20:45:15 -07:00
parent 516afaff41
commit ba9b15f7d6
No known key found for this signature in database
GPG Key ID: 0EA784685083E75B
3 changed files with 38 additions and 11 deletions

View File

@ -2102,6 +2102,17 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
self.register_helper_proc(spec_sym, spec_layout, ProcSource::Helper); self.register_helper_proc(spec_sym, spec_layout, ProcSource::Helper);
} }
self.get_existing_refcount_fn_index(proc_symbol, layout, op)
}
/// return a pointer (table index) to a refcount helper procedure.
/// This allows it to be indirectly called from Zig code
pub fn get_existing_refcount_fn_index(
&mut self,
proc_symbol: Symbol,
layout: InLayout<'a>,
op: HelperOp,
) -> u32 {
let layout_repr = if op.is_indirect() { let layout_repr = if op.is_indirect() {
LayoutRepr::Ptr(layout) LayoutRepr::Ptr(layout)
} else { } else {

View File

@ -341,6 +341,8 @@ impl<'a> LowLevelCall<'a> {
ListDecref => { ListDecref => {
let input_list: Symbol = self.arguments[0]; let input_list: Symbol = self.arguments[0];
let dec_fn_sym = self.arguments[1];
let list_layout = backend let list_layout = backend
.layout_interner .layout_interner
.get_repr(backend.storage.symbol_layouts[&input_list]); .get_repr(backend.storage.symbol_layouts[&input_list]);
@ -350,8 +352,12 @@ impl<'a> LowLevelCall<'a> {
elem_layout.stack_size_and_alignment(backend.layout_interner); elem_layout.stack_size_and_alignment(backend.layout_interner);
let elem_refcounted = backend.layout_interner.contains_refcounted(elem_in_layout); let elem_refcounted = backend.layout_interner.contains_refcounted(elem_in_layout);
let dec_fn_ptr = let dec_fn = backend.get_existing_refcount_fn_index(
build_refcount_element_fn(backend, elem_in_layout, HelperOp::IndirectDec); dec_fn_sym,
elem_in_layout,
HelperOp::IndirectDec,
);
let dec_fn_ptr = backend.get_fn_ptr(dec_fn);
// Zig arguments Wasm types // Zig arguments Wasm types
// input_list: &RocList i32 // input_list: &RocList i32
@ -2998,11 +3004,6 @@ fn build_refcount_element_fn<'a>(
elem_layout: InLayout<'a>, elem_layout: InLayout<'a>,
rc_op: HelperOp, rc_op: HelperOp,
) -> i32 { ) -> i32 {
// The refcount function receives a pointer to an element in the list let rc_fn = backend.get_refcount_fn_index(elem_layout, rc_op);
// This is the same as a Struct containing the element
let in_memory_layout = backend
.layout_interner
.insert_direct_no_semantic(LayoutRepr::Struct(backend.env.arena.alloc([elem_layout])));
let rc_fn = backend.get_refcount_fn_index(in_memory_layout, rc_op);
backend.get_fn_ptr(rc_fn) backend.get_fn_ptr(rc_fn)
} }

View File

@ -196,7 +196,14 @@ pub fn refcount_generic<'a>(
rc_return_stmt(root, ident_ids, ctx) rc_return_stmt(root, ident_ids, ctx)
} }
LayoutRepr::Builtin(Builtin::Str) => refcount_str(root, ident_ids, ctx), LayoutRepr::Builtin(Builtin::Str) => refcount_str(root, ident_ids, ctx),
LayoutRepr::Builtin(Builtin::List(_)) => refcount_list(root, ident_ids, ctx, structure), LayoutRepr::Builtin(Builtin::List(element_layout)) => refcount_list(
root,
ident_ids,
ctx,
layout_interner,
element_layout,
structure,
),
LayoutRepr::Struct(field_layouts) => refcount_struct( LayoutRepr::Struct(field_layouts) => refcount_struct(
root, root,
ident_ids, ident_ids,
@ -945,6 +952,8 @@ fn refcount_list<'a>(
root: &mut CodeGenHelp<'a>, root: &mut CodeGenHelp<'a>,
ident_ids: &mut IdentIds, ident_ids: &mut IdentIds,
ctx: &mut Context<'a>, ctx: &mut Context<'a>,
layout_interner: &mut STLayoutInterner<'a>,
element_layout: InLayout<'a>,
_structure: Symbol, _structure: Symbol,
) -> Stmt<'a> { ) -> Stmt<'a> {
let arena = root.arena; let arena = root.arena;
@ -964,13 +973,19 @@ fn refcount_list<'a>(
}) })
} }
HelperOp::DecRef(_) | HelperOp::Dec => { HelperOp::DecRef(_) | HelperOp::Dec => {
let rc_list_args = refcount_args(root, ctx, list); let (rc_sym, linker_data) = root.gen_refcount_proc(
ident_ids,
layout_interner,
element_layout,
HelperOp::IndirectDec,
);
ctx.new_linker_data.extend_from_slice(&linker_data);
Expr::Call(Call { Expr::Call(Call {
call_type: CallType::LowLevel { call_type: CallType::LowLevel {
op: LowLevel::ListDecref, op: LowLevel::ListDecref,
update_mode: UpdateModeId::BACKEND_DUMMY, update_mode: UpdateModeId::BACKEND_DUMMY,
}, },
arguments: rc_list_args, arguments: root.arena.alloc([list, rc_sym]),
}) })
} }
_ => unreachable!(), _ => unreachable!(),