Merge pull request #3392 from rtfeldman/wasm-boxed-eq-and-refcount

Dev backends: Eq and refcount for Boxed layout
This commit is contained in:
Folkert de Vries 2022-07-04 13:17:37 +02:00 committed by GitHub
commit 1441e8c347
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 181 additions and 17 deletions

View file

@ -530,12 +530,43 @@ fn eq_tag_fields<'a>(
}
fn eq_boxed<'a>(
_root: &mut CodeGenHelp<'a>,
_ident_ids: &mut IdentIds,
_ctx: &mut Context<'a>,
_inner_layout: &'a Layout<'a>,
root: &mut CodeGenHelp<'a>,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
inner_layout: &'a Layout<'a>,
) -> Stmt<'a> {
todo!()
let a = root.create_symbol(ident_ids, "a");
let b = root.create_symbol(ident_ids, "b");
let result = root.create_symbol(ident_ids, "result");
let a_expr = Expr::ExprUnbox { symbol: ARG_1 };
let b_expr = Expr::ExprUnbox { symbol: ARG_2 };
let eq_call_expr = root
.call_specialized_op(ident_ids, ctx, *inner_layout, root.arena.alloc([a, b]))
.unwrap();
Stmt::Let(
a,
a_expr,
*inner_layout,
root.arena.alloc(
//
Stmt::Let(
b,
b_expr,
*inner_layout,
root.arena.alloc(
//
Stmt::Let(
result,
eq_call_expr,
LAYOUT_BOOL,
root.arena.alloc(Stmt::Ret(result)),
),
),
),
),
)
}
/// List equality

View file

@ -286,11 +286,11 @@ impl<'a> CodeGenHelp<'a> {
&mut self,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
layout: Layout<'a>,
orig_layout: Layout<'a>,
) -> Symbol {
use HelperOp::*;
let layout = self.replace_rec_ptr(ctx, layout);
let layout = self.replace_rec_ptr(ctx, orig_layout);
let found = self
.specializations
@ -454,7 +454,9 @@ impl<'a> CodeGenHelp<'a> {
layout
}
Layout::Boxed(inner) => self.replace_rec_ptr(ctx, *inner),
Layout::Boxed(inner) => {
Layout::Boxed(self.arena.alloc(self.replace_rec_ptr(ctx, *inner)))
}
Layout::LambdaSet(lambda_set) => {
self.replace_rec_ptr(ctx, lambda_set.runtime_representation())

View file

@ -129,7 +129,9 @@ pub fn refcount_generic<'a>(
Layout::RecursivePointer => unreachable!(
"We should never call a refcounting helper on a RecursivePointer layout directly"
),
Layout::Boxed(_) => rc_todo(),
Layout::Boxed(inner_layout) => {
refcount_boxed(root, ident_ids, ctx, &layout, inner_layout, structure)
}
}
}
@ -343,7 +345,7 @@ pub fn is_rc_implemented_yet(layout: &Layout) -> bool {
is_rc_implemented_yet(&lambda_set.runtime_representation())
}
Layout::RecursivePointer => true,
Layout::Boxed(_) => false,
Layout::Boxed(_) => true,
}
}
@ -1465,3 +1467,66 @@ fn refcount_tag_fields<'a>(
stmt
}
fn refcount_boxed<'a>(
root: &mut CodeGenHelp<'a>,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
layout: &Layout,
inner_layout: &'a Layout,
outer: Symbol,
) -> Stmt<'a> {
let arena = root.arena;
//
// modify refcount of the inner and outer structures
// RC on inner first, to avoid use-after-free for Dec
// We're defining statements in reverse, so define outer first
//
let rc_ptr = root.create_symbol(ident_ids, "rc_ptr");
let alignment = layout.alignment_bytes(root.target_info);
let ret_stmt = rc_return_stmt(root, ident_ids, ctx);
let modify_outer = modify_refcount(
root,
ident_ids,
ctx,
rc_ptr,
alignment,
arena.alloc(ret_stmt),
);
let get_rc_and_modify_outer = rc_ptr_from_data_ptr(
root,
ident_ids,
outer,
rc_ptr,
false,
arena.alloc(modify_outer),
);
if inner_layout.is_refcounted() && !ctx.op.is_decref() {
let inner = root.create_symbol(ident_ids, "inner");
let inner_expr = Expr::ExprUnbox { symbol: outer };
let mod_inner_unit = root.create_symbol(ident_ids, "mod_inner_unit");
let mod_inner_args = refcount_args(root, ctx, inner);
let mod_inner_expr = root
.call_specialized_op(ident_ids, ctx, *inner_layout, mod_inner_args)
.unwrap();
Stmt::Let(
inner,
inner_expr,
*inner_layout,
arena.alloc(Stmt::Let(
mod_inner_unit,
mod_inner_expr,
LAYOUT_UNIT,
arena.alloc(get_rc_and_modify_outer),
)),
)
} else {
get_rc_and_modify_outer
}
}