mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Push interned layouts as mut throughout the backend, and intern box layouts
This commit is contained in:
parent
dd6a72fc46
commit
7ab7fdfa7b
26 changed files with 769 additions and 375 deletions
|
@ -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);
|
||||
|
|
|
@ -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()),
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue