mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 13:59:08 +00:00
Wrap layouts in a LayoutRepr
constructor
Part 1 of support semantic layout representations.
This commit is contained in:
parent
c2d2bd4bb9
commit
c3eeb5e2cc
32 changed files with 1254 additions and 1021 deletions
|
@ -7,7 +7,7 @@ use crate::ir::{
|
|||
BranchInfo, Call, CallType, Expr, JoinPointId, Literal, Param, Stmt, UpdateModeId,
|
||||
};
|
||||
use crate::layout::{
|
||||
Builtin, InLayout, Layout, LayoutInterner, STLayoutInterner, TagIdIntType, UnionLayout,
|
||||
InLayout, Layout, LayoutInterner, LayoutRepr, STLayoutInterner, TagIdIntType, UnionLayout,
|
||||
};
|
||||
|
||||
use super::{let_lowlevel, CodeGenHelp, Context, LAYOUT_BOOL};
|
||||
|
@ -22,30 +22,26 @@ pub fn eq_generic<'a>(
|
|||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout: InLayout<'a>,
|
||||
) -> Stmt<'a> {
|
||||
let main_body = match layout_interner.get(layout) {
|
||||
Layout::Builtin(Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal) => {
|
||||
use crate::layout::Builtin::*;
|
||||
use LayoutRepr::*;
|
||||
let main_body = match layout_interner.get(layout).repr {
|
||||
Builtin(Int(_) | Float(_) | Bool | Decimal) => {
|
||||
unreachable!(
|
||||
"No generated proc for `==`. Use direct code gen for {:?}",
|
||||
layout
|
||||
)
|
||||
}
|
||||
Layout::Builtin(Builtin::Str) => {
|
||||
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, layout_interner, elem_layout)
|
||||
}
|
||||
Layout::Struct { field_layouts, .. } => {
|
||||
Builtin(List(elem_layout)) => eq_list(root, ident_ids, ctx, layout_interner, elem_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(_) => {
|
||||
Union(union_layout) => eq_tag_union(root, ident_ids, ctx, layout_interner, union_layout),
|
||||
Boxed(inner_layout) => eq_boxed(root, ident_ids, ctx, layout_interner, inner_layout),
|
||||
LambdaSet(_) => unreachable!("`==` is not defined on functions"),
|
||||
RecursivePointer(_) => {
|
||||
unreachable!(
|
||||
"Can't perform `==` on RecursivePointer. Should have been replaced by a tag union."
|
||||
)
|
||||
|
@ -440,7 +436,9 @@ fn eq_tag_union_help<'a>(
|
|||
if is_non_recursive {
|
||||
compare_ptr_or_value
|
||||
} else {
|
||||
let union_layout = layout_interner.insert(Layout::Union(union_layout));
|
||||
let union_layout = layout_interner.insert(Layout {
|
||||
repr: LayoutRepr::Union(union_layout),
|
||||
});
|
||||
let loop_params_iter = operands.iter().map(|arg| Param {
|
||||
symbol: *arg,
|
||||
ownership: Ownership::Borrowed,
|
||||
|
@ -472,9 +470,12 @@ fn eq_tag_fields<'a>(
|
|||
) -> Stmt<'a> {
|
||||
// Find a RecursivePointer to use in the tail recursion loop
|
||||
// (If there are more than one, the others will use non-tail recursion)
|
||||
let rec_ptr_index = field_layouts
|
||||
.iter()
|
||||
.position(|field| matches!(layout_interner.get(*field), Layout::RecursivePointer(_)));
|
||||
let rec_ptr_index = field_layouts.iter().position(|field| {
|
||||
matches!(
|
||||
layout_interner.get(*field).repr,
|
||||
LayoutRepr::RecursivePointer(_)
|
||||
)
|
||||
});
|
||||
|
||||
let (tailrec_index, innermost_stmt) = match rec_ptr_index {
|
||||
None => {
|
||||
|
@ -660,7 +661,9 @@ fn eq_list<'a>(
|
|||
let arena = root.arena;
|
||||
|
||||
// A "Box" layout (heap pointer to a single list element)
|
||||
let box_layout = layout_interner.insert(Layout::Boxed(elem_layout));
|
||||
let box_layout = layout_interner.insert(Layout {
|
||||
repr: LayoutRepr::Boxed(elem_layout),
|
||||
});
|
||||
|
||||
// Compare lengths
|
||||
|
||||
|
|
|
@ -10,7 +10,8 @@ use crate::ir::{
|
|||
Proc, ProcLayout, SelfRecursive, Stmt, UpdateModeId,
|
||||
};
|
||||
use crate::layout::{
|
||||
Builtin, InLayout, LambdaName, Layout, LayoutInterner, Niche, STLayoutInterner, UnionLayout,
|
||||
Builtin, InLayout, LambdaName, Layout, LayoutInterner, LayoutRepr, Niche, STLayoutInterner,
|
||||
UnionLayout,
|
||||
};
|
||||
|
||||
mod equality;
|
||||
|
@ -285,11 +286,13 @@ impl<'a> CodeGenHelp<'a> {
|
|||
self.debug_recursion_depth += 1;
|
||||
|
||||
let layout = if matches!(
|
||||
layout_interner.get(called_layout),
|
||||
Layout::RecursivePointer(_)
|
||||
layout_interner.get(called_layout).repr,
|
||||
LayoutRepr::RecursivePointer(_)
|
||||
) {
|
||||
let union_layout = ctx.recursive_union.unwrap();
|
||||
layout_interner.insert(Layout::Union(union_layout))
|
||||
layout_interner.insert(Layout {
|
||||
repr: LayoutRepr::Union(union_layout),
|
||||
})
|
||||
} else {
|
||||
called_layout
|
||||
};
|
||||
|
@ -300,7 +303,9 @@ impl<'a> CodeGenHelp<'a> {
|
|||
|
||||
let (ret_layout, arg_layouts): (InLayout<'a>, &'a [InLayout<'a>]) = {
|
||||
let arg = self.replace_rec_ptr(ctx, layout_interner, layout);
|
||||
let box_arg = layout_interner.insert(Layout::Boxed(arg));
|
||||
let box_arg = layout_interner.insert(Layout {
|
||||
repr: LayoutRepr::Boxed(arg),
|
||||
});
|
||||
|
||||
match ctx.op {
|
||||
Dec | DecRef(_) => (LAYOUT_UNIT, self.arena.alloc([arg])),
|
||||
|
@ -429,12 +434,16 @@ impl<'a> CodeGenHelp<'a> {
|
|||
}
|
||||
Dec | DecRef(_) | Reset | ResetRef => self.arena.alloc([roc_value]),
|
||||
IndirectInc => {
|
||||
let box_layout = layout_interner.insert(Layout::Boxed(layout));
|
||||
let box_layout = layout_interner.insert(Layout {
|
||||
repr: LayoutRepr::Boxed(layout),
|
||||
});
|
||||
let inc_amount = (self.layout_isize, ARG_2);
|
||||
self.arena.alloc([(box_layout, ARG_1), inc_amount])
|
||||
}
|
||||
IndirectDec => {
|
||||
let box_layout = layout_interner.insert(Layout::Boxed(layout));
|
||||
let box_layout = layout_interner.insert(Layout {
|
||||
repr: LayoutRepr::Boxed(layout),
|
||||
});
|
||||
self.arena.alloc([(box_layout, ARG_1)])
|
||||
}
|
||||
Eq => self.arena.alloc([roc_value, (layout, ARG_2)]),
|
||||
|
@ -482,7 +491,9 @@ impl<'a> CodeGenHelp<'a> {
|
|||
niche: Niche::NONE,
|
||||
},
|
||||
HelperOp::IndirectInc => {
|
||||
let box_layout = layout_interner.insert(Layout::Boxed(layout));
|
||||
let box_layout = layout_interner.insert(Layout {
|
||||
repr: LayoutRepr::Boxed(layout),
|
||||
});
|
||||
|
||||
ProcLayout {
|
||||
arguments: self.arena.alloc([box_layout, self.layout_isize]),
|
||||
|
@ -491,7 +502,9 @@ impl<'a> CodeGenHelp<'a> {
|
|||
}
|
||||
}
|
||||
HelperOp::IndirectDec => {
|
||||
let box_layout = layout_interner.insert(Layout::Boxed(layout));
|
||||
let box_layout = layout_interner.insert(Layout {
|
||||
repr: LayoutRepr::Boxed(layout),
|
||||
});
|
||||
|
||||
ProcLayout {
|
||||
arguments: self.arena.alloc([box_layout]),
|
||||
|
@ -532,15 +545,15 @@ impl<'a> CodeGenHelp<'a> {
|
|||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout: InLayout<'a>,
|
||||
) -> InLayout<'a> {
|
||||
let layout = match layout_interner.get(layout) {
|
||||
Layout::Builtin(Builtin::List(v)) => {
|
||||
let repr = match layout_interner.get(layout).repr {
|
||||
LayoutRepr::Builtin(Builtin::List(v)) => {
|
||||
let v = self.replace_rec_ptr(ctx, layout_interner, v);
|
||||
Layout::Builtin(Builtin::List(v))
|
||||
LayoutRepr::Builtin(Builtin::List(v))
|
||||
}
|
||||
|
||||
Layout::Builtin(_) => return layout,
|
||||
LayoutRepr::Builtin(_) => return layout,
|
||||
|
||||
Layout::Struct {
|
||||
LayoutRepr::Struct {
|
||||
field_layouts,
|
||||
field_order_hash,
|
||||
} => {
|
||||
|
@ -548,13 +561,13 @@ impl<'a> CodeGenHelp<'a> {
|
|||
for f in field_layouts.iter() {
|
||||
new_field_layouts.push(self.replace_rec_ptr(ctx, layout_interner, *f));
|
||||
}
|
||||
Layout::Struct {
|
||||
LayoutRepr::Struct {
|
||||
field_layouts: new_field_layouts.into_bump_slice(),
|
||||
field_order_hash,
|
||||
}
|
||||
}
|
||||
|
||||
Layout::Union(UnionLayout::NonRecursive(tags)) => {
|
||||
LayoutRepr::Union(UnionLayout::NonRecursive(tags)) => {
|
||||
let mut new_tags = Vec::with_capacity_in(tags.len(), self.arena);
|
||||
for fields in tags {
|
||||
let mut new_fields = Vec::with_capacity_in(fields.len(), self.arena);
|
||||
|
@ -563,28 +576,28 @@ impl<'a> CodeGenHelp<'a> {
|
|||
}
|
||||
new_tags.push(new_fields.into_bump_slice());
|
||||
}
|
||||
Layout::Union(UnionLayout::NonRecursive(new_tags.into_bump_slice()))
|
||||
LayoutRepr::Union(UnionLayout::NonRecursive(new_tags.into_bump_slice()))
|
||||
}
|
||||
|
||||
Layout::Union(_) => {
|
||||
LayoutRepr::Union(_) => {
|
||||
// we always fully unroll recursive types. That means tha when we find a
|
||||
// recursive tag union we can replace it with the layout
|
||||
return layout;
|
||||
}
|
||||
|
||||
Layout::Boxed(inner) => {
|
||||
LayoutRepr::Boxed(inner) => {
|
||||
let inner = self.replace_rec_ptr(ctx, layout_interner, inner);
|
||||
Layout::Boxed(inner)
|
||||
LayoutRepr::Boxed(inner)
|
||||
}
|
||||
|
||||
Layout::LambdaSet(lambda_set) => {
|
||||
LayoutRepr::LambdaSet(lambda_set) => {
|
||||
return self.replace_rec_ptr(ctx, layout_interner, lambda_set.representation)
|
||||
}
|
||||
|
||||
// This line is the whole point of the function
|
||||
Layout::RecursivePointer(_) => Layout::Union(ctx.recursive_union.unwrap()),
|
||||
LayoutRepr::RecursivePointer(_) => LayoutRepr::Union(ctx.recursive_union.unwrap()),
|
||||
};
|
||||
layout_interner.insert(layout)
|
||||
layout_interner.insert(Layout { repr })
|
||||
}
|
||||
|
||||
fn union_tail_recursion_fields(
|
||||
|
@ -668,16 +681,22 @@ impl<'a> CallerProc<'a> {
|
|||
};
|
||||
|
||||
let box_capture_layout = if let Some(capture_layout) = capture_layout {
|
||||
layout_interner.insert(Layout::Boxed(capture_layout))
|
||||
layout_interner.insert(Layout {
|
||||
repr: LayoutRepr::Boxed(capture_layout),
|
||||
})
|
||||
} else {
|
||||
layout_interner.insert(Layout::Boxed(Layout::UNIT))
|
||||
layout_interner.insert(Layout {
|
||||
repr: LayoutRepr::Boxed(Layout::UNIT),
|
||||
})
|
||||
};
|
||||
|
||||
let box_argument_layout =
|
||||
layout_interner.insert(Layout::Boxed(passed_function.argument_layouts[0]));
|
||||
let box_argument_layout = layout_interner.insert(Layout {
|
||||
repr: LayoutRepr::Boxed(passed_function.argument_layouts[0]),
|
||||
});
|
||||
|
||||
let box_return_layout =
|
||||
layout_interner.insert(Layout::Boxed(passed_function.return_layout));
|
||||
let box_return_layout = layout_interner.insert(Layout {
|
||||
repr: LayoutRepr::Boxed(passed_function.return_layout),
|
||||
});
|
||||
|
||||
let proc_layout = ProcLayout {
|
||||
arguments: arena.alloc([box_capture_layout, box_argument_layout, box_return_layout]),
|
||||
|
@ -826,22 +845,22 @@ fn layout_needs_helper_proc<'a>(
|
|||
layout: InLayout<'a>,
|
||||
op: HelperOp,
|
||||
) -> bool {
|
||||
match layout_interner.get(layout) {
|
||||
Layout::Builtin(Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal) => {
|
||||
false
|
||||
}
|
||||
Layout::Builtin(Builtin::Str) => {
|
||||
match layout_interner.get(layout).repr {
|
||||
LayoutRepr::Builtin(
|
||||
Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal,
|
||||
) => false,
|
||||
LayoutRepr::Builtin(Builtin::Str) => {
|
||||
// Str type can use either Zig functions or generated IR, since it's not generic.
|
||||
// Eq uses a Zig function, refcount uses generated IR.
|
||||
// Both are fine, they were just developed at different times.
|
||||
matches!(op, HelperOp::Inc | HelperOp::Dec | HelperOp::DecRef(_))
|
||||
}
|
||||
Layout::Builtin(Builtin::List(_)) => true,
|
||||
Layout::Struct { .. } => true, // note: we do generate a helper for Unit, with just a Stmt::Ret
|
||||
Layout::Union(UnionLayout::NonRecursive(tags)) => !tags.is_empty(),
|
||||
Layout::Union(_) => true,
|
||||
Layout::LambdaSet(_) => true,
|
||||
Layout::RecursivePointer(_) => false,
|
||||
Layout::Boxed(_) => true,
|
||||
LayoutRepr::Builtin(Builtin::List(_)) => true,
|
||||
LayoutRepr::Struct { .. } => true, // note: we do generate a helper for Unit, with just a Stmt::Ret
|
||||
LayoutRepr::Union(UnionLayout::NonRecursive(tags)) => !tags.is_empty(),
|
||||
LayoutRepr::Union(_) => true,
|
||||
LayoutRepr::LambdaSet(_) => true,
|
||||
LayoutRepr::RecursivePointer(_) => false,
|
||||
LayoutRepr::Boxed(_) => true,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,8 @@ use crate::ir::{
|
|||
BranchInfo, Call, CallType, Expr, JoinPointId, Literal, ModifyRc, Param, Stmt, UpdateModeId,
|
||||
};
|
||||
use crate::layout::{
|
||||
Builtin, InLayout, Layout, LayoutInterner, STLayoutInterner, TagIdIntType, UnionLayout,
|
||||
Builtin, InLayout, Layout, LayoutInterner, LayoutRepr, STLayoutInterner, TagIdIntType,
|
||||
UnionLayout,
|
||||
};
|
||||
|
||||
use super::{CodeGenHelp, Context, HelperOp};
|
||||
|
@ -74,9 +75,9 @@ pub fn refcount_stmt<'a>(
|
|||
}
|
||||
|
||||
ModifyRc::DecRef(structure) => {
|
||||
match layout_interner.get(layout) {
|
||||
match layout_interner.get(layout).repr {
|
||||
// Str has no children, so Dec is the same as DecRef.
|
||||
Layout::Builtin(Builtin::Str) => {
|
||||
LayoutRepr::Builtin(Builtin::Str) => {
|
||||
ctx.op = HelperOp::Dec;
|
||||
refcount_stmt(
|
||||
root,
|
||||
|
@ -90,8 +91,8 @@ pub fn refcount_stmt<'a>(
|
|||
}
|
||||
|
||||
// Struct and non-recursive Unions are stack-only, so DecRef is a no-op
|
||||
Layout::Struct { .. } => following,
|
||||
Layout::Union(UnionLayout::NonRecursive(_)) => following,
|
||||
LayoutRepr::Struct { .. } => following,
|
||||
LayoutRepr::Union(UnionLayout::NonRecursive(_)) => following,
|
||||
|
||||
// Inline the refcounting code instead of making a function. Don't iterate fields,
|
||||
// and replace any return statements with jumps to the `following` statement.
|
||||
|
@ -181,14 +182,16 @@ pub fn refcount_generic<'a>(
|
|||
layout: InLayout<'a>,
|
||||
structure: Symbol,
|
||||
) -> Stmt<'a> {
|
||||
match layout_interner.get(layout) {
|
||||
Layout::Builtin(Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal) => {
|
||||
match layout_interner.get(layout).repr {
|
||||
LayoutRepr::Builtin(
|
||||
Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal,
|
||||
) => {
|
||||
// Generate a dummy function that immediately returns Unit
|
||||
// Some higher-order Zig builtins *always* call an RC function on List elements.
|
||||
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(
|
||||
LayoutRepr::Builtin(Builtin::Str) => refcount_str(root, ident_ids, ctx),
|
||||
LayoutRepr::Builtin(Builtin::List(elem_layout)) => refcount_list(
|
||||
root,
|
||||
ident_ids,
|
||||
ctx,
|
||||
|
@ -196,7 +199,7 @@ pub fn refcount_generic<'a>(
|
|||
elem_layout,
|
||||
structure,
|
||||
),
|
||||
Layout::Struct { field_layouts, .. } => refcount_struct(
|
||||
LayoutRepr::Struct { field_layouts, .. } => refcount_struct(
|
||||
root,
|
||||
ident_ids,
|
||||
ctx,
|
||||
|
@ -204,7 +207,7 @@ pub fn refcount_generic<'a>(
|
|||
field_layouts,
|
||||
structure,
|
||||
),
|
||||
Layout::Union(union_layout) => refcount_union(
|
||||
LayoutRepr::Union(union_layout) => refcount_union(
|
||||
root,
|
||||
ident_ids,
|
||||
ctx,
|
||||
|
@ -213,7 +216,7 @@ pub fn refcount_generic<'a>(
|
|||
union_layout,
|
||||
structure,
|
||||
),
|
||||
Layout::LambdaSet(lambda_set) => {
|
||||
LayoutRepr::LambdaSet(lambda_set) => {
|
||||
let runtime_layout = lambda_set.representation;
|
||||
refcount_generic(
|
||||
root,
|
||||
|
@ -224,10 +227,10 @@ pub fn refcount_generic<'a>(
|
|||
structure,
|
||||
)
|
||||
}
|
||||
Layout::RecursivePointer(_) => unreachable!(
|
||||
LayoutRepr::RecursivePointer(_) => unreachable!(
|
||||
"We should never call a refcounting helper on a RecursivePointer layout directly"
|
||||
),
|
||||
Layout::Boxed(inner_layout) => refcount_boxed(
|
||||
LayoutRepr::Boxed(inner_layout) => refcount_boxed(
|
||||
root,
|
||||
ident_ids,
|
||||
ctx,
|
||||
|
@ -298,15 +301,17 @@ pub fn refcount_reset_proc_body<'a>(
|
|||
let is_unique = root.create_symbol(ident_ids, "is_unique");
|
||||
let addr = root.create_symbol(ident_ids, "addr");
|
||||
|
||||
let union_layout = match layout_interner.get(layout) {
|
||||
Layout::Union(u) => u,
|
||||
let union_layout = match layout_interner.get(layout).repr {
|
||||
LayoutRepr::Union(u) => u,
|
||||
_ => unimplemented!("Reset is only implemented for UnionLayout"),
|
||||
};
|
||||
|
||||
// Whenever we recurse into a child layout we will want to Decrement
|
||||
ctx.op = HelperOp::Dec;
|
||||
ctx.recursive_union = Some(union_layout);
|
||||
let recursion_ptr = layout_interner.insert(Layout::RecursivePointer(layout));
|
||||
let recursion_ptr = layout_interner.insert(Layout {
|
||||
repr: LayoutRepr::RecursivePointer(layout),
|
||||
});
|
||||
|
||||
// Reset structure is unique. Decrement its children and return a pointer to the allocation.
|
||||
let then_stmt = {
|
||||
|
@ -480,15 +485,17 @@ pub fn refcount_resetref_proc_body<'a>(
|
|||
let is_unique = root.create_symbol(ident_ids, "is_unique");
|
||||
let addr = root.create_symbol(ident_ids, "addr");
|
||||
|
||||
let union_layout = match layout_interner.get(layout) {
|
||||
Layout::Union(u) => u,
|
||||
let union_layout = match layout_interner.get(layout).repr {
|
||||
LayoutRepr::Union(u) => u,
|
||||
_ => unimplemented!("Reset is only implemented for UnionLayout"),
|
||||
};
|
||||
|
||||
// Whenever we recurse into a child layout we will want to Decrement
|
||||
ctx.op = HelperOp::Dec;
|
||||
ctx.recursive_union = Some(union_layout);
|
||||
let recursion_ptr = layout_interner.insert(Layout::RecursivePointer(layout));
|
||||
let recursion_ptr = layout_interner.insert(Layout {
|
||||
repr: LayoutRepr::RecursivePointer(layout),
|
||||
});
|
||||
|
||||
// Reset structure is unique. Return a pointer to the allocation.
|
||||
let then_stmt = Stmt::Ret(addr);
|
||||
|
@ -859,7 +866,9 @@ fn refcount_list<'a>(
|
|||
let arena = root.arena;
|
||||
|
||||
// A "Box" layout (heap pointer to a single list element)
|
||||
let box_layout = layout_interner.insert(Layout::Boxed(elem_layout));
|
||||
let box_layout = layout_interner.insert(Layout {
|
||||
repr: LayoutRepr::Boxed(elem_layout),
|
||||
});
|
||||
|
||||
//
|
||||
// Check if the list is empty
|
||||
|
@ -1480,8 +1489,10 @@ fn refcount_union_rec<'a>(
|
|||
};
|
||||
|
||||
let rc_structure_stmt = {
|
||||
let alignment = Layout::Union(union_layout)
|
||||
.allocation_alignment_bytes(layout_interner, root.target_info);
|
||||
let alignment = Layout {
|
||||
repr: LayoutRepr::Union(union_layout),
|
||||
}
|
||||
.allocation_alignment_bytes(layout_interner, root.target_info);
|
||||
let ret_stmt = rc_return_stmt(root, ident_ids, ctx);
|
||||
|
||||
modify_refcount(
|
||||
|
@ -1537,7 +1548,9 @@ fn refcount_union_tailrec<'a>(
|
|||
let tailrec_loop = JoinPointId(root.create_symbol(ident_ids, "tailrec_loop"));
|
||||
let current = root.create_symbol(ident_ids, "current");
|
||||
let next_ptr = root.create_symbol(ident_ids, "next_ptr");
|
||||
let layout = layout_interner.insert(Layout::Union(union_layout));
|
||||
let layout = layout_interner.insert(Layout {
|
||||
repr: LayoutRepr::Union(union_layout),
|
||||
});
|
||||
|
||||
let tag_id_layout = union_layout.tag_id_layout();
|
||||
|
||||
|
@ -1682,7 +1695,9 @@ fn refcount_union_tailrec<'a>(
|
|||
let jump_with_null_ptr = Stmt::Let(
|
||||
null_pointer,
|
||||
Expr::NullPointer,
|
||||
layout_interner.insert(Layout::Union(union_layout)),
|
||||
layout_interner.insert(Layout {
|
||||
repr: LayoutRepr::Union(union_layout),
|
||||
}),
|
||||
root.arena.alloc(Stmt::Jump(
|
||||
jp_modify_union,
|
||||
root.arena.alloc([null_pointer]),
|
||||
|
@ -1726,7 +1741,9 @@ fn refcount_union_tailrec<'a>(
|
|||
));
|
||||
|
||||
let loop_init = Stmt::Jump(tailrec_loop, root.arena.alloc([initial_structure]));
|
||||
let union_layout = layout_interner.insert(Layout::Union(union_layout));
|
||||
let union_layout = layout_interner.insert(Layout {
|
||||
repr: LayoutRepr::Union(union_layout),
|
||||
});
|
||||
let loop_param = Param {
|
||||
symbol: current,
|
||||
ownership: Ownership::Borrowed,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue