diff --git a/compiler/gen_llvm/src/llvm/build.rs b/compiler/gen_llvm/src/llvm/build.rs index 9100f2bc64..cd2a76e585 100644 --- a/compiler/gen_llvm/src/llvm/build.rs +++ b/compiler/gen_llvm/src/llvm/build.rs @@ -970,15 +970,25 @@ pub fn build_exp_expr<'a, 'ctx, 'env>( struct_from_fields(env, struct_type, field_vals.into_iter().enumerate()).into() } - Tag { + Reuse { + arguments, + tag_layout: union_layout, + tag_id, + .. + } + | Tag { arguments, tag_layout: union_layout, tag_id, .. } => build_tag(env, scope, union_layout, *tag_id, arguments), - Reset(_) => todo!(), - Reuse { .. } => todo!(), + Reset(_) => { + // 1. fetch refcount + // 2. if rc == 1, reset the value + // TODO + env.context.i64_type().const_zero().into() + } StructAtIndex { index, structure, .. diff --git a/compiler/load/src/file.rs b/compiler/load/src/file.rs index a3f77a67f7..7c1a69c05f 100644 --- a/compiler/load/src/file.rs +++ b/compiler/load/src/file.rs @@ -2072,6 +2072,8 @@ fn update<'a>( &mut state.procedures, ); + Proc::insert_refcount_operations(arena, &mut state.procedures); + // display the mono IR of the module, for debug purposes if roc_mono::ir::PRETTY_PRINT_IR_SYMBOLS { let procs_string = state @@ -2085,8 +2087,6 @@ fn update<'a>( println!("{}", result); } - Proc::insert_refcount_operations(arena, &mut state.procedures); - // This is not safe with the new non-recursive RC updates that we do for tag unions // // Proc::optimize_refcount_operations( diff --git a/compiler/mono/src/alias_analysis.rs b/compiler/mono/src/alias_analysis.rs index a439cd62e0..7d3c509d70 100644 --- a/compiler/mono/src/alias_analysis.rs +++ b/compiler/mono/src/alias_analysis.rs @@ -832,7 +832,14 @@ fn expr_spec( match expr { Literal(literal) => literal_spec(builder, block, literal), Call(call) => call_spec(builder, env, block, layout, call), - Tag { + Reuse { + tag_layout, + tag_name: _, + tag_id, + arguments, + .. + } + | Tag { tag_layout, tag_name: _, tag_id, @@ -914,8 +921,12 @@ fn expr_spec( Err(()) => unreachable!("empty array does not have a list layout"), } } - Reuse { .. } => todo!("currently unused"), - Reset(_) => todo!("currently unused"), + Reset(symbol) => { + let type_id = layout_spec(builder, layout)?; + let value_id = env.symbols[symbol]; + + builder.add_unknown_with(block, &[value_id], type_id) + } RuntimeErrorFunction(_) => { let type_id = layout_spec(builder, layout)?; diff --git a/compiler/mono/src/ir.rs b/compiler/mono/src/ir.rs index 0a485d309e..a99f6ee844 100644 --- a/compiler/mono/src/ir.rs +++ b/compiler/mono/src/ir.rs @@ -234,7 +234,8 @@ impl<'a> Proc<'a> { procs: &mut MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>, ) { for (key, proc) in procs.iter_mut() { - let new_proc = crate::reset_reuse::insert_reset_reuse(arena, home, ident_ids, proc.clone()); + let new_proc = + crate::reset_reuse::insert_reset_reuse(arena, home, ident_ids, proc.clone()); *proc = new_proc; } } @@ -1287,11 +1288,12 @@ impl<'a> Expr<'a> { alloc .text("Reuse ") .append(symbol_to_doc(alloc, *symbol)) + .append(alloc.space()) .append(doc_tag) .append(alloc.space()) .append(alloc.intersperse(it, " ")) } - Reset(symbol) => alloc.text("Reuse ").append(symbol_to_doc(alloc, *symbol)), + Reset(symbol) => alloc.text("Reset ").append(symbol_to_doc(alloc, *symbol)), Struct(args) => { let it = args.iter().map(|s| symbol_to_doc(alloc, *s)); diff --git a/compiler/mono/src/reset_reuse.rs b/compiler/mono/src/reset_reuse.rs index 506bc6da20..39464fadfc 100644 --- a/compiler/mono/src/reset_reuse.rs +++ b/compiler/mono/src/reset_reuse.rs @@ -1,5 +1,5 @@ use crate::inc_dec::{collect_stmt, occurring_variables_expr, JPLiveVarMap, LiveVarSet}; -use crate::ir::{Call, Expr, Proc, Stmt, BranchInfo}; +use crate::ir::{BranchInfo, Call, Expr, Proc, Stmt}; use crate::layout::{Layout, UnionLayout}; use bumpalo::collections::Vec; use bumpalo::Bump; @@ -25,15 +25,16 @@ pub fn insert_reset_reuse<'a, 'i>( proc } +#[derive(Debug)] struct CtorInfo<'a> { id: u8, layout: UnionLayout<'a>, } fn may_reuse(tag_layout: UnionLayout, tag_id: u8, other: &CtorInfo) -> bool { - if tag_layout != other.layout { - return false; - } + // if tag_layout != other.layout { + // return false; + // } // if the tag id is represented as NULL, there is no memory to re-use match tag_layout { @@ -248,32 +249,34 @@ fn function_d_main<'a, 'i>( let arena = env.arena; match stmt { - Let(symbol, expr, layout, continuation) => match expr { - Expr::Tag { arguments, .. } if arguments.iter().any(|s| *s == x) => { - // If the scrutinee `x` (the one that is providing memory) is being - // stored in a constructor, then reuse will probably not be able to reuse memory at runtime. - // It may work only if the new cell is consumed, but we ignore this case. - (stmt, true) - } - _ => { - let (b, found) = function_d_main(env, x, c, continuation); + Let(symbol, expr, layout, continuation) => { + match expr { + Expr::Tag { arguments, .. } if arguments.iter().any(|s| *s == x) => { + // If the scrutinee `x` (the one that is providing memory) is being + // stored in a constructor, then reuse will probably not be able to reuse memory at runtime. + // It may work only if the new cell is consumed, but we ignore this case. + (stmt, true) + } + _ => { + let (b, found) = function_d_main(env, x, c, continuation); - let mut result = MutSet::default(); - if found || { - occurring_variables_expr(expr, &mut result); - !result.contains(&x) - } { - let let_stmt = Let(*symbol, expr.clone(), *layout, b); + let mut result = MutSet::default(); + if found || { + occurring_variables_expr(expr, &mut result); + !result.contains(&x) + } { + let let_stmt = Let(*symbol, expr.clone(), *layout, b); - (arena.alloc(let_stmt), found) - } else { - let b = try_function_s(env, x, c, b); - let let_stmt = Let(*symbol, expr.clone(), *layout, b); + (arena.alloc(let_stmt), found) + } else { + let b = try_function_s(env, x, c, b); + let let_stmt = Let(*symbol, expr.clone(), *layout, b); - (arena.alloc(let_stmt), found) + (arena.alloc(let_stmt), found) + } } } - }, + } Invoke { symbol, call, @@ -409,17 +412,19 @@ fn function_r<'a, 'i>(env: &mut Env<'a, 'i>, stmt: &'a Stmt<'a>) -> &'a Stmt<'a> let new_body = match info { BranchInfo::None => temp, - BranchInfo::Constructor { scrutinee, layout, tag_id } => { - match layout { - Layout::Union(union_layout) => { - let ctor_info = CtorInfo { - layout: *union_layout, - id: *tag_id, - }; - function_d(env, *scrutinee, &ctor_info, temp) - }, - _ => temp, + BranchInfo::Constructor { + scrutinee, + layout, + tag_id, + } => match layout { + Layout::Union(union_layout) => { + let ctor_info = CtorInfo { + layout: *union_layout, + id: *tag_id, + }; + function_d(env, *scrutinee, &ctor_info, temp) } + _ => temp, }, }; @@ -432,17 +437,19 @@ fn function_r<'a, 'i>(env: &mut Env<'a, 'i>, stmt: &'a Stmt<'a>) -> &'a Stmt<'a> let new_body = match info { BranchInfo::None => temp, - BranchInfo::Constructor { scrutinee, layout, tag_id } => { - match layout { - Layout::Union(union_layout) => { - let ctor_info = CtorInfo { - layout: *union_layout, - id: *tag_id, - }; - function_d(env, *scrutinee, &ctor_info, temp) - }, - _ => temp, + BranchInfo::Constructor { + scrutinee, + layout, + tag_id, + } => match layout { + Layout::Union(union_layout) => { + let ctor_info = CtorInfo { + layout: *union_layout, + id: *tag_id, + }; + function_d(env, *scrutinee, &ctor_info, temp) } + _ => temp, }, };