Merge branch 'main' into Frame-Limited

This commit is contained in:
J.Teeuwissen 2023-04-18 07:19:54 +02:00
commit 363e2e1074
No known key found for this signature in database
GPG key ID: DB5F7A1ED8D478AD
31 changed files with 1244 additions and 646 deletions

View file

@ -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,

View file

@ -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,