diff --git a/compiler/gen/src/llvm/build.rs b/compiler/gen/src/llvm/build.rs index 0f211333f8..cce6bf6f8e 100644 --- a/compiler/gen/src/llvm/build.rs +++ b/compiler/gen/src/llvm/build.rs @@ -453,11 +453,12 @@ pub fn build_expr<'a, 'ctx, 'env>( let mut field_types = Vec::with_capacity_in(num_fields, env.arena); let mut field_vals = Vec::with_capacity_in(num_fields, env.arena); - for (field_expr, field_layout) in it { + for (field_symbol, field_layout) in it { // Zero-sized fields have no runtime representation. // The layout of the struct expects them to be dropped! if field_layout.stack_size(ptr_bytes) != 0 { - let val = build_expr(env, layout_ids, &scope, parent, field_expr); + let val = load_symbol(env, scope, field_symbol); + let field_type = basic_type_from_layout( env.arena, env.context, @@ -507,13 +508,13 @@ pub fn build_expr<'a, 'ctx, 'env>( let mut field_types = Vec::with_capacity_in(num_fields, env.arena); let mut field_vals = Vec::with_capacity_in(num_fields, env.arena); - for (field_expr, field_layout) in arguments.iter() { + for (field_symbol, field_layout) in arguments.iter() { let field_size = field_layout.stack_size(ptr_size); // Zero-sized fields have no runtime representation. // The layout of the struct expects them to be dropped! if field_size != 0 { - let val = build_expr(env, layout_ids, &scope, parent, field_expr); + let val = load_symbol(env, scope, field_symbol); let field_type = basic_type_from_layout(env.arena, env.context, &field_layout, ptr_size); @@ -684,7 +685,7 @@ pub fn build_expr<'a, 'ctx, 'env>( None => panic!("There was no entry for {:?} in scope {:?}", symbol, scope), Some((layout, ptr)) => { match layout { - Layout::Builtin(Builtin::List(Ownership::Owned, _elem_layout)) => { + Layout::Builtin(Builtin::List(Ownership::Owned, _elem_layout)) if false => { // first run the body let body = build_expr(env, layout_ids, scope, parent, expr); diff --git a/compiler/mono/src/expr.rs b/compiler/mono/src/expr.rs index c3974c2b07..038a08b631 100644 --- a/compiler/mono/src/expr.rs +++ b/compiler/mono/src/expr.rs @@ -375,7 +375,7 @@ pub enum Expr<'a> { tag_name: TagName, tag_id: u8, union_size: u8, - arguments: &'a [(Expr<'a>, Layout<'a>)], + arguments: &'a [(Symbol, Layout<'a>)], }, Struct(&'a [(Expr<'a>, Layout<'a>)]), AccessAtIndex { @@ -525,7 +525,9 @@ impl<'a> Expr<'a> { TagName::Global(s) => alloc.text(s.as_str()), TagName::Private(s) => alloc.text(format!("{}", s)), }; - let doc_args = arguments.iter().map(|(expr, _)| expr.to_doc(alloc, true)); + let doc_args = arguments + .iter() + .map(|(symbol, _)| alloc.text(format!("{}", symbol))); let it = std::iter::once(doc_tag).chain(doc_args); @@ -1067,14 +1069,30 @@ fn from_can<'a>( .expect("tag must be in its own type"); let mut arguments = Vec::with_capacity_in(args.len(), arena); + let mut stores = Vec::with_capacity_in(args.len(), arena); - let it = std::iter::once(Expr::Int(tag_id as i64)).chain( - args.into_iter() - .map(|(_, arg)| from_can(env, arg.value, procs, layout_cache)), - ); + let expr_it = std::iter::once((Expr::Int(tag_id as i64), env.unique_symbol())) + .chain({ + let transform = |(_, arg): (_, Located)| { + let expr = from_can(env, arg.value, procs, layout_cache); + let symbol = env.unique_symbol(); - for (arg_layout, arg_expr) in argument_layouts.iter().zip(it) { - arguments.push((arg_expr, arg_layout.clone())); + (expr, symbol) + }; + + args.into_iter().map(transform) + }); + + let layout_it = argument_layouts.iter(); + + for (arg_layout, (arg_expr, symbol)) in layout_it.zip(expr_it) { + // arguments.push((arg_expr, arg_layout.clone())); + if let Expr::Load(existing) = arg_expr { + arguments.push((existing, arg_layout.clone())); + } else { + arguments.push((symbol, arg_layout.clone())); + stores.push((symbol, arg_layout.clone(), arg_expr)); + } } let mut layouts: Vec<&'a [Layout<'a>]> = @@ -1086,13 +1104,15 @@ fn from_can<'a>( let layout = Layout::Union(layouts.into_bump_slice()); - Expr::Tag { + let tag = Expr::Tag { tag_layout: layout, tag_name, tag_id: tag_id as u8, union_size, arguments: arguments.into_bump_slice(), - } + }; + + Expr::Store(stores.into_bump_slice(), env.arena.alloc(tag)) } } } diff --git a/compiler/mono/src/reset_reuse.rs b/compiler/mono/src/reset_reuse.rs index 8315e70755..0df4c2f867 100644 --- a/compiler/mono/src/reset_reuse.rs +++ b/compiler/mono/src/reset_reuse.rs @@ -441,8 +441,8 @@ fn symbols_in_expr<'a>(initial: &Expr<'a>) -> MutSet { } Tag { arguments, .. } => { - for (expr, _) in arguments.iter() { - stack.push(expr); + for (symbol, _) in arguments.iter() { + result.insert(*symbol); } }