Merge pull request #5406 from JTeeuwissen/cross-layout-reuse

Cross layout reuse
This commit is contained in:
Folkert de Vries 2023-05-15 15:20:23 +02:00 committed by GitHub
commit f2a033d0da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 1075 additions and 270 deletions

View file

@ -500,13 +500,12 @@ impl<'a> CodeGenHelp<'a> {
niche: Niche::NONE,
}
}
HelperOp::Reset => ProcLayout {
HelperOp::Reset | HelperOp::ResetRef => ProcLayout {
arguments: self.arena.alloc([layout]),
result: layout,
niche: Niche::NONE,
},
HelperOp::DecRef(_) => unreachable!("No generated Proc for DecRef"),
HelperOp::ResetRef => unreachable!("No generated Proc for ResetRef"),
HelperOp::Eq => ProcLayout {
arguments: self.arena.alloc([layout, layout]),
result: LAYOUT_BOOL,

View file

@ -485,7 +485,7 @@ pub fn refcount_resetref_proc_body<'a>(
let union_layout = match layout_interner.get(layout).repr {
LayoutRepr::Union(u) => u,
_ => unimplemented!("Reset is only implemented for UnionLayout"),
_ => unimplemented!("Resetref is only implemented for UnionLayout"),
};
// Whenever we recurse into a child layout we will want to Decrement
@ -498,29 +498,33 @@ pub fn refcount_resetref_proc_body<'a>(
// Reset structure is not unique. Decrement it and return a NULL pointer.
let else_stmt = {
let decrement_unit = root.create_symbol(ident_ids, "decrement_unit");
let decrement_expr = root
.call_specialized_op(
ident_ids,
ctx,
layout_interner,
layout,
root.arena.alloc([structure]),
)
.unwrap();
let decrement_stmt = |next| Stmt::Let(decrement_unit, decrement_expr, LAYOUT_UNIT, next);
// Set up the context for a decref.
let jp_decref = JoinPointId(root.create_symbol(ident_ids, "jp_decref"));
ctx.op = HelperOp::DecRef(jp_decref);
// Generate the decref code.
let rc_stmt = refcount_generic(root, ident_ids, ctx, layout_interner, layout, structure);
// Null pointer with union layout
let null = root.create_symbol(ident_ids, "null");
let null_stmt = |next| Stmt::Let(null, Expr::NullPointer, layout, next);
decrement_stmt(root.arena.alloc(
//
null_stmt(root.arena.alloc(
// Inline the refcounting code instead of making a function. Don't iterate fields,
// and replace any return statements with jumps to the `following` statement.
let join = Stmt::Join {
id: jp_decref,
parameters: &[],
body: root.arena.alloc(root.arena.alloc(
//
Stmt::Ret(null),
null_stmt(root.arena.alloc(
//
Stmt::Ret(null),
)),
)),
))
remainder: root.arena.alloc(rc_stmt),
};
root.arena.alloc(join)
};
let if_stmt = Stmt::if_then_else(