Push interned layouts as mut throughout the backend, and intern box layouts

This commit is contained in:
Ayaz Hafiz 2022-12-28 18:51:26 -06:00
parent dd6a72fc46
commit 7ab7fdfa7b
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
26 changed files with 769 additions and 375 deletions

View file

@ -1,11 +1,12 @@
use bumpalo::collections::vec::Vec;
use roc_intern::Interner;
use roc_module::low_level::LowLevel;
use roc_module::symbol::{IdentIds, Symbol};
use crate::ir::{
BranchInfo, Call, CallType, Expr, JoinPointId, Literal, Param, Stmt, UpdateModeId,
};
use crate::layout::{Builtin, Layout, TagIdIntType, UnionLayout};
use crate::layout::{Builtin, InLayout, Layout, STLayoutInterner, TagIdIntType, UnionLayout};
use super::{let_lowlevel, CodeGenHelp, Context, LAYOUT_BOOL};
@ -16,6 +17,7 @@ pub fn eq_generic<'a>(
root: &mut CodeGenHelp<'a>,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
layout_interner: &mut STLayoutInterner<'a>,
layout: Layout<'a>,
) -> Stmt<'a> {
let main_body = match layout {
@ -28,10 +30,18 @@ pub fn eq_generic<'a>(
Layout::Builtin(Builtin::Str) => {
unreachable!("No generated helper proc for `==` on Str. Use Zig function.")
}
Layout::Builtin(Builtin::List(elem_layout)) => eq_list(root, ident_ids, ctx, elem_layout),
Layout::Struct { field_layouts, .. } => eq_struct(root, ident_ids, ctx, field_layouts),
Layout::Union(union_layout) => eq_tag_union(root, ident_ids, ctx, union_layout),
Layout::Boxed(inner_layout) => eq_boxed(root, ident_ids, ctx, inner_layout),
Layout::Builtin(Builtin::List(elem_layout)) => {
eq_list(root, ident_ids, ctx, layout_interner, elem_layout)
}
Layout::Struct { field_layouts, .. } => {
eq_struct(root, ident_ids, ctx, layout_interner, field_layouts)
}
Layout::Union(union_layout) => {
eq_tag_union(root, ident_ids, ctx, layout_interner, union_layout)
}
Layout::Boxed(inner_layout) => {
eq_boxed(root, ident_ids, ctx, layout_interner, inner_layout)
}
Layout::LambdaSet(_) => unreachable!("`==` is not defined on functions"),
Layout::RecursivePointer => {
unreachable!(
@ -129,6 +139,7 @@ fn eq_struct<'a>(
root: &mut CodeGenHelp<'a>,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
layout_interner: &mut STLayoutInterner<'a>,
field_layouts: &'a [Layout<'a>],
) -> Stmt<'a> {
let mut else_stmt = Stmt::Ret(Symbol::BOOL_TRUE);
@ -153,6 +164,7 @@ fn eq_struct<'a>(
.call_specialized_op(
ident_ids,
ctx,
layout_interner,
*layout,
root.arena.alloc([field1_sym, field2_sym]),
)
@ -181,6 +193,7 @@ fn eq_tag_union<'a>(
root: &mut CodeGenHelp<'a>,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
layout_interner: &mut STLayoutInterner<'a>,
union_layout: UnionLayout<'a>,
) -> Stmt<'a> {
use UnionLayout::*;
@ -191,13 +204,37 @@ fn eq_tag_union<'a>(
}
let body = match union_layout {
NonRecursive(tags) => eq_tag_union_help(root, ident_ids, ctx, union_layout, tags, None),
NonRecursive(tags) => eq_tag_union_help(
root,
ident_ids,
ctx,
layout_interner,
union_layout,
tags,
None,
),
Recursive(tags) => eq_tag_union_help(root, ident_ids, ctx, union_layout, tags, None),
Recursive(tags) => eq_tag_union_help(
root,
ident_ids,
ctx,
layout_interner,
union_layout,
tags,
None,
),
NonNullableUnwrapped(field_layouts) => {
let tags = root.arena.alloc([field_layouts]);
eq_tag_union_help(root, ident_ids, ctx, union_layout, tags, None)
eq_tag_union_help(
root,
ident_ids,
ctx,
layout_interner,
union_layout,
tags,
None,
)
}
NullableWrapped {
@ -207,6 +244,7 @@ fn eq_tag_union<'a>(
root,
ident_ids,
ctx,
layout_interner,
union_layout,
other_tags,
Some(nullable_id),
@ -219,6 +257,7 @@ fn eq_tag_union<'a>(
root,
ident_ids,
ctx,
layout_interner,
union_layout,
root.arena.alloc([other_fields]),
Some(nullable_id as TagIdIntType),
@ -234,6 +273,7 @@ fn eq_tag_union_help<'a>(
root: &mut CodeGenHelp<'a>,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
layout_interner: &mut STLayoutInterner<'a>,
union_layout: UnionLayout<'a>,
tag_layouts: &'a [&'a [Layout<'a>]],
nullable_id: Option<TagIdIntType>,
@ -314,6 +354,7 @@ fn eq_tag_union_help<'a>(
root,
ident_ids,
ctx,
layout_interner,
tailrec_loop,
union_layout,
field_layouts,
@ -335,6 +376,7 @@ fn eq_tag_union_help<'a>(
root,
ident_ids,
ctx,
layout_interner,
tailrec_loop,
union_layout,
tag_layouts.last().unwrap(),
@ -395,6 +437,7 @@ fn eq_tag_fields<'a>(
root: &mut CodeGenHelp<'a>,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
layout_interner: &mut STLayoutInterner<'a>,
tailrec_loop: JoinPointId,
union_layout: UnionLayout<'a>,
field_layouts: &'a [Layout<'a>],
@ -482,6 +525,7 @@ fn eq_tag_fields<'a>(
.call_specialized_op(
ident_ids,
ctx,
layout_interner,
*layout,
root.arena.alloc([field1_sym, field2_sym]),
)
@ -530,8 +574,11 @@ fn eq_boxed<'a>(
root: &mut CodeGenHelp<'a>,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
inner_layout: &'a Layout<'a>,
layout_interner: &mut STLayoutInterner<'a>,
inner_layout: InLayout<'a>,
) -> Stmt<'a> {
let inner_layout = layout_interner.get(inner_layout);
let a = root.create_symbol(ident_ids, "a");
let b = root.create_symbol(ident_ids, "b");
let result = root.create_symbol(ident_ids, "result");
@ -539,7 +586,13 @@ fn eq_boxed<'a>(
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]))
.call_specialized_op(
ident_ids,
ctx,
layout_interner,
*inner_layout,
root.arena.alloc([a, b]),
)
.unwrap();
Stmt::Let(
@ -576,6 +629,7 @@ fn eq_list<'a>(
root: &mut CodeGenHelp<'a>,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
layout_interner: &mut STLayoutInterner<'a>,
elem_layout: &Layout<'a>,
) -> Stmt<'a> {
use LowLevel::*;
@ -629,7 +683,7 @@ fn eq_list<'a>(
// let size = literal int
let size = root.create_symbol(ident_ids, "size");
let size_expr = Expr::Literal(Literal::Int(
(elem_layout.stack_size(root.layout_interner, root.target_info) as i128).to_ne_bytes(),
(elem_layout.stack_size(layout_interner, root.target_info) as i128).to_ne_bytes(),
));
let size_stmt = |next| Stmt::Let(size, size_expr, layout_isize, next);
@ -703,7 +757,7 @@ fn eq_list<'a>(
let eq_elems = root.create_symbol(ident_ids, "eq_elems");
let eq_elems_args = root.arena.alloc([elem1, elem2]);
let eq_elems_expr = root
.call_specialized_op(ident_ids, ctx, *elem_layout, eq_elems_args)
.call_specialized_op(ident_ids, ctx, layout_interner, *elem_layout, eq_elems_args)
.unwrap();
let eq_elems_stmt = |next| Stmt::Let(eq_elems, eq_elems_expr, LAYOUT_BOOL, next);

View file

@ -1,5 +1,6 @@
use bumpalo::collections::vec::Vec;
use bumpalo::Bump;
use roc_intern::Interner;
use roc_module::low_level::LowLevel;
use roc_module::symbol::{IdentIds, ModuleId, Symbol};
use roc_target::TargetInfo;
@ -73,7 +74,6 @@ pub struct Context<'a> {
///
pub struct CodeGenHelp<'a> {
arena: &'a Bump,
layout_interner: &'a STLayoutInterner<'a>,
home: ModuleId,
target_info: TargetInfo,
layout_isize: Layout<'a>,
@ -83,12 +83,7 @@ pub struct CodeGenHelp<'a> {
}
impl<'a> CodeGenHelp<'a> {
pub fn new(
arena: &'a Bump,
layout_interner: &'a STLayoutInterner<'a>,
target_info: TargetInfo,
home: ModuleId,
) -> Self {
pub fn new(arena: &'a Bump, target_info: TargetInfo, home: ModuleId) -> Self {
let layout_isize = Layout::isize(target_info);
// Refcount is a boxed isize. TODO: use the new Box layout when dev backends support it
@ -96,7 +91,6 @@ impl<'a> CodeGenHelp<'a> {
CodeGenHelp {
arena,
layout_interner,
home,
target_info,
layout_isize,
@ -125,11 +119,12 @@ impl<'a> CodeGenHelp<'a> {
pub fn expand_refcount_stmt(
&mut self,
ident_ids: &mut IdentIds,
layout_interner: &mut STLayoutInterner<'a>,
layout: Layout<'a>,
modify: &ModifyRc,
following: &'a Stmt<'a>,
) -> (&'a Stmt<'a>, Vec<'a, (Symbol, ProcLayout<'a>)>) {
if !refcount::is_rc_implemented_yet(self.layout_interner, &layout) {
if !refcount::is_rc_implemented_yet(layout_interner, &layout) {
// Just a warning, so we can decouple backend development from refcounting development.
// When we are closer to completion, we can change it to a panic.
println!(
@ -154,13 +149,22 @@ impl<'a> CodeGenHelp<'a> {
op,
};
let rc_stmt = refcount::refcount_stmt(self, ident_ids, &mut ctx, layout, modify, following);
let rc_stmt = refcount::refcount_stmt(
self,
ident_ids,
&mut ctx,
layout_interner,
layout,
modify,
following,
);
(rc_stmt, ctx.new_linker_data)
}
pub fn call_reset_refcount(
&mut self,
ident_ids: &mut IdentIds,
layout_interner: &mut STLayoutInterner<'a>,
layout: Layout<'a>,
argument: Symbol,
) -> (Expr<'a>, Vec<'a, (Symbol, ProcLayout<'a>)>) {
@ -170,7 +174,7 @@ impl<'a> CodeGenHelp<'a> {
op: HelperOp::Reset,
};
let proc_name = self.find_or_create_proc(ident_ids, &mut ctx, layout);
let proc_name = self.find_or_create_proc(ident_ids, &mut ctx, layout_interner, layout);
let arguments = self.arena.alloc([argument]);
let ret_layout = self.arena.alloc(layout);
@ -194,6 +198,7 @@ impl<'a> CodeGenHelp<'a> {
pub fn gen_refcount_proc(
&mut self,
ident_ids: &mut IdentIds,
layout_interner: &mut STLayoutInterner<'a>,
layout: Layout<'a>,
op: HelperOp,
) -> (Symbol, Vec<'a, (Symbol, ProcLayout<'a>)>) {
@ -203,7 +208,7 @@ impl<'a> CodeGenHelp<'a> {
op,
};
let proc_name = self.find_or_create_proc(ident_ids, &mut ctx, layout);
let proc_name = self.find_or_create_proc(ident_ids, &mut ctx, layout_interner, layout);
(proc_name, ctx.new_linker_data)
}
@ -213,6 +218,7 @@ impl<'a> CodeGenHelp<'a> {
pub fn call_specialized_equals(
&mut self,
ident_ids: &mut IdentIds,
layout_interner: &mut STLayoutInterner<'a>,
layout: &Layout<'a>,
arguments: &'a [Symbol],
) -> (Expr<'a>, Vec<'a, (Symbol, ProcLayout<'a>)>) {
@ -223,7 +229,7 @@ impl<'a> CodeGenHelp<'a> {
};
let expr = self
.call_specialized_op(ident_ids, &mut ctx, *layout, arguments)
.call_specialized_op(ident_ids, &mut ctx, layout_interner, *layout, arguments)
.unwrap();
(expr, ctx.new_linker_data)
@ -239,6 +245,7 @@ impl<'a> CodeGenHelp<'a> {
&mut self,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
layout_interner: &mut STLayoutInterner<'a>,
called_layout: Layout<'a>,
arguments: &'a [Symbol],
) -> Option<Expr<'a>> {
@ -255,10 +262,10 @@ impl<'a> CodeGenHelp<'a> {
};
if layout_needs_helper_proc(&layout, ctx.op) {
let proc_name = self.find_or_create_proc(ident_ids, ctx, layout);
let proc_name = self.find_or_create_proc(ident_ids, ctx, layout_interner, layout);
let (ret_layout, arg_layouts): (&'a Layout<'a>, &'a [Layout<'a>]) = {
let arg = self.replace_rec_ptr(ctx, layout);
let arg = self.replace_rec_ptr(ctx, layout_interner, layout);
match ctx.op {
Dec | DecRef(_) => (&LAYOUT_UNIT, self.arena.alloc([arg])),
Reset => (self.arena.alloc(layout), self.arena.alloc([layout])),
@ -293,11 +300,12 @@ impl<'a> CodeGenHelp<'a> {
&mut self,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
layout_interner: &mut STLayoutInterner<'a>,
orig_layout: Layout<'a>,
) -> Symbol {
use HelperOp::*;
let layout = self.replace_rec_ptr(ctx, orig_layout);
let layout = self.replace_rec_ptr(ctx, layout_interner, orig_layout);
let found = self
.specializations
@ -325,15 +333,29 @@ impl<'a> CodeGenHelp<'a> {
let (ret_layout, body) = match ctx.op {
Inc | Dec | DecRef(_) => (
LAYOUT_UNIT,
refcount::refcount_generic(self, ident_ids, ctx, layout, Symbol::ARG_1),
refcount::refcount_generic(
self,
ident_ids,
ctx,
layout_interner,
layout,
Symbol::ARG_1,
),
),
Reset => (
layout,
refcount::refcount_reset_proc_body(self, ident_ids, ctx, layout, Symbol::ARG_1),
refcount::refcount_reset_proc_body(
self,
ident_ids,
ctx,
layout_interner,
layout,
Symbol::ARG_1,
),
),
Eq => (
LAYOUT_BOOL,
equality::eq_generic(self, ident_ids, ctx, layout),
equality::eq_generic(self, ident_ids, ctx, layout_interner, layout),
),
};
@ -415,10 +437,16 @@ impl<'a> CodeGenHelp<'a> {
// For example if a program uses `RoseTree a : [Tree a (List (RoseTree a))]`
// then it could have both `RoseTree I64` and `RoseTree Str`. In this case it
// needs *two* specializations for `List(RecursivePointer)`, not just one.
fn replace_rec_ptr(&self, ctx: &Context<'a>, layout: Layout<'a>) -> Layout<'a> {
fn replace_rec_ptr(
&mut self,
ctx: &Context<'a>,
layout_interner: &mut STLayoutInterner<'a>,
layout: Layout<'a>,
) -> Layout<'a> {
match layout {
Layout::Builtin(Builtin::List(v)) => Layout::Builtin(Builtin::List(
self.arena.alloc(self.replace_rec_ptr(ctx, *v)),
self.arena
.alloc(self.replace_rec_ptr(ctx, layout_interner, *v)),
)),
Layout::Builtin(_) => layout,
@ -427,9 +455,12 @@ impl<'a> CodeGenHelp<'a> {
field_layouts,
field_order_hash,
} => {
let new_fields_iter = field_layouts.iter().map(|f| self.replace_rec_ptr(ctx, *f));
let mut new_field_layouts = Vec::with_capacity_in(field_layouts.len(), self.arena);
for f in field_layouts.iter() {
new_field_layouts.push(self.replace_rec_ptr(ctx, layout_interner, *f));
}
Layout::Struct {
field_layouts: self.arena.alloc_slice_fill_iter(new_fields_iter),
field_layouts: new_field_layouts.into_bump_slice(),
field_order_hash,
}
}
@ -439,7 +470,7 @@ impl<'a> CodeGenHelp<'a> {
for fields in tags {
let mut new_fields = Vec::with_capacity_in(fields.len(), self.arena);
for field in fields.iter() {
new_fields.push(self.replace_rec_ptr(ctx, *field))
new_fields.push(self.replace_rec_ptr(ctx, layout_interner, *field))
}
new_tags.push(new_fields.into_bump_slice());
}
@ -453,12 +484,19 @@ impl<'a> CodeGenHelp<'a> {
}
Layout::Boxed(inner) => {
Layout::Boxed(self.arena.alloc(self.replace_rec_ptr(ctx, *inner)))
let inner = layout_interner.get(inner);
let inner = self
.arena
.alloc(self.replace_rec_ptr(ctx, layout_interner, *inner));
let inner = layout_interner.insert(inner);
Layout::Boxed(inner)
}
Layout::LambdaSet(lambda_set) => {
self.replace_rec_ptr(ctx, lambda_set.runtime_representation(self.layout_interner))
}
Layout::LambdaSet(lambda_set) => self.replace_rec_ptr(
ctx,
layout_interner,
lambda_set.runtime_representation(layout_interner),
),
// This line is the whole point of the function
Layout::RecursivePointer => Layout::Union(ctx.recursive_union.unwrap()),

View file

@ -9,7 +9,7 @@ use crate::code_gen_help::let_lowlevel;
use crate::ir::{
BranchInfo, Call, CallType, Expr, JoinPointId, Literal, ModifyRc, Param, Stmt, UpdateModeId,
};
use crate::layout::{Builtin, Layout, TagIdIntType, UnionLayout};
use crate::layout::{Builtin, Layout, STLayoutInterner, TagIdIntType, UnionLayout};
use super::{CodeGenHelp, Context, HelperOp};
@ -24,6 +24,7 @@ pub fn refcount_stmt<'a>(
root: &mut CodeGenHelp<'a>,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
layout_interner: &mut STLayoutInterner<'a>,
layout: Layout<'a>,
modify: &ModifyRc,
following: &'a Stmt<'a>,
@ -45,6 +46,7 @@ pub fn refcount_stmt<'a>(
.call_specialized_op(
ident_ids,
ctx,
layout_interner,
layout,
arena.alloc([*structure, amount_sym]),
)
@ -58,7 +60,13 @@ pub fn refcount_stmt<'a>(
// Call helper proc, passing the Roc structure
let call_result_empty = root.create_symbol(ident_ids, "call_result_empty");
let call_expr = root
.call_specialized_op(ident_ids, ctx, layout, arena.alloc([*structure]))
.call_specialized_op(
ident_ids,
ctx,
layout_interner,
layout,
arena.alloc([*structure]),
)
.unwrap();
let call_stmt = Stmt::Let(call_result_empty, call_expr, LAYOUT_UNIT, following);
arena.alloc(call_stmt)
@ -69,7 +77,15 @@ pub fn refcount_stmt<'a>(
// Str has no children, so we might as well do what we normally do and call the helper.
Layout::Builtin(Builtin::Str) => {
ctx.op = HelperOp::Dec;
refcount_stmt(root, ident_ids, ctx, layout, modify, following)
refcount_stmt(
root,
ident_ids,
ctx,
layout_interner,
layout,
modify,
following,
)
}
// Struct and non-recursive Unions are stack-only, so DecRef is a no-op
@ -80,7 +96,14 @@ pub fn refcount_stmt<'a>(
// and replace any return statements with jumps to the `following` statement.
_ => match ctx.op {
HelperOp::DecRef(jp_decref) => {
let rc_stmt = refcount_generic(root, ident_ids, ctx, layout, *structure);
let rc_stmt = refcount_generic(
root,
ident_ids,
ctx,
layout_interner,
layout,
*structure,
);
let join = Stmt::Join {
id: jp_decref,
parameters: &[],
@ -100,10 +123,11 @@ pub fn refcount_generic<'a>(
root: &mut CodeGenHelp<'a>,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
layout_interner: &mut STLayoutInterner<'a>,
layout: Layout<'a>,
structure: Symbol,
) -> Stmt<'a> {
debug_assert!(is_rc_implemented_yet(root.layout_interner, &layout));
debug_assert!(is_rc_implemented_yet(layout_interner, &layout));
match layout {
Layout::Builtin(Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal) => {
@ -112,24 +136,56 @@ pub fn refcount_generic<'a>(
rc_return_stmt(root, ident_ids, ctx)
}
Layout::Builtin(Builtin::Str) => refcount_str(root, ident_ids, ctx),
Layout::Builtin(Builtin::List(elem_layout)) => {
refcount_list(root, ident_ids, ctx, &layout, elem_layout, structure)
}
Layout::Struct { field_layouts, .. } => {
refcount_struct(root, ident_ids, ctx, field_layouts, structure)
}
Layout::Union(union_layout) => {
refcount_union(root, ident_ids, ctx, union_layout, structure)
}
Layout::Builtin(Builtin::List(elem_layout)) => refcount_list(
root,
ident_ids,
ctx,
layout_interner,
&layout,
elem_layout,
structure,
),
Layout::Struct { field_layouts, .. } => refcount_struct(
root,
ident_ids,
ctx,
layout_interner,
field_layouts,
structure,
),
Layout::Union(union_layout) => refcount_union(
root,
ident_ids,
ctx,
layout_interner,
union_layout,
structure,
),
Layout::LambdaSet(lambda_set) => {
let runtime_layout = lambda_set.runtime_representation(root.layout_interner);
refcount_generic(root, ident_ids, ctx, runtime_layout, structure)
let runtime_layout = lambda_set.runtime_representation(layout_interner);
refcount_generic(
root,
ident_ids,
ctx,
layout_interner,
runtime_layout,
structure,
)
}
Layout::RecursivePointer => unreachable!(
"We should never call a refcounting helper on a RecursivePointer layout directly"
),
Layout::Boxed(inner_layout) => {
refcount_boxed(root, ident_ids, ctx, &layout, inner_layout, structure)
let inner_layout = layout_interner.get(inner_layout);
refcount_boxed(
root,
ident_ids,
ctx,
layout_interner,
&layout,
inner_layout,
structure,
)
}
}
}
@ -138,6 +194,7 @@ pub fn refcount_reset_proc_body<'a>(
root: &mut CodeGenHelp<'a>,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
layout_interner: &mut STLayoutInterner<'a>,
layout: Layout<'a>,
structure: Symbol,
) -> Stmt<'a> {
@ -206,8 +263,7 @@ pub fn refcount_reset_proc_body<'a>(
let alloc_addr_stmt = {
let alignment = root.create_symbol(ident_ids, "alignment");
let alignment_expr = Expr::Literal(Literal::Int(
(layout.alignment_bytes(root.layout_interner, root.target_info) as i128)
.to_ne_bytes(),
(layout.alignment_bytes(layout_interner, root.target_info) as i128).to_ne_bytes(),
));
let alloc_addr = root.create_symbol(ident_ids, "alloc_addr");
let alloc_addr_expr = Expr::Call(Call {
@ -241,6 +297,7 @@ pub fn refcount_reset_proc_body<'a>(
root,
ident_ids,
ctx,
layout_interner,
union_layout,
tag_layouts,
null_id,
@ -260,7 +317,13 @@ pub fn refcount_reset_proc_body<'a>(
let else_stmt = {
let decrement_unit = root.create_symbol(ident_ids, "decrement_unit");
let decrement_expr = root
.call_specialized_op(ident_ids, ctx, layout, root.arena.alloc([structure]))
.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);
@ -694,6 +757,7 @@ fn refcount_list<'a>(
root: &mut CodeGenHelp<'a>,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
layout_interner: &mut STLayoutInterner<'a>,
layout: &Layout,
elem_layout: &'a Layout,
structure: Symbol,
@ -743,7 +807,7 @@ fn refcount_list<'a>(
//
let rc_ptr = root.create_symbol(ident_ids, "rc_ptr");
let alignment = layout.alignment_bytes(root.layout_interner, root.target_info);
let alignment = layout.alignment_bytes(layout_interner, root.target_info);
let ret_stmt = rc_return_stmt(root, ident_ids, ctx);
let modify_list = modify_refcount(
@ -769,6 +833,7 @@ fn refcount_list<'a>(
root,
ident_ids,
ctx,
layout_interner,
elem_layout,
LAYOUT_UNIT,
box_union_layout,
@ -819,6 +884,7 @@ fn refcount_list_elems<'a>(
root: &mut CodeGenHelp<'a>,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
layout_interner: &mut STLayoutInterner<'a>,
elem_layout: &Layout<'a>,
ret_layout: Layout<'a>,
box_union_layout: UnionLayout<'a>,
@ -841,7 +907,7 @@ fn refcount_list_elems<'a>(
// let size = literal int
let elem_size = root.create_symbol(ident_ids, "elem_size");
let elem_size_expr = Expr::Literal(Literal::Int(
(elem_layout.stack_size(root.layout_interner, root.target_info) as i128).to_ne_bytes(),
(elem_layout.stack_size(layout_interner, root.target_info) as i128).to_ne_bytes(),
));
let elem_size_stmt = |next| Stmt::Let(elem_size, elem_size_expr, layout_isize, next);
@ -901,7 +967,7 @@ fn refcount_list_elems<'a>(
let mod_elem_unit = root.create_symbol(ident_ids, "mod_elem_unit");
let mod_elem_args = refcount_args(root, ctx, elem);
let mod_elem_expr = root
.call_specialized_op(ident_ids, ctx, *elem_layout, mod_elem_args)
.call_specialized_op(ident_ids, ctx, layout_interner, *elem_layout, mod_elem_args)
.unwrap();
let mod_elem_stmt = |next| Stmt::Let(mod_elem_unit, mod_elem_expr, LAYOUT_UNIT, next);
@ -984,13 +1050,14 @@ fn refcount_struct<'a>(
root: &mut CodeGenHelp<'a>,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
layout_interner: &mut STLayoutInterner<'a>,
field_layouts: &'a [Layout<'a>],
structure: Symbol,
) -> Stmt<'a> {
let mut stmt = rc_return_stmt(root, ident_ids, ctx);
for (i, field_layout) in field_layouts.iter().enumerate().rev() {
if field_layout.contains_refcounted(root.layout_interner) {
if field_layout.contains_refcounted(layout_interner) {
let field_val = root.create_symbol(ident_ids, &format!("field_val_{}", i));
let field_val_expr = Expr::StructAtIndex {
index: i as u64,
@ -1002,7 +1069,7 @@ fn refcount_struct<'a>(
let mod_unit = root.create_symbol(ident_ids, &format!("mod_field_{}", i));
let mod_args = refcount_args(root, ctx, field_val);
let mod_expr = root
.call_specialized_op(ident_ids, ctx, *field_layout, mod_args)
.call_specialized_op(ident_ids, ctx, layout_interner, *field_layout, mod_args)
.unwrap();
let mod_stmt = |next| Stmt::Let(mod_unit, mod_expr, LAYOUT_UNIT, next);
@ -1023,6 +1090,7 @@ fn refcount_union<'a>(
root: &mut CodeGenHelp<'a>,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
layout_interner: &mut STLayoutInterner<'a>,
union: UnionLayout<'a>,
structure: Symbol,
) -> Stmt<'a> {
@ -1034,14 +1102,41 @@ fn refcount_union<'a>(
}
let body = match union {
NonRecursive(tags) => refcount_union_nonrec(root, ident_ids, ctx, union, tags, structure),
NonRecursive(tags) => refcount_union_nonrec(
root,
ident_ids,
ctx,
layout_interner,
union,
tags,
structure,
),
Recursive(tags) => {
let (is_tailrec, tail_idx) = root.union_tail_recursion_fields(union);
if is_tailrec && !ctx.op.is_decref() {
refcount_union_tailrec(root, ident_ids, ctx, union, tags, None, tail_idx, structure)
refcount_union_tailrec(
root,
ident_ids,
ctx,
layout_interner,
union,
tags,
None,
tail_idx,
structure,
)
} else {
refcount_union_rec(root, ident_ids, ctx, union, tags, None, structure)
refcount_union_rec(
root,
ident_ids,
ctx,
layout_interner,
union,
tags,
None,
structure,
)
}
}
@ -1051,7 +1146,16 @@ fn refcount_union<'a>(
// a direct RecursionPointer is only possible if there's at least one non-recursive variant.
// This nesting makes it harder to do tail recursion, so we just don't.
let tags = root.arena.alloc([field_layouts]);
refcount_union_rec(root, ident_ids, ctx, union, tags, None, structure)
refcount_union_rec(
root,
ident_ids,
ctx,
layout_interner,
union,
tags,
None,
structure,
)
}
NullableWrapped {
@ -1062,10 +1166,27 @@ fn refcount_union<'a>(
let (is_tailrec, tail_idx) = root.union_tail_recursion_fields(union);
if is_tailrec && !ctx.op.is_decref() {
refcount_union_tailrec(
root, ident_ids, ctx, union, tags, null_id, tail_idx, structure,
root,
ident_ids,
ctx,
layout_interner,
union,
tags,
null_id,
tail_idx,
structure,
)
} else {
refcount_union_rec(root, ident_ids, ctx, union, tags, null_id, structure)
refcount_union_rec(
root,
ident_ids,
ctx,
layout_interner,
union,
tags,
null_id,
structure,
)
}
}
@ -1078,10 +1199,27 @@ fn refcount_union<'a>(
let (is_tailrec, tail_idx) = root.union_tail_recursion_fields(union);
if is_tailrec && !ctx.op.is_decref() {
refcount_union_tailrec(
root, ident_ids, ctx, union, tags, null_id, tail_idx, structure,
root,
ident_ids,
ctx,
layout_interner,
union,
tags,
null_id,
tail_idx,
structure,
)
} else {
refcount_union_rec(root, ident_ids, ctx, union, tags, null_id, structure)
refcount_union_rec(
root,
ident_ids,
ctx,
layout_interner,
union,
tags,
null_id,
structure,
)
}
}
};
@ -1095,6 +1233,7 @@ fn refcount_union_nonrec<'a>(
root: &mut CodeGenHelp<'a>,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
layout_interner: &mut STLayoutInterner<'a>,
union_layout: UnionLayout<'a>,
tag_layouts: &'a [&'a [Layout<'a>]],
structure: Symbol,
@ -1120,6 +1259,7 @@ fn refcount_union_nonrec<'a>(
root,
ident_ids,
ctx,
layout_interner,
union_layout,
tag_layouts,
None,
@ -1140,6 +1280,7 @@ fn refcount_union_contents<'a>(
root: &mut CodeGenHelp<'a>,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
layout_interner: &mut STLayoutInterner<'a>,
union_layout: UnionLayout<'a>,
tag_layouts: &'a [&'a [Layout<'a>]],
null_id: Option<TagIdIntType>,
@ -1173,6 +1314,7 @@ fn refcount_union_contents<'a>(
root,
ident_ids,
ctx,
layout_interner,
union_layout,
field_layouts,
structure,
@ -1207,6 +1349,7 @@ fn refcount_union_rec<'a>(
root: &mut CodeGenHelp<'a>,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
layout_interner: &mut STLayoutInterner<'a>,
union_layout: UnionLayout<'a>,
tag_layouts: &'a [&'a [Layout<'a>]],
null_id: Option<TagIdIntType>,
@ -1231,7 +1374,7 @@ fn refcount_union_rec<'a>(
let rc_ptr = root.create_symbol(ident_ids, "rc_ptr");
let alignment =
Layout::Union(union_layout).alignment_bytes(root.layout_interner, root.target_info);
Layout::Union(union_layout).alignment_bytes(layout_interner, root.target_info);
let ret_stmt = rc_return_stmt(root, ident_ids, ctx);
let modify_structure_stmt = modify_refcount(
root,
@ -1259,6 +1402,7 @@ fn refcount_union_rec<'a>(
root,
ident_ids,
ctx,
layout_interner,
union_layout,
tag_layouts,
null_id,
@ -1285,6 +1429,7 @@ fn refcount_union_tailrec<'a>(
root: &mut CodeGenHelp<'a>,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
layout_interner: &mut STLayoutInterner<'a>,
union_layout: UnionLayout<'a>,
tag_layouts: &'a [&'a [Layout<'a>]],
null_id: Option<TagIdIntType>,
@ -1339,7 +1484,7 @@ fn refcount_union_tailrec<'a>(
)
};
let alignment = layout.alignment_bytes(root.layout_interner, root.target_info);
let alignment = layout.alignment_bytes(layout_interner, root.target_info);
let modify_structure_stmt = modify_refcount(
root,
ident_ids,
@ -1427,6 +1572,7 @@ fn refcount_union_tailrec<'a>(
root,
ident_ids,
ctx,
layout_interner,
union_layout,
non_tailrec_fields,
current,
@ -1488,6 +1634,7 @@ fn refcount_tag_fields<'a>(
root: &mut CodeGenHelp<'a>,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
layout_interner: &mut STLayoutInterner<'a>,
union_layout: UnionLayout<'a>,
field_layouts: &'a [Layout<'a>],
structure: Symbol,
@ -1497,7 +1644,7 @@ fn refcount_tag_fields<'a>(
let mut stmt = following;
for (i, field_layout) in field_layouts.iter().enumerate().rev() {
if field_layout.contains_refcounted(root.layout_interner) {
if field_layout.contains_refcounted(layout_interner) {
let field_val = root.create_symbol(ident_ids, &format!("field_{}_{}", tag_id, i));
let field_val_expr = Expr::UnionAtIndex {
union_layout,
@ -1510,7 +1657,7 @@ fn refcount_tag_fields<'a>(
let mod_unit = root.create_symbol(ident_ids, &format!("mod_field_{}_{}", tag_id, i));
let mod_args = refcount_args(root, ctx, field_val);
let mod_expr = root
.call_specialized_op(ident_ids, ctx, *field_layout, mod_args)
.call_specialized_op(ident_ids, ctx, layout_interner, *field_layout, mod_args)
.unwrap();
let mod_stmt = |next| Stmt::Let(mod_unit, mod_expr, LAYOUT_UNIT, next);
@ -1531,6 +1678,7 @@ fn refcount_boxed<'a>(
root: &mut CodeGenHelp<'a>,
ident_ids: &mut IdentIds,
ctx: &mut Context<'a>,
layout_interner: &mut STLayoutInterner<'a>,
layout: &Layout,
inner_layout: &'a Layout,
outer: Symbol,
@ -1544,7 +1692,7 @@ fn refcount_boxed<'a>(
//
let rc_ptr = root.create_symbol(ident_ids, "rc_ptr");
let alignment = layout.alignment_bytes(root.layout_interner, root.target_info);
let alignment = layout.alignment_bytes(layout_interner, root.target_info);
let ret_stmt = rc_return_stmt(root, ident_ids, ctx);
let modify_outer = modify_refcount(
root,
@ -1571,7 +1719,13 @@ fn refcount_boxed<'a>(
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)
.call_specialized_op(
ident_ids,
ctx,
layout_interner,
*inner_layout,
mod_inner_args,
)
.unwrap();
Stmt::Let(