diff --git a/compiler/gen_dev/src/lib.rs b/compiler/gen_dev/src/lib.rs index 09f24f1a51..803ec32f4b 100644 --- a/compiler/gen_dev/src/lib.rs +++ b/compiler/gen_dev/src/lib.rs @@ -686,8 +686,8 @@ where self.set_last_seen(*sym, stmt, &owning_symbol); } } - Expr::Reset(sym) => { - self.set_last_seen(*sym, stmt, &owning_symbol); + Expr::Reset { symbol, .. } => { + self.set_last_seen(*symbol, stmt, &owning_symbol); } Expr::EmptyArray => {} Expr::RuntimeErrorFunction(_) => {} diff --git a/compiler/gen_llvm/src/llvm/build.rs b/compiler/gen_llvm/src/llvm/build.rs index a5038fc2a5..69168415c0 100644 --- a/compiler/gen_llvm/src/llvm/build.rs +++ b/compiler/gen_llvm/src/llvm/build.rs @@ -1108,7 +1108,7 @@ pub fn build_exp_expr<'a, 'ctx, 'env>( .. } => build_tag(env, scope, union_layout, *tag_id, arguments, None, parent), - Reset(symbol) => { + Reset { symbol, .. } => { let (tag_ptr, layout) = load_symbol_and_layout(scope, symbol); let tag_ptr = tag_ptr.into_pointer_value(); diff --git a/compiler/load/src/file.rs b/compiler/load/src/file.rs index 4ac1f371e1..c75a803ea2 100644 --- a/compiler/load/src/file.rs +++ b/compiler/load/src/file.rs @@ -20,6 +20,7 @@ use roc_module::symbol::{ }; use roc_mono::ir::{ CapturedSymbols, EntryPoint, ExternalSpecializations, PartialProc, Proc, ProcLayout, Procs, + UpdateModeIds, }; use roc_mono::layout::{Layout, LayoutCache, LayoutProblem}; use roc_parse::ast::{self, StrLiteral, TypeAnnotation}; @@ -835,6 +836,7 @@ enum Msg<'a> { external_specializations_requested: BumpMap, procedures: MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>, problems: Vec, + update_mode_ids: UpdateModeIds, module_timing: ModuleTiming, subs: Subs, }, @@ -2098,6 +2100,7 @@ fn update<'a>( MadeSpecializations { module_id, mut ident_ids, + mut update_mode_ids, subs, procedures, external_specializations_requested, @@ -2124,6 +2127,7 @@ fn update<'a>( arena, module_id, &mut ident_ids, + &mut update_mode_ids, &mut state.procedures, ); @@ -3922,6 +3926,7 @@ fn make_specializations<'a>( ) -> Msg<'a> { let make_specializations_start = SystemTime::now(); let mut mono_problems = Vec::new(); + let mut update_mode_ids = UpdateModeIds::new(); // do the thing let mut mono_env = roc_mono::ir::Env { arena, @@ -3930,7 +3935,7 @@ fn make_specializations<'a>( home, ident_ids: &mut ident_ids, ptr_bytes, - update_mode_counter: 0, + update_mode_ids: &mut update_mode_ids, // call_specialization_counter=0 is reserved call_specialization_counter: 1, }; @@ -3973,6 +3978,7 @@ fn make_specializations<'a>( layout_cache, procedures, problems: mono_problems, + update_mode_ids, subs, external_specializations_requested, module_timing, @@ -4016,6 +4022,7 @@ fn build_pending_specializations<'a>( }; let mut mono_problems = std::vec::Vec::new(); + let mut update_mode_ids = UpdateModeIds::new(); let mut subs = solved_subs.into_inner(); let mut mono_env = roc_mono::ir::Env { arena, @@ -4024,7 +4031,7 @@ fn build_pending_specializations<'a>( home, ident_ids: &mut ident_ids, ptr_bytes, - update_mode_counter: 0, + update_mode_ids: &mut update_mode_ids, // call_specialization_counter=0 is reserved call_specialization_counter: 1, }; diff --git a/compiler/mono/src/alias_analysis.rs b/compiler/mono/src/alias_analysis.rs index 88a2b1ce46..0803bac802 100644 --- a/compiler/mono/src/alias_analysis.rs +++ b/compiler/mono/src/alias_analysis.rs @@ -210,12 +210,15 @@ where let mut builder = TypeDefBuilder::new(); - let variant_types = build_variant_types(&mut builder, &union_layout)?; + let variant_types = recursive_variant_types(&mut builder, &union_layout)?; let root_type = if let UnionLayout::NonNullableUnwrapped(_) = union_layout { debug_assert_eq!(variant_types.len(), 1); variant_types[0] } else { - builder.add_union_type(&variant_types)? + let data_type = builder.add_union_type(&variant_types)?; + let cell_type = builder.add_heap_cell_type(); + + builder.add_tuple_type(&[cell_type, data_type])? }; let type_def = builder.build(root_type)?; @@ -867,8 +870,7 @@ fn call_spec( builder.add_update(block, update_mode_var, cell)?; - let new_cell = builder.add_new_heap_cell(block)?; - builder.add_make_tuple(block, &[new_cell, bag]) + with_new_heap_cell(builder, block, bag) }; let state_layout = Layout::Builtin(Builtin::List(&arg_layouts[0])); @@ -998,9 +1000,8 @@ fn call_spec( builder.add_recursive_touch(block, removed_element)?; let new_bag = builder.add_get_tuple_field(block, removed, 0)?; - let new_cell = builder.add_new_heap_cell(block)?; - builder.add_make_tuple(block, &[new_cell, new_bag]) + with_new_heap_cell(builder, block, new_bag) }; let state_layout = Layout::Builtin(Builtin::List(&arg_layouts[0])); @@ -1181,8 +1182,7 @@ fn list_append( let new_bag = builder.add_bag_insert(block, bag, to_insert)?; - let new_cell = builder.add_new_heap_cell(block)?; - builder.add_make_tuple(block, &[new_cell, new_bag]) + with_new_heap_cell(builder, block, new_bag) } fn lowlevel_spec( @@ -1268,8 +1268,7 @@ fn lowlevel_spec( builder.add_bag_insert(block, bag, to_insert)?; - let new_cell = builder.add_new_heap_cell(block)?; - builder.add_make_tuple(block, &[new_cell, bag]) + with_new_heap_cell(builder, block, bag) } ListSwap => { let list = env.symbols[&arguments[0]]; @@ -1279,8 +1278,7 @@ fn lowlevel_spec( let _unit = builder.add_update(block, update_mode_var, cell)?; - let new_cell = builder.add_new_heap_cell(block)?; - builder.add_make_tuple(block, &[new_cell, bag]) + with_new_heap_cell(builder, block, bag) } ListReverse => { let list = env.symbols[&arguments[0]]; @@ -1290,8 +1288,7 @@ fn lowlevel_spec( let _unit = builder.add_update(block, update_mode_var, cell)?; - let new_cell = builder.add_new_heap_cell(block)?; - builder.add_make_tuple(block, &[new_cell, bag]) + with_new_heap_cell(builder, block, bag) } ListAppend => { let list = env.symbols[&arguments[0]]; @@ -1359,8 +1356,7 @@ fn lowlevel_spec( builder.add_bag_insert(block, bag, key_value)?; - let new_cell = builder.add_new_heap_cell(block)?; - builder.add_make_tuple(block, &[new_cell, bag]) + with_new_heap_cell(builder, block, bag) } _other => { // println!("missing {:?}", _other); @@ -1381,13 +1377,10 @@ fn recursive_tag_variant( ) -> Result { let when_recursive = WhenRecursive::Loop(*union_layout); - let data_id = build_recursive_tuple_type(builder, fields, &when_recursive)?; - let cell_id = builder.add_heap_cell_type(); - - builder.add_tuple_type(&[cell_id, data_id]) + build_recursive_tuple_type(builder, fields, &when_recursive) } -fn build_variant_types( +fn recursive_variant_types( builder: &mut impl TypeContext, union_layout: &UnionLayout, ) -> Result> { @@ -1396,12 +1389,8 @@ fn build_variant_types( let mut result; match union_layout { - NonRecursive(tags) => { - result = Vec::with_capacity(tags.len()); - - for tag in tags.iter() { - result.push(build_tuple_type(builder, tag)?); - } + NonRecursive(_) => { + unreachable!() } Recursive(tags) => { result = Vec::with_capacity(tags.len()); @@ -1425,8 +1414,7 @@ fn build_variant_types( result.push(recursive_tag_variant(builder, union_layout, tag)?); } - let unit = builder.add_tuple_type(&[])?; - result.push(unit); + result.push(recursive_tag_variant(builder, union_layout, &[])?); for tag in tags[cutoff..].iter() { result.push(recursive_tag_variant(builder, union_layout, tag)?); @@ -1436,7 +1424,7 @@ fn build_variant_types( nullable_id, other_fields: fields, } => { - let unit = builder.add_tuple_type(&[])?; + let unit = recursive_tag_variant(builder, union_layout, &[])?; let other_type = recursive_tag_variant(builder, union_layout, fields)?; if *nullable_id { @@ -1482,18 +1470,16 @@ fn expr_spec<'a>( tag_id, arguments, } => { - let variant_types = build_variant_types(builder, tag_layout)?; - let data_id = build_tuple_value(builder, env, block, arguments)?; - let cell_id = builder.add_new_heap_cell(block)?; let value_id = match tag_layout { - UnionLayout::NonRecursive(_) => { + UnionLayout::NonRecursive(tags) => { + let variant_types = non_recursive_variant_types(builder, tags)?; let value_id = build_tuple_value(builder, env, block, arguments)?; return builder.add_make_union(block, &variant_types, *tag_id as u32, value_id); } UnionLayout::NonNullableUnwrapped(_) => { - let value_id = builder.add_make_tuple(block, &[cell_id, data_id])?; + let value_id = data_id; let type_name_bytes = recursive_tag_union_name_bytes(tag_layout).as_bytes(); let type_name = TypeName(&type_name_bytes); @@ -1502,32 +1488,24 @@ fn expr_spec<'a>( return builder.add_make_named(block, MOD_APP, type_name, value_id); } - UnionLayout::Recursive(_) => builder.add_make_tuple(block, &[cell_id, data_id])?, - UnionLayout::NullableWrapped { nullable_id, .. } => { - if *tag_id == *nullable_id as _ { - data_id - } else { - builder.add_make_tuple(block, &[cell_id, data_id])? - } - } - UnionLayout::NullableUnwrapped { nullable_id, .. } => { - if *tag_id == *nullable_id as _ { - data_id - } else { - builder.add_make_tuple(block, &[cell_id, data_id])? - } - } + UnionLayout::Recursive(_) => data_id, + UnionLayout::NullableWrapped { .. } => data_id, + UnionLayout::NullableUnwrapped { .. } => data_id, }; + let variant_types = recursive_variant_types(builder, tag_layout)?; + let union_id = builder.add_make_union(block, &variant_types, *tag_id as u32, value_id)?; + let tag_value_id = with_new_heap_cell(builder, block, union_id)?; + let type_name_bytes = recursive_tag_union_name_bytes(tag_layout).as_bytes(); let type_name = TypeName(&type_name_bytes); env.type_names.insert(*tag_layout); - builder.add_make_named(block, MOD_APP, type_name, union_id) + builder.add_make_named(block, MOD_APP, type_name, tag_value_id) } Struct(fields) => build_tuple_value(builder, env, block, fields), UnionAtIndex { @@ -1553,16 +1531,20 @@ fn expr_spec<'a>( let type_name_bytes = recursive_tag_union_name_bytes(union_layout).as_bytes(); let type_name = TypeName(&type_name_bytes); + // unwrap the named wrapper let union_id = builder.add_unwrap_named(block, MOD_APP, type_name, tag_value_id)?; - let variant_id = builder.add_unwrap_union(block, union_id, *tag_id as u32)?; + + // now we have a tuple (cell, union { ... }); decompose + let heap_cell = builder.add_get_tuple_field(block, union_id, TAG_CELL_INDEX)?; + let union_data = builder.add_get_tuple_field(block, union_id, TAG_DATA_INDEX)?; // we're reading from this value, so touch the heap cell - let heap_cell = builder.add_get_tuple_field(block, variant_id, 0)?; builder.add_touch(block, heap_cell)?; - let tuple_value_id = builder.add_get_tuple_field(block, variant_id, 1)?; + // next, unwrap the union at the tag id that we've got + let variant_id = builder.add_unwrap_union(block, union_data, *tag_id as u32)?; - builder.add_get_tuple_field(block, tuple_value_id, index) + builder.add_get_tuple_field(block, variant_id, index) } UnionLayout::NonNullableUnwrapped { .. } => { let index = (*index) as u32; @@ -1573,16 +1555,20 @@ fn expr_spec<'a>( let type_name_bytes = recursive_tag_union_name_bytes(union_layout).as_bytes(); let type_name = TypeName(&type_name_bytes); - let variant_id = - builder.add_unwrap_named(block, MOD_APP, type_name, tag_value_id)?; + // a tuple ( cell, union { ... } ) + let union_id = builder.add_unwrap_named(block, MOD_APP, type_name, tag_value_id)?; + + // decompose + let heap_cell = builder.add_get_tuple_field(block, union_id, TAG_CELL_INDEX)?; + let union_data = builder.add_get_tuple_field(block, union_id, TAG_DATA_INDEX)?; // we're reading from this value, so touch the heap cell - let heap_cell = builder.add_get_tuple_field(block, variant_id, 0)?; builder.add_touch(block, heap_cell)?; - let tuple_value_id = builder.add_get_tuple_field(block, variant_id, 1)?; + // next, unwrap the union at the tag id that we've got + let variant_id = builder.add_unwrap_union(block, union_data, *tag_id as u32)?; - builder.add_get_tuple_field(block, tuple_value_id, index) + builder.add_get_tuple_field(block, variant_id, index) } }, StructAtIndex { @@ -1613,9 +1599,7 @@ fn expr_spec<'a>( if all_constants { new_static_list(builder, block) } else { - let cell = builder.add_new_heap_cell(block)?; - - builder.add_make_tuple(block, &[cell, bag]) + with_new_heap_cell(builder, block, bag) } } @@ -1626,7 +1610,7 @@ fn expr_spec<'a>( } _ => unreachable!("empty array does not have a list layout"), }, - Reset(symbol) => { + Reset { symbol, .. } => { let type_id = layout_spec(builder, layout)?; let value_id = env.symbols[symbol]; @@ -1637,7 +1621,11 @@ fn expr_spec<'a>( builder.add_terminate(block, type_id) } - GetTagId { .. } => builder.add_make_tuple(block, &[]), + GetTagId { .. } => { + // TODO touch heap cell in recursive cases + + builder.add_make_tuple(block, &[]) + } } } @@ -1658,6 +1646,19 @@ fn layout_spec(builder: &mut impl TypeContext, layout: &Layout) -> Result Result> { + let mut result = Vec::with_capacity(tags.len()); + + for tag in tags.iter() { + result.push(build_tuple_type(builder, tag)?); + } + + Ok(result) +} + fn layout_spec_help( builder: &mut impl TypeContext, layout: &Layout, @@ -1674,8 +1675,6 @@ fn layout_spec_help( when_recursive, ), Union(union_layout) => { - let variant_types = build_variant_types(builder, union_layout)?; - match union_layout { UnionLayout::NonRecursive(&[]) => { // must model Void as Unit, otherwise we run into problems where @@ -1683,7 +1682,10 @@ fn layout_spec_help( // which is of course not possible builder.add_tuple_type(&[]) } - UnionLayout::NonRecursive(_) => builder.add_union_type(&variant_types), + UnionLayout::NonRecursive(tags) => { + let variant_types = non_recursive_variant_types(builder, tags)?; + builder.add_union_type(&variant_types) + } UnionLayout::Recursive(_) | UnionLayout::NullableUnwrapped { .. } | UnionLayout::NullableWrapped { .. } @@ -1777,10 +1779,21 @@ const LIST_BAG_INDEX: u32 = 1; const DICT_CELL_INDEX: u32 = LIST_CELL_INDEX; const DICT_BAG_INDEX: u32 = LIST_BAG_INDEX; -fn new_list(builder: &mut FuncDefBuilder, block: BlockId, element_type: TypeId) -> Result { +const TAG_CELL_INDEX: u32 = 0; +const TAG_DATA_INDEX: u32 = 1; + +fn with_new_heap_cell( + builder: &mut FuncDefBuilder, + block: BlockId, + value: ValueId, +) -> Result { let cell = builder.add_new_heap_cell(block)?; + builder.add_make_tuple(block, &[cell, value]) +} + +fn new_list(builder: &mut FuncDefBuilder, block: BlockId, element_type: TypeId) -> Result { let bag = builder.add_empty_bag(block, element_type)?; - builder.add_make_tuple(block, &[cell, bag]) + with_new_heap_cell(builder, block, bag) } fn new_dict( @@ -1789,10 +1802,9 @@ fn new_dict( key_type: TypeId, value_type: TypeId, ) -> Result { - let cell = builder.add_new_heap_cell(block)?; let element_type = builder.add_tuple_type(&[key_type, value_type])?; let bag = builder.add_empty_bag(block, element_type)?; - builder.add_make_tuple(block, &[cell, bag]) + with_new_heap_cell(builder, block, bag) } fn new_static_string(builder: &mut FuncDefBuilder, block: BlockId) -> Result { diff --git a/compiler/mono/src/borrow.rs b/compiler/mono/src/borrow.rs index bc5492c8bf..e29eca34ed 100644 --- a/compiler/mono/src/borrow.rs +++ b/compiler/mono/src/borrow.rs @@ -726,7 +726,7 @@ impl<'a> BorrowInfState<'a> { // the function must take it as an owned parameter self.own_args_if_param(xs); } - Reset(x) => { + Reset { symbol: x, .. } => { self.own_var(z); self.own_var(*x); } diff --git a/compiler/mono/src/inc_dec.rs b/compiler/mono/src/inc_dec.rs index c6dfd67314..3eb3896b13 100644 --- a/compiler/mono/src/inc_dec.rs +++ b/compiler/mono/src/inc_dec.rs @@ -110,7 +110,7 @@ pub fn occurring_variables_expr(expr: &Expr<'_>, result: &mut MutSet) { result.extend(arguments.iter().copied()); result.insert(*symbol); } - Reset(x) => { + Reset { symbol: x, .. } => { result.insert(*x); } @@ -761,7 +761,7 @@ impl<'a> Context<'a> { self.arena.alloc(Stmt::Let(z, v, l, b)) } - EmptyArray | Literal(_) | Reset(_) | RuntimeErrorFunction(_) => { + EmptyArray | Literal(_) | Reset { .. } | RuntimeErrorFunction(_) => { // EmptyArray is always stack-allocated // function pointers are persistent self.arena.alloc(Stmt::Let(z, v, l, b)) @@ -779,7 +779,7 @@ impl<'a> Context<'a> { // must this value be consumed? let consume = consume_expr(&self.vars, expr); - let reset = matches!(expr, Expr::Reset(_)); + let reset = matches!(expr, Expr::Reset { .. }); self.update_var_info_help(symbol, layout, persistent, consume, reset) } diff --git a/compiler/mono/src/ir.rs b/compiler/mono/src/ir.rs index d4956d4ba9..5ba8154c2b 100644 --- a/compiler/mono/src/ir.rs +++ b/compiler/mono/src/ir.rs @@ -37,8 +37,8 @@ static_assertions::assert_eq_size!([u8; 19 * 8], Stmt); #[cfg(target_arch = "aarch64")] static_assertions::assert_eq_size!([u8; 20 * 8], Stmt); static_assertions::assert_eq_size!([u8; 6 * 8], ProcLayout); -static_assertions::assert_eq_size!([u8; 8 * 8], Call); -static_assertions::assert_eq_size!([u8; 6 * 8], CallType); +static_assertions::assert_eq_size!([u8; 7 * 8], Call); +static_assertions::assert_eq_size!([u8; 5 * 8], CallType); macro_rules! return_on_layout_error { ($env:expr, $layout_result:expr) => { @@ -318,11 +318,17 @@ impl<'a> Proc<'a> { arena: &'a Bump, home: ModuleId, ident_ids: &'i mut IdentIds, + update_mode_ids: &'i mut UpdateModeIds, procs: &mut MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>, ) { for (_, 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, + update_mode_ids, + proc.clone(), + ); *proc = new_proc; } } @@ -988,8 +994,8 @@ pub struct Env<'a, 'i> { pub home: ModuleId, pub ident_ids: &'i mut IdentIds, pub ptr_bytes: u32, - pub update_mode_counter: u64, - pub call_specialization_counter: u64, + pub update_mode_ids: &'i mut UpdateModeIds, + pub call_specialization_counter: u32, } impl<'a, 'i> Env<'a, 'i> { @@ -1000,13 +1006,7 @@ impl<'a, 'i> Env<'a, 'i> { } pub fn next_update_mode_id(&mut self) -> UpdateModeId { - let id = UpdateModeId { - id: self.update_mode_counter, - }; - - self.update_mode_counter += 1; - - id + self.update_mode_ids.next_id() } pub fn next_call_specialization_id(&mut self) -> CallSpecId { @@ -1282,26 +1282,43 @@ impl<'a> Call<'a> { #[derive(Clone, Copy, Debug, PartialEq)] pub struct CallSpecId { - id: u64, + id: u32, } impl CallSpecId { - pub fn to_bytes(self) -> [u8; 8] { + pub fn to_bytes(self) -> [u8; 4] { self.id.to_ne_bytes() } } #[derive(Clone, Copy, Debug, PartialEq)] pub struct UpdateModeId { - id: u64, + id: u32, } impl UpdateModeId { - pub fn to_bytes(self) -> [u8; 8] { + pub fn to_bytes(self) -> [u8; 4] { self.id.to_ne_bytes() } } +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct UpdateModeIds { + next: u32, +} + +impl UpdateModeIds { + pub const fn new() -> Self { + Self { next: 0 } + } + + pub fn next_id(&mut self) -> UpdateModeId { + let id = UpdateModeId { id: self.next }; + self.next += 1; + id + } +} + #[derive(Clone, Debug, PartialEq)] pub enum CallType<'a> { ByName { @@ -1390,13 +1407,17 @@ pub enum Expr<'a> { Reuse { symbol: Symbol, update_tag_id: bool, + update_mode: UpdateModeId, // normal Tag fields tag_layout: UnionLayout<'a>, tag_name: TagName, tag_id: TagIdIntType, arguments: &'a [Symbol], }, - Reset(Symbol), + Reset { + symbol: Symbol, + update_mode: UpdateModeId, + }, RuntimeErrorFunction(&'a str), } @@ -1491,6 +1512,7 @@ impl<'a> Expr<'a> { symbol, tag_name, arguments, + update_mode, .. } => { let doc_tag = match tag_name { @@ -1508,11 +1530,19 @@ impl<'a> Expr<'a> { .text("Reuse ") .append(symbol_to_doc(alloc, *symbol)) .append(alloc.space()) + .append(format!("{:?}", update_mode)) + .append(alloc.space()) .append(doc_tag) .append(alloc.space()) .append(alloc.intersperse(it, " ")) } - Reset(symbol) => alloc.text("Reset ").append(symbol_to_doc(alloc, *symbol)), + Reset { + symbol, + update_mode, + } => alloc.text(format!( + "Reset {{ symbol: {:?}, id: {} }}", + symbol, update_mode.id + )), Struct(args) => { let it = args.iter().map(|s| symbol_to_doc(alloc, *s)); @@ -5715,7 +5745,7 @@ fn substitute_in_expr<'a>( } } - Reuse { .. } | Reset(_) => unreachable!("reset/reuse have not been introduced yet"), + Reuse { .. } | Reset { .. } => unreachable!("reset/reuse have not been introduced yet"), Struct(args) => { let mut did_change = false; diff --git a/compiler/mono/src/reset_reuse.rs b/compiler/mono/src/reset_reuse.rs index cf8ecff9cf..fc63890d73 100644 --- a/compiler/mono/src/reset_reuse.rs +++ b/compiler/mono/src/reset_reuse.rs @@ -1,5 +1,7 @@ use crate::inc_dec::{collect_stmt, occurring_variables_expr, JPLiveVarMap, LiveVarSet}; -use crate::ir::{BranchInfo, Call, Expr, ListLiteralElement, Proc, Stmt}; +use crate::ir::{ + BranchInfo, Call, Expr, ListLiteralElement, Proc, Stmt, UpdateModeId, UpdateModeIds, +}; use crate::layout::{Layout, TagIdIntType, UnionLayout}; use bumpalo::collections::Vec; use bumpalo::Bump; @@ -10,12 +12,14 @@ pub fn insert_reset_reuse<'a, 'i>( arena: &'a Bump, home: ModuleId, ident_ids: &'i mut IdentIds, + update_mode_ids: &'i mut UpdateModeIds, mut proc: Proc<'a>, ) -> Proc<'a> { let mut env = Env { arena, home, ident_ids, + update_mode_ids, jp_live_vars: Default::default(), }; @@ -50,6 +54,7 @@ struct Env<'a, 'i> { /// required for creating new `Symbol`s home: ModuleId, ident_ids: &'i mut IdentIds, + update_mode_ids: &'i mut UpdateModeIds, jp_live_vars: JPLiveVarMap, } @@ -64,7 +69,7 @@ impl<'a, 'i> Env<'a, 'i> { fn function_s<'a, 'i>( env: &mut Env<'a, 'i>, - w: Symbol, + w: Opportunity, c: &CtorInfo<'a>, stmt: &'a Stmt<'a>, ) -> &'a Stmt<'a> { @@ -84,7 +89,8 @@ fn function_s<'a, 'i>( let update_tag_id = true; let new_expr = Expr::Reuse { - symbol: w, + symbol: w.symbol, + update_mode: w.update_mode, update_tag_id, tag_layout: *tag_layout, tag_id: *tag_id, @@ -175,13 +181,22 @@ fn function_s<'a, 'i>( } } +#[derive(Clone, Copy)] +struct Opportunity { + symbol: Symbol, + update_mode: UpdateModeId, +} + fn try_function_s<'a, 'i>( env: &mut Env<'a, 'i>, x: Symbol, c: &CtorInfo<'a>, stmt: &'a Stmt<'a>, ) -> &'a Stmt<'a> { - let w = env.unique_symbol(); + let w = Opportunity { + symbol: env.unique_symbol(), + update_mode: env.update_mode_ids.next_id(), + }; let new_stmt = function_s(env, w, c, stmt); @@ -194,7 +209,7 @@ fn try_function_s<'a, 'i>( fn insert_reset<'a>( env: &mut Env<'a, '_>, - w: Symbol, + w: Opportunity, x: Symbol, union_layout: UnionLayout<'a>, mut stmt: &'a Stmt<'a>, @@ -216,16 +231,21 @@ fn insert_reset<'a>( | Array { .. } | EmptyArray | Reuse { .. } - | Reset(_) + | Reset { .. } | RuntimeErrorFunction(_) => break, } } - let reset_expr = Expr::Reset(x); + let reset_expr = Expr::Reset { + symbol: x, + update_mode: w.update_mode, + }; let layout = Layout::Union(union_layout); - stmt = env.arena.alloc(Stmt::Let(w, reset_expr, layout, stmt)); + stmt = env + .arena + .alloc(Stmt::Let(w.symbol, reset_expr, layout, stmt)); for (symbol, expr, expr_layout) in stack.into_iter().rev() { stmt = env @@ -584,7 +604,7 @@ fn has_live_var_expr<'a>(expr: &'a Expr<'a>, needle: Symbol) -> bool { Expr::Reuse { symbol, arguments, .. } => needle == *symbol || arguments.iter().any(|s| *s == needle), - Expr::Reset(symbol) => needle == *symbol, + Expr::Reset { symbol, .. } => needle == *symbol, Expr::RuntimeErrorFunction(_) => false, } } diff --git a/reporting/tests/test_reporting.rs b/reporting/tests/test_reporting.rs index 735861ebb3..948860825c 100644 --- a/reporting/tests/test_reporting.rs +++ b/reporting/tests/test_reporting.rs @@ -13,7 +13,7 @@ mod test_reporting { use crate::helpers::{can_expr, infer_expr, CanExprOut, ParseErrOut}; use bumpalo::Bump; use roc_module::symbol::{Interns, ModuleId}; - use roc_mono::ir::{Procs, Stmt}; + use roc_mono::ir::{Procs, Stmt, UpdateModeIds}; use roc_mono::layout::LayoutCache; use roc_reporting::report::{ can_problem, mono_problem, parse_problem, type_problem, Report, Severity, BLUE_CODE, @@ -91,6 +91,7 @@ mod test_reporting { // Compile and add all the Procs before adding main let mut procs = Procs::new_in(&arena); let mut ident_ids = interns.all_ident_ids.remove(&home).unwrap(); + let mut update_mode_ids = UpdateModeIds::new(); // Populate Procs and Subs, and get the low-level Expr from the canonical Expr let ptr_bytes = 8; @@ -101,8 +102,8 @@ mod test_reporting { problems: &mut mono_problems, home, ident_ids: &mut ident_ids, + update_mode_ids: &mut update_mode_ids, ptr_bytes, - update_mode_counter: 0, // call_specialization_counter=0 is reserved call_specialization_counter: 1, };