mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 23:31:12 +00:00
WIP
This commit is contained in:
parent
c9efeed17e
commit
9b6b81a438
6 changed files with 76 additions and 34 deletions
|
@ -37,9 +37,6 @@ impl HelperOp {
|
|||
fn is_decref(&self) -> bool {
|
||||
matches!(self, Self::DecRef(_))
|
||||
}
|
||||
fn is_reset(&self) -> bool {
|
||||
matches!(self, Self::Reset)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -151,7 +148,7 @@ impl<'a> CodeGenHelp<'a> {
|
|||
pub fn call_reset_refcount(
|
||||
&mut self,
|
||||
ident_ids: &mut IdentIds,
|
||||
layout: &Layout<'a>,
|
||||
layout: Layout<'a>,
|
||||
argument: Symbol,
|
||||
) -> (Expr<'a>, Vec<'a, (Symbol, ProcLayout<'a>)>) {
|
||||
let mut ctx = Context {
|
||||
|
@ -160,11 +157,20 @@ impl<'a> CodeGenHelp<'a> {
|
|||
op: HelperOp::Reset,
|
||||
};
|
||||
|
||||
let arguments = self.arena.alloc([argument]);
|
||||
let proc_name = self.find_or_create_proc(ident_ids, &mut ctx, layout);
|
||||
|
||||
let expr = self
|
||||
.call_specialized_op(ident_ids, &mut ctx, *layout, arguments)
|
||||
.unwrap();
|
||||
let arguments = self.arena.alloc([argument]);
|
||||
let ret_layout = self.arena.alloc(layout);
|
||||
let arg_layouts = self.arena.alloc([layout]);
|
||||
let expr = Expr::Call(Call {
|
||||
call_type: CallType::ByName {
|
||||
name: proc_name,
|
||||
ret_layout,
|
||||
arg_layouts,
|
||||
specialization_id: CallSpecId::BACKEND_DUMMY,
|
||||
},
|
||||
arguments,
|
||||
});
|
||||
|
||||
(expr, ctx.new_linker_data)
|
||||
}
|
||||
|
@ -283,10 +289,14 @@ impl<'a> CodeGenHelp<'a> {
|
|||
|
||||
// Recursively generate the body of the Proc and sub-procs
|
||||
let (ret_layout, body) = match ctx.op {
|
||||
Inc | Dec | DecRef(_) | Reset => (
|
||||
Inc | Dec | DecRef(_) => (
|
||||
LAYOUT_UNIT,
|
||||
refcount::refcount_generic(self, ident_ids, ctx, layout, Symbol::ARG_1),
|
||||
),
|
||||
Reset => (
|
||||
layout,
|
||||
refcount::refcount_reset_proc_body(self, ident_ids, ctx, layout, Symbol::ARG_1),
|
||||
),
|
||||
Eq => (
|
||||
LAYOUT_BOOL,
|
||||
equality::eq_generic(self, ident_ids, ctx, layout),
|
||||
|
|
|
@ -128,6 +128,40 @@ pub fn refcount_generic<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn refcount_reset_proc_body<'a>(
|
||||
root: &mut CodeGenHelp<'a>,
|
||||
ident_ids: &mut IdentIds,
|
||||
ctx: &mut Context<'a>,
|
||||
layout: Layout<'a>,
|
||||
structure: Symbol,
|
||||
) -> Stmt<'a> {
|
||||
// Reset is a fancy Decrement. When we recurse into child layouts we just want Dec.
|
||||
ctx.op = HelperOp::Dec;
|
||||
|
||||
/*
|
||||
assert layout is union
|
||||
create the context, with op=Dec
|
||||
|
||||
load the rc value
|
||||
- do I have a helper for this?
|
||||
|
||||
let isUnique = lowlevel Eq rc refcount_unique
|
||||
switch
|
||||
True => {
|
||||
refcount union contents
|
||||
ret structure
|
||||
}
|
||||
False => {
|
||||
call specialized op Dec
|
||||
let zero = 0
|
||||
let typed_null = lowlevel PtrCast zero
|
||||
ret typed_null
|
||||
}
|
||||
*/
|
||||
|
||||
todo!()
|
||||
}
|
||||
|
||||
// Check if refcounting is implemented yet. In the long term, this will be deleted.
|
||||
// In the short term, it helps us to skip refcounting and let it leak, so we can make
|
||||
// progress incrementally. Kept in sync with generate_procs using assertions.
|
||||
|
@ -786,7 +820,7 @@ fn refcount_union<'a>(
|
|||
|
||||
Recursive(tags) => {
|
||||
let (is_tailrec, tail_idx) = root.union_tail_recursion_fields(union);
|
||||
if is_tailrec && !ctx.op.is_decref() && !ctx.op.is_reset() {
|
||||
if is_tailrec && !ctx.op.is_decref() {
|
||||
refcount_union_tailrec(root, ident_ids, ctx, union, tags, None, tail_idx, structure)
|
||||
} else {
|
||||
refcount_union_rec(root, ident_ids, ctx, union, tags, None, structure)
|
||||
|
@ -808,7 +842,7 @@ fn refcount_union<'a>(
|
|||
} => {
|
||||
let null_id = Some(nullable_id);
|
||||
let (is_tailrec, tail_idx) = root.union_tail_recursion_fields(union);
|
||||
if is_tailrec && !ctx.op.is_decref() && !ctx.op.is_reset() {
|
||||
if is_tailrec && !ctx.op.is_decref() {
|
||||
refcount_union_tailrec(
|
||||
root, ident_ids, ctx, union, tags, null_id, tail_idx, structure,
|
||||
)
|
||||
|
@ -824,7 +858,7 @@ fn refcount_union<'a>(
|
|||
let null_id = Some(nullable_id as TagIdIntType);
|
||||
let tags = root.arena.alloc([other_fields]);
|
||||
let (is_tailrec, tail_idx) = root.union_tail_recursion_fields(union);
|
||||
if is_tailrec && !ctx.op.is_decref() && !ctx.op.is_reset() {
|
||||
if is_tailrec && !ctx.op.is_decref() {
|
||||
refcount_union_tailrec(
|
||||
root, ident_ids, ctx, union, tags, null_id, tail_idx, structure,
|
||||
)
|
||||
|
@ -980,18 +1014,14 @@ fn refcount_union_rec<'a>(
|
|||
|
||||
let alignment = Layout::Union(union_layout).alignment_bytes(root.target_info);
|
||||
let ret_stmt = rc_return_stmt(root, ident_ids, ctx);
|
||||
let modify_structure_stmt = if ctx.op.is_reset() {
|
||||
ret_stmt
|
||||
} else {
|
||||
modify_refcount(
|
||||
root,
|
||||
ident_ids,
|
||||
ctx,
|
||||
rc_ptr,
|
||||
alignment,
|
||||
root.arena.alloc(ret_stmt),
|
||||
)
|
||||
};
|
||||
let modify_structure_stmt = modify_refcount(
|
||||
root,
|
||||
ident_ids,
|
||||
ctx,
|
||||
rc_ptr,
|
||||
alignment,
|
||||
root.arena.alloc(ret_stmt),
|
||||
);
|
||||
|
||||
rc_ptr_from_data_ptr(
|
||||
root,
|
||||
|
@ -1020,13 +1050,13 @@ fn refcount_union_rec<'a>(
|
|||
)
|
||||
};
|
||||
|
||||
match ctx.op {
|
||||
HelperOp::DecRef(_) if null_id.is_none() => rc_contents_then_structure,
|
||||
HelperOp::Reset => rc_contents_then_structure,
|
||||
_ => tag_id_stmt(root.arena.alloc(
|
||||
if ctx.op.is_decref() && null_id.is_none() {
|
||||
rc_contents_then_structure
|
||||
} else {
|
||||
tag_id_stmt(root.arena.alloc(
|
||||
//
|
||||
rc_contents_then_structure,
|
||||
)),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue