mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Merge branch 'main' into Frame-Limited
This commit is contained in:
commit
363e2e1074
31 changed files with 1244 additions and 646 deletions
|
@ -213,7 +213,7 @@ fn eq_tag_union<'a>(
|
|||
layout_interner,
|
||||
union_layout,
|
||||
tags,
|
||||
None,
|
||||
NullableId::None,
|
||||
),
|
||||
|
||||
Recursive(tags) => eq_tag_union_help(
|
||||
|
@ -223,7 +223,7 @@ fn eq_tag_union<'a>(
|
|||
layout_interner,
|
||||
union_layout,
|
||||
tags,
|
||||
None,
|
||||
NullableId::None,
|
||||
),
|
||||
|
||||
NonNullableUnwrapped(field_layouts) => {
|
||||
|
@ -235,7 +235,7 @@ fn eq_tag_union<'a>(
|
|||
layout_interner,
|
||||
union_layout,
|
||||
tags,
|
||||
None,
|
||||
NullableId::None,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -249,7 +249,7 @@ fn eq_tag_union<'a>(
|
|||
layout_interner,
|
||||
union_layout,
|
||||
other_tags,
|
||||
Some(nullable_id),
|
||||
NullableId::Wrapped(nullable_id),
|
||||
),
|
||||
|
||||
NullableUnwrapped {
|
||||
|
@ -262,7 +262,7 @@ fn eq_tag_union<'a>(
|
|||
layout_interner,
|
||||
union_layout,
|
||||
root.arena.alloc([other_fields]),
|
||||
Some(nullable_id as TagIdIntType),
|
||||
NullableId::Unwrapped(nullable_id),
|
||||
),
|
||||
};
|
||||
|
||||
|
@ -271,6 +271,12 @@ fn eq_tag_union<'a>(
|
|||
body
|
||||
}
|
||||
|
||||
enum NullableId {
|
||||
None,
|
||||
Wrapped(TagIdIntType),
|
||||
Unwrapped(bool),
|
||||
}
|
||||
|
||||
fn eq_tag_union_help<'a>(
|
||||
root: &mut CodeGenHelp<'a>,
|
||||
ident_ids: &mut IdentIds,
|
||||
|
@ -278,7 +284,7 @@ fn eq_tag_union_help<'a>(
|
|||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
union_layout: UnionLayout<'a>,
|
||||
tag_layouts: &'a [&'a [InLayout<'a>]],
|
||||
nullable_id: Option<TagIdIntType>,
|
||||
nullable_id: NullableId,
|
||||
) -> Stmt<'a> {
|
||||
let tailrec_loop = JoinPointId(root.create_symbol(ident_ids, "tailrec_loop"));
|
||||
let is_non_recursive = matches!(union_layout, UnionLayout::NonRecursive(_));
|
||||
|
@ -340,33 +346,46 @@ fn eq_tag_union_help<'a>(
|
|||
let mut tag_branches = Vec::with_capacity_in(tag_layouts.len(), root.arena);
|
||||
|
||||
// If there's a null tag, check it first. We might not need to load any data from memory.
|
||||
if let Some(id) = nullable_id {
|
||||
if let NullableId::Wrapped(id) = nullable_id {
|
||||
tag_branches.push((id as u64, BranchInfo::None, Stmt::Ret(Symbol::BOOL_TRUE)))
|
||||
} else if let NullableId::Unwrapped(id) = nullable_id {
|
||||
tag_branches.push((
|
||||
id as TagIdIntType as u64,
|
||||
BranchInfo::None,
|
||||
Stmt::Ret(Symbol::BOOL_TRUE),
|
||||
))
|
||||
}
|
||||
|
||||
let mut tag_id: TagIdIntType = 0;
|
||||
for field_layouts in tag_layouts.iter().take(tag_layouts.len() - 1) {
|
||||
if let Some(null_id) = nullable_id {
|
||||
if tag_id == null_id as TagIdIntType {
|
||||
tag_id += 1;
|
||||
let default_tag = if let NullableId::Unwrapped(tag_id) = nullable_id {
|
||||
(!tag_id) as TagIdIntType
|
||||
} else {
|
||||
let mut tag_id: TagIdIntType = 0;
|
||||
|
||||
for field_layouts in tag_layouts.iter().take(tag_layouts.len() - 1) {
|
||||
if let NullableId::Wrapped(null_id) = nullable_id {
|
||||
if tag_id == null_id as TagIdIntType {
|
||||
tag_id += 1;
|
||||
}
|
||||
}
|
||||
|
||||
let tag_stmt = eq_tag_fields(
|
||||
root,
|
||||
ident_ids,
|
||||
ctx,
|
||||
layout_interner,
|
||||
tailrec_loop,
|
||||
union_layout,
|
||||
field_layouts,
|
||||
operands,
|
||||
tag_id,
|
||||
);
|
||||
tag_branches.push((tag_id as u64, BranchInfo::None, tag_stmt));
|
||||
|
||||
tag_id += 1;
|
||||
}
|
||||
|
||||
let tag_stmt = eq_tag_fields(
|
||||
root,
|
||||
ident_ids,
|
||||
ctx,
|
||||
layout_interner,
|
||||
tailrec_loop,
|
||||
union_layout,
|
||||
field_layouts,
|
||||
operands,
|
||||
tag_id,
|
||||
);
|
||||
tag_branches.push((tag_id as u64, BranchInfo::None, tag_stmt));
|
||||
|
||||
tag_id += 1;
|
||||
}
|
||||
tag_id
|
||||
};
|
||||
|
||||
let tag_switch_stmt = Stmt::Switch {
|
||||
cond_symbol: tag_id_a,
|
||||
|
@ -383,7 +402,7 @@ fn eq_tag_union_help<'a>(
|
|||
union_layout,
|
||||
tag_layouts.last().unwrap(),
|
||||
operands,
|
||||
tag_id,
|
||||
default_tag,
|
||||
)),
|
||||
),
|
||||
ret_layout: LAYOUT_BOOL,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
use bumpalo::collections::vec::Vec;
|
||||
use bumpalo::collections::CollectIn;
|
||||
use roc_module::low_level::{LowLevel, LowLevel::*};
|
||||
use roc_module::symbol::{IdentIds, Symbol};
|
||||
use roc_target::PtrWidth;
|
||||
|
@ -258,12 +259,10 @@ 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_interner
|
||||
.get(layout)
|
||||
.alignment_bytes(layout_interner, root.target_info) as i128)
|
||||
.to_ne_bytes(),
|
||||
));
|
||||
let alignment_int = layout_interner
|
||||
.get(layout)
|
||||
.allocation_alignment_bytes(layout_interner, root.target_info);
|
||||
let alignment_expr = Expr::Literal(Literal::Int((alignment_int as i128).to_ne_bytes()));
|
||||
let alloc_addr = root.create_symbol(ident_ids, "alloc_addr");
|
||||
let alloc_addr_expr = Expr::Call(Call {
|
||||
call_type: CallType::LowLevel {
|
||||
|
@ -756,6 +755,7 @@ fn modify_refcount<'a>(
|
|||
}
|
||||
|
||||
HelperOp::Dec | HelperOp::DecRef(_) => {
|
||||
debug_assert!(alignment >= root.target_info.ptr_width() as u32);
|
||||
let alignment_sym = root.create_symbol(ident_ids, "alignment");
|
||||
let alignment_expr = Expr::Literal(Literal::Int((alignment as i128).to_ne_bytes()));
|
||||
let alignment_stmt = |next| Stmt::Let(alignment_sym, alignment_expr, LAYOUT_U32, next);
|
||||
|
@ -933,7 +933,10 @@ fn refcount_list<'a>(
|
|||
//
|
||||
|
||||
let rc_ptr = root.create_symbol(ident_ids, "rc_ptr");
|
||||
let elem_alignment = layout_interner.alignment_bytes(elem_layout);
|
||||
let alignment = Ord::max(
|
||||
root.target_info.ptr_width() as u32,
|
||||
layout_interner.alignment_bytes(elem_layout),
|
||||
);
|
||||
|
||||
let ret_stmt = rc_return_stmt(root, ident_ids, ctx);
|
||||
let modify_list = modify_refcount(
|
||||
|
@ -941,7 +944,7 @@ fn refcount_list<'a>(
|
|||
ident_ids,
|
||||
ctx,
|
||||
rc_ptr,
|
||||
elem_alignment,
|
||||
alignment,
|
||||
arena.alloc(ret_stmt),
|
||||
);
|
||||
|
||||
|
@ -1439,6 +1442,13 @@ fn refcount_union_contents<'a>(
|
|||
// (Order is important, to avoid use-after-free for Dec)
|
||||
let following = Stmt::Jump(jp_contents_modified, &[]);
|
||||
|
||||
let field_layouts = field_layouts
|
||||
.iter()
|
||||
.copied()
|
||||
.enumerate()
|
||||
.collect_in::<Vec<_>>(root.arena)
|
||||
.into_bump_slice();
|
||||
|
||||
let fields_stmt = refcount_tag_fields(
|
||||
root,
|
||||
ident_ids,
|
||||
|
@ -1503,8 +1513,8 @@ fn refcount_union_rec<'a>(
|
|||
let rc_structure_stmt = {
|
||||
let rc_ptr = root.create_symbol(ident_ids, "rc_ptr");
|
||||
|
||||
let alignment =
|
||||
Layout::Union(union_layout).alignment_bytes(layout_interner, root.target_info);
|
||||
let alignment = Layout::Union(union_layout)
|
||||
.allocation_alignment_bytes(layout_interner, root.target_info);
|
||||
let ret_stmt = rc_return_stmt(root, ident_ids, ctx);
|
||||
let modify_structure_stmt = modify_refcount(
|
||||
root,
|
||||
|
@ -1615,7 +1625,7 @@ fn refcount_union_tailrec<'a>(
|
|||
)
|
||||
};
|
||||
|
||||
let alignment = layout_interner.alignment_bytes(layout);
|
||||
let alignment = layout_interner.allocation_alignment_bytes(layout);
|
||||
let modify_structure_stmt = modify_refcount(
|
||||
root,
|
||||
ident_ids,
|
||||
|
@ -1663,7 +1673,7 @@ fn refcount_union_tailrec<'a>(
|
|||
let mut tail_stmt = None;
|
||||
for (i, field) in field_layouts.iter().enumerate() {
|
||||
if i != tailrec_index {
|
||||
filtered.push(*field);
|
||||
filtered.push((i, *field));
|
||||
} else {
|
||||
let field_val =
|
||||
root.create_symbol(ident_ids, &format!("field_{}_{}", tag_id, i));
|
||||
|
@ -1697,7 +1707,14 @@ fn refcount_union_tailrec<'a>(
|
|||
)),
|
||||
));
|
||||
|
||||
(*field_layouts, tail_stmt)
|
||||
let field_layouts = field_layouts
|
||||
.iter()
|
||||
.copied()
|
||||
.enumerate()
|
||||
.collect_in::<Vec<_>>(root.arena)
|
||||
.into_bump_slice();
|
||||
|
||||
(field_layouts, tail_stmt)
|
||||
};
|
||||
|
||||
let fields_stmt = refcount_tag_fields(
|
||||
|
@ -1768,20 +1785,20 @@ fn refcount_tag_fields<'a>(
|
|||
ctx: &mut Context<'a>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
union_layout: UnionLayout<'a>,
|
||||
field_layouts: &'a [InLayout<'a>],
|
||||
field_layouts: &'a [(usize, InLayout<'a>)],
|
||||
structure: Symbol,
|
||||
tag_id: TagIdIntType,
|
||||
following: Stmt<'a>,
|
||||
) -> Stmt<'a> {
|
||||
let mut stmt = following;
|
||||
|
||||
for (i, field_layout) in field_layouts.iter().enumerate().rev() {
|
||||
for (i, field_layout) in field_layouts.iter().rev() {
|
||||
if layout_interner.contains_refcounted(*field_layout) {
|
||||
let field_val = root.create_symbol(ident_ids, &format!("field_{}_{}", tag_id, i));
|
||||
let field_val_expr = Expr::UnionAtIndex {
|
||||
union_layout,
|
||||
tag_id,
|
||||
index: i as u64,
|
||||
index: *i as u64,
|
||||
structure,
|
||||
};
|
||||
let field_val_stmt = |next| Stmt::Let(field_val, field_val_expr, *field_layout, next);
|
||||
|
@ -1824,7 +1841,7 @@ fn refcount_boxed<'a>(
|
|||
//
|
||||
|
||||
let rc_ptr = root.create_symbol(ident_ids, "rc_ptr");
|
||||
let alignment = layout_interner.alignment_bytes(layout);
|
||||
let alignment = layout_interner.allocation_alignment_bytes(layout);
|
||||
let ret_stmt = rc_return_stmt(root, ident_ids, ctx);
|
||||
let modify_outer = modify_refcount(
|
||||
root,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue