diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index 9c6c11110d..ee4cc886af 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -6411,11 +6411,11 @@ fn to_cc_type<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout: &Layout<'a>, ) -> BasicTypeEnum<'ctx> { - match layout { - Layout::Builtin(builtin) => to_cc_type_builtin(env, builtin), - _ => { + match layout.runtime_representation() { + Layout::Builtin(builtin) => to_cc_type_builtin(env, &builtin), + layout => { // TODO this is almost certainly incorrect for bigger structs - basic_type_from_layout(env, layout) + basic_type_from_layout(env, &layout) } } } diff --git a/crates/compiler/gen_wasm/src/backend.rs b/crates/compiler/gen_wasm/src/backend.rs index b87bffe0c8..6bf90f5309 100644 --- a/crates/compiler/gen_wasm/src/backend.rs +++ b/crates/compiler/gen_wasm/src/backend.rs @@ -517,7 +517,7 @@ impl<'a> WasmBackend<'a> { // Load all the arguments for the inner function for (i, wrapper_arg) in wrapper_arg_layouts.iter().enumerate() { - let is_closure_data = i == 0; // Skip closure data (first for wrapper, last for inner) + let is_closure_data = i == 0; // Skip closure data (first for wrapper, last for inner). We'll handle it below. let is_return_pointer = i == wrapper_arg_layouts.len() - 1; // Skip return pointer (may not be an arg for inner. And if it is, swaps from end to start) if is_closure_data || is_return_pointer { continue; @@ -540,7 +540,23 @@ impl<'a> WasmBackend<'a> { // If the inner function has closure data, it's the last arg of the inner fn let closure_data_layout = wrapper_arg_layouts[0]; if closure_data_layout.stack_size(TARGET_INFO) > 0 { + // The closure data exists, and will have been passed in to the wrapper as a + // one-element struct. + let inner_closure_data_layout = match closure_data_layout { + Layout::Struct { + field_layouts: [inner], + .. + } => inner, + other => internal_error!( + "Expected a boxed layout for wrapped closure data, got {:?}", + other + ), + }; self.code_builder.get_local(LocalId(0)); + // Since the closure data is wrapped in a one-element struct, we've been passed in the + // pointer to that struct in the stack memory. To get the closure data we just need to + // dereference the pointer. + self.dereference_boxed_value(inner_closure_data_layout); } // Call the wrapped inner function diff --git a/crates/compiler/gen_wasm/src/low_level.rs b/crates/compiler/gen_wasm/src/low_level.rs index 0941e83c01..5da5f22212 100644 --- a/crates/compiler/gen_wasm/src/low_level.rs +++ b/crates/compiler/gen_wasm/src/low_level.rs @@ -1857,11 +1857,15 @@ impl<'a> LowLevelCall<'a> { /// Equality and inequality /// These can operate on any data type (except functions) so they're more complex than other operators. fn eq_or_neq(&self, backend: &mut WasmBackend<'a>) { - let arg_layout = backend.storage.symbol_layouts[&self.arguments[0]]; - let other_arg_layout = backend.storage.symbol_layouts[&self.arguments[1]]; + let arg_layout = + backend.storage.symbol_layouts[&self.arguments[0]].runtime_representation(); + let other_arg_layout = + backend.storage.symbol_layouts[&self.arguments[1]].runtime_representation(); debug_assert!( arg_layout == other_arg_layout, - "Cannot do `==` comparison on different types" + "Cannot do `==` comparison on different types: {:?} vs {:?}", + arg_layout, + other_arg_layout ); let invert_result = matches!(self.lowlevel, LowLevel::NotEq); @@ -2113,6 +2117,18 @@ pub fn call_higher_order_lowlevel<'a>( .. } = passed_function; + // The zig lowlevel builtins expect the passed functions' closure data to always + // be sent as an opaque pointer. On the Roc side, however, we need to call the passed function + // with the Roc representation of the closure data. There are three possible cases for that + // representation: + // + // 1. The closure data is a struct + // 2. The closure data is an unwrapped value + // 3. There is no closure data + // + // To uniformly deal with the first two cases, always put the closure data, when it exists, + // into a one-element struct. That way, we get a pointer (i32) that can be passed to the zig lowlevels. + // The wrapper around the passed function will access the actual closure data in the struct. let (closure_data_layout, closure_data_exists) = match backend.storage.symbol_layouts[captured_environment] { Layout::LambdaSet(lambda_set) => { @@ -2131,6 +2147,46 @@ pub fn call_higher_order_lowlevel<'a>( x => internal_error!("Closure data has an invalid layout\n{:?}", x), }; + let (wrapped_captured_environment, wrapped_captures_layout) = if closure_data_exists { + // If there is closure data, make sure we put in a struct it before passing it to the + // external builtin impl. That way it's always an `i32` pointer. + let wrapped_closure_data_sym = backend.create_symbol("wrapped_captures"); + let wrapped_captures_layout = + Layout::struct_no_name_order(backend.env.arena.alloc([closure_data_layout])); + + // make sure that the wrapping struct is available in stack memory, so we can hand out a + // pointer to it. + let wrapped_storage = backend.storage.allocate_var( + wrapped_captures_layout, + wrapped_closure_data_sym, + crate::storage::StoredVarKind::Variable, + ); + + let (wrapped_storage_local_ptr, wrapped_storage_offset) = match wrapped_storage { + StoredValue::StackMemory { location, .. } => { + location.local_and_offset(backend.storage.stack_frame_pointer) + } + other => internal_error!( + "Struct should be allocated in stack memory, but it's in {:?}", + other + ), + }; + + // copy the actual closure data into the first and only element of the wrapping struct. + backend.storage.copy_value_to_memory( + &mut backend.code_builder, + wrapped_storage_local_ptr, + wrapped_storage_offset, + *captured_environment, + ); + + (wrapped_closure_data_sym, wrapped_captures_layout) + } else { + // If we don't capture anything, pass along the captured environment as-is - the wrapper + // function will take care not to unwrap this. + (*captured_environment, closure_data_layout) + }; + // We create a wrapper around the passed function, which just unboxes the arguments. // This allows Zig builtins to have a generic pointer-based interface. let helper_proc_source = { @@ -2164,7 +2220,7 @@ pub fn call_higher_order_lowlevel<'a>( argument_layouts.len() }; - wrapper_arg_layouts.push(closure_data_layout); + wrapper_arg_layouts.push(wrapped_captures_layout); wrapper_arg_layouts.extend( argument_layouts .iter() @@ -2204,7 +2260,7 @@ pub fn call_higher_order_lowlevel<'a>( .get_refcount_fn_index(Layout::Builtin(Builtin::Int(IntWidth::I32)), HelperOp::Inc); backend.get_fn_ptr(inc_fn) } else { - let inc_fn = backend.get_refcount_fn_index(closure_data_layout, HelperOp::Inc); + let inc_fn = backend.get_refcount_fn_index(wrapped_captures_layout, HelperOp::Inc); backend.get_fn_ptr(inc_fn) }; @@ -2218,7 +2274,7 @@ pub fn call_higher_order_lowlevel<'a>( wrapper_fn_ptr, inc_fn_ptr, closure_data_exists, - *captured_environment, + wrapped_captured_environment, *owns_captured_environment, ), @@ -2231,7 +2287,7 @@ pub fn call_higher_order_lowlevel<'a>( wrapper_fn_ptr, inc_fn_ptr, closure_data_exists, - *captured_environment, + wrapped_captured_environment, *owns_captured_environment, ), @@ -2244,7 +2300,7 @@ pub fn call_higher_order_lowlevel<'a>( wrapper_fn_ptr, inc_fn_ptr, closure_data_exists, - *captured_environment, + wrapped_captured_environment, *owns_captured_environment, ), @@ -2257,7 +2313,7 @@ pub fn call_higher_order_lowlevel<'a>( wrapper_fn_ptr, inc_fn_ptr, closure_data_exists, - *captured_environment, + wrapped_captured_environment, *owns_captured_environment, ), @@ -2280,7 +2336,9 @@ pub fn call_higher_order_lowlevel<'a>( backend.storage.load_symbol_zig(cb, *xs); cb.i32_const(wrapper_fn_ptr); if closure_data_exists { - backend.storage.load_symbols(cb, &[*captured_environment]); + backend + .storage + .load_symbols(cb, &[wrapped_captured_environment]); } else { // load_symbols assumes that a zero-size arg should be eliminated in code gen, // but that's a specialization that our Zig code doesn't have! Pass a null pointer. diff --git a/crates/compiler/gen_wasm/src/storage.rs b/crates/compiler/gen_wasm/src/storage.rs index 90000cc0ff..830361f20d 100644 --- a/crates/compiler/gen_wasm/src/storage.rs +++ b/crates/compiler/gen_wasm/src/storage.rs @@ -719,9 +719,10 @@ impl<'a> Storage<'a> { ) => { debug_assert!(to_value_type == from_value_type); debug_assert!(to_size == from_size); + // Note: load_symbols will not destroy the value, so we can use it again later. + // It will leave a Popped marker in the VM stack model in CodeBuilder self.load_symbols(code_builder, &[from_symbol]); code_builder.set_local(*to_local_id); - self.symbol_storage_map.insert(from_symbol, to.clone()); } ( diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index bb9a528084..cc08598ca5 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -1,8 +1,9 @@ #![allow(clippy::manual_map)] use crate::layout::{ - Builtin, CapturesNiche, ClosureRepresentation, LambdaName, LambdaSet, Layout, LayoutCache, - LayoutProblem, RawFunctionLayout, TagIdIntType, UnionLayout, WrappedVariant, + Builtin, CapturesNiche, ClosureCallOptions, ClosureRepresentation, EnumDispatch, LambdaName, + LambdaSet, Layout, LayoutCache, LayoutProblem, RawFunctionLayout, TagIdIntType, UnionLayout, + WrappedVariant, }; use bumpalo::collections::{CollectIn, Vec}; use bumpalo::Bump; @@ -3114,6 +3115,8 @@ fn specialize_external<'a>( closure: opt_closure_layout, ret_layout, } => { + let mut proc_args = Vec::from_iter_in(proc_args.iter().copied(), env.arena); + // unpack the closure symbols, if any match (opt_closure_layout, captured_symbols) { (Some(closure_layout), CapturedSymbols::Captured(captured)) => { @@ -3233,41 +3236,35 @@ fn specialize_external<'a>( } } - ClosureRepresentation::Other(layout) => match layout { - Layout::Builtin(Builtin::Bool) => { - // just ignore this value - // IDEA don't pass this value in the future - } - Layout::Builtin(Builtin::Int(IntWidth::U8)) => { - // just ignore this value - // IDEA don't pass this value in the future - } - other => { - // NOTE other values always should be wrapped in a 1-element record - unreachable!( - "{:?} is not a valid closure data representation", - other - ) - } - }, + ClosureRepresentation::UnwrappedCapture(_layout) => { + debug_assert_eq!(captured.len(), 1); + let (captured_symbol, _captured_layout) = captured[0]; + + // The capture set is unwrapped, so simply replace the closure argument + // to the function with the unwrapped capture name. + let captured_symbol = get_specialized_name(captured_symbol); + let closure_arg = proc_args.last_mut().unwrap(); + debug_assert_eq!(closure_arg.1, Symbol::ARG_CLOSURE); + closure_arg.1 = captured_symbol; + } + + ClosureRepresentation::EnumDispatch(_) => { + // just ignore this value, since it's not a capture + // IDEA don't pass this value in the future + } } } (None, CapturedSymbols::None) | (None, CapturedSymbols::Captured([])) => {} _ => unreachable!("to closure or not to closure?"), } - let proc_args: Vec<_> = proc_args - .iter() - .map(|&(layout, symbol)| { - // Grab the specialization symbol, if it exists. - let symbol = procs - .symbol_specializations - .remove_single(symbol) - .unwrap_or(symbol); - - (layout, symbol) - }) - .collect_in(env.arena); + proc_args.iter_mut().for_each(|(_layout, symbol)| { + // Grab the specialization symbol, if it exists. + *symbol = procs + .symbol_specializations + .remove_single(*symbol) + .unwrap_or(*symbol); + }); // reset subs, so we don't get type errors when specializing for a different signature layout_cache.rollback_to(cache_snapshot); @@ -5383,29 +5380,42 @@ where Stmt::Let(assigned, expr, lambda_set_layout, hole) } - ClosureRepresentation::Other(Layout::Builtin(Builtin::Bool)) => { - debug_assert_eq!(symbols.len(), 0); + ClosureRepresentation::UnwrappedCapture(_layout) => { + debug_assert_eq!(symbols.len(), 1); - debug_assert_eq!(lambda_set.set.len(), 2); - let tag_id = name.name() != lambda_set.iter_set().next().unwrap().name(); - let expr = Expr::Literal(Literal::Bool(tag_id)); + let mut symbols = symbols; + let (captured_symbol, _) = symbols.next().unwrap(); - Stmt::Let(assigned, expr, lambda_set_layout, hole) + // The capture set is unwrapped, so just replaced the assigned capture symbol with the + // only capture. + let mut hole = hole.clone(); + substitute_in_exprs(env.arena, &mut hole, assigned, *captured_symbol); + hole } - ClosureRepresentation::Other(Layout::Builtin(Builtin::Int(IntWidth::U8))) => { - debug_assert_eq!(symbols.len(), 0); + ClosureRepresentation::EnumDispatch(repr) => match repr { + EnumDispatch::Bool => { + debug_assert_eq!(symbols.len(), 0); - debug_assert!(lambda_set.set.len() > 2); - let tag_id = lambda_set - .iter_set() - .position(|s| s.name() == name.name()) - .unwrap() as u8; + debug_assert_eq!(lambda_set.len(), 2); + let tag_id = name.name() != lambda_set.iter_set().next().unwrap().name(); + let expr = Expr::Literal(Literal::Bool(tag_id)); - let expr = Expr::Literal(Literal::Byte(tag_id)); + Stmt::Let(assigned, expr, lambda_set_layout, hole) + } + EnumDispatch::U8 => { + debug_assert_eq!(symbols.len(), 0); - Stmt::Let(assigned, expr, lambda_set_layout, hole) - } - _ => unreachable!(), + debug_assert!(lambda_set.len() > 2); + let tag_id = lambda_set + .iter_set() + .position(|s| s.name() == name.name()) + .unwrap() as u8; + + let expr = Expr::Literal(Literal::Byte(tag_id)); + + Stmt::Let(assigned, expr, lambda_set_layout, hole) + } + }, }; result @@ -5844,10 +5854,7 @@ fn register_capturing_closure<'a>( Content::Structure(FlatType::Func(_, closure_var, _)) => { match LambdaSet::from_var(env.arena, env.subs, closure_var, env.target_info) { Ok(lambda_set) => { - if let Layout::Struct { - field_layouts: &[], .. - } = lambda_set.runtime_representation() - { + if lambda_set.is_represented().is_none() { CapturedSymbols::None } else { let mut temp = Vec::from_iter_in(captured_symbols, env.arena); @@ -9088,9 +9095,9 @@ fn lowlevel_match_on_lambda_set<'a, ToLowLevelCall>( where ToLowLevelCall: Fn(ToLowLevelCallArguments<'a>) -> Call<'a> + Copy, { - match lambda_set.runtime_representation() { - Layout::VOID => empty_lambda_set_error(), - Layout::Union(union_layout) => { + match lambda_set.call_by_name_options() { + ClosureCallOptions::Void => empty_lambda_set_error(), + ClosureCallOptions::Union(union_layout) => { let closure_tag_id_symbol = env.unique_symbol(); let result = lowlevel_union_lambda_set_to_switch( @@ -9119,7 +9126,7 @@ where env.arena.alloc(result), ) } - Layout::Struct { .. } => match lambda_set.iter_set().next() { + ClosureCallOptions::Struct { .. } => match lambda_set.iter_set().next() { Some(lambda_name) => { let call_spec_id = env.next_call_specialization_id(); let update_mode = env.next_update_mode_id(); @@ -9144,39 +9151,58 @@ where hole.clone() } }, - Layout::Builtin(Builtin::Bool) => { - let closure_tag_id_symbol = closure_data_symbol; + ClosureCallOptions::UnwrappedCapture(_) => { + let lambda_name = lambda_set + .iter_set() + .next() + .expect("no function in lambda set"); - lowlevel_enum_lambda_set_to_switch( - env, - lambda_set.iter_set(), - closure_tag_id_symbol, - Layout::Builtin(Builtin::Bool), + let call_spec_id = env.next_call_specialization_id(); + let update_mode = env.next_update_mode_id(); + let call = to_lowlevel_call(( + lambda_name, closure_data_symbol, lambda_set.is_represented(), - to_lowlevel_call, - return_layout, - assigned, - hole, - ) - } - Layout::Builtin(Builtin::Int(IntWidth::U8)) => { - let closure_tag_id_symbol = closure_data_symbol; + call_spec_id, + update_mode, + )); - lowlevel_enum_lambda_set_to_switch( - env, - lambda_set.iter_set(), - closure_tag_id_symbol, - Layout::Builtin(Builtin::Int(IntWidth::U8)), - closure_data_symbol, - lambda_set.is_represented(), - to_lowlevel_call, - return_layout, - assigned, - hole, - ) + build_call(env, call, assigned, return_layout, env.arena.alloc(hole)) } - other => todo!("{:?}", other), + ClosureCallOptions::EnumDispatch(repr) => match repr { + EnumDispatch::Bool => { + let closure_tag_id_symbol = closure_data_symbol; + + lowlevel_enum_lambda_set_to_switch( + env, + lambda_set.iter_set(), + closure_tag_id_symbol, + Layout::Builtin(Builtin::Bool), + closure_data_symbol, + lambda_set.is_represented(), + to_lowlevel_call, + return_layout, + assigned, + hole, + ) + } + EnumDispatch::U8 => { + let closure_tag_id_symbol = closure_data_symbol; + + lowlevel_enum_lambda_set_to_switch( + env, + lambda_set.iter_set(), + closure_tag_id_symbol, + Layout::Builtin(Builtin::Int(IntWidth::U8)), + closure_data_symbol, + lambda_set.is_represented(), + to_lowlevel_call, + return_layout, + assigned, + hole, + ) + } + }, } } @@ -9267,15 +9293,14 @@ fn match_on_lambda_set<'a>( assigned: Symbol, hole: &'a Stmt<'a>, ) -> Stmt<'a> { - match lambda_set.runtime_representation() { - Layout::VOID => empty_lambda_set_error(), - Layout::Union(union_layout) => { + match lambda_set.call_by_name_options() { + ClosureCallOptions::Void => empty_lambda_set_error(), + ClosureCallOptions::Union(union_layout) => { let closure_tag_id_symbol = env.unique_symbol(); let result = union_lambda_set_to_switch( env, lambda_set, - Layout::Union(union_layout), closure_tag_id_symbol, union_layout.tag_id_layout(), closure_data_symbol, @@ -9299,9 +9324,9 @@ fn match_on_lambda_set<'a>( env.arena.alloc(result), ) } - Layout::Struct { + ClosureCallOptions::Struct { field_layouts, - field_order_hash, + field_order_hash: _, } => { let function_symbol = match lambda_set.iter_set().next() { Some(function_symbol) => function_symbol, @@ -9325,10 +9350,6 @@ fn match_on_lambda_set<'a>( _ => ClosureInfo::Captures { lambda_set, closure_data_symbol, - closure_data_layout: Layout::Struct { - field_layouts, - field_order_hash, - }, }, }; @@ -9343,15 +9364,21 @@ fn match_on_lambda_set<'a>( hole, ) } - Layout::Builtin(Builtin::Bool) => { - let closure_tag_id_symbol = closure_data_symbol; + ClosureCallOptions::UnwrappedCapture(_) => { + let function_symbol = lambda_set + .iter_set() + .next() + .expect("no function in lambda set"); - enum_lambda_set_to_switch( - env, - lambda_set.iter_set(), - closure_tag_id_symbol, - Layout::Builtin(Builtin::Bool), + let closure_info = ClosureInfo::Captures { + lambda_set, closure_data_symbol, + }; + + union_lambda_set_branch_help( + env, + function_symbol, + closure_info, argument_symbols, argument_layouts, return_layout, @@ -9359,23 +9386,38 @@ fn match_on_lambda_set<'a>( hole, ) } - Layout::Builtin(Builtin::Int(IntWidth::U8)) => { - let closure_tag_id_symbol = closure_data_symbol; + ClosureCallOptions::EnumDispatch(repr) => match repr { + EnumDispatch::Bool => { + let closure_tag_id_symbol = closure_data_symbol; - enum_lambda_set_to_switch( - env, - lambda_set.iter_set(), - closure_tag_id_symbol, - Layout::Builtin(Builtin::Int(IntWidth::U8)), - closure_data_symbol, - argument_symbols, - argument_layouts, - return_layout, - assigned, - hole, - ) - } - other => todo!("{:?}", other), + enum_lambda_set_to_switch( + env, + lambda_set.iter_set(), + closure_tag_id_symbol, + Layout::Builtin(Builtin::Bool), + argument_symbols, + argument_layouts, + return_layout, + assigned, + hole, + ) + } + EnumDispatch::U8 => { + let closure_tag_id_symbol = closure_data_symbol; + + enum_lambda_set_to_switch( + env, + lambda_set.iter_set(), + closure_tag_id_symbol, + Layout::Builtin(Builtin::Int(IntWidth::U8)), + argument_symbols, + argument_layouts, + return_layout, + assigned, + hole, + ) + } + }, } } @@ -9383,7 +9425,6 @@ fn match_on_lambda_set<'a>( fn union_lambda_set_to_switch<'a>( env: &mut Env<'a, '_>, lambda_set: LambdaSet<'a>, - closure_layout: Layout<'a>, closure_tag_id_symbol: Symbol, closure_tag_id_layout: Layout<'a>, closure_data_symbol: Symbol, @@ -9393,7 +9434,7 @@ fn union_lambda_set_to_switch<'a>( assigned: Symbol, hole: &'a Stmt<'a>, ) -> Stmt<'a> { - if lambda_set.set.is_empty() { + if lambda_set.is_empty() { // NOTE this can happen if there is a type error somewhere. Since the lambda set is empty, // there is really nothing we can do here. We generate a runtime error here which allows // code gen to proceed. We then assume that we hit another (more descriptive) error before @@ -9403,7 +9444,7 @@ fn union_lambda_set_to_switch<'a>( let join_point_id = JoinPointId(env.unique_symbol()); - let mut branches = Vec::with_capacity_in(lambda_set.set.len(), env.arena); + let mut branches = Vec::with_capacity_in(lambda_set.len(), env.arena); for (i, lambda_name) in lambda_set.iter_set().enumerate() { let closure_info = if lambda_name.no_captures() { @@ -9412,7 +9453,6 @@ fn union_lambda_set_to_switch<'a>( ClosureInfo::Captures { lambda_set, closure_data_symbol, - closure_data_layout: closure_layout, } }; @@ -9482,11 +9522,10 @@ fn union_lambda_set_branch<'a>( ) } +#[derive(Clone, Copy)] enum ClosureInfo<'a> { Captures { closure_data_symbol: Symbol, - /// The layout of this closure variant - closure_data_layout: Layout<'a>, /// The whole lambda set representation this closure is a variant of lambda_set: LambdaSet<'a>, }, @@ -9508,34 +9547,21 @@ fn union_lambda_set_branch_help<'a>( ClosureInfo::Captures { lambda_set, closure_data_symbol, - closure_data_layout, - } => match closure_data_layout { - Layout::Struct { - field_layouts: &[], .. - } - | Layout::Builtin(Builtin::Bool) - | Layout::Builtin(Builtin::Int(IntWidth::U8)) => { - (argument_layouts_slice, argument_symbols_slice) - } - _ => { - // extend layouts with the layout of the closure environment - let mut argument_layouts = - Vec::with_capacity_in(argument_layouts_slice.len() + 1, env.arena); - argument_layouts.extend(argument_layouts_slice); - argument_layouts.push(Layout::LambdaSet(lambda_set)); - + } => { + let argument_layouts = + lambda_set.extend_argument_list(env.arena, argument_layouts_slice); + let argument_symbols = if argument_layouts.len() > argument_layouts_slice.len() { // extend symbols with the symbol of the closure environment let mut argument_symbols = Vec::with_capacity_in(argument_symbols_slice.len() + 1, env.arena); argument_symbols.extend(argument_symbols_slice); argument_symbols.push(closure_data_symbol); - - ( - argument_layouts.into_bump_slice(), - argument_symbols.into_bump_slice(), - ) - } - }, + argument_symbols.into_bump_slice() + } else { + argument_symbols_slice + }; + (argument_layouts, argument_symbols) + } ClosureInfo::DoesNotCapture => { // sometimes unification causes a function that does not itself capture anything // to still get a lambda set that does store information. We must not pass a closure @@ -9559,13 +9585,14 @@ fn union_lambda_set_branch_help<'a>( build_call(env, call, assigned, *return_layout, hole) } +/// Switches over a enum lambda set, which may dispatch to different functions, none of which +/// capture. #[allow(clippy::too_many_arguments)] fn enum_lambda_set_to_switch<'a>( env: &mut Env<'a, '_>, lambda_set: impl ExactSizeIterator>, closure_tag_id_symbol: Symbol, closure_tag_id_layout: Layout<'a>, - closure_data_symbol: Symbol, argument_symbols: &'a [Symbol], argument_layouts: &'a [Layout<'a>], return_layout: &'a Layout<'a>, @@ -9578,15 +9605,11 @@ fn enum_lambda_set_to_switch<'a>( let mut branches = Vec::with_capacity_in(lambda_set.len(), env.arena); - let closure_layout = closure_tag_id_layout; - for (i, lambda_name) in lambda_set.into_iter().enumerate() { let stmt = enum_lambda_set_branch( env, join_point_id, lambda_name, - closure_data_symbol, - closure_layout, argument_symbols, argument_layouts, return_layout, @@ -9622,15 +9645,14 @@ fn enum_lambda_set_to_switch<'a>( } } +/// A branch for an enum lambda set branch dispatch, which never capture! #[allow(clippy::too_many_arguments)] fn enum_lambda_set_branch<'a>( env: &mut Env<'a, '_>, join_point_id: JoinPointId, lambda_name: LambdaName<'a>, - closure_data_symbol: Symbol, - closure_data_layout: Layout<'a>, - argument_symbols_slice: &'a [Symbol], - argument_layouts_slice: &'a [Layout<'a>], + argument_symbols: &'a [Symbol], + argument_layouts: &'a [Layout<'a>], return_layout: &'a Layout<'a>, ) -> Stmt<'a> { let result_symbol = env.unique_symbol(); @@ -9639,34 +9661,6 @@ fn enum_lambda_set_branch<'a>( let assigned = result_symbol; - let (argument_layouts, argument_symbols) = match closure_data_layout { - Layout::Struct { - field_layouts: &[], .. - } - | Layout::Builtin(Builtin::Bool) - | Layout::Builtin(Builtin::Int(IntWidth::U8)) => { - (argument_layouts_slice, argument_symbols_slice) - } - _ => { - // extend layouts with the layout of the closure environment - let mut argument_layouts = - Vec::with_capacity_in(argument_layouts_slice.len() + 1, env.arena); - argument_layouts.extend(argument_layouts_slice); - argument_layouts.push(closure_data_layout); - - // extend symbols with the symbol of the closure environment - let mut argument_symbols = - Vec::with_capacity_in(argument_symbols_slice.len() + 1, env.arena); - argument_symbols.extend(argument_symbols_slice); - argument_symbols.push(closure_data_symbol); - - ( - argument_layouts.into_bump_slice(), - argument_symbols.into_bump_slice(), - ) - } - }; - let call = self::Call { call_type: CallType::ByName { name: lambda_name, diff --git a/crates/compiler/mono/src/layout.rs b/crates/compiler/mono/src/layout.rs index 6bb280ab18..48efdf91f8 100644 --- a/crates/compiler/mono/src/layout.rs +++ b/crates/compiler/mono/src/layout.rs @@ -783,28 +783,56 @@ impl<'a> LambdaName<'a> { #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct LambdaSet<'a> { /// collection of function names and their closure arguments - pub set: &'a [(Symbol, &'a [Layout<'a>])], + set: &'a [(Symbol, &'a [Layout<'a>])], /// how the closure will be represented at runtime representation: &'a Layout<'a>, } +#[derive(Debug)] +pub enum EnumDispatch { + Bool, + U8, +} + /// representation of the closure *for a particular function* #[derive(Debug)] pub enum ClosureRepresentation<'a> { - /// the closure is represented as a union. Includes the tag ID! + /// The closure is represented as a union. Includes the tag ID! + /// Each variant is a different function, and its payloads are the captures. Union { alphabetic_order_fields: &'a [Layout<'a>], closure_name: Symbol, tag_id: TagIdIntType, union_layout: UnionLayout<'a>, }, - /// The closure is represented as a struct. The layouts are sorted - /// alphabetically by the identifier that is captured. + /// The closure is one function, whose captures are represented as a struct. + /// The layouts are sorted alphabetically by the identifier that is captured. /// /// We MUST sort these according to their stack size before code gen! AlphabeticOrderStruct(&'a [Layout<'a>]), - /// the representation is anything but a union - Other(Layout<'a>), + /// The closure is one function that captures a single identifier, whose value is unwrapped. + UnwrappedCapture(Layout<'a>), + /// The closure dispatches to multiple functions, but none of them capture anything, so this is + /// a boolean or integer flag. + EnumDispatch(EnumDispatch), +} + +/// How the closure should be seen when determining a call-by-name. +#[derive(Debug)] +pub enum ClosureCallOptions<'a> { + /// This is an empty lambda set, dispatching is an error + Void, + /// One of a few capturing functions can be called to + Union(UnionLayout<'a>), + /// The closure is one function, whose captures are represented as a struct. + Struct { + field_layouts: &'a [Layout<'a>], + field_order_hash: FieldOrderHash, + }, + /// The closure is one function that captures a single identifier, whose value is unwrapped. + UnwrappedCapture(Layout<'a>), + /// The closure dispatches to multiple possible functions, none of which capture. + EnumDispatch(EnumDispatch), } impl<'a> LambdaSet<'a> { @@ -818,13 +846,17 @@ impl<'a> LambdaSet<'a> { } pub fn is_represented(&self) -> Option> { - match self.representation { - Layout::Struct { - field_layouts: &[], .. + if self.has_unwrapped_capture_repr() { + Some(*self.representation) + } else if self.has_enum_dispatch_repr() { + None + } else { + match self.representation { + Layout::Struct { + field_layouts: &[], .. + } => None, + repr => Some(*repr), } - | Layout::Builtin(Builtin::Bool) - | Layout::Builtin(Builtin::Int(..)) => None, - repr => Some(*repr), } } @@ -835,6 +867,16 @@ impl<'a> LambdaSet<'a> { }) } + #[inline(always)] + pub fn len(&self) -> usize { + self.set.len() + } + + #[inline(always)] + pub fn is_empty(&self) -> bool { + self.set.is_empty() + } + pub fn layout_for_member_with_lambda_name( &self, lambda_name: LambdaName, @@ -923,6 +965,11 @@ impl<'a> LambdaSet<'a> { where F: Fn(Symbol, &[Layout]) -> bool, { + if self.has_unwrapped_capture_repr() { + // Only one function, that captures one identifier. + return ClosureRepresentation::UnwrappedCapture(*self.representation); + } + match self.representation { Layout::Union(union) => { // here we rely on the fact that a union in a closure would be stored in a one-element record. @@ -1004,7 +1051,58 @@ impl<'a> LambdaSet<'a> { ClosureRepresentation::AlphabeticOrderStruct(fields) } - _ => ClosureRepresentation::Other(*self.representation), + layout => { + debug_assert!(self.has_enum_dispatch_repr(),); + let enum_repr = match layout { + Layout::Builtin(Builtin::Bool) => EnumDispatch::Bool, + Layout::Builtin(Builtin::Int(IntWidth::U8)) => EnumDispatch::U8, + other => internal_error!("Invalid layout for enum dispatch: {:?}", other), + }; + ClosureRepresentation::EnumDispatch(enum_repr) + } + } + } + + fn has_unwrapped_capture_repr(&self) -> bool { + self.set.len() == 1 && self.set[0].1.len() == 1 + } + + fn has_enum_dispatch_repr(&self) -> bool { + self.set.len() > 1 && self.set.iter().all(|(_, captures)| captures.is_empty()) + } + + pub fn call_by_name_options(&self) -> ClosureCallOptions<'a> { + if self.has_unwrapped_capture_repr() { + return ClosureCallOptions::UnwrappedCapture(*self.representation); + } + + match self.representation { + Layout::Union(union_layout) => { + if self.representation == &Layout::VOID { + debug_assert!(self.set.is_empty()); + return ClosureCallOptions::Void; + } + ClosureCallOptions::Union(*union_layout) + } + Layout::Struct { + field_layouts, + field_order_hash, + } => { + debug_assert_eq!(self.set.len(), 1); + ClosureCallOptions::Struct { + field_layouts, + field_order_hash: *field_order_hash, + } + } + layout => { + debug_assert!(self.has_enum_dispatch_repr()); + let enum_repr = match layout { + Layout::Builtin(Builtin::Bool) => EnumDispatch::Bool, + Layout::Builtin(Builtin::Int(IntWidth::U8)) => EnumDispatch::U8, + other => internal_error!("Invalid layout for enum dispatch: {:?}", other), + }; + ClosureCallOptions::EnumDispatch(enum_repr) + } } } @@ -1013,30 +1111,27 @@ impl<'a> LambdaSet<'a> { arena: &'a Bump, argument_layouts: &'a [Layout<'a>], ) -> &'a [Layout<'a>] { - if let [] = self.set { - // TERRIBLE HACK for builting functions - argument_layouts - } else { - match self.representation { - Layout::Struct { - field_layouts: &[], .. - } => { - // this function does not have anything in its closure, and the lambda set is a - // singleton, so we pass no extra argument - argument_layouts - } - Layout::Builtin(Builtin::Bool) - | Layout::Builtin(Builtin::Int(IntWidth::I8 | IntWidth::U8)) => { - // we don't pass this along either - argument_layouts - } - _ => { - let mut arguments = Vec::with_capacity_in(argument_layouts.len() + 1, arena); - arguments.extend(argument_layouts); - arguments.push(Layout::LambdaSet(*self)); + match self.call_by_name_options() { + ClosureCallOptions::Void => argument_layouts, + ClosureCallOptions::Struct { + field_layouts: &[], .. + } => { + // this function does not have anything in its closure, and the lambda set is a + // singleton, so we pass no extra argument + argument_layouts + } + ClosureCallOptions::Struct { .. } + | ClosureCallOptions::Union(_) + | ClosureCallOptions::UnwrappedCapture(_) => { + let mut arguments = Vec::with_capacity_in(argument_layouts.len() + 1, arena); + arguments.extend(argument_layouts); + arguments.push(Layout::LambdaSet(*self)); - arguments.into_bump_slice() - } + arguments.into_bump_slice() + } + ClosureCallOptions::EnumDispatch(_) => { + // No captures, don't pass this along + argument_layouts } } } @@ -1053,7 +1148,7 @@ impl<'a> LambdaSet<'a> { lambdas.sort_by_key(|(sym, _)| *sym); let mut set: Vec<(Symbol, &[Layout])> = Vec::with_capacity_in(lambdas.len(), arena); - let mut set_with_variables: std::vec::Vec<(Symbol, std::vec::Vec)> = + let mut set_with_variables: std::vec::Vec<(&Symbol, &[Variable])> = std::vec::Vec::with_capacity(lambdas.len()); let mut last_function_symbol = None; @@ -1090,7 +1185,7 @@ impl<'a> LambdaSet<'a> { has_duplicate_lambda_names = has_duplicate_lambda_names || is_multimorphic; set.push((*function_symbol, arguments)); - set_with_variables.push((*function_symbol, variables.to_vec())); + set_with_variables.push((function_symbol, variables.as_slice())); last_function_symbol = Some(function_symbol); } @@ -1151,70 +1246,23 @@ impl<'a> LambdaSet<'a> { fn make_representation( arena: &'a Bump, subs: &Subs, - tags: std::vec::Vec<(Symbol, std::vec::Vec)>, + tags: std::vec::Vec<(&Symbol, &[Variable])>, opt_rec_var: Option, target_info: TargetInfo, ) -> Layout<'a> { - if let Some(rec_var) = opt_rec_var { - let tags: std::vec::Vec<_> = tags - .iter() - .map(|(sym, vars)| (sym, vars.as_slice())) - .collect(); - let tags = UnsortedUnionLabels { tags }; - let mut env = Env { - seen: Vec::new_in(arena), - target_info, - arena, - subs, - }; + let union_labels = UnsortedUnionLabels { tags }; + let mut env = Env { + seen: Vec::new_in(arena), + target_info, + arena, + subs, + }; - return layout_from_recursive_union(&mut env, rec_var, &tags) - .expect("unable to create lambda set representation"); - } + match opt_rec_var { + Some(rec_var) => layout_from_recursive_union(&mut env, rec_var, &union_labels) + .expect("unable to create lambda set representation"), - // otherwise, this is a closure with a payload - let variant = union_sorted_tags_help(arena, tags, opt_rec_var, subs, target_info); - - use UnionVariant::*; - match variant { - Never => Layout::VOID, - BoolUnion { .. } => Layout::bool(), - ByteUnion { .. } => Layout::u8(), - Unit | UnitWithArguments => { - // no useful information to store - Layout::UNIT - } - Newtype { - arguments: layouts, .. - } => Layout::struct_no_name_order(layouts.into_bump_slice()), - Wrapped(variant) => { - use WrappedVariant::*; - - match variant { - NonRecursive { - sorted_tag_layouts: tags, - } => { - debug_assert!(tags.len() > 1); - - // if the closed-over value is actually a layout, it should be wrapped in a 1-element record - debug_assert!(matches!(tags[0].0, TagOrClosure::Closure(_))); - - let mut tag_arguments = Vec::with_capacity_in(tags.len(), arena); - - for (_, tag_args) in tags.iter() { - tag_arguments.push(&tag_args[0..]); - } - Layout::Union(UnionLayout::NonRecursive(tag_arguments.into_bump_slice())) - } - - Recursive { .. } - | NullableUnwrapped { .. } - | NullableWrapped { .. } - | NonNullableUnwrapped { .. } => { - internal_error!("Recursive layouts should be produced in an earlier branch") - } - } - } + None => layout_from_union(&mut env, &union_labels), } } @@ -1777,6 +1825,13 @@ impl<'a> Layout<'a> { } } } + + pub fn runtime_representation(&self) -> Self { + match self { + Layout::LambdaSet(lambda_set) => lambda_set.runtime_representation(), + other => *other, + } + } } /// Avoid recomputing Layout from Variable multiple times. diff --git a/crates/compiler/test_gen/src/gen_primitives.rs b/crates/compiler/test_gen/src/gen_primitives.rs index d986c46c19..b9e14b6d2b 100644 --- a/crates/compiler/test_gen/src/gen_primitives.rs +++ b/crates/compiler/test_gen/src/gen_primitives.rs @@ -1234,8 +1234,8 @@ fn return_wrapped_closure() { main = foo "# ), - [5], - [i64; 1] + 5, + i64 ); } diff --git a/crates/compiler/test_mono/generated/closure_in_list.txt b/crates/compiler/test_mono/generated/closure_in_list.txt index 520a8a1808..26e9a06eae 100644 --- a/crates/compiler/test_mono/generated/closure_in_list.txt +++ b/crates/compiler/test_mono/generated/closure_in_list.txt @@ -4,17 +4,15 @@ procedure List.6 (#Attr.2): procedure Test.1 (Test.5): let Test.2 : I64 = 41i64; - let Test.10 : {I64} = Struct {Test.2}; - let Test.9 : List {I64} = Array [Test.10]; + let Test.9 : List I64 = Array [Test.2]; ret Test.9; -procedure Test.3 (Test.8, #Attr.12): - let Test.2 : I64 = StructAtIndex 0 #Attr.12; +procedure Test.3 (Test.8, Test.2): ret Test.2; procedure Test.0 (): let Test.7 : {} = Struct {}; - let Test.4 : List {I64} = CallByName Test.1 Test.7; + let Test.4 : List I64 = CallByName Test.1 Test.7; let Test.6 : U64 = CallByName List.6 Test.4; dec Test.4; ret Test.6; diff --git a/crates/compiler/test_mono/generated/encode.txt b/crates/compiler/test_mono/generated/encode.txt index f7bc46f32d..03cb371d02 100644 --- a/crates/compiler/test_mono/generated/encode.txt +++ b/crates/compiler/test_mono/generated/encode.txt @@ -12,22 +12,20 @@ procedure List.71 (#Attr.2, #Attr.3): let List.388 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; ret List.388; -procedure Test.23 (Test.24, Test.35, #Attr.12): - let Test.22 : U8 = StructAtIndex 0 #Attr.12; +procedure Test.23 (Test.24, Test.35, Test.22): let Test.37 : List U8 = CallByName List.4 Test.24 Test.22; ret Test.37; procedure Test.8 (Test.22): - let Test.34 : {U8} = Struct {Test.22}; - ret Test.34; + ret Test.22; procedure Test.9 (Test.27): - let Test.33 : {U8} = CallByName Test.8 Test.27; + let Test.33 : U8 = CallByName Test.8 Test.27; ret Test.33; procedure Test.0 (): let Test.32 : U8 = 15i64; - let Test.28 : {U8} = CallByName Test.9 Test.32; + let Test.28 : U8 = CallByName Test.9 Test.32; let Test.30 : List U8 = Array []; let Test.31 : {} = Struct {}; let Test.29 : List U8 = CallByName Test.23 Test.30 Test.31 Test.28; diff --git a/crates/compiler/test_mono/generated/encode_derived_nested_record_string.txt b/crates/compiler/test_mono/generated/encode_derived_nested_record_string.txt index 3404bdc22a..2e9010b165 100644 --- a/crates/compiler/test_mono/generated/encode_derived_nested_record_string.txt +++ b/crates/compiler/test_mono/generated/encode_derived_nested_record_string.txt @@ -1,34 +1,26 @@ procedure #Derived.0 (#Derived.1): - let #Derived_gen.1 : {Str} = Struct {#Derived.1}; - let #Derived_gen.0 : {Str} = CallByName Encode.22 #Derived_gen.1; + let #Derived_gen.0 : Str = CallByName Encode.22 #Derived.1; ret #Derived_gen.0; -procedure #Derived.2 (#Derived.3, #Derived.4, #Attr.12): - let #Derived.1 : Str = StructAtIndex 0 #Attr.12; - inc #Derived.1; - dec #Attr.12; +procedure #Derived.2 (#Derived.3, #Derived.4, #Derived.1): let #Derived_gen.7 : Str = "a"; - let #Derived_gen.8 : {Str} = CallByName #Derived.5 #Derived.1; - let #Derived_gen.6 : {Str, {Str}} = Struct {#Derived_gen.7, #Derived_gen.8}; - let #Derived_gen.5 : List {Str, {Str}} = Array [#Derived_gen.6]; - let #Derived_gen.4 : {List {Str, {Str}}} = CallByName Json.20 #Derived_gen.5; + let #Derived_gen.8 : Str = CallByName #Derived.5 #Derived.1; + let #Derived_gen.6 : {Str, Str} = Struct {#Derived_gen.7, #Derived_gen.8}; + let #Derived_gen.5 : List {Str, Str} = Array [#Derived_gen.6]; + let #Derived_gen.4 : List {Str, Str} = CallByName Json.20 #Derived_gen.5; let #Derived_gen.3 : List U8 = CallByName Encode.23 #Derived.3 #Derived_gen.4 #Derived.4; ret #Derived_gen.3; procedure #Derived.5 (#Derived.6): - let #Derived_gen.15 : {Str} = Struct {#Derived.6}; - let #Derived_gen.14 : {Str} = CallByName Encode.22 #Derived_gen.15; + let #Derived_gen.14 : Str = CallByName Encode.22 #Derived.6; ret #Derived_gen.14; -procedure #Derived.7 (#Derived.8, #Derived.9, #Attr.12): - let #Derived.6 : Str = StructAtIndex 0 #Attr.12; - inc #Derived.6; - dec #Attr.12; +procedure #Derived.7 (#Derived.8, #Derived.9, #Derived.6): let #Derived_gen.21 : Str = "b"; - let #Derived_gen.22 : {Str} = CallByName Json.18 #Derived.6; - let #Derived_gen.20 : {Str, {Str}} = Struct {#Derived_gen.21, #Derived_gen.22}; - let #Derived_gen.19 : List {Str, {Str}} = Array [#Derived_gen.20]; - let #Derived_gen.18 : {List {Str, {Str}}} = CallByName Json.20 #Derived_gen.19; + let #Derived_gen.22 : Str = CallByName Json.18 #Derived.6; + let #Derived_gen.20 : {Str, Str} = Struct {#Derived_gen.21, #Derived_gen.22}; + let #Derived_gen.19 : List {Str, Str} = Array [#Derived_gen.20]; + let #Derived_gen.18 : List {Str, Str} = CallByName Json.20 #Derived_gen.19; let #Derived_gen.17 : List U8 = CallByName Encode.23 #Derived.8 #Derived_gen.18 #Derived.9; ret #Derived_gen.17; @@ -69,7 +61,7 @@ procedure Encode.23 (Encode.94, Encode.102, Encode.96): procedure Encode.25 (Encode.100, Encode.101): let Encode.104 : List U8 = Array []; - let Encode.105 : {Str} = CallByName #Derived.0 Encode.100; + let Encode.105 : Str = CallByName #Derived.0 Encode.100; let Encode.103 : List U8 = CallByName Encode.23 Encode.104 Encode.105 Encode.101; ret Encode.103; @@ -77,10 +69,7 @@ procedure Json.1 (): let Json.318 : {} = Struct {}; ret Json.318; -procedure Json.103 (Json.104, Json.321, #Attr.12): - let Json.102 : List {Str, {Str}} = StructAtIndex 0 #Attr.12; - inc Json.102; - dec #Attr.12; +procedure Json.103 (Json.104, Json.321, Json.102): let Json.354 : I32 = 123i64; let Json.353 : U8 = CallByName Num.123 Json.354; let Json.106 : List U8 = CallByName List.4 Json.104 Json.353; @@ -97,10 +86,7 @@ procedure Json.103 (Json.104, Json.321, #Attr.12): let Json.325 : List U8 = CallByName List.4 Json.108 Json.326; ret Json.325; -procedure Json.103 (Json.104, Json.321, #Attr.12): - let Json.102 : List {Str, {Str}} = StructAtIndex 0 #Attr.12; - inc Json.102; - dec #Attr.12; +procedure Json.103 (Json.104, Json.321, Json.102): let Json.397 : I32 = 123i64; let Json.396 : U8 = CallByName Num.123 Json.397; let Json.106 : List U8 = CallByName List.4 Json.104 Json.396; @@ -120,7 +106,7 @@ procedure Json.103 (Json.104, Json.321, #Attr.12): procedure Json.105 (Json.323, Json.324): let Json.111 : Str = StructAtIndex 0 Json.324; inc Json.111; - let Json.112 : {Str} = StructAtIndex 1 Json.324; + let Json.112 : Str = StructAtIndex 1 Json.324; inc Json.112; dec Json.324; let Json.109 : List U8 = StructAtIndex 0 Json.323; @@ -159,7 +145,7 @@ procedure Json.105 (Json.323, Json.324): procedure Json.105 (Json.323, Json.324): let Json.111 : Str = StructAtIndex 0 Json.324; inc Json.111; - let Json.112 : {Str} = StructAtIndex 1 Json.324; + let Json.112 : Str = StructAtIndex 1 Json.324; inc Json.112; dec Json.324; let Json.109 : List U8 = StructAtIndex 0 Json.323; @@ -196,24 +182,18 @@ procedure Json.105 (Json.323, Json.324): jump Json.378 Json.113; procedure Json.18 (Json.86): - let Json.365 : {Str} = Struct {Json.86}; - let Json.364 : {Str} = CallByName Encode.22 Json.365; + let Json.364 : Str = CallByName Encode.22 Json.86; ret Json.364; procedure Json.20 (Json.102): - let Json.320 : {List {Str, {Str}}} = Struct {Json.102}; - let Json.319 : {List {Str, {Str}}} = CallByName Encode.22 Json.320; + let Json.319 : List {Str, Str} = CallByName Encode.22 Json.102; ret Json.319; procedure Json.20 (Json.102): - let Json.362 : {List {Str, {Str}}} = Struct {Json.102}; - let Json.361 : {List {Str, {Str}}} = CallByName Encode.22 Json.362; + let Json.361 : List {Str, Str} = CallByName Encode.22 Json.102; ret Json.361; -procedure Json.87 (Json.88, Json.366, #Attr.12): - let Json.86 : Str = StructAtIndex 0 #Attr.12; - inc Json.86; - dec #Attr.12; +procedure Json.87 (Json.88, Json.366, Json.86): let Json.406 : I32 = 34i64; let Json.405 : U8 = CallByName Num.123 Json.406; let Json.403 : List U8 = CallByName List.4 Json.88 Json.405; @@ -224,21 +204,18 @@ procedure Json.87 (Json.88, Json.366, #Attr.12): let Json.399 : List U8 = CallByName List.4 Json.400 Json.401; ret Json.399; -procedure List.133 (List.134, List.135, #Attr.12): - let List.132 : {} = StructAtIndex 0 #Attr.12; +procedure List.133 (List.134, List.135, List.132): let List.434 : {List U8, U64} = CallByName Json.105 List.134 List.135; let List.433 : [C [], C {List U8, U64}] = TagId(1) List.434; ret List.433; -procedure List.133 (List.134, List.135, #Attr.12): - let List.132 : {} = StructAtIndex 0 #Attr.12; +procedure List.133 (List.134, List.135, List.132): let List.515 : {List U8, U64} = CallByName Json.105 List.134 List.135; let List.514 : [C [], C {List U8, U64}] = TagId(1) List.515; ret List.514; procedure List.18 (List.130, List.131, List.132): - let List.411 : {{}} = Struct {List.132}; - let List.405 : [C [], C {List U8, U64}] = CallByName List.75 List.130 List.131 List.411; + let List.405 : [C [], C {List U8, U64}] = CallByName List.75 List.130 List.131 List.132; let List.408 : U8 = 1i64; let List.409 : U8 = GetTagId List.405; let List.410 : Int1 = lowlevel Eq List.408 List.409; @@ -254,8 +231,7 @@ procedure List.18 (List.130, List.131, List.132): ret List.407; procedure List.18 (List.130, List.131, List.132): - let List.491 : {{}} = Struct {List.132}; - let List.485 : [C [], C {List U8, U64}] = CallByName List.75 List.130 List.131 List.491; + let List.485 : [C [], C {List U8, U64}] = CallByName List.75 List.130 List.131 List.132; let List.488 : U8 = 1i64; let List.489 : U8 = GetTagId List.485; let List.490 : Int1 = lowlevel Eq List.488 List.489; @@ -289,11 +265,11 @@ procedure List.6 (#Attr.2): ret List.494; procedure List.66 (#Attr.2, #Attr.3): - let List.432 : {Str, {Str}} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + let List.432 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.432; procedure List.66 (#Attr.2, #Attr.3): - let List.513 : {Str, {Str}} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + let List.513 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.513; procedure List.69 (#Attr.2): @@ -328,7 +304,7 @@ procedure List.86 (List.448, List.449, List.450, List.451, List.452): joinpoint List.420 List.364 List.365 List.366 List.367 List.368: let List.422 : Int1 = CallByName Num.22 List.367 List.368; if List.422 then - let List.431 : {Str, {Str}} = CallByName List.66 List.364 List.367; + let List.431 : {Str, Str} = CallByName List.66 List.364 List.367; let List.423 : [C [], C {List U8, U64}] = CallByName List.133 List.365 List.431 List.366; let List.428 : U8 = 1i64; let List.429 : U8 = GetTagId List.423; @@ -355,7 +331,7 @@ procedure List.86 (List.529, List.530, List.531, List.532, List.533): joinpoint List.501 List.364 List.365 List.366 List.367 List.368: let List.503 : Int1 = CallByName Num.22 List.367 List.368; if List.503 then - let List.512 : {Str, {Str}} = CallByName List.66 List.364 List.367; + let List.512 : {Str, Str} = CallByName List.66 List.364 List.367; let List.504 : [C [], C {List U8, U64}] = CallByName List.133 List.365 List.512 List.366; let List.509 : U8 = 1i64; let List.510 : U8 = GetTagId List.504; diff --git a/crates/compiler/test_mono/generated/encode_derived_record_one_field_string.txt b/crates/compiler/test_mono/generated/encode_derived_record_one_field_string.txt index 733350c9e4..3398a4c5e9 100644 --- a/crates/compiler/test_mono/generated/encode_derived_record_one_field_string.txt +++ b/crates/compiler/test_mono/generated/encode_derived_record_one_field_string.txt @@ -1,17 +1,13 @@ procedure #Derived.0 (#Derived.1): - let #Derived_gen.1 : {Str} = Struct {#Derived.1}; - let #Derived_gen.0 : {Str} = CallByName Encode.22 #Derived_gen.1; + let #Derived_gen.0 : Str = CallByName Encode.22 #Derived.1; ret #Derived_gen.0; -procedure #Derived.2 (#Derived.3, #Derived.4, #Attr.12): - let #Derived.1 : Str = StructAtIndex 0 #Attr.12; - inc #Derived.1; - dec #Attr.12; +procedure #Derived.2 (#Derived.3, #Derived.4, #Derived.1): let #Derived_gen.7 : Str = "a"; - let #Derived_gen.8 : {Str} = CallByName Json.18 #Derived.1; - let #Derived_gen.6 : {Str, {Str}} = Struct {#Derived_gen.7, #Derived_gen.8}; - let #Derived_gen.5 : List {Str, {Str}} = Array [#Derived_gen.6]; - let #Derived_gen.4 : {List {Str, {Str}}} = CallByName Json.20 #Derived_gen.5; + let #Derived_gen.8 : Str = CallByName Json.18 #Derived.1; + let #Derived_gen.6 : {Str, Str} = Struct {#Derived_gen.7, #Derived_gen.8}; + let #Derived_gen.5 : List {Str, Str} = Array [#Derived_gen.6]; + let #Derived_gen.4 : List {Str, Str} = CallByName Json.20 #Derived_gen.5; let #Derived_gen.3 : List U8 = CallByName Encode.23 #Derived.3 #Derived_gen.4 #Derived.4; ret #Derived_gen.3; @@ -38,7 +34,7 @@ procedure Encode.23 (Encode.94, Encode.102, Encode.96): procedure Encode.25 (Encode.100, Encode.101): let Encode.104 : List U8 = Array []; - let Encode.105 : {Str} = CallByName #Derived.0 Encode.100; + let Encode.105 : Str = CallByName #Derived.0 Encode.100; let Encode.103 : List U8 = CallByName Encode.23 Encode.104 Encode.105 Encode.101; ret Encode.103; @@ -46,10 +42,7 @@ procedure Json.1 (): let Json.318 : {} = Struct {}; ret Json.318; -procedure Json.103 (Json.104, Json.321, #Attr.12): - let Json.102 : List {Str, {Str}} = StructAtIndex 0 #Attr.12; - inc Json.102; - dec #Attr.12; +procedure Json.103 (Json.104, Json.321, Json.102): let Json.357 : I32 = 123i64; let Json.356 : U8 = CallByName Num.123 Json.357; let Json.106 : List U8 = CallByName List.4 Json.104 Json.356; @@ -69,7 +62,7 @@ procedure Json.103 (Json.104, Json.321, #Attr.12): procedure Json.105 (Json.326, Json.327): let Json.111 : Str = StructAtIndex 0 Json.327; inc Json.111; - let Json.112 : {Str} = StructAtIndex 1 Json.327; + let Json.112 : Str = StructAtIndex 1 Json.327; inc Json.112; dec Json.327; let Json.109 : List U8 = StructAtIndex 0 Json.326; @@ -106,19 +99,14 @@ procedure Json.105 (Json.326, Json.327): jump Json.338 Json.113; procedure Json.18 (Json.86): - let Json.323 : {Str} = Struct {Json.86}; - let Json.322 : {Str} = CallByName Encode.22 Json.323; + let Json.322 : Str = CallByName Encode.22 Json.86; ret Json.322; procedure Json.20 (Json.102): - let Json.320 : {List {Str, {Str}}} = Struct {Json.102}; - let Json.319 : {List {Str, {Str}}} = CallByName Encode.22 Json.320; + let Json.319 : List {Str, Str} = CallByName Encode.22 Json.102; ret Json.319; -procedure Json.87 (Json.88, Json.324, #Attr.12): - let Json.86 : Str = StructAtIndex 0 #Attr.12; - inc Json.86; - dec #Attr.12; +procedure Json.87 (Json.88, Json.324, Json.86): let Json.366 : I32 = 34i64; let Json.365 : U8 = CallByName Num.123 Json.366; let Json.363 : List U8 = CallByName List.4 Json.88 Json.365; @@ -129,15 +117,13 @@ procedure Json.87 (Json.88, Json.324, #Attr.12): let Json.359 : List U8 = CallByName List.4 Json.360 Json.361; ret Json.359; -procedure List.133 (List.134, List.135, #Attr.12): - let List.132 : {} = StructAtIndex 0 #Attr.12; +procedure List.133 (List.134, List.135, List.132): let List.441 : {List U8, U64} = CallByName Json.105 List.134 List.135; let List.440 : [C [], C {List U8, U64}] = TagId(1) List.441; ret List.440; procedure List.18 (List.130, List.131, List.132): - let List.417 : {{}} = Struct {List.132}; - let List.411 : [C [], C {List U8, U64}] = CallByName List.75 List.130 List.131 List.417; + let List.411 : [C [], C {List U8, U64}] = CallByName List.75 List.130 List.131 List.132; let List.414 : U8 = 1i64; let List.415 : U8 = GetTagId List.411; let List.416 : Int1 = lowlevel Eq List.414 List.415; @@ -167,7 +153,7 @@ procedure List.6 (#Attr.2): ret List.420; procedure List.66 (#Attr.2, #Attr.3): - let List.439 : {Str, {Str}} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + let List.439 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.439; procedure List.69 (#Attr.2): @@ -196,7 +182,7 @@ procedure List.86 (List.455, List.456, List.457, List.458, List.459): joinpoint List.427 List.364 List.365 List.366 List.367 List.368: let List.429 : Int1 = CallByName Num.22 List.367 List.368; if List.429 then - let List.438 : {Str, {Str}} = CallByName List.66 List.364 List.367; + let List.438 : {Str, Str} = CallByName List.66 List.364 List.367; let List.430 : [C [], C {List U8, U64}] = CallByName List.133 List.365 List.438 List.366; let List.435 : U8 = 1i64; let List.436 : U8 = GetTagId List.430; diff --git a/crates/compiler/test_mono/generated/encode_derived_record_two_field_strings.txt b/crates/compiler/test_mono/generated/encode_derived_record_two_field_strings.txt index 918c446170..0aff7f2c04 100644 --- a/crates/compiler/test_mono/generated/encode_derived_record_two_field_strings.txt +++ b/crates/compiler/test_mono/generated/encode_derived_record_two_field_strings.txt @@ -1,25 +1,21 @@ procedure #Derived.0 (#Derived.1): - let #Derived_gen.1 : {{Str, Str}} = Struct {#Derived.1}; - let #Derived_gen.0 : {{Str, Str}} = CallByName Encode.22 #Derived_gen.1; + let #Derived_gen.0 : {Str, Str} = CallByName Encode.22 #Derived.1; ret #Derived_gen.0; -procedure #Derived.2 (#Derived.3, #Derived.4, #Attr.12): - let #Derived.1 : {Str, Str} = StructAtIndex 0 #Attr.12; - inc #Derived.1; - dec #Attr.12; +procedure #Derived.2 (#Derived.3, #Derived.4, #Derived.1): let #Derived_gen.11 : Str = "a"; let #Derived_gen.13 : Str = StructAtIndex 0 #Derived.1; inc #Derived_gen.13; - let #Derived_gen.12 : {Str} = CallByName Json.18 #Derived_gen.13; - let #Derived_gen.6 : {Str, {Str}} = Struct {#Derived_gen.11, #Derived_gen.12}; + let #Derived_gen.12 : Str = CallByName Json.18 #Derived_gen.13; + let #Derived_gen.6 : {Str, Str} = Struct {#Derived_gen.11, #Derived_gen.12}; let #Derived_gen.8 : Str = "b"; let #Derived_gen.10 : Str = StructAtIndex 1 #Derived.1; inc #Derived_gen.10; dec #Derived.1; - let #Derived_gen.9 : {Str} = CallByName Json.18 #Derived_gen.10; - let #Derived_gen.7 : {Str, {Str}} = Struct {#Derived_gen.8, #Derived_gen.9}; - let #Derived_gen.5 : List {Str, {Str}} = Array [#Derived_gen.6, #Derived_gen.7]; - let #Derived_gen.4 : {List {Str, {Str}}} = CallByName Json.20 #Derived_gen.5; + let #Derived_gen.9 : Str = CallByName Json.18 #Derived_gen.10; + let #Derived_gen.7 : {Str, Str} = Struct {#Derived_gen.8, #Derived_gen.9}; + let #Derived_gen.5 : List {Str, Str} = Array [#Derived_gen.6, #Derived_gen.7]; + let #Derived_gen.4 : List {Str, Str} = CallByName Json.20 #Derived_gen.5; let #Derived_gen.3 : List U8 = CallByName Encode.23 #Derived.3 #Derived_gen.4 #Derived.4; ret #Derived_gen.3; @@ -46,7 +42,7 @@ procedure Encode.23 (Encode.94, Encode.102, Encode.96): procedure Encode.25 (Encode.100, Encode.101): let Encode.104 : List U8 = Array []; - let Encode.105 : {{Str, Str}} = CallByName #Derived.0 Encode.100; + let Encode.105 : {Str, Str} = CallByName #Derived.0 Encode.100; let Encode.103 : List U8 = CallByName Encode.23 Encode.104 Encode.105 Encode.101; ret Encode.103; @@ -54,10 +50,7 @@ procedure Json.1 (): let Json.318 : {} = Struct {}; ret Json.318; -procedure Json.103 (Json.104, Json.321, #Attr.12): - let Json.102 : List {Str, {Str}} = StructAtIndex 0 #Attr.12; - inc Json.102; - dec #Attr.12; +procedure Json.103 (Json.104, Json.321, Json.102): let Json.360 : I32 = 123i64; let Json.359 : U8 = CallByName Num.123 Json.360; let Json.106 : List U8 = CallByName List.4 Json.104 Json.359; @@ -77,7 +70,7 @@ procedure Json.103 (Json.104, Json.321, #Attr.12): procedure Json.105 (Json.329, Json.330): let Json.111 : Str = StructAtIndex 0 Json.330; inc Json.111; - let Json.112 : {Str} = StructAtIndex 1 Json.330; + let Json.112 : Str = StructAtIndex 1 Json.330; inc Json.112; dec Json.330; let Json.109 : List U8 = StructAtIndex 0 Json.329; @@ -114,19 +107,14 @@ procedure Json.105 (Json.329, Json.330): jump Json.341 Json.113; procedure Json.18 (Json.86): - let Json.326 : {Str} = Struct {Json.86}; - let Json.325 : {Str} = CallByName Encode.22 Json.326; + let Json.325 : Str = CallByName Encode.22 Json.86; ret Json.325; procedure Json.20 (Json.102): - let Json.320 : {List {Str, {Str}}} = Struct {Json.102}; - let Json.319 : {List {Str, {Str}}} = CallByName Encode.22 Json.320; + let Json.319 : List {Str, Str} = CallByName Encode.22 Json.102; ret Json.319; -procedure Json.87 (Json.88, Json.324, #Attr.12): - let Json.86 : Str = StructAtIndex 0 #Attr.12; - inc Json.86; - dec #Attr.12; +procedure Json.87 (Json.88, Json.324, Json.86): let Json.369 : I32 = 34i64; let Json.368 : U8 = CallByName Num.123 Json.369; let Json.366 : List U8 = CallByName List.4 Json.88 Json.368; @@ -137,15 +125,13 @@ procedure Json.87 (Json.88, Json.324, #Attr.12): let Json.362 : List U8 = CallByName List.4 Json.363 Json.364; ret Json.362; -procedure List.133 (List.134, List.135, #Attr.12): - let List.132 : {} = StructAtIndex 0 #Attr.12; +procedure List.133 (List.134, List.135, List.132): let List.441 : {List U8, U64} = CallByName Json.105 List.134 List.135; let List.440 : [C [], C {List U8, U64}] = TagId(1) List.441; ret List.440; procedure List.18 (List.130, List.131, List.132): - let List.417 : {{}} = Struct {List.132}; - let List.411 : [C [], C {List U8, U64}] = CallByName List.75 List.130 List.131 List.417; + let List.411 : [C [], C {List U8, U64}] = CallByName List.75 List.130 List.131 List.132; let List.414 : U8 = 1i64; let List.415 : U8 = GetTagId List.411; let List.416 : Int1 = lowlevel Eq List.414 List.415; @@ -175,7 +161,7 @@ procedure List.6 (#Attr.2): ret List.420; procedure List.66 (#Attr.2, #Attr.3): - let List.439 : {Str, {Str}} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + let List.439 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.439; procedure List.69 (#Attr.2): @@ -204,7 +190,7 @@ procedure List.86 (List.455, List.456, List.457, List.458, List.459): joinpoint List.427 List.364 List.365 List.366 List.367 List.368: let List.429 : Int1 = CallByName Num.22 List.367 List.368; if List.429 then - let List.438 : {Str, {Str}} = CallByName List.66 List.364 List.367; + let List.438 : {Str, Str} = CallByName List.66 List.364 List.367; let List.430 : [C [], C {List U8, U64}] = CallByName List.133 List.365 List.438 List.366; let List.435 : U8 = 1i64; let List.436 : U8 = GetTagId List.430; diff --git a/crates/compiler/test_mono/generated/encode_derived_string.txt b/crates/compiler/test_mono/generated/encode_derived_string.txt index e4fe6488dd..5fd131fd3f 100644 --- a/crates/compiler/test_mono/generated/encode_derived_string.txt +++ b/crates/compiler/test_mono/generated/encode_derived_string.txt @@ -7,7 +7,7 @@ procedure Encode.23 (Encode.94, Encode.102, Encode.96): procedure Encode.25 (Encode.100, Encode.101): let Encode.104 : List U8 = Array []; - let Encode.105 : {Str} = CallByName Json.18 Encode.100; + let Encode.105 : Str = CallByName Json.18 Encode.100; let Encode.103 : List U8 = CallByName Encode.23 Encode.104 Encode.105 Encode.101; ret Encode.103; @@ -16,14 +16,10 @@ procedure Json.1 (): ret Json.318; procedure Json.18 (Json.86): - let Json.320 : {Str} = Struct {Json.86}; - let Json.319 : {Str} = CallByName Encode.22 Json.320; + let Json.319 : Str = CallByName Encode.22 Json.86; ret Json.319; -procedure Json.87 (Json.88, Json.321, #Attr.12): - let Json.86 : Str = StructAtIndex 0 #Attr.12; - inc Json.86; - dec #Attr.12; +procedure Json.87 (Json.88, Json.321, Json.86): let Json.330 : I32 = 34i64; let Json.329 : U8 = CallByName Num.123 Json.330; let Json.327 : List U8 = CallByName List.4 Json.88 Json.329; diff --git a/crates/compiler/test_mono/generated/encode_derived_tag_one_field_string.txt b/crates/compiler/test_mono/generated/encode_derived_tag_one_field_string.txt index 41fc52f97d..1dab5efd61 100644 --- a/crates/compiler/test_mono/generated/encode_derived_tag_one_field_string.txt +++ b/crates/compiler/test_mono/generated/encode_derived_tag_one_field_string.txt @@ -1,20 +1,16 @@ procedure #Derived.0 (#Derived.1): - let #Derived_gen.1 : {Str} = Struct {#Derived.1}; - let #Derived_gen.0 : {Str} = CallByName Encode.22 #Derived_gen.1; + let #Derived_gen.0 : Str = CallByName Encode.22 #Derived.1; ret #Derived_gen.0; -procedure #Derived.3 (#Derived.4, #Derived.5, #Attr.12): - let #Derived.1 : Str = StructAtIndex 0 #Attr.12; - inc #Derived.1; - dec #Attr.12; +procedure #Derived.3 (#Derived.4, #Derived.5, #Derived.1): joinpoint #Derived_gen.5 #Derived_gen.4: let #Derived_gen.3 : List U8 = CallByName Encode.23 #Derived.4 #Derived_gen.4 #Derived.5; ret #Derived_gen.3; in let #Derived_gen.7 : Str = "A"; - let #Derived_gen.9 : {Str} = CallByName Json.18 #Derived.1; - let #Derived_gen.8 : List {Str} = Array [#Derived_gen.9]; - let #Derived_gen.6 : {Str, List {Str}} = CallByName Json.21 #Derived_gen.7 #Derived_gen.8; + let #Derived_gen.9 : Str = CallByName Json.18 #Derived.1; + let #Derived_gen.8 : List Str = Array [#Derived_gen.9]; + let #Derived_gen.6 : {Str, List Str} = CallByName Json.21 #Derived_gen.7 #Derived_gen.8; jump #Derived_gen.5 #Derived_gen.6; procedure Encode.22 (Encode.93): @@ -40,7 +36,7 @@ procedure Encode.23 (Encode.94, Encode.102, Encode.96): procedure Encode.25 (Encode.100, Encode.101): let Encode.104 : List U8 = Array []; - let Encode.105 : {Str} = CallByName #Derived.0 Encode.100; + let Encode.105 : Str = CallByName #Derived.0 Encode.100; let Encode.103 : List U8 = CallByName Encode.23 Encode.104 Encode.105 Encode.101; ret Encode.103; @@ -49,7 +45,7 @@ procedure Json.1 (): ret Json.318; procedure Json.117 (Json.118, Json.321, #Attr.12): - let Json.116 : List {Str} = StructAtIndex 1 #Attr.12; + let Json.116 : List Str = StructAtIndex 1 #Attr.12; inc Json.116; let Json.115 : Str = StructAtIndex 0 #Attr.12; inc Json.115; @@ -111,19 +107,15 @@ procedure Json.119 (Json.326, Json.125): jump Json.340 Json.126; procedure Json.18 (Json.86): - let Json.323 : {Str} = Struct {Json.86}; - let Json.322 : {Str} = CallByName Encode.22 Json.323; + let Json.322 : Str = CallByName Encode.22 Json.86; ret Json.322; procedure Json.21 (Json.115, Json.116): - let Json.320 : {Str, List {Str}} = Struct {Json.115, Json.116}; - let Json.319 : {Str, List {Str}} = CallByName Encode.22 Json.320; + let Json.320 : {Str, List Str} = Struct {Json.115, Json.116}; + let Json.319 : {Str, List Str} = CallByName Encode.22 Json.320; ret Json.319; -procedure Json.87 (Json.88, Json.324, #Attr.12): - let Json.86 : Str = StructAtIndex 0 #Attr.12; - inc Json.86; - dec #Attr.12; +procedure Json.87 (Json.88, Json.324, Json.86): let Json.371 : I32 = 34i64; let Json.370 : U8 = CallByName Num.123 Json.371; let Json.368 : List U8 = CallByName List.4 Json.88 Json.370; @@ -134,15 +126,13 @@ procedure Json.87 (Json.88, Json.324, #Attr.12): let Json.364 : List U8 = CallByName List.4 Json.365 Json.366; ret Json.364; -procedure List.133 (List.134, List.135, #Attr.12): - let List.132 : {} = StructAtIndex 0 #Attr.12; +procedure List.133 (List.134, List.135, List.132): let List.447 : {List U8, U64} = CallByName Json.119 List.134 List.135; let List.446 : [C [], C {List U8, U64}] = TagId(1) List.447; ret List.446; procedure List.18 (List.130, List.131, List.132): - let List.423 : {{}} = Struct {List.132}; - let List.417 : [C [], C {List U8, U64}] = CallByName List.75 List.130 List.131 List.423; + let List.417 : [C [], C {List U8, U64}] = CallByName List.75 List.130 List.131 List.132; let List.420 : U8 = 1i64; let List.421 : U8 = GetTagId List.417; let List.422 : Int1 = lowlevel Eq List.420 List.421; @@ -172,7 +162,7 @@ procedure List.6 (#Attr.2): ret List.424; procedure List.66 (#Attr.2, #Attr.3): - let List.445 : {Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + let List.445 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.445; procedure List.69 (#Attr.2): @@ -201,7 +191,7 @@ procedure List.86 (List.461, List.462, List.463, List.464, List.465): joinpoint List.433 List.364 List.365 List.366 List.367 List.368: let List.435 : Int1 = CallByName Num.22 List.367 List.368; if List.435 then - let List.444 : {Str} = CallByName List.66 List.364 List.367; + let List.444 : Str = CallByName List.66 List.364 List.367; let List.436 : [C [], C {List U8, U64}] = CallByName List.133 List.365 List.444 List.366; let List.441 : U8 = 1i64; let List.442 : U8 = GetTagId List.436; diff --git a/crates/compiler/test_mono/generated/encode_derived_tag_two_payloads_string.txt b/crates/compiler/test_mono/generated/encode_derived_tag_two_payloads_string.txt index fc88805f4c..81035c77b5 100644 --- a/crates/compiler/test_mono/generated/encode_derived_tag_two_payloads_string.txt +++ b/crates/compiler/test_mono/generated/encode_derived_tag_two_payloads_string.txt @@ -1,12 +1,8 @@ procedure #Derived.0 (#Derived.1): - let #Derived_gen.1 : {{Str, Str}} = Struct {#Derived.1}; - let #Derived_gen.0 : {{Str, Str}} = CallByName Encode.22 #Derived_gen.1; + let #Derived_gen.0 : {Str, Str} = CallByName Encode.22 #Derived.1; ret #Derived_gen.0; -procedure #Derived.4 (#Derived.5, #Derived.6, #Attr.12): - let #Derived.1 : {Str, Str} = StructAtIndex 0 #Attr.12; - inc #Derived.1; - dec #Attr.12; +procedure #Derived.4 (#Derived.5, #Derived.6, #Derived.1): joinpoint #Derived_gen.5 #Derived_gen.4: let #Derived_gen.3 : List U8 = CallByName Encode.23 #Derived.5 #Derived_gen.4 #Derived.6; ret #Derived_gen.3; @@ -17,10 +13,10 @@ procedure #Derived.4 (#Derived.5, #Derived.6, #Attr.12): inc #Derived.3; dec #Derived.1; let #Derived_gen.7 : Str = "A"; - let #Derived_gen.9 : {Str} = CallByName Json.18 #Derived.2; - let #Derived_gen.10 : {Str} = CallByName Json.18 #Derived.3; - let #Derived_gen.8 : List {Str} = Array [#Derived_gen.9, #Derived_gen.10]; - let #Derived_gen.6 : {Str, List {Str}} = CallByName Json.21 #Derived_gen.7 #Derived_gen.8; + let #Derived_gen.9 : Str = CallByName Json.18 #Derived.2; + let #Derived_gen.10 : Str = CallByName Json.18 #Derived.3; + let #Derived_gen.8 : List Str = Array [#Derived_gen.9, #Derived_gen.10]; + let #Derived_gen.6 : {Str, List Str} = CallByName Json.21 #Derived_gen.7 #Derived_gen.8; jump #Derived_gen.5 #Derived_gen.6; procedure Encode.22 (Encode.93): @@ -46,7 +42,7 @@ procedure Encode.23 (Encode.94, Encode.102, Encode.96): procedure Encode.25 (Encode.100, Encode.101): let Encode.104 : List U8 = Array []; - let Encode.105 : {{Str, Str}} = CallByName #Derived.0 Encode.100; + let Encode.105 : {Str, Str} = CallByName #Derived.0 Encode.100; let Encode.103 : List U8 = CallByName Encode.23 Encode.104 Encode.105 Encode.101; ret Encode.103; @@ -55,7 +51,7 @@ procedure Json.1 (): ret Json.318; procedure Json.117 (Json.118, Json.321, #Attr.12): - let Json.116 : List {Str} = StructAtIndex 1 #Attr.12; + let Json.116 : List Str = StructAtIndex 1 #Attr.12; inc Json.116; let Json.115 : Str = StructAtIndex 0 #Attr.12; inc Json.115; @@ -117,19 +113,15 @@ procedure Json.119 (Json.329, Json.125): jump Json.343 Json.126; procedure Json.18 (Json.86): - let Json.326 : {Str} = Struct {Json.86}; - let Json.325 : {Str} = CallByName Encode.22 Json.326; + let Json.325 : Str = CallByName Encode.22 Json.86; ret Json.325; procedure Json.21 (Json.115, Json.116): - let Json.320 : {Str, List {Str}} = Struct {Json.115, Json.116}; - let Json.319 : {Str, List {Str}} = CallByName Encode.22 Json.320; + let Json.320 : {Str, List Str} = Struct {Json.115, Json.116}; + let Json.319 : {Str, List Str} = CallByName Encode.22 Json.320; ret Json.319; -procedure Json.87 (Json.88, Json.324, #Attr.12): - let Json.86 : Str = StructAtIndex 0 #Attr.12; - inc Json.86; - dec #Attr.12; +procedure Json.87 (Json.88, Json.324, Json.86): let Json.374 : I32 = 34i64; let Json.373 : U8 = CallByName Num.123 Json.374; let Json.371 : List U8 = CallByName List.4 Json.88 Json.373; @@ -140,15 +132,13 @@ procedure Json.87 (Json.88, Json.324, #Attr.12): let Json.367 : List U8 = CallByName List.4 Json.368 Json.369; ret Json.367; -procedure List.133 (List.134, List.135, #Attr.12): - let List.132 : {} = StructAtIndex 0 #Attr.12; +procedure List.133 (List.134, List.135, List.132): let List.447 : {List U8, U64} = CallByName Json.119 List.134 List.135; let List.446 : [C [], C {List U8, U64}] = TagId(1) List.447; ret List.446; procedure List.18 (List.130, List.131, List.132): - let List.423 : {{}} = Struct {List.132}; - let List.417 : [C [], C {List U8, U64}] = CallByName List.75 List.130 List.131 List.423; + let List.417 : [C [], C {List U8, U64}] = CallByName List.75 List.130 List.131 List.132; let List.420 : U8 = 1i64; let List.421 : U8 = GetTagId List.417; let List.422 : Int1 = lowlevel Eq List.420 List.421; @@ -178,7 +168,7 @@ procedure List.6 (#Attr.2): ret List.424; procedure List.66 (#Attr.2, #Attr.3): - let List.445 : {Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + let List.445 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.445; procedure List.69 (#Attr.2): @@ -207,7 +197,7 @@ procedure List.86 (List.461, List.462, List.463, List.464, List.465): joinpoint List.433 List.364 List.365 List.366 List.367 List.368: let List.435 : Int1 = CallByName Num.22 List.367 List.368; if List.435 then - let List.444 : {Str} = CallByName List.66 List.364 List.367; + let List.444 : Str = CallByName List.66 List.364 List.367; let List.436 : [C [], C {List U8, U64}] = CallByName List.133 List.365 List.444 List.366; let List.441 : U8 = 1i64; let List.442 : U8 = GetTagId List.436; diff --git a/crates/compiler/test_mono/generated/lambda_capture_niches_have_captured_function_in_closure.txt b/crates/compiler/test_mono/generated/lambda_capture_niches_have_captured_function_in_closure.txt index 5228441c5b..83658eacbb 100644 --- a/crates/compiler/test_mono/generated/lambda_capture_niches_have_captured_function_in_closure.txt +++ b/crates/compiler/test_mono/generated/lambda_capture_niches_have_captured_function_in_closure.txt @@ -2,10 +2,7 @@ procedure Test.11 (Test.37): let Test.38 : Str = ""; ret Test.38; -procedure Test.13 (Test.51, #Attr.12): - let Test.12 : Str = StructAtIndex 0 #Attr.12; - inc Test.12; - dec #Attr.12; +procedure Test.13 (Test.51, Test.12): ret Test.12; procedure Test.15 (Test.39): @@ -29,8 +26,8 @@ procedure Test.3 (Test.17): ret Test.36; procedure Test.4 (Test.18): - let Test.50 : {Str} = Struct {Test.18}; - ret Test.50; + inc Test.18; + ret Test.18; procedure Test.9 (Test.29, #Attr.12): let Test.8 : {} = UnionAtIndex (Id 0) (Index 1) #Attr.12; @@ -48,7 +45,8 @@ procedure Test.9 (Test.29, #Attr.12): let Test.7 : {} = UnionAtIndex (Id 1) (Index 0) #Attr.12; let Test.49 : {} = Struct {}; let Test.48 : Str = CallByName Test.16 Test.49; - let Test.45 : {Str} = CallByName Test.4 Test.48; + let Test.45 : Str = CallByName Test.4 Test.48; + dec Test.48; let Test.47 : {} = Struct {}; let Test.46 : Str = CallByName Test.13 Test.47 Test.45; ret Test.46; diff --git a/crates/compiler/test_mono/generated/lambda_set_niche_same_layout_different_constructor.txt b/crates/compiler/test_mono/generated/lambda_set_niche_same_layout_different_constructor.txt index ae024a188f..7e624d7a76 100644 --- a/crates/compiler/test_mono/generated/lambda_set_niche_same_layout_different_constructor.txt +++ b/crates/compiler/test_mono/generated/lambda_set_niche_same_layout_different_constructor.txt @@ -1,11 +1,9 @@ procedure Test.1 (Test.4): - let Test.5 : {Str} = Struct {Test.4}; - ret Test.5; - -procedure Test.5 (Test.12, #Attr.12): - let Test.4 : Str = StructAtIndex 0 #Attr.12; inc Test.4; - dec #Attr.12; + ret Test.4; + +procedure Test.5 (Test.12, Test.4): + dec Test.4; let Test.14 : Str = ""; ret Test.14; @@ -18,9 +16,11 @@ procedure Test.0 (): let Test.20 : Int1 = lowlevel Eq Test.19 Test.2; if Test.20 then let Test.15 : Str = ""; - let Test.10 : {Str} = CallByName Test.1 Test.15; + let Test.10 : Str = CallByName Test.1 Test.15; + dec Test.15; jump Test.9 Test.10; else let Test.18 : Str = ""; - let Test.16 : {Str} = CallByName Test.1 Test.18; + let Test.16 : Str = CallByName Test.1 Test.18; + dec Test.18; jump Test.9 Test.16; diff --git a/crates/compiler/test_mono/generated/nested_closure.txt b/crates/compiler/test_mono/generated/nested_closure.txt index 304722fa96..1b9d1a6f1d 100644 --- a/crates/compiler/test_mono/generated/nested_closure.txt +++ b/crates/compiler/test_mono/generated/nested_closure.txt @@ -1,15 +1,13 @@ procedure Test.1 (Test.5): let Test.2 : I64 = 42i64; - let Test.3 : {I64} = Struct {Test.2}; - ret Test.3; + ret Test.2; -procedure Test.3 (Test.9, #Attr.12): - let Test.2 : I64 = StructAtIndex 0 #Attr.12; +procedure Test.3 (Test.9, Test.2): ret Test.2; procedure Test.0 (): let Test.8 : {} = Struct {}; - let Test.4 : {I64} = CallByName Test.1 Test.8; + let Test.4 : I64 = CallByName Test.1 Test.8; let Test.7 : {} = Struct {}; let Test.6 : I64 = CallByName Test.3 Test.7 Test.4; ret Test.6; diff --git a/crates/compiler/test_mono/generated/recursive_call_capturing_function.txt b/crates/compiler/test_mono/generated/recursive_call_capturing_function.txt index a298bf4ab4..95837c3b32 100644 --- a/crates/compiler/test_mono/generated/recursive_call_capturing_function.txt +++ b/crates/compiler/test_mono/generated/recursive_call_capturing_function.txt @@ -4,20 +4,17 @@ procedure Num.19 (#Attr.2, #Attr.3): procedure Test.1 (Test.2): let Test.9 : U32 = 0i64; - let Test.16 : {U32} = Struct {Test.2}; - let Test.8 : U32 = CallByName Test.3 Test.9 Test.16; + let Test.8 : U32 = CallByName Test.3 Test.9 Test.2; ret Test.8; procedure Test.3 (Test.18, Test.19): - joinpoint Test.10 Test.4 #Attr.12: - let Test.2 : U32 = StructAtIndex 0 #Attr.12; + joinpoint Test.10 Test.4 Test.2: let Test.14 : Int1 = true; if Test.14 then ret Test.4; else let Test.12 : U32 = CallByName Num.19 Test.4 Test.2; - let Test.13 : {U32} = Struct {Test.2}; - jump Test.10 Test.12 Test.13; + jump Test.10 Test.12 Test.2; in jump Test.10 Test.18 Test.19;