From c848a85eb41f8a6330f60e5e1029400f34694ad7 Mon Sep 17 00:00:00 2001 From: Folkert Date: Mon, 17 Apr 2023 14:09:49 +0200 Subject: [PATCH] fix index bug in recursive decrements --- .../mono/src/code_gen_help/refcount.rs | 25 ++++++++++++---- crates/compiler/mono/src/layout.rs | 5 +++- crates/compiler/test_gen/src/gen_refcount.rs | 30 +++++++++++++++++++ 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/crates/compiler/mono/src/code_gen_help/refcount.rs b/crates/compiler/mono/src/code_gen_help/refcount.rs index 9f646b2f18..ab13acaecd 100644 --- a/crates/compiler/mono/src/code_gen_help/refcount.rs +++ b/crates/compiler/mono/src/code_gen_help/refcount.rs @@ -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; @@ -1279,6 +1280,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::>(root.arena) + .into_bump_slice(); + let fields_stmt = refcount_tag_fields( root, ident_ids, @@ -1503,7 +1511,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)); @@ -1537,7 +1545,14 @@ fn refcount_union_tailrec<'a>( )), )); - (*field_layouts, tail_stmt) + let field_layouts = field_layouts + .iter() + .copied() + .enumerate() + .collect_in::>(root.arena) + .into_bump_slice(); + + (field_layouts, tail_stmt) }; let fields_stmt = refcount_tag_fields( @@ -1608,20 +1623,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); diff --git a/crates/compiler/mono/src/layout.rs b/crates/compiler/mono/src/layout.rs index 4d7e38e7a1..a90a275234 100644 --- a/crates/compiler/mono/src/layout.rs +++ b/crates/compiler/mono/src/layout.rs @@ -2661,7 +2661,10 @@ impl<'a> Layout<'a> { Layout::RecursivePointer(_) => { unreachable!("should be looked up to get an actual layout") } - Layout::Boxed(inner) => Ord::max(ptr_width, interner.get(*inner).alignment_bytes(interner, target_info)), + Layout::Boxed(inner) => Ord::max( + ptr_width, + interner.get(*inner).alignment_bytes(interner, target_info), + ), } } diff --git a/crates/compiler/test_gen/src/gen_refcount.rs b/crates/compiler/test_gen/src/gen_refcount.rs index dad781e82a..56393d78d4 100644 --- a/crates/compiler/test_gen/src/gen_refcount.rs +++ b/crates/compiler/test_gen/src/gen_refcount.rs @@ -496,3 +496,33 @@ fn boxed_str_dec() { ] ); } + +#[test] +#[cfg(any(feature = "gen-wasm"))] +fn non_nullable_unwrapped_alignment_8() { + assert_refcounts!( + indoc!( + r#" + Expr : [ZAdd Expr Expr, Val I64, Var I64] + + eval : Expr -> I64 + eval = \e -> + when e is + Var _ -> 0 + Val v -> v + ZAdd l r -> eval l + eval r + + expr : Expr + expr = (ZAdd (Val 4) (Val 5)) + + eval expr + "# + ), + i64, + &[ + Deallocated, // Val 4 + Deallocated, // Val 5 + Deallocated, // ZAdd _ _ + ] + ); +}