diff --git a/crates/compiler/gen_llvm/src/llvm/bitcode.rs b/crates/compiler/gen_llvm/src/llvm/bitcode.rs index e91b029248..8aee64db01 100644 --- a/crates/compiler/gen_llvm/src/llvm/bitcode.rs +++ b/crates/compiler/gen_llvm/src/llvm/bitcode.rs @@ -17,7 +17,9 @@ use inkwell::values::{ use inkwell::AddressSpace; use roc_error_macros::internal_error; use roc_module::symbol::Symbol; -use roc_mono::layout::{Builtin, LambdaSet, Layout, LayoutIds, STLayoutInterner}; +use roc_mono::layout::{ + Builtin, InLayout, LambdaSet, Layout, LayoutIds, LayoutInterner, STLayoutInterner, +}; use super::build::{create_entry_block_alloca, BuilderExt}; use super::convert::zig_list_type; @@ -98,7 +100,7 @@ pub fn call_bitcode_fn_fixing_for_convention<'a, 'ctx, 'env>( layout_interner: &mut STLayoutInterner<'a>, bitcode_return_type: StructType<'ctx>, args: &[BasicValueEnum<'ctx>], - return_layout: &Layout<'a>, + return_layout: InLayout<'a>, fn_name: &str, ) -> BasicValueEnum<'ctx> { // Calling zig bitcode, so we must follow C calling conventions. @@ -168,8 +170,8 @@ pub(crate) fn build_transform_caller<'a, 'ctx, 'env>( layout_interner: &mut STLayoutInterner<'a>, function: FunctionValue<'ctx>, closure_data_layout: LambdaSet<'a>, - argument_layouts: &[Layout<'a>], - result_layout: Layout<'a>, + argument_layouts: &[InLayout<'a>], + result_layout: InLayout<'a>, ) -> FunctionValue<'ctx> { let fn_name: &str = &format!( "{}_zig_function_caller", @@ -195,8 +197,8 @@ fn build_transform_caller_help<'a, 'ctx, 'env>( layout_interner: &mut STLayoutInterner<'a>, roc_function: FunctionValue<'ctx>, closure_data_layout: LambdaSet<'a>, - argument_layouts: &[Layout<'a>], - result_layout: Layout<'a>, + argument_layouts: &[InLayout<'a>], + result_layout: InLayout<'a>, fn_name: &str, ) -> FunctionValue<'ctx> { debug_assert!(argument_layouts.len() <= 7); @@ -242,7 +244,7 @@ fn build_transform_caller_help<'a, 'ctx, 'env>( for (argument_ptr, layout) in arguments.iter().zip(argument_layouts) { let basic_type = - basic_type_from_layout(env, layout_interner, layout).ptr_type(AddressSpace::Generic); + basic_type_from_layout(env, layout_interner, *layout).ptr_type(AddressSpace::Generic); let cast_ptr = env.builder.build_pointer_cast( argument_ptr.into_pointer_value(), @@ -265,13 +267,13 @@ fn build_transform_caller_help<'a, 'ctx, 'env>( closure_data_layout .is_represented(layout_interner) .is_some(), - closure_data_layout.runtime_representation(layout_interner), + closure_data_layout.runtime_representation(), ) { (false, _) => { // the function doesn't expect a closure argument, nothing to add } (true, layout) => { - let closure_type = basic_type_from_layout(env, layout_interner, &layout) + let closure_type = basic_type_from_layout(env, layout_interner, layout) .ptr_type(AddressSpace::Generic); let closure_cast = @@ -289,7 +291,7 @@ fn build_transform_caller_help<'a, 'ctx, 'env>( env, layout_interner, roc_function, - &result_layout, + result_layout, arguments_cast.as_slice(), ); @@ -325,7 +327,7 @@ pub fn build_inc_n_wrapper<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, layout_ids: &mut LayoutIds<'a>, - layout: &Layout<'a>, + layout: InLayout<'a>, ) -> FunctionValue<'ctx> { build_rc_wrapper(env, layout_interner, layout_ids, layout, Mode::IncN) } @@ -335,7 +337,7 @@ pub fn build_inc_wrapper<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, layout_ids: &mut LayoutIds<'a>, - layout: &Layout<'a>, + layout: InLayout<'a>, ) -> FunctionValue<'ctx> { build_rc_wrapper(env, layout_interner, layout_ids, layout, Mode::Inc) } @@ -344,7 +346,7 @@ pub fn build_dec_wrapper<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, layout_ids: &mut LayoutIds<'a>, - layout: &Layout<'a>, + layout: InLayout<'a>, ) -> FunctionValue<'ctx> { build_rc_wrapper(env, layout_interner, layout_ids, layout, Mode::Dec) } @@ -353,7 +355,7 @@ fn build_rc_wrapper<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, layout_ids: &mut LayoutIds<'a>, - layout: &Layout<'a>, + layout: InLayout<'a>, rc_operation: Mode, ) -> FunctionValue<'ctx> { let block = env.builder.get_insert_block().expect("to be in a function"); @@ -361,7 +363,7 @@ fn build_rc_wrapper<'a, 'ctx, 'env>( let symbol = Symbol::GENERIC_RC_REF; let fn_name = layout_ids - .get(symbol, layout) + .get(symbol, &layout) .to_symbol_string(symbol, &env.interns); let fn_name = match rc_operation { @@ -417,7 +419,7 @@ fn build_rc_wrapper<'a, 'ctx, 'env>( // even though this looks like a `load_roc_value`, that gives segfaults in practice. // I suspect it has something to do with the lifetime of the alloca that is created by // `load_roc_value` - let value = if layout.is_passed_by_reference(layout_interner, env.target_info) { + let value = if layout_interner.is_passed_by_reference(layout) { value_ptr.into() } else { env.builder @@ -457,14 +459,14 @@ pub fn build_eq_wrapper<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, layout_ids: &mut LayoutIds<'a>, - layout: &Layout<'a>, + layout: InLayout<'a>, ) -> FunctionValue<'ctx> { let block = env.builder.get_insert_block().expect("to be in a function"); let di_location = env.builder.get_current_debug_location().unwrap(); let symbol = Symbol::GENERIC_EQ_REF; let fn_name = layout_ids - .get(symbol, layout) + .get(symbol, &layout) .to_symbol_string(symbol, &env.interns); let function_value = match env.module.get_function(fn_name.as_str()) { @@ -511,8 +513,8 @@ pub fn build_eq_wrapper<'a, 'ctx, 'env>( .build_pointer_cast(value_ptr2, value_type, "load_opaque"); // load_roc_value(env, *element_layout, elem_ptr, "get_elem") - let value1 = load_roc_value(env, layout_interner, *layout, value_cast1, "load_opaque"); - let value2 = load_roc_value(env, layout_interner, *layout, value_cast2, "load_opaque"); + let value1 = load_roc_value(env, layout_interner, layout, value_cast1, "load_opaque"); + let value2 = load_roc_value(env, layout_interner, layout, value_cast2, "load_opaque"); let result = crate::llvm::compare::generic_eq( env, @@ -542,7 +544,7 @@ pub fn build_compare_wrapper<'a, 'ctx, 'env>( layout_interner: &mut STLayoutInterner<'a>, roc_function: FunctionValue<'ctx>, closure_data_layout: LambdaSet<'a>, - layout: &Layout<'a>, + layout: InLayout<'a>, ) -> FunctionValue<'ctx> { let block = env.builder.get_insert_block().expect("to be in a function"); let di_location = env.builder.get_current_debug_location().unwrap(); @@ -609,15 +611,18 @@ pub fn build_compare_wrapper<'a, 'ctx, 'env>( let default = [value1.into(), value2.into()]; - let arguments_cast = match closure_data_layout.runtime_representation(layout_interner) { + let closure_data_repr = closure_data_layout.runtime_representation(); + + let arguments_cast = match layout_interner.get(closure_data_repr) { Layout::Struct { field_layouts: &[], .. } => { // nothing to add &default } - other => { - let closure_type = basic_type_from_layout(env, layout_interner, &other); + _ => { + let closure_type = + basic_type_from_layout(env, layout_interner, closure_data_repr); let closure_ptr_type = closure_type.ptr_type(AddressSpace::Generic); let closure_cast = env.builder.build_pointer_cast( diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index 2431b17753..d34e2f5516 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -44,8 +44,8 @@ use roc_mono::ir::{ OptLevel, ProcLayout, SingleEntryPoint, }; use roc_mono::layout::{ - Builtin, LambdaName, LambdaSet, Layout, LayoutIds, LayoutInterner, Niche, RawFunctionLayout, - STLayoutInterner, TagIdIntType, UnionLayout, + Builtin, InLayout, LambdaName, LambdaSet, Layout, LayoutIds, LayoutInterner, Niche, + RawFunctionLayout, STLayoutInterner, TagIdIntType, UnionLayout, }; use roc_std::RocDec; use roc_target::{PtrWidth, TargetInfo}; @@ -163,16 +163,16 @@ macro_rules! debug_info_init { #[derive(Default, Debug, Clone, PartialEq, Eq)] pub struct Scope<'a, 'ctx> { - symbols: ImMap, BasicValueEnum<'ctx>)>, + symbols: ImMap, BasicValueEnum<'ctx>)>, pub top_level_thunks: ImMap, FunctionValue<'ctx>)>, join_points: ImMap, std::vec::Vec>)>, } impl<'a, 'ctx> Scope<'a, 'ctx> { - pub(crate) fn get(&self, symbol: &Symbol) -> Option<&(Layout<'a>, BasicValueEnum<'ctx>)> { + pub(crate) fn get(&self, symbol: &Symbol) -> Option<&(InLayout<'a>, BasicValueEnum<'ctx>)> { self.symbols.get(symbol) } - pub(crate) fn insert(&mut self, symbol: Symbol, value: (Layout<'a>, BasicValueEnum<'ctx>)) { + pub(crate) fn insert(&mut self, symbol: Symbol, value: (InLayout<'a>, BasicValueEnum<'ctx>)) { self.symbols.insert(symbol, value); } pub(crate) fn insert_top_level_thunk( @@ -335,9 +335,9 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> { pub fn alignment_intvalue( &self, layout_interner: &mut STLayoutInterner<'a>, - element_layout: &Layout<'a>, + element_layout: InLayout<'a>, ) -> BasicValueEnum<'ctx> { - let alignment = element_layout.alignment_bytes(layout_interner, self.target_info); + let alignment = layout_interner.alignment_bytes(element_layout); let alignment_iv = self.alignment_const(alignment); alignment_iv.into() @@ -619,8 +619,7 @@ fn promote_to_main_function<'a, 'ctx, 'env>( top_level: ProcLayout<'a>, ) -> (&'static str, FunctionValue<'ctx>) { let it = top_level.arguments.iter().copied(); - let bytes = - roc_alias_analysis::func_name_bytes_help(symbol, it, Niche::NONE, &top_level.result); + let bytes = roc_alias_analysis::func_name_bytes_help(symbol, it, Niche::NONE, top_level.result); let func_name = FuncName(&bytes); let func_solutions = mod_solutions.func_solutions(func_name).unwrap(); @@ -633,7 +632,7 @@ fn promote_to_main_function<'a, 'ctx, 'env>( // NOTE fake layout; it is only used for debug prints let roc_main_fn = - function_value_by_func_spec(env, *func_spec, symbol, &[], Niche::NONE, &Layout::UNIT); + function_value_by_func_spec(env, *func_spec, symbol, &[], Niche::NONE, Layout::UNIT); let main_fn_name = "$Test.main"; @@ -670,8 +669,7 @@ fn promote_to_wasm_test_wrapper<'a, 'ctx, 'env>( let main_fn_name = "test_wrapper"; let it = top_level.arguments.iter().copied(); - let bytes = - roc_alias_analysis::func_name_bytes_help(symbol, it, Niche::NONE, &top_level.result); + let bytes = roc_alias_analysis::func_name_bytes_help(symbol, it, Niche::NONE, top_level.result); let func_name = FuncName(&bytes); let func_solutions = mod_solutions.func_solutions(func_name).unwrap(); @@ -684,7 +682,7 @@ fn promote_to_wasm_test_wrapper<'a, 'ctx, 'env>( // NOTE fake layout; it is only used for debug prints let roc_main_fn = - function_value_by_func_spec(env, *func_spec, symbol, &[], Niche::NONE, &Layout::UNIT); + function_value_by_func_spec(env, *func_spec, symbol, &[], Niche::NONE, Layout::UNIT); let output_type = match roc_main_fn.get_type().get_return_type() { Some(return_type) => { @@ -720,12 +718,10 @@ fn promote_to_wasm_test_wrapper<'a, 'ctx, 'env>( builder.position_at_end(entry); let roc_main_fn_result = - call_roc_function(env, layout_interner, roc_main_fn, &top_level.result, &[]); + call_roc_function(env, layout_interner, roc_main_fn, top_level.result, &[]); // For consistency, we always return with a heap-allocated value - let (size, alignment) = top_level - .result - .stack_size_and_alignment(layout_interner, env.target_info); + let (size, alignment) = layout_interner.stack_size_and_alignment(top_level.result); let number_of_bytes = env.ptr_int().const_int(size as _, false); let void_ptr = env.call_alloc(number_of_bytes, alignment); @@ -776,30 +772,31 @@ fn float_with_precision<'a, 'ctx, 'env>( pub fn build_exp_literal<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, + layout_interner: &STLayoutInterner<'a>, parent: FunctionValue<'ctx>, - layout: &Layout<'_>, + layout: InLayout<'_>, literal: &roc_mono::ir::Literal<'a>, ) -> BasicValueEnum<'ctx> { use roc_mono::ir::Literal::*; match literal { - Int(bytes) => match layout { + Int(bytes) => match layout_interner.get(layout) { Layout::Builtin(Builtin::Bool) => env .context .bool_type() .const_int(i128::from_ne_bytes(*bytes) as u64, false) .into(), Layout::Builtin(Builtin::Int(int_width)) => { - int_with_precision(env, i128::from_ne_bytes(*bytes), *int_width).into() + int_with_precision(env, i128::from_ne_bytes(*bytes), int_width).into() } _ => panic!("Invalid layout for int literal = {:?}", layout), }, U128(bytes) => const_u128(env, u128::from_ne_bytes(*bytes)).into(), - Float(float) => match layout { + Float(float) => match layout_interner.get(layout) { Layout::Builtin(Builtin::Float(float_width)) => { - float_with_precision(env, *float, *float_width) + float_with_precision(env, *float, float_width) } _ => panic!("Invalid layout for float literal = {:?}", layout), }, @@ -928,7 +925,7 @@ pub fn build_exp_call<'a, 'ctx, 'env>( func_spec_solutions: &FuncSpecSolutions, scope: &mut Scope<'a, 'ctx>, parent: FunctionValue<'ctx>, - layout: &Layout<'a>, + layout: InLayout<'a>, call: &roc_mono::ir::Call<'a>, ) -> BasicValueEnum<'ctx> { let roc_mono::ir::Call { @@ -959,7 +956,7 @@ pub fn build_exp_call<'a, 'ctx, 'env>( env, layout_interner, arg_layouts, - ret_layout, + *ret_layout, *name, func_spec, arg_tuples.into_bump_slice(), @@ -1011,7 +1008,7 @@ pub fn build_exp_call<'a, 'ctx, 'env>( scope, foreign_symbol, arguments, - ret_layout, + *ret_layout, ), } } @@ -1046,7 +1043,7 @@ fn struct_pointer_from_fields<'a, 'ctx, 'env, I>( input_pointer: PointerValue<'ctx>, values: I, ) where - I: Iterator, BasicValueEnum<'ctx>))>, + I: Iterator, BasicValueEnum<'ctx>))>, { let struct_ptr = env .builder @@ -1075,13 +1072,13 @@ pub fn build_exp_expr<'a, 'ctx, 'env>( func_spec_solutions: &FuncSpecSolutions, scope: &mut Scope<'a, 'ctx>, parent: FunctionValue<'ctx>, - layout: &Layout<'a>, + layout: InLayout<'a>, expr: &roc_mono::ir::Expr<'a>, ) -> BasicValueEnum<'ctx> { use roc_mono::ir::Expr::*; match expr { - Literal(literal) => build_exp_literal(env, parent, layout, literal), + Literal(literal) => build_exp_literal(env, layout_interner, parent, layout, literal), Call(call) => build_exp_call( env, @@ -1138,11 +1135,11 @@ pub fn build_exp_expr<'a, 'ctx, 'env>( let allocation = reserve_with_refcount_help( env, basic_type, - layout.stack_size(layout_interner, env.target_info), - layout.alignment_bytes(layout_interner, env.target_info), + layout_interner.stack_size(layout), + layout_interner.alignment_bytes(layout), ); - store_roc_value(env, layout_interner, *layout, allocation, value); + store_roc_value(env, layout_interner, layout, allocation, value); allocation.into() } @@ -1155,7 +1152,7 @@ pub fn build_exp_expr<'a, 'ctx, 'env>( load_roc_value( env, layout_interner, - *layout, + layout, value.into_pointer_value(), "load_boxed_value", ) @@ -1175,7 +1172,7 @@ pub fn build_exp_expr<'a, 'ctx, 'env>( let tag_ptr = tag_ptr.into_pointer_value(); // reset is only generated for union values - let union_layout = match layout { + let union_layout = match layout_interner.get(layout) { Layout::Union(ul) => ul, _ => unreachable!(), }; @@ -1201,7 +1198,7 @@ pub fn build_exp_expr<'a, 'ctx, 'env>( // referenced value, and returns the location of the now-invalid cell env.builder.position_at_end(then_block); - let reset_function = build_reset(env, layout_interner, layout_ids, *union_layout); + let reset_function = build_reset(env, layout_interner, layout_ids, union_layout); let call = env .builder .build_call(reset_function, &[tag_ptr.into()], "call_reset"); @@ -1235,14 +1232,14 @@ pub fn build_exp_expr<'a, 'ctx, 'env>( } => { let (value, layout) = load_symbol_and_layout(scope, structure); - let layout = if let Layout::LambdaSet(lambda_set) = layout { - lambda_set.runtime_representation(layout_interner) + let layout = if let Layout::LambdaSet(lambda_set) = layout_interner.get(layout) { + lambda_set.runtime_representation() } else { - *layout + layout }; // extract field from a record - match (value, layout) { + match (value, layout_interner.get(layout)) { (StructValue(argument), Layout::Struct { field_layouts, .. }) => { debug_assert!(!field_layouts.is_empty()); @@ -1277,7 +1274,7 @@ pub fn build_exp_expr<'a, 'ctx, 'env>( EmptyArray => empty_polymorphic_list(env), Array { elem_layout, elems } => { - list_literal(env, layout_interner, parent, scope, elem_layout, elems) + list_literal(env, layout_interner, parent, scope, *elem_layout, elems) } RuntimeErrorFunction(_) => todo!(), @@ -1296,8 +1293,9 @@ pub fn build_exp_expr<'a, 'ctx, 'env>( let field_layouts = tag_layouts[*tag_id as usize]; - let struct_layout = Layout::struct_no_name_order(field_layouts); - let struct_type = basic_type_from_layout(env, layout_interner, &struct_layout); + let struct_layout = + layout_interner.insert(Layout::struct_no_name_order(field_layouts)); + let struct_type = basic_type_from_layout(env, layout_interner, struct_layout); let opaque_data_ptr = env .builder @@ -1351,9 +1349,10 @@ pub fn build_exp_expr<'a, 'ctx, 'env>( ) } UnionLayout::NonNullableUnwrapped(field_layouts) => { - let struct_layout = Layout::struct_no_name_order(field_layouts); + let struct_layout = + layout_interner.insert(Layout::struct_no_name_order(field_layouts)); - let struct_type = basic_type_from_layout(env, layout_interner, &struct_layout); + let struct_type = basic_type_from_layout(env, layout_interner, struct_layout); lookup_at_index_ptr( env, @@ -1398,9 +1397,10 @@ pub fn build_exp_expr<'a, 'ctx, 'env>( debug_assert_ne!(*tag_id != 0, *nullable_id); let field_layouts = other_fields; - let struct_layout = Layout::struct_no_name_order(field_layouts); + let struct_layout = + layout_interner.insert(Layout::struct_no_name_order(field_layouts)); - let struct_type = basic_type_from_layout(env, layout_interner, &struct_layout); + let struct_type = basic_type_from_layout(env, layout_interner, struct_layout); lookup_at_index_ptr( env, @@ -1435,8 +1435,8 @@ fn build_wrapped_tag<'a, 'ctx, 'env>( union_layout: &UnionLayout<'a>, tag_id: u8, arguments: &[Symbol], - tag_field_layouts: &[Layout<'a>], - tags: &[&[Layout<'a>]], + tag_field_layouts: &[InLayout<'a>], + tags: &[&[InLayout<'a>]], reuse_allocation: Option>, parent: FunctionValue<'ctx>, ) -> BasicValueEnum<'ctx> { @@ -1471,7 +1471,7 @@ fn build_wrapped_tag<'a, 'ctx, 'env>( .unwrap(); let tag_id_type = - basic_type_from_layout(env, layout_interner, &tag_id_layout).into_int_type(); + basic_type_from_layout(env, layout_interner, tag_id_layout).into_int_type(); env.builder .build_store(tag_id_ptr, tag_id_type.const_int(tag_id as u64, false)); @@ -1526,9 +1526,9 @@ fn build_tag_field_value<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, value: BasicValueEnum<'ctx>, - tag_field_layout: Layout<'a>, + tag_field_layout: InLayout<'a>, ) -> BasicValueEnum<'ctx> { - if let Layout::RecursivePointer = tag_field_layout { + if let Layout::RecursivePointer = layout_interner.get(tag_field_layout) { debug_assert!(value.is_pointer_value()); // we store recursive pointers as `i64*` @@ -1539,7 +1539,7 @@ fn build_tag_field_value<'a, 'ctx, 'env>( "cast_recursive_pointer", ) .into() - } else if tag_field_layout.is_passed_by_reference(layout_interner, env.target_info) { + } else if layout_interner.is_passed_by_reference(tag_field_layout) { debug_assert!(value.is_pointer_value()); // NOTE: we rely on this being passed to `store_roc_value` so that @@ -1557,11 +1557,11 @@ fn build_tag_fields<'a, 'r, 'ctx, 'env>( env: &'r Env<'a, 'ctx, 'env>, layout_interner: &'r mut STLayoutInterner<'a>, scope: &'r Scope<'a, 'ctx>, - fields: &[Layout<'a>], + fields: &[InLayout<'a>], arguments: &[Symbol], ) -> ( std::vec::Vec>, - std::vec::Vec<(Layout<'a>, BasicValueEnum<'ctx>)>, + std::vec::Vec<(InLayout<'a>, BasicValueEnum<'ctx>)>, ) { debug_assert_eq!(fields.len(), arguments.len()); @@ -1570,7 +1570,7 @@ fn build_tag_fields<'a, 'r, 'ctx, 'env>( let mut field_values = std::vec::Vec::with_capacity(capacity); for (field_symbol, tag_field_layout) in arguments.iter().zip(fields.iter()) { - let field_type = basic_type_from_layout(env, layout_interner, tag_field_layout); + let field_type = basic_type_from_layout(env, layout_interner, *tag_field_layout); field_types.push(field_type); let raw_value: BasicValueEnum<'ctx> = load_symbol(scope, field_symbol); @@ -1599,11 +1599,11 @@ fn build_struct<'a, 'ctx, 'env>( // Zero-sized fields have no runtime representation. // The layout of the struct expects them to be dropped! let (field_expr, field_layout) = load_symbol_and_layout(scope, symbol); - if !field_layout.is_dropped_because_empty() { + if !layout_interner.get(field_layout).is_dropped_because_empty() { let field_type = basic_type_from_layout(env, layout_interner, field_layout); field_types.push(field_type); - if field_layout.is_passed_by_reference(layout_interner, env.target_info) { + if layout_interner.is_passed_by_reference(field_layout) { let field_value = env.builder.new_build_load( field_type, field_expr.into_pointer_value(), @@ -1683,9 +1683,9 @@ fn build_tag<'a, 'ctx, 'env>( use std::cmp::Ordering::*; match tag_id.cmp(&(*nullable_id as _)) { Equal => { - let layout = Layout::Union(*union_layout); + let layout = layout_interner.insert(Layout::Union(*union_layout)); - return basic_type_from_layout(env, layout_interner, &layout) + return basic_type_from_layout(env, layout_interner, layout) .into_pointer_type() .const_null() .into(); @@ -1853,7 +1853,7 @@ fn allocate_tag<'a, 'ctx, 'env>( parent: FunctionValue<'ctx>, reuse_allocation: Option>, union_layout: &UnionLayout<'a>, - tags: &[&[Layout<'a>]], + tags: &[&[InLayout<'a>]], ) -> PointerValue<'ctx> { match reuse_allocation { Some(ptr) => { @@ -1918,7 +1918,7 @@ pub fn get_tag_id<'a, 'ctx, 'env>( let tag_id_layout = union_layout.tag_id_layout(); let tag_id_int_type = - basic_type_from_layout(env, layout_interner, &tag_id_layout).into_int_type(); + basic_type_from_layout(env, layout_interner, tag_id_layout).into_int_type(); match union_layout { UnionLayout::NonRecursive(_) => { @@ -1994,7 +1994,7 @@ fn lookup_at_index_ptr<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, union_layout: &UnionLayout<'a>, - field_layouts: &[Layout<'a>], + field_layouts: &[InLayout<'a>], index: usize, value: PointerValue<'ctx>, struct_type: StructType<'ctx>, @@ -2020,11 +2020,14 @@ fn lookup_at_index_ptr<'a, 'ctx, 'env>( "load_at_index_ptr_old", ); - if let Some(Layout::RecursivePointer) = field_layouts.get(index as usize) { + if let Some(Layout::RecursivePointer) = field_layouts + .get(index as usize) + .map(|l| layout_interner.get(*l)) + { // a recursive field is stored as a `i64*`, to use it we must cast it to // a pointer to the block of memory representation - let actual_type = - basic_type_from_layout(env, layout_interner, &Layout::Union(*union_layout)); + let union_layout = layout_interner.insert(Layout::Union(*union_layout)); + let actual_type = basic_type_from_layout(env, layout_interner, union_layout); debug_assert!(actual_type.is_pointer_type()); builder @@ -2043,15 +2046,15 @@ fn lookup_at_index_ptr2<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, union_layout: &UnionLayout<'a>, - field_layouts: &[Layout<'a>], + field_layouts: &'a [InLayout<'a>], index: usize, value: PointerValue<'ctx>, ) -> BasicValueEnum<'ctx> { let builder = env.builder; - let struct_layout = Layout::struct_no_name_order(field_layouts); + let struct_layout = layout_interner.insert(Layout::struct_no_name_order(field_layouts)); let struct_type = - basic_type_from_layout(env, layout_interner, &struct_layout).into_struct_type(); + basic_type_from_layout(env, layout_interner, struct_layout).into_struct_type(); let data_ptr = env.builder.build_pointer_cast( value, @@ -2077,12 +2080,15 @@ fn lookup_at_index_ptr2<'a, 'ctx, 'env>( "load_at_index_ptr", ); - if let Some(Layout::RecursivePointer) = field_layouts.get(index as usize) { + if let Some(Layout::RecursivePointer) = field_layouts + .get(index as usize) + .map(|l| layout_interner.get(*l)) + { // a recursive field is stored as a `i64*`, to use it we must cast it to // a pointer to the block of memory representation - let actual_type = - basic_type_from_layout(env, layout_interner, &Layout::Union(*union_layout)); + let union_layout = layout_interner.insert(Layout::Union(*union_layout)); + let actual_type = basic_type_from_layout(env, layout_interner, union_layout); debug_assert!(actual_type.is_pointer_type()); builder @@ -2100,10 +2106,10 @@ fn lookup_at_index_ptr2<'a, 'ctx, 'env>( pub fn reserve_with_refcount<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, - layout: &Layout<'a>, + layout: InLayout<'a>, ) -> PointerValue<'ctx> { - let stack_size = layout.stack_size(layout_interner, env.target_info); - let alignment_bytes = layout.alignment_bytes(layout_interner, env.target_info); + let stack_size = layout_interner.stack_size(layout); + let alignment_bytes = layout_interner.alignment_bytes(layout); let basic_type = basic_type_from_layout(env, layout_interner, layout); @@ -2114,7 +2120,7 @@ fn reserve_with_refcount_union_as_block_of_memory<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, union_layout: UnionLayout<'a>, - fields: &[&[Layout<'a>]], + fields: &[&[InLayout<'a>]], ) -> PointerValue<'ctx> { let ptr_bytes = env.target_info; @@ -2148,7 +2154,7 @@ fn reserve_with_refcount_help<'a, 'ctx, 'env>( pub fn allocate_with_refcount<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, - layout: &Layout<'a>, + layout: InLayout<'a>, value: BasicValueEnum<'ctx>, ) -> PointerValue<'ctx> { let data_ptr = reserve_with_refcount(env, layout_interner, layout); @@ -2186,7 +2192,7 @@ fn list_literal<'a, 'ctx, 'env>( layout_interner: &mut STLayoutInterner<'a>, parent: FunctionValue<'ctx>, scope: &Scope<'a, 'ctx>, - element_layout: &Layout<'a>, + element_layout: InLayout<'a>, elems: &[ListLiteralElement], ) -> BasicValueEnum<'ctx> { let ctx = env.context; @@ -2202,10 +2208,10 @@ fn list_literal<'a, 'ctx, 'env>( // if element_type.is_int_type() { if false { let element_type = element_type.into_int_type(); - let element_width = element_layout.stack_size(layout_interner, env.target_info); + let element_width = layout_interner.stack_size(element_layout); let size = list_length * element_width as usize; - let alignment = element_layout - .alignment_bytes(layout_interner, env.target_info) + let alignment = layout_interner + .alignment_bytes(element_layout) .max(env.target_info.ptr_width() as u32); let mut is_all_constant = true; @@ -2237,7 +2243,13 @@ fn list_literal<'a, 'ctx, 'env>( for (index, element) in elems.iter().enumerate() { match element { ListLiteralElement::Literal(literal) => { - let val = build_exp_literal(env, parent, element_layout, literal); + let val = build_exp_literal( + env, + layout_interner, + parent, + element_layout, + literal, + ); global_elements.push(val.into_int_value()); } ListLiteralElement::Symbol(symbol) => { @@ -2328,7 +2340,7 @@ fn list_literal<'a, 'ctx, 'env>( for (index, element) in elems.iter().enumerate() { let val = match element { ListLiteralElement::Literal(literal) => { - build_exp_literal(env, parent, element_layout, literal) + build_exp_literal(env, layout_interner, parent, element_layout, literal) } ListLiteralElement::Symbol(symbol) => load_symbol(scope, symbol), }; @@ -2337,7 +2349,7 @@ fn list_literal<'a, 'ctx, 'env>( builder.new_build_in_bounds_gep(element_type, ptr, &[index_val], "index") }; - store_roc_value(env, layout_interner, *element_layout, elem_ptr, val); + store_roc_value(env, layout_interner, element_layout, elem_ptr, val); } super::build_list::store_list(env, ptr, list_length_intval).into() @@ -2347,13 +2359,13 @@ fn list_literal<'a, 'ctx, 'env>( pub fn load_roc_value<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, - layout: Layout<'a>, + layout: InLayout<'a>, source: PointerValue<'ctx>, name: &str, ) -> BasicValueEnum<'ctx> { - let basic_type = basic_type_from_layout(env, layout_interner, &layout); + let basic_type = basic_type_from_layout(env, layout_interner, layout); - if layout.is_passed_by_reference(layout_interner, env.target_info) { + if layout_interner.is_passed_by_reference(layout) { let alloca = entry_block_alloca_zerofill(env, basic_type, name); store_roc_value(env, layout_interner, layout, alloca, source.into()); @@ -2367,14 +2379,14 @@ pub fn load_roc_value<'a, 'ctx, 'env>( pub fn use_roc_value<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, - layout: Layout<'a>, + layout: InLayout<'a>, source: BasicValueEnum<'ctx>, name: &str, ) -> BasicValueEnum<'ctx> { - if layout.is_passed_by_reference(layout_interner, env.target_info) { + if layout_interner.is_passed_by_reference(layout) { let alloca = entry_block_alloca_zerofill( env, - basic_type_from_layout(env, layout_interner, &layout), + basic_type_from_layout(env, layout_interner, layout), name, ); @@ -2389,12 +2401,12 @@ pub fn use_roc_value<'a, 'ctx, 'env>( pub fn store_roc_value_opaque<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, - layout: Layout<'a>, + layout: InLayout<'a>, opaque_destination: PointerValue<'ctx>, value: BasicValueEnum<'ctx>, ) { let target_type = - basic_type_from_layout(env, layout_interner, &layout).ptr_type(AddressSpace::Generic); + basic_type_from_layout(env, layout_interner, layout).ptr_type(AddressSpace::Generic); let destination = env.builder .build_pointer_cast(opaque_destination, target_type, "store_roc_value_opaque"); @@ -2405,20 +2417,19 @@ pub fn store_roc_value_opaque<'a, 'ctx, 'env>( pub fn store_roc_value<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, - layout: Layout<'a>, + layout: InLayout<'a>, destination: PointerValue<'ctx>, value: BasicValueEnum<'ctx>, ) { - if layout.is_passed_by_reference(layout_interner, env.target_info) { + if layout_interner.is_passed_by_reference(layout) { debug_assert!(value.is_pointer_value()); - let align_bytes = layout.alignment_bytes(layout_interner, env.target_info); + let align_bytes = layout_interner.alignment_bytes(layout); if align_bytes > 0 { - let size = env.ptr_int().const_int( - layout.stack_size(layout_interner, env.target_info) as u64, - false, - ); + let size = env + .ptr_int() + .const_int(layout_interner.stack_size(layout) as u64, false); env.builder .build_memcpy( @@ -2470,7 +2481,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>( let mut stack = Vec::with_capacity_in(queue.len(), env.arena); for (symbol, expr, layout) in queue { - debug_assert!(layout != &Layout::RecursivePointer); + debug_assert!(layout_interner.get(*layout) != Layout::RecursivePointer); let val = build_exp_expr( env, @@ -2479,7 +2490,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>( func_spec_solutions, scope, parent, - layout, + *layout, expr, ); @@ -2532,8 +2543,8 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>( // store_roc_value(env, *layout, out_parameter.into_pointer_value(), value); let destination = out_parameter.into_pointer_value(); - if layout.is_passed_by_reference(layout_interner, env.target_info) { - let align_bytes = layout.alignment_bytes(layout_interner, env.target_info); + if layout_interner.is_passed_by_reference(layout) { + let align_bytes = layout_interner.alignment_bytes(layout); if align_bytes > 0 { debug_assert!( @@ -2563,8 +2574,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>( // // Hence, we explicitly memcpy source to destination, and rely on // LLVM optimizing away any inefficiencies. - let target_info = env.target_info; - let width = layout.stack_size(layout_interner, target_info); + let width = layout_interner.stack_size(layout); let size = env.ptr_int().const_int(width as _, false); env.builder @@ -2605,7 +2615,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>( cond_layout, cond_symbol, } => { - let ret_type = basic_type_from_layout(env, layout_interner, ret_layout); + let ret_type = basic_type_from_layout(env, layout_interner, *ret_layout); let switch_args = SwitchArgsIr { cond_layout: *cond_layout, @@ -2643,12 +2653,9 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>( builder.position_at_end(cont_block); for param in parameters.iter() { - let basic_type = basic_type_from_layout(env, layout_interner, ¶m.layout); + let basic_type = basic_type_from_layout(env, layout_interner, param.layout); - let phi_type = if param - .layout - .is_passed_by_reference(layout_interner, env.target_info) - { + let phi_type = if layout_interner.is_passed_by_reference(param.layout) { basic_type.ptr_type(AddressSpace::Generic).into() } else { basic_type @@ -2731,16 +2738,14 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>( match modify { Inc(symbol, inc_amount) => { let (value, layout) = load_symbol_and_layout(scope, symbol); - let layout = *layout; - - if layout.contains_refcounted(layout_interner) { + if layout_interner.contains_refcounted(layout) { increment_refcount_layout( env, layout_interner, layout_ids, *inc_amount, value, - &layout, + layout, ); } @@ -2757,7 +2762,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>( Dec(symbol) => { let (value, layout) = load_symbol_and_layout(scope, symbol); - if layout.contains_refcounted(layout_interner) { + if layout_interner.contains_refcounted(layout) { decrement_refcount_layout(env, layout_interner, layout_ids, value, layout); } @@ -2774,18 +2779,18 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>( DecRef(symbol) => { let (value, layout) = load_symbol_and_layout(scope, symbol); - match layout { + match layout_interner.get(layout) { Layout::Builtin(Builtin::Str) => todo!(), Layout::Builtin(Builtin::List(element_layout)) => { debug_assert!(value.is_struct_value()); - let element_layout = layout_interner.get(*element_layout); + let element_layout = layout_interner.get(element_layout); let alignment = element_layout.alignment_bytes(layout_interner, env.target_info); build_list::decref(env, value.into_struct_value(), alignment); } - _ if layout.is_refcounted() => { + lay if lay.is_refcounted() => { if value.is_pointer_value() { let value_ptr = value.into_pointer_value(); @@ -3028,9 +3033,9 @@ pub fn load_symbol<'a, 'ctx>(scope: &Scope<'a, 'ctx>, symbol: &Symbol) -> BasicV pub(crate) fn load_symbol_and_layout<'a, 'ctx, 'b>( scope: &'b Scope<'a, 'ctx>, symbol: &Symbol, -) -> (BasicValueEnum<'ctx>, &'b Layout<'a>) { +) -> (BasicValueEnum<'ctx>, InLayout<'a>) { match scope.get(symbol) { - Some((layout, ptr)) => (*ptr, layout), + Some((layout, ptr)) => (*ptr, *layout), None => panic!("There was no entry for {:?} in scope {:?}", symbol, scope), } } @@ -3236,7 +3241,7 @@ fn get_tag_id_wrapped<'a, 'ctx, 'env>( from_value: PointerValue<'ctx>, ) -> IntValue<'ctx> { let union_struct_type = struct_type_from_union_layout(env, layout_interner, &union_layout); - let tag_id_type = basic_type_from_layout(env, layout_interner, &union_layout.tag_id_layout()); + let tag_id_type = basic_type_from_layout(env, layout_interner, union_layout.tag_id_layout()); let tag_id_ptr = env .builder @@ -3265,7 +3270,7 @@ pub fn get_tag_id_non_recursive<'a, 'ctx, 'env>( struct SwitchArgsIr<'a, 'ctx> { pub cond_symbol: Symbol, - pub cond_layout: Layout<'a>, + pub cond_layout: InLayout<'a>, pub branches: &'a [(u64, BranchInfo<'a>, roc_mono::ir::Stmt<'a>)], pub default_branch: &'a roc_mono::ir::Stmt<'a>, pub ret_type: BasicTypeEnum<'ctx>, @@ -3325,7 +3330,7 @@ fn build_switch_ir<'a, 'ctx, 'env>( let (cond_value, stored_layout) = load_symbol_and_layout(scope, cond_symbol); debug_assert_eq!( - basic_type_from_layout(env, layout_interner, &cond_layout), + basic_type_from_layout(env, layout_interner, cond_layout), basic_type_from_layout(env, layout_interner, stored_layout), "This switch matches on {:?}, but the matched-on symbol {:?} has layout {:?}", cond_layout, @@ -3336,7 +3341,7 @@ fn build_switch_ir<'a, 'ctx, 'env>( let cont_block = context.append_basic_block(parent, "cont"); // Build the condition - let cond = match cond_layout { + let cond = match layout_interner.get(cond_layout) { Layout::Builtin(Builtin::Float(float_width)) => { // float matches are done on the bit pattern cond_layout = Layout::float_width(float_width); @@ -3362,7 +3367,7 @@ fn build_switch_ir<'a, 'ctx, 'env>( // Build the cases let mut incoming = Vec::with_capacity_in(branches.len(), arena); - if let Layout::Builtin(Builtin::Bool) = cond_layout { + if let Layout::Builtin(Builtin::Bool) = layout_interner.get(cond_layout) { match (branches, default_branch) { ([(0, _, false_branch)], true_branch) | ([(1, _, true_branch)], false_branch) => { let then_block = context.append_basic_block(parent, "then_block"); @@ -3524,9 +3529,9 @@ fn expose_function_to_host<'a, 'ctx, 'env>( layout_interner: &mut STLayoutInterner<'a>, symbol: Symbol, roc_function: FunctionValue<'ctx>, - arguments: &'a [Layout<'a>], + arguments: &'a [InLayout<'a>], niche: Niche<'a>, - return_layout: Layout<'a>, + return_layout: InLayout<'a>, layout_ids: &mut LayoutIds<'a>, ) { let ident_string = symbol.as_str(&env.interns); @@ -3556,15 +3561,15 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, roc_function: FunctionValue<'ctx>, - arguments: &[Layout<'a>], - return_layout: Layout<'a>, + arguments: &[InLayout<'a>], + return_layout: InLayout<'a>, c_function_name: &str, ) -> FunctionValue<'ctx> { // NOTE we ingore env.mode here let mut cc_argument_types = Vec::with_capacity_in(arguments.len(), env.arena); for layout in arguments { - cc_argument_types.push(to_cc_type(env, layout_interner, layout)); + cc_argument_types.push(to_cc_type(env, layout_interner, *layout)); } // STEP 1: turn `f : a,b,c -> d` into `f : a,b,c, &d -> {}` @@ -3663,12 +3668,16 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx, 'env>( builder.position_at_end(entry); - let wrapped_layout = roc_call_result_layout(env.arena, return_layout, env.target_info); + let wrapped_layout = layout_interner.insert(roc_call_result_layout( + env.arena, + return_layout, + env.target_info, + )); call_roc_function( env, layout_interner, roc_function, - &wrapped_layout, + wrapped_layout, arguments_for_call, ) } else { @@ -3676,7 +3685,7 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx, 'env>( env, layout_interner, roc_function, - &return_layout, + return_layout, arguments_for_call, ) }; @@ -3699,8 +3708,8 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx, 'env>( layout_interner: &mut STLayoutInterner<'a>, ident_string: &str, roc_function: FunctionValue<'ctx>, - arguments: &[Layout<'a>], - return_layout: Layout<'a>, + arguments: &[InLayout<'a>], + return_layout: InLayout<'a>, c_function_name: &str, ) -> FunctionValue<'ctx> { // a tagged union to indicate to the test loader that a panic occurred. @@ -3708,12 +3717,12 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx, 'env>( // does not seem to be a smarter solution let wrapper_return_type = roc_call_result_type( env, - basic_type_from_layout(env, layout_interner, &return_layout), + basic_type_from_layout(env, layout_interner, return_layout), ); let mut cc_argument_types = Vec::with_capacity_in(arguments.len(), env.arena); for layout in arguments { - cc_argument_types.push(to_cc_type(env, layout_interner, layout)); + cc_argument_types.push(to_cc_type(env, layout_interner, *layout)); } // STEP 1: turn `f : a,b,c -> d` into `f : a,b,c, &d -> {}` if the C abi demands it @@ -3766,7 +3775,7 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx, 'env>( // the C and Fast calling conventions agree arguments_for_call.push(*arg); } else { - match layout { + match layout_interner.get(*layout) { Layout::Builtin(Builtin::List(_)) => { let loaded = env.builder.new_build_load( arg_type, @@ -3796,11 +3805,15 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx, 'env>( builder.position_at_end(last_block); + let wrapper_result = layout_interner.insert(Layout::struct_no_name_order( + env.arena.alloc([Layout::U64, return_layout]), + )); + call_roc_function( env, layout_interner, roc_wrapper_function, - &Layout::struct_no_name_order(env.arena.alloc([Layout::u64(), return_layout])), + wrapper_result, arguments_for_call, ) }; @@ -3851,19 +3864,19 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, roc_function: FunctionValue<'ctx>, - arguments: &[Layout<'a>], - return_layout: Layout<'a>, + arguments: &[InLayout<'a>], + return_layout: InLayout<'a>, c_function_name: &str, ) -> FunctionValue<'ctx> { let it = arguments .iter() - .map(|l| to_cc_type(env, layout_interner, l)); + .map(|l| to_cc_type(env, layout_interner, *l)); let argument_types = Vec::from_iter_in(it, env.arena); - let return_type = basic_type_from_layout(env, layout_interner, &return_layout); + let return_type = basic_type_from_layout(env, layout_interner, return_layout); - let cc_return = to_cc_return(env, layout_interner, &return_layout); - let roc_return = RocReturn::from_layout(env, layout_interner, &return_layout); + let cc_return = to_cc_return(env, layout_interner, return_layout); + let roc_return = RocReturn::from_layout(env, layout_interner, return_layout); let c_function_spec = FunctionSpec::cconv(env, cc_return, Some(return_type), &argument_types); @@ -3893,7 +3906,7 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx, 'env>( }; for (i, layout) in arguments.iter().enumerate() { - if let Layout::Builtin(Builtin::Str) = layout { + if let Layout::Builtin(Builtin::Str) = layout_interner.get(*layout) { // Indicate to LLVM that this argument is semantically passed by-value // even though technically (because of its size) it is passed by-reference let byval_attribute_id = Attribute::get_named_enum_kind_id("byval"); @@ -3973,7 +3986,7 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx, 'env>( env.target_info.architecture, roc_target::Architecture::X86_32 | roc_target::Architecture::X86_64 ) { - let c_abi_type = match layout { + let c_abi_type = match layout_interner.get(*layout) { Layout::Builtin(Builtin::Str | Builtin::List(_)) => c_abi_roc_str_type, _ => todo!("figure out what the C type is"), }; @@ -4014,7 +4027,7 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx, 'env>( env, layout_interner, roc_function, - &return_layout, + return_layout, arguments.as_slice(), ); @@ -4065,8 +4078,8 @@ fn expose_function_to_host_help_c_abi<'a, 'ctx, 'env>( layout_interner: &mut STLayoutInterner<'a>, ident_string: &str, roc_function: FunctionValue<'ctx>, - arguments: &[Layout<'a>], - return_layout: Layout<'a>, + arguments: &[InLayout<'a>], + return_layout: InLayout<'a>, c_function_name: &str, ) -> FunctionValue<'ctx> { match env.mode { @@ -4136,7 +4149,7 @@ fn expose_function_to_host_help_c_abi<'a, 'ctx, 'env>( } LlvmBackendMode::Binary | LlvmBackendMode::BinaryDev => { - basic_type_from_layout(env, layout_interner, &return_layout) + basic_type_from_layout(env, layout_interner, return_layout) } }; @@ -4279,12 +4292,12 @@ fn set_jump_and_catch_long_jump<'a, 'ctx, 'env>( parent: FunctionValue<'ctx>, roc_function: FunctionValue<'ctx>, arguments: &[BasicValueEnum<'ctx>], - return_layout: Layout<'a>, + return_layout: InLayout<'a>, ) -> BasicValueEnum<'ctx> { let context = env.context; let builder = env.builder; - let return_type = basic_type_from_layout(env, layout_interner, &return_layout); + let return_type = basic_type_from_layout(env, layout_interner, return_layout); let call_result_type = roc_call_result_type(env, return_type.as_basic_type_enum()); let result_alloca = builder.build_alloca(call_result_type, "result"); @@ -4307,13 +4320,8 @@ fn set_jump_and_catch_long_jump<'a, 'ctx, 'env>( { builder.position_at_end(then_block); - let call_result = call_roc_function( - env, - layout_interner, - roc_function, - &return_layout, - arguments, - ); + let call_result = + call_roc_function(env, layout_interner, roc_function, return_layout, arguments); let return_value = make_good_roc_result(env, layout_interner, return_layout, call_result); @@ -4364,7 +4372,7 @@ fn make_exception_catcher<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, roc_function: FunctionValue<'ctx>, - return_layout: Layout<'a>, + return_layout: InLayout<'a>, ) -> FunctionValue<'ctx> { let wrapper_function_name = format!("{}_catcher", roc_function.get_name().to_str().unwrap()); @@ -4383,10 +4391,10 @@ fn make_exception_catcher<'a, 'ctx, 'env>( fn roc_call_result_layout<'a>( arena: &'a Bump, - return_layout: Layout<'a>, + return_layout: InLayout<'a>, target_info: TargetInfo, ) -> Layout<'a> { - let elements = [Layout::u64(), Layout::usize(target_info), return_layout]; + let elements = [Layout::U64, Layout::usize(target_info), return_layout]; Layout::struct_no_name_order(arena.alloc(elements)) } @@ -4408,17 +4416,17 @@ fn roc_call_result_type<'a, 'ctx, 'env>( fn make_good_roc_result<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, - return_layout: Layout<'a>, + return_layout: InLayout<'a>, return_value: BasicValueEnum<'ctx>, ) -> BasicValueEnum<'ctx> { let context = env.context; let builder = env.builder; - let return_type = basic_type_from_layout(env, layout_interner, &return_layout); + let return_type = basic_type_from_layout(env, layout_interner, return_layout); let v1 = roc_call_result_type( env, - basic_type_from_layout(env, layout_interner, &return_layout), + basic_type_from_layout(env, layout_interner, return_layout), ) .const_zero(); @@ -4426,7 +4434,7 @@ fn make_good_roc_result<'a, 'ctx, 'env>( .build_insert_value(v1, context.i64_type().const_zero(), 0, "set_no_error") .unwrap(); - let v3 = if return_layout.is_passed_by_reference(layout_interner, env.target_info) { + let v3 = if layout_interner.is_passed_by_reference(return_layout) { let loaded = env.builder.new_build_load( return_type, return_value.into_pointer_value(), @@ -4448,7 +4456,7 @@ fn make_exception_catching_wrapper<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, roc_function: FunctionValue<'ctx>, - return_layout: Layout<'a>, + return_layout: InLayout<'a>, wrapper_function_name: &str, ) -> FunctionValue<'ctx> { // build the C calling convention wrapper @@ -4457,7 +4465,7 @@ fn make_exception_catching_wrapper<'a, 'ctx, 'env>( let builder = env.builder; let roc_function_type = roc_function.get_type(); - let argument_types = match RocReturn::from_layout(env, layout_interner, &return_layout) { + let argument_types = match RocReturn::from_layout(env, layout_interner, return_layout) { RocReturn::Return => roc_function_type.get_param_types(), RocReturn::ByPointer => { // Our fastcc passes the return pointer as the last parameter. @@ -4471,7 +4479,7 @@ fn make_exception_catching_wrapper<'a, 'ctx, 'env>( let wrapper_return_type = roc_call_result_type( env, - basic_type_from_layout(env, layout_interner, &return_layout), + basic_type_from_layout(env, layout_interner, return_layout), ); // argument_types.push(wrapper_return_type.ptr_type(AddressSpace::Generic).into()); @@ -4668,7 +4676,7 @@ pub fn build_procedures_expose_expects<'a, 'ctx, 'env>( for symbol in expects.iter().copied() { let it = top_level.arguments.iter().copied(); let bytes = - roc_alias_analysis::func_name_bytes_help(symbol, it, captures_niche, &top_level.result); + roc_alias_analysis::func_name_bytes_help(symbol, it, captures_niche, top_level.result); let func_name = FuncName(&bytes); let func_solutions = mod_solutions.func_solutions(func_name).unwrap(); @@ -4684,14 +4692,8 @@ pub fn build_procedures_expose_expects<'a, 'ctx, 'env>( ); // NOTE fake layout; it is only used for debug prints - let roc_main_fn = function_value_by_func_spec( - env, - *func_spec, - symbol, - &[], - captures_niche, - &Layout::UNIT, - ); + let roc_main_fn = + function_value_by_func_spec(env, *func_spec, symbol, &[], captures_niche, Layout::UNIT); let name = roc_main_fn.get_name().to_str().unwrap(); @@ -4852,16 +4854,16 @@ fn build_proc_header<'a, 'ctx, 'env>( let fn_name = func_spec_name(env.arena, &env.interns, symbol, func_spec); - let ret_type = basic_type_from_layout(env, layout_interner, &proc.ret_layout); + let ret_type = basic_type_from_layout(env, layout_interner, proc.ret_layout); let mut arg_basic_types = Vec::with_capacity_in(args.len(), arena); for (layout, _) in args.iter() { - let arg_type = argument_type_from_layout(env, layout_interner, layout); + let arg_type = argument_type_from_layout(env, layout_interner, *layout); arg_basic_types.push(arg_type); } - let roc_return = RocReturn::from_layout(env, layout_interner, &proc.ret_layout); + let roc_return = RocReturn::from_layout(env, layout_interner, proc.ret_layout); let fn_spec = FunctionSpec::fastcc(env, roc_return, ret_type, arg_basic_types); let fn_val = add_func( @@ -4931,7 +4933,7 @@ fn expose_alias_to_host<'a, 'ctx, 'env>( exposed_function_symbol, it, Niche::NONE, - &top_level.result, + top_level.result, ); let func_name = FuncName(&bytes); let func_solutions = mod_solutions.func_solutions(func_name).unwrap(); @@ -4950,7 +4952,7 @@ fn expose_alias_to_host<'a, 'ctx, 'env>( exposed_function_symbol, top_level.arguments, Niche::NONE, - &top_level.result, + top_level.result, ) } None => { @@ -4979,7 +4981,7 @@ fn expose_alias_to_host<'a, 'ctx, 'env>( // // * roc__mainForHost_1_Update_result_size() -> i64 - let result_type = basic_type_from_layout(env, layout_interner, &result); + let result_type = basic_type_from_layout(env, layout_interner, result); build_host_exposed_alias_size_help( env, @@ -4998,26 +5000,23 @@ fn build_closure_caller<'a, 'ctx, 'env>( def_name: &str, evaluator: FunctionValue<'ctx>, alias_symbol: Symbol, - arguments: &[Layout<'a>], - return_layout: &Layout<'a>, + arguments: &[InLayout<'a>], + return_layout: InLayout<'a>, lambda_set: LambdaSet<'a>, - result: &Layout<'a>, + result: InLayout<'a>, ) { let mut argument_types = Vec::with_capacity_in(arguments.len() + 3, env.arena); for layout in arguments { - let arg_type = basic_type_from_layout(env, layout_interner, layout); + let arg_type = basic_type_from_layout(env, layout_interner, *layout); let arg_ptr_type = arg_type.ptr_type(AddressSpace::Generic); argument_types.push(arg_ptr_type.into()); } let closure_argument_type = { - let basic_type = basic_type_from_layout( - env, - layout_interner, - &lambda_set.runtime_representation(layout_interner), - ); + let basic_type = + basic_type_from_layout(env, layout_interner, lambda_set.runtime_representation()); basic_type.ptr_type(AddressSpace::Generic) }; @@ -5064,13 +5063,11 @@ fn build_closure_caller<'a, 'ctx, 'env>( // NOTE this may be incorrect in the long run // here we load any argument that is a pointer - let closure_layout = lambda_set.runtime_representation(layout_interner); + let closure_layout = lambda_set.runtime_representation(); let layouts_it = arguments.iter().chain(std::iter::once(&closure_layout)); for (param, layout) in evaluator_arguments.iter_mut().zip(layouts_it) { - if param.is_pointer_value() - && !layout.is_passed_by_reference(layout_interner, env.target_info) - { - let basic_type = basic_type_from_layout(env, layout_interner, layout); + if param.is_pointer_value() && !layout_interner.is_passed_by_reference(*layout) { + let basic_type = basic_type_from_layout(env, layout_interner, *layout); *param = builder.new_build_load(basic_type, param.into_pointer_value(), "load_param"); } } @@ -5082,7 +5079,7 @@ fn build_closure_caller<'a, 'ctx, 'env>( function_value, evaluator, &evaluator_arguments, - *return_layout, + return_layout, ); builder.build_store(output, call_result); @@ -5095,14 +5092,13 @@ fn build_closure_caller<'a, 'ctx, 'env>( &evaluator_arguments, ); - if return_layout.is_passed_by_reference(layout_interner, env.target_info) { - let align_bytes = return_layout.alignment_bytes(layout_interner, env.target_info); + if layout_interner.is_passed_by_reference(return_layout) { + let align_bytes = layout_interner.alignment_bytes(return_layout); if align_bytes > 0 { - let size = env.ptr_int().const_int( - return_layout.stack_size(layout_interner, env.target_info) as u64, - false, - ); + let size = env + .ptr_int() + .const_int(layout_interner.stack_size(return_layout) as u64, false); env.builder .build_memcpy( @@ -5130,7 +5126,7 @@ fn build_closure_caller<'a, 'ctx, 'env>( layout_interner, def_name, alias_symbol, - lambda_set.runtime_representation(layout_interner), + lambda_set.runtime_representation(), ); } @@ -5139,14 +5135,14 @@ fn build_host_exposed_alias_size<'a, 'r, 'ctx, 'env>( layout_interner: &'r mut STLayoutInterner<'a>, def_name: &str, alias_symbol: Symbol, - layout: Layout<'a>, + layout: InLayout<'a>, ) { build_host_exposed_alias_size_help( env, def_name, alias_symbol, None, - basic_type_from_layout(env, layout_interner, &layout), + basic_type_from_layout(env, layout_interner, layout), ) } @@ -5283,9 +5279,9 @@ pub(crate) fn function_value_by_func_spec<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, func_spec: FuncSpec, symbol: Symbol, - arguments: &[Layout<'a>], + arguments: &[InLayout<'a>], niche: Niche<'a>, - result: &Layout<'a>, + result: InLayout<'a>, ) -> FunctionValue<'ctx> { let fn_name = func_spec_name(env.arena, &env.interns, symbol, func_spec); let fn_name = fn_name.as_str(); @@ -5295,9 +5291,9 @@ pub(crate) fn function_value_by_func_spec<'a, 'ctx, 'env>( fn function_value_by_name_help<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, - arguments: &[Layout<'a>], + arguments: &[InLayout<'a>], _niche: Niche<'a>, - result: &Layout<'a>, + result: InLayout<'a>, symbol: Symbol, fn_name: &str, ) -> FunctionValue<'ctx> { @@ -5336,8 +5332,8 @@ fn function_value_by_name_help<'a, 'ctx, 'env>( fn roc_call_with_args<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, - argument_layouts: &[Layout<'a>], - result_layout: &Layout<'a>, + argument_layouts: &[InLayout<'a>], + result_layout: InLayout<'a>, name: LambdaName<'a>, func_spec: FuncSpec, arguments: &[BasicValueEnum<'ctx>], @@ -5358,7 +5354,7 @@ pub fn call_roc_function<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, roc_function: FunctionValue<'ctx>, - result_layout: &Layout<'a>, + result_layout: InLayout<'a>, arguments: &[BasicValueEnum<'ctx>], ) -> BasicValueEnum<'ctx> { let pass_by_pointer = roc_function.get_type().get_param_types().len() == arguments.len() + 1; @@ -5407,7 +5403,7 @@ pub fn call_roc_function<'a, 'ctx, 'env>( debug_assert_eq!(roc_function.get_call_conventions(), FAST_CALL_CONV); call.set_call_convention(FAST_CALL_CONV); - if result_layout.is_passed_by_reference(layout_interner, env.target_info) { + if layout_interner.is_passed_by_reference(result_layout) { result_alloca.into() } else { env.builder.new_build_load( @@ -5477,8 +5473,8 @@ pub(crate) fn roc_function_call<'a, 'ctx, 'env>( closure_data: BasicValueEnum<'ctx>, lambda_set: LambdaSet<'a>, closure_data_is_owned: bool, - argument_layouts: &[Layout<'a>], - result_layout: Layout<'a>, + argument_layouts: &[InLayout<'a>], + result_layout: InLayout<'a>, ) -> RocFunctionCall<'ctx> { use crate::llvm::bitcode::{build_inc_n_wrapper, build_transform_caller}; @@ -5502,7 +5498,7 @@ pub(crate) fn roc_function_call<'a, 'ctx, 'env>( env, layout_interner, layout_ids, - &lambda_set.runtime_representation(layout_interner), + lambda_set.runtime_representation(), ) .as_global_value() .as_pointer_value(); @@ -5527,13 +5523,13 @@ pub(crate) fn roc_function_call<'a, 'ctx, 'env>( fn to_cc_type<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, - layout: &Layout<'a>, + layout: InLayout<'a>, ) -> BasicTypeEnum<'ctx> { - match layout.runtime_representation(layout_interner) { + match layout_interner.runtime_representation(layout) { 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_interner, &layout) + basic_type_from_layout(env, layout_interner, layout) } } } @@ -5574,9 +5570,9 @@ impl RocReturn { fn roc_return_by_pointer( interner: &STLayoutInterner, target_info: TargetInfo, - layout: Layout, + layout: InLayout, ) -> bool { - match layout { + match interner.get(layout) { Layout::Builtin(builtin) => { use Builtin::*; @@ -5593,7 +5589,7 @@ impl RocReturn { Layout::LambdaSet(lambda_set) => RocReturn::roc_return_by_pointer( interner, target_info, - lambda_set.runtime_representation(interner), + lambda_set.runtime_representation(), ), _ => false, } @@ -5602,9 +5598,9 @@ impl RocReturn { pub(crate) fn from_layout<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, - layout: &Layout<'a>, + layout: InLayout<'a>, ) -> Self { - if Self::roc_return_by_pointer(layout_interner, env.target_info, *layout) { + if Self::roc_return_by_pointer(layout_interner, env.target_info, layout) { RocReturn::ByPointer } else { RocReturn::Return @@ -5741,9 +5737,9 @@ impl<'ctx> FunctionSpec<'ctx> { pub fn to_cc_return<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, - layout: &Layout<'a>, + layout: InLayout<'a>, ) -> CCReturn { - let return_size = layout.stack_size(layout_interner, env.target_info); + let return_size = layout_interner.stack_size(layout); let pass_result_by_pointer = match env.target_info.operating_system { roc_target::OperatingSystem::Windows => { return_size >= 2 * env.target_info.ptr_width() as u32 @@ -5775,7 +5771,7 @@ fn build_foreign_symbol<'a, 'ctx, 'env>( scope: &mut Scope<'a, 'ctx>, foreign: &roc_module::ident::ForeignSymbol, argument_symbols: &[Symbol], - ret_layout: &Layout<'a>, + ret_layout: InLayout<'a>, ) -> BasicValueEnum<'ctx> { let builder = env.builder; let context = env.context; diff --git a/crates/compiler/gen_llvm/src/llvm/build_list.rs b/crates/compiler/gen_llvm/src/llvm/build_list.rs index d0e3776c65..33eb9e0c47 100644 --- a/crates/compiler/gen_llvm/src/llvm/build_list.rs +++ b/crates/compiler/gen_llvm/src/llvm/build_list.rs @@ -11,7 +11,7 @@ use inkwell::{AddressSpace, IntPredicate}; use morphic_lib::UpdateMode; use roc_builtins::bitcode; use roc_module::symbol::Symbol; -use roc_mono::layout::{Builtin, InLayout, Layout, LayoutIds, LayoutInterner, STLayoutInterner}; +use roc_mono::layout::{Builtin, InLayout, LayoutIds, LayoutInterner, STLayoutInterner}; use super::bitcode::{call_list_bitcode_fn, BitcodeReturns}; use super::build::{ @@ -63,9 +63,9 @@ fn pass_element_as_opaque<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, element: BasicValueEnum<'ctx>, - layout: Layout<'a>, + layout: InLayout<'a>, ) -> BasicValueEnum<'ctx> { - let element_type = basic_type_from_layout(env, layout_interner, &layout); + let element_type = basic_type_from_layout(env, layout_interner, layout); let element_ptr = env .builder .build_alloca(element_type, "element_to_pass_as_opaque"); @@ -83,13 +83,10 @@ fn pass_element_as_opaque<'a, 'ctx, 'env>( pub(crate) fn layout_width<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, - layout: &Layout<'a>, + layout: InLayout<'a>, ) -> BasicValueEnum<'ctx> { env.ptr_int() - .const_int( - layout.stack_size(layout_interner, env.target_info) as u64, - false, - ) + .const_int(layout_interner.stack_size(layout) as u64, false) .into() } @@ -112,14 +109,13 @@ pub(crate) fn list_with_capacity<'a, 'ctx, 'env>( capacity: IntValue<'ctx>, element_layout: InLayout<'a>, ) -> BasicValueEnum<'ctx> { - let element_layout = layout_interner.get(element_layout); call_list_bitcode_fn( env, &[], &[ capacity.into(), - env.alignment_intvalue(layout_interner, &element_layout), - layout_width(env, layout_interner, &element_layout), + env.alignment_intvalue(layout_interner, element_layout), + layout_width(env, layout_interner, element_layout), ], BitcodeReturns::List, bitcode::LIST_WITH_CAPACITY, @@ -136,8 +132,7 @@ pub(crate) fn list_get_unsafe<'a, 'ctx, 'env>( ) -> BasicValueEnum<'ctx> { let builder = env.builder; - let element_layout = layout_interner.get(element_layout); - let elem_type = basic_type_from_layout(env, layout_interner, &element_layout); + let elem_type = basic_type_from_layout(env, layout_interner, element_layout); let ptr_type = elem_type.ptr_type(AddressSpace::Generic); // Load the pointer to the array data let array_data_ptr = load_list_ptr(builder, wrapper_struct, ptr_type); @@ -161,7 +156,7 @@ pub(crate) fn list_get_unsafe<'a, 'ctx, 'env>( "list_get_load_element", ); - increment_refcount_layout(env, layout_interner, layout_ids, 1, result, &element_layout); + increment_refcount_layout(env, layout_interner, layout_ids, 1, result, element_layout); result } @@ -175,14 +170,13 @@ pub(crate) fn list_reserve<'a, 'ctx, 'env>( element_layout: InLayout<'a>, update_mode: UpdateMode, ) -> BasicValueEnum<'ctx> { - let element_layout = layout_interner.get(element_layout); call_list_bitcode_fn_1( env, list.into_struct_value(), &[ - env.alignment_intvalue(layout_interner, &element_layout), + env.alignment_intvalue(layout_interner, element_layout), spare, - layout_width(env, layout_interner, &element_layout), + layout_width(env, layout_interner, element_layout), pass_update_mode(env, update_mode), ], bitcode::LIST_RESERVE, @@ -195,13 +189,13 @@ pub(crate) fn list_append_unsafe<'a, 'ctx, 'env>( layout_interner: &mut STLayoutInterner<'a>, original_wrapper: StructValue<'ctx>, element: BasicValueEnum<'ctx>, - element_layout: &Layout<'a>, + element_layout: InLayout<'a>, ) -> BasicValueEnum<'ctx> { call_list_bitcode_fn_1( env, original_wrapper, &[ - pass_element_as_opaque(env, layout_interner, element, *element_layout), + pass_element_as_opaque(env, layout_interner, element, element_layout), layout_width(env, layout_interner, element_layout), ], bitcode::LIST_APPEND_UNSAFE, @@ -214,14 +208,14 @@ pub(crate) fn list_prepend<'a, 'ctx, 'env>( layout_interner: &mut STLayoutInterner<'a>, original_wrapper: StructValue<'ctx>, element: BasicValueEnum<'ctx>, - element_layout: &Layout<'a>, + element_layout: InLayout<'a>, ) -> BasicValueEnum<'ctx> { call_list_bitcode_fn_1( env, original_wrapper, &[ env.alignment_intvalue(layout_interner, element_layout), - pass_element_as_opaque(env, layout_interner, element, *element_layout), + pass_element_as_opaque(env, layout_interner, element, element_layout), layout_width(env, layout_interner, element_layout), ], bitcode::LIST_PREPEND, @@ -238,13 +232,12 @@ pub(crate) fn list_swap<'a, 'ctx, 'env>( element_layout: InLayout<'a>, update_mode: UpdateMode, ) -> BasicValueEnum<'ctx> { - let element_layout = layout_interner.get(element_layout); call_list_bitcode_fn_1( env, original_wrapper, &[ - env.alignment_intvalue(layout_interner, &element_layout), - layout_width(env, layout_interner, &element_layout), + env.alignment_intvalue(layout_interner, element_layout), + layout_width(env, layout_interner, element_layout), index_1.into(), index_2.into(), pass_update_mode(env, update_mode), @@ -263,14 +256,13 @@ pub(crate) fn list_sublist<'a, 'ctx, 'env>( len: IntValue<'ctx>, element_layout: InLayout<'a>, ) -> BasicValueEnum<'ctx> { - let element_layout = layout_interner.get(element_layout); - let dec_element_fn = build_dec_wrapper(env, layout_interner, layout_ids, &element_layout); + let dec_element_fn = build_dec_wrapper(env, layout_interner, layout_ids, element_layout); call_list_bitcode_fn_1( env, original_wrapper, &[ - env.alignment_intvalue(layout_interner, &element_layout), - layout_width(env, layout_interner, &element_layout), + env.alignment_intvalue(layout_interner, element_layout), + layout_width(env, layout_interner, element_layout), start.into(), len.into(), dec_element_fn.as_global_value().as_pointer_value().into(), @@ -288,14 +280,13 @@ pub(crate) fn list_drop_at<'a, 'ctx, 'env>( count: IntValue<'ctx>, element_layout: InLayout<'a>, ) -> BasicValueEnum<'ctx> { - let element_layout = layout_interner.get(element_layout); - let dec_element_fn = build_dec_wrapper(env, layout_interner, layout_ids, &element_layout); + let dec_element_fn = build_dec_wrapper(env, layout_interner, layout_ids, element_layout); call_list_bitcode_fn_1( env, original_wrapper, &[ - env.alignment_intvalue(layout_interner, &element_layout), - layout_width(env, layout_interner, &element_layout), + env.alignment_intvalue(layout_interner, element_layout), + layout_width(env, layout_interner, element_layout), count.into(), dec_element_fn.as_global_value().as_pointer_value().into(), ], @@ -311,7 +302,7 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>( list: BasicValueEnum<'ctx>, index: IntValue<'ctx>, element: BasicValueEnum<'ctx>, - element_layout: &Layout<'a>, + element_layout: InLayout<'a>, update_mode: UpdateMode, ) -> BasicValueEnum<'ctx> { let element_type = basic_type_from_layout(env, layout_interner, element_layout); @@ -327,7 +318,7 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>( list.into_struct_value(), &[ index.into(), - pass_element_as_opaque(env, layout_interner, element, *element_layout), + pass_element_as_opaque(env, layout_interner, element, element_layout), layout_width(env, layout_interner, element_layout), pass_as_opaque(env, element_ptr), ], @@ -339,7 +330,7 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>( &[ env.alignment_intvalue(layout_interner, element_layout), index.into(), - pass_element_as_opaque(env, layout_interner, element, *element_layout), + pass_element_as_opaque(env, layout_interner, element, element_layout), layout_width(env, layout_interner, element_layout), pass_as_opaque(env, element_ptr), ], @@ -354,7 +345,7 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>( // the list has the same alignment as a usize / ptr. The element comes first in the struct if // its alignment is bigger than that of a list. - let element_align = element_layout.alignment_bytes(layout_interner, env.target_info); + let element_align = layout_interner.alignment_bytes(element_layout); let element_first = element_align > env.target_info.ptr_width() as u32; let fields = if element_first { @@ -443,7 +434,7 @@ pub(crate) fn list_sort_with<'a, 'ctx, 'env>( roc_function_call: RocFunctionCall<'ctx>, compare_wrapper: PointerValue<'ctx>, list: BasicValueEnum<'ctx>, - element_layout: &Layout<'a>, + element_layout: InLayout<'a>, ) -> BasicValueEnum<'ctx> { call_list_bitcode_fn_1( env, @@ -466,8 +457,8 @@ pub(crate) fn list_map<'a, 'ctx, 'env>( layout_interner: &mut STLayoutInterner<'a>, roc_function_call: RocFunctionCall<'ctx>, list: BasicValueEnum<'ctx>, - element_layout: &Layout<'a>, - return_layout: &Layout<'a>, + element_layout: InLayout<'a>, + return_layout: InLayout<'a>, ) -> BasicValueEnum<'ctx> { call_list_bitcode_fn_1( env, @@ -492,9 +483,9 @@ pub(crate) fn list_map2<'a, 'ctx, 'env>( roc_function_call: RocFunctionCall<'ctx>, list1: BasicValueEnum<'ctx>, list2: BasicValueEnum<'ctx>, - element1_layout: &Layout<'a>, - element2_layout: &Layout<'a>, - return_layout: &Layout<'a>, + element1_layout: InLayout<'a>, + element2_layout: InLayout<'a>, + return_layout: InLayout<'a>, ) -> BasicValueEnum<'ctx> { let dec_a = build_dec_wrapper(env, layout_interner, layout_ids, element1_layout); let dec_b = build_dec_wrapper(env, layout_interner, layout_ids, element2_layout); @@ -527,10 +518,10 @@ pub(crate) fn list_map3<'a, 'ctx, 'env>( list1: BasicValueEnum<'ctx>, list2: BasicValueEnum<'ctx>, list3: BasicValueEnum<'ctx>, - element1_layout: &Layout<'a>, - element2_layout: &Layout<'a>, - element3_layout: &Layout<'a>, - result_layout: &Layout<'a>, + element1_layout: InLayout<'a>, + element2_layout: InLayout<'a>, + element3_layout: InLayout<'a>, + result_layout: InLayout<'a>, ) -> BasicValueEnum<'ctx> { let dec_a = build_dec_wrapper(env, layout_interner, layout_ids, element1_layout); let dec_b = build_dec_wrapper(env, layout_interner, layout_ids, element2_layout); @@ -571,11 +562,11 @@ pub(crate) fn list_map4<'a, 'ctx, 'env>( list2: BasicValueEnum<'ctx>, list3: BasicValueEnum<'ctx>, list4: BasicValueEnum<'ctx>, - element1_layout: &Layout<'a>, - element2_layout: &Layout<'a>, - element3_layout: &Layout<'a>, - element4_layout: &Layout<'a>, - result_layout: &Layout<'a>, + element1_layout: InLayout<'a>, + element2_layout: InLayout<'a>, + element3_layout: InLayout<'a>, + element4_layout: InLayout<'a>, + result_layout: InLayout<'a>, ) -> BasicValueEnum<'ctx> { let dec_a = build_dec_wrapper(env, layout_interner, layout_ids, element1_layout); let dec_b = build_dec_wrapper(env, layout_interner, layout_ids, element2_layout); @@ -619,13 +610,12 @@ pub(crate) fn list_concat<'a, 'ctx, 'env>( list2: BasicValueEnum<'ctx>, element_layout: InLayout<'a>, ) -> BasicValueEnum<'ctx> { - let element_layout = layout_interner.get(element_layout); call_list_bitcode_fn( env, &[list1.into_struct_value(), list2.into_struct_value()], &[ - env.alignment_intvalue(layout_interner, &element_layout), - layout_width(env, layout_interner, &element_layout), + env.alignment_intvalue(layout_interner, element_layout), + layout_width(env, layout_interner, element_layout), ], BitcodeReturns::List, bitcode::LIST_CONCAT, @@ -636,7 +626,7 @@ pub(crate) fn incrementing_elem_loop<'a, 'r, 'ctx, 'env, LoopFn>( env: &Env<'a, 'ctx, 'env>, layout_interner: &'r mut STLayoutInterner<'a>, parent: FunctionValue<'ctx>, - element_layout: Layout<'a>, + element_layout: InLayout<'a>, ptr: PointerValue<'ctx>, len: IntValue<'ctx>, index_name: &str, @@ -647,7 +637,7 @@ where { let builder = env.builder; - let element_type = basic_type_from_layout(env, layout_interner, &element_layout); + let element_type = basic_type_from_layout(env, layout_interner, element_layout); incrementing_index_loop( env, @@ -770,19 +760,19 @@ pub(crate) fn load_list_ptr<'ctx>( pub(crate) fn allocate_list<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, - elem_layout: &Layout<'a>, + elem_layout: InLayout<'a>, number_of_elements: IntValue<'ctx>, ) -> PointerValue<'ctx> { let builder = env.builder; let len_type = env.ptr_int(); - let elem_bytes = elem_layout.stack_size(layout_interner, env.target_info) as u64; + let elem_bytes = layout_interner.stack_size(elem_layout) as u64; let bytes_per_element = len_type.const_int(elem_bytes, false); let number_of_data_bytes = builder.build_int_mul(bytes_per_element, number_of_elements, "data_length"); let basic_type = basic_type_from_layout(env, layout_interner, elem_layout); - let alignment_bytes = elem_layout.alignment_bytes(layout_interner, env.target_info); + let alignment_bytes = layout_interner.alignment_bytes(elem_layout); allocate_with_refcount_help(env, basic_type, alignment_bytes, number_of_data_bytes) } diff --git a/crates/compiler/gen_llvm/src/llvm/build_str.rs b/crates/compiler/gen_llvm/src/llvm/build_str.rs index 020d0188db..faebc9cac0 100644 --- a/crates/compiler/gen_llvm/src/llvm/build_str.rs +++ b/crates/compiler/gen_llvm/src/llvm/build_str.rs @@ -2,13 +2,13 @@ use crate::llvm::build::Env; use inkwell::values::{BasicValueEnum, PointerValue, StructValue}; use inkwell::AddressSpace; use roc_builtins::bitcode; -use roc_mono::layout::Layout; +use roc_mono::layout::{InLayout, Layout}; use roc_target::PtrWidth; use super::bitcode::{call_str_bitcode_fn, BitcodeReturns}; use super::build::BuilderExt; -pub static CHAR_LAYOUT: Layout = Layout::u8(); +pub static CHAR_LAYOUT: InLayout = Layout::U8; pub(crate) fn decode_from_utf8_result<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, diff --git a/crates/compiler/gen_llvm/src/llvm/compare.rs b/crates/compiler/gen_llvm/src/llvm/compare.rs index 24f50fb5ea..e5221ee039 100644 --- a/crates/compiler/gen_llvm/src/llvm/compare.rs +++ b/crates/compiler/gen_llvm/src/llvm/compare.rs @@ -27,8 +27,8 @@ pub fn generic_eq<'a, 'ctx, 'env>( layout_ids: &mut LayoutIds<'a>, lhs_val: BasicValueEnum<'ctx>, rhs_val: BasicValueEnum<'ctx>, - lhs_layout: &Layout<'a>, - rhs_layout: &Layout<'a>, + lhs_layout: InLayout<'a>, + rhs_layout: InLayout<'a>, ) -> BasicValueEnum<'ctx> { build_eq( env, @@ -48,8 +48,8 @@ pub fn generic_neq<'a, 'ctx, 'env>( layout_ids: &mut LayoutIds<'a>, lhs_val: BasicValueEnum<'ctx>, rhs_val: BasicValueEnum<'ctx>, - lhs_layout: &Layout<'a>, - rhs_layout: &Layout<'a>, + lhs_layout: InLayout<'a>, + rhs_layout: InLayout<'a>, ) -> BasicValueEnum<'ctx> { build_neq( env, @@ -129,16 +129,19 @@ fn build_eq_builtin<'a, 'ctx, 'env>( Builtin::Decimal => dec_binop_with_unchecked(env, bitcode::DEC_EQ, lhs_val, rhs_val), Builtin::Str => str_equal(env, lhs_val, rhs_val), - Builtin::List(elem) => build_list_eq( - env, - layout_interner, - layout_ids, - &Layout::Builtin(*builtin), - *elem, - lhs_val.into_struct_value(), - rhs_val.into_struct_value(), - when_recursive, - ), + Builtin::List(elem) => { + let list_layout = layout_interner.insert(Layout::Builtin(*builtin)); + build_list_eq( + env, + layout_interner, + layout_ids, + list_layout, + *elem, + lhs_val.into_struct_value(), + rhs_val.into_struct_value(), + when_recursive, + ) + } } } @@ -148,12 +151,11 @@ fn build_eq<'a, 'ctx, 'env>( layout_ids: &mut LayoutIds<'a>, lhs_val: BasicValueEnum<'ctx>, rhs_val: BasicValueEnum<'ctx>, - lhs_layout: &Layout<'a>, - rhs_layout: &Layout<'a>, + lhs_layout: InLayout<'a>, + rhs_layout: InLayout<'a>, when_recursive: WhenRecursive<'a>, ) -> BasicValueEnum<'ctx> { - let lhs_layout = &lhs_layout.runtime_representation(layout_interner); - let rhs_layout = &rhs_layout.runtime_representation(layout_interner); + let lhs_layout_raw = &layout_interner.runtime_representation(lhs_layout); if lhs_layout != rhs_layout { panic!( "Equality of different layouts; did you have a type mismatch?\n{:?} == {:?}", @@ -161,7 +163,7 @@ fn build_eq<'a, 'ctx, 'env>( ); } - match lhs_layout { + match lhs_layout_raw { Layout::Builtin(builtin) => build_eq_builtin( env, layout_interner, @@ -211,9 +213,9 @@ fn build_eq<'a, 'ctx, 'env>( } WhenRecursive::Loop(union_layout) => { - let layout = Layout::Union(union_layout); + let layout = layout_interner.insert(Layout::Union(union_layout)); - let bt = basic_type_from_layout(env, layout_interner, &layout); + let bt = basic_type_from_layout(env, layout_interner, layout); // cast the i64 pointer to a pointer to block of memory let field1_cast = env.builder.build_pointer_cast( @@ -314,11 +316,12 @@ fn build_neq_builtin<'a, 'ctx, 'env>( result.into() } Builtin::List(elem) => { + let builtin_layout = layout_interner.insert(Layout::Builtin(*builtin)); let is_equal = build_list_eq( env, layout_interner, layout_ids, - &Layout::Builtin(*builtin), + builtin_layout, *elem, lhs_val.into_struct_value(), rhs_val.into_struct_value(), @@ -339,8 +342,8 @@ fn build_neq<'a, 'ctx, 'env>( layout_ids: &mut LayoutIds<'a>, lhs_val: BasicValueEnum<'ctx>, rhs_val: BasicValueEnum<'ctx>, - lhs_layout: &Layout<'a>, - rhs_layout: &Layout<'a>, + lhs_layout: InLayout<'a>, + rhs_layout: InLayout<'a>, when_recursive: WhenRecursive<'a>, ) -> BasicValueEnum<'ctx> { if lhs_layout != rhs_layout { @@ -350,14 +353,14 @@ fn build_neq<'a, 'ctx, 'env>( ); } - match lhs_layout { + match layout_interner.get(lhs_layout) { Layout::Builtin(builtin) => build_neq_builtin( env, layout_interner, layout_ids, lhs_val, rhs_val, - builtin, + &builtin, when_recursive, ), @@ -384,7 +387,7 @@ fn build_neq<'a, 'ctx, 'env>( layout_interner, layout_ids, when_recursive, - union_layout, + &union_layout, lhs_val, rhs_val, ) @@ -402,7 +405,7 @@ fn build_neq<'a, 'ctx, 'env>( layout_ids, when_recursive, lhs_layout, - *inner_layout, + inner_layout, lhs_val, rhs_val, ) @@ -424,7 +427,7 @@ fn build_list_eq<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, layout_ids: &mut LayoutIds<'a>, - list_layout: &Layout<'a>, + list_layout: InLayout<'a>, element_layout: InLayout<'a>, list1: StructValue<'ctx>, list2: StructValue<'ctx>, @@ -436,6 +439,7 @@ fn build_list_eq<'a, 'ctx, 'env>( let symbol = Symbol::LIST_EQ; let element_layout = layout_interner.get(element_layout); let element_layout = when_recursive.unwrap_recursive_pointer(element_layout); + let element_layout = layout_interner.insert(element_layout); let fn_name = layout_ids .get(symbol, &element_layout) .to_symbol_string(symbol, &env.interns); @@ -458,7 +462,7 @@ fn build_list_eq<'a, 'ctx, 'env>( layout_ids, when_recursive, function_value, - &element_layout, + element_layout, ); function_value @@ -483,7 +487,7 @@ fn build_list_eq_help<'a, 'ctx, 'env>( layout_ids: &mut LayoutIds<'a>, when_recursive: WhenRecursive<'a>, parent: FunctionValue<'ctx>, - element_layout: &Layout<'a>, + element_layout: InLayout<'a>, ) { let ctx = env.context; let builder = env.builder; @@ -582,14 +586,14 @@ fn build_list_eq_help<'a, 'ctx, 'env>( let elem_ptr = unsafe { builder.new_build_in_bounds_gep(element_type, ptr1, &[curr_index], "load_index") }; - load_roc_value(env, layout_interner, *element_layout, elem_ptr, "get_elem") + load_roc_value(env, layout_interner, element_layout, elem_ptr, "get_elem") }; let elem2 = { let elem_ptr = unsafe { builder.new_build_in_bounds_gep(element_type, ptr2, &[curr_index], "load_index") }; - load_roc_value(env, layout_interner, *element_layout, elem_ptr, "get_elem") + load_roc_value(env, layout_interner, element_layout, elem_ptr, "get_elem") }; let are_equal = build_eq( @@ -641,7 +645,7 @@ fn build_struct_eq<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, layout_ids: &mut LayoutIds<'a>, - field_layouts: &'a [Layout<'a>], + field_layouts: &'a [InLayout<'a>], when_recursive: WhenRecursive<'a>, struct1: StructValue<'ctx>, struct2: StructValue<'ctx>, @@ -649,7 +653,7 @@ fn build_struct_eq<'a, 'ctx, 'env>( let block = env.builder.get_insert_block().expect("to be in a function"); let di_location = env.builder.get_current_debug_location().unwrap(); - let struct_layout = Layout::struct_no_name_order(field_layouts); + let struct_layout = layout_interner.insert(Layout::struct_no_name_order(field_layouts)); let symbol = Symbol::GENERIC_EQ; let fn_name = layout_ids @@ -659,7 +663,7 @@ fn build_struct_eq<'a, 'ctx, 'env>( let function = match env.module.get_function(fn_name.as_str()) { Some(function_value) => function_value, None => { - let arg_type = basic_type_from_layout(env, layout_interner, &struct_layout); + let arg_type = basic_type_from_layout(env, layout_interner, struct_layout); let function_value = crate::llvm::refcounting::build_header_help( env, @@ -699,7 +703,7 @@ fn build_struct_eq_help<'a, 'ctx, 'env>( layout_ids: &mut LayoutIds<'a>, parent: FunctionValue<'ctx>, when_recursive: WhenRecursive<'a>, - field_layouts: &[Layout<'a>], + field_layouts: &[InLayout<'a>], ) { let ctx = env.context; let builder = env.builder; @@ -756,15 +760,15 @@ fn build_struct_eq_help<'a, 'ctx, 'env>( .build_extract_value(struct2, index as u32, "eq_field") .unwrap(); - let are_equal = if let Layout::RecursivePointer = field_layout { + let are_equal = if let Layout::RecursivePointer = layout_interner.get(*field_layout) { match &when_recursive { WhenRecursive::Unreachable => { unreachable!("The current layout should not be recursive, but is") } WhenRecursive::Loop(union_layout) => { - let field_layout = Layout::Union(*union_layout); + let field_layout = layout_interner.insert(Layout::Union(*union_layout)); - let bt = basic_type_from_layout(env, layout_interner, &field_layout); + let bt = basic_type_from_layout(env, layout_interner, field_layout); // cast the i64 pointer to a pointer to block of memory let field1_cast = env.builder.build_pointer_cast( @@ -785,8 +789,8 @@ fn build_struct_eq_help<'a, 'ctx, 'env>( layout_ids, field1_cast.into(), field2_cast.into(), - &field_layout, - &field_layout, + field_layout, + field_layout, WhenRecursive::Loop(*union_layout), ) .into_int_value() @@ -801,8 +805,8 @@ fn build_struct_eq_help<'a, 'ctx, 'env>( layout_ids, lhs, rhs, - field_layout, - field_layout, + *field_layout, + *field_layout, when_recursive, ) .into_int_value() @@ -842,7 +846,7 @@ fn build_tag_eq<'a, 'ctx, 'env>( let block = env.builder.get_insert_block().expect("to be in a function"); let di_location = env.builder.get_current_debug_location().unwrap(); - let tag_layout = Layout::Union(*union_layout); + let tag_layout = layout_interner.insert(Layout::Union(*union_layout)); let symbol = Symbol::GENERIC_EQ; let fn_name = layout_ids .get(symbol, &tag_layout) @@ -1285,13 +1289,13 @@ fn eq_ptr_to_struct<'a, 'ctx, 'env>( layout_ids: &mut LayoutIds<'a>, union_layout: &UnionLayout<'a>, opt_when_recursive: Option>, - field_layouts: &'a [Layout<'a>], + field_layouts: &'a [InLayout<'a>], tag1: PointerValue<'ctx>, tag2: PointerValue<'ctx>, ) -> IntValue<'ctx> { - let struct_layout = Layout::struct_no_name_order(field_layouts); + let struct_layout = layout_interner.insert(Layout::struct_no_name_order(field_layouts)); - let wrapper_type = basic_type_from_layout(env, layout_interner, &struct_layout); + let wrapper_type = basic_type_from_layout(env, layout_interner, struct_layout); debug_assert!(wrapper_type.is_struct_type()); // cast the opaque pointer to a pointer of the correct shape @@ -1336,7 +1340,7 @@ fn build_box_eq<'a, 'ctx, 'env>( layout_interner: &mut STLayoutInterner<'a>, layout_ids: &mut LayoutIds<'a>, when_recursive: WhenRecursive<'a>, - box_layout: &Layout<'a>, + box_layout: InLayout<'a>, inner_layout: InLayout<'a>, tag1: BasicValueEnum<'ctx>, tag2: BasicValueEnum<'ctx>, @@ -1346,7 +1350,7 @@ fn build_box_eq<'a, 'ctx, 'env>( let symbol = Symbol::GENERIC_EQ; let fn_name = layout_ids - .get(symbol, box_layout) + .get(symbol, &box_layout) .to_symbol_string(symbol, &env.interns); let function = match env.module.get_function(fn_name.as_str()) { @@ -1456,8 +1460,6 @@ fn build_box_eq_help<'a, 'ctx, 'env>( let box1 = box1.into_pointer_value(); let box2 = box2.into_pointer_value(); - let inner_layout = layout_interner.get(inner_layout); - let value1 = load_roc_value(env, layout_interner, inner_layout, box1, "load_box1"); let value2 = load_roc_value(env, layout_interner, inner_layout, box2, "load_box2"); @@ -1467,8 +1469,8 @@ fn build_box_eq_help<'a, 'ctx, 'env>( layout_ids, value1, value2, - &inner_layout, - &inner_layout, + inner_layout, + inner_layout, when_recursive, ); diff --git a/crates/compiler/gen_llvm/src/llvm/convert.rs b/crates/compiler/gen_llvm/src/llvm/convert.rs index 9c7a68cc7a..2cff4e2f9f 100644 --- a/crates/compiler/gen_llvm/src/llvm/convert.rs +++ b/crates/compiler/gen_llvm/src/llvm/convert.rs @@ -6,19 +6,19 @@ use inkwell::values::StructValue; use inkwell::AddressSpace; use roc_builtins::bitcode::{FloatWidth, IntWidth}; use roc_mono::layout::{ - round_up_to_alignment, Builtin, Layout, LayoutInterner, STLayoutInterner, UnionLayout, + round_up_to_alignment, Builtin, InLayout, Layout, LayoutInterner, STLayoutInterner, UnionLayout, }; use roc_target::TargetInfo; fn basic_type_from_record<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, - fields: &[Layout<'_>], + fields: &[InLayout<'_>], ) -> BasicTypeEnum<'ctx> { let mut field_types = Vec::with_capacity_in(fields.len(), env.arena); for field_layout in fields.iter() { - field_types.push(basic_type_from_layout(env, layout_interner, field_layout)); + field_types.push(basic_type_from_layout(env, layout_interner, *field_layout)); } env.context @@ -29,34 +29,31 @@ fn basic_type_from_record<'a, 'ctx, 'env>( pub fn basic_type_from_layout<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &'env mut STLayoutInterner<'a>, - layout: &Layout<'_>, + layout: InLayout<'_>, ) -> BasicTypeEnum<'ctx> { use Layout::*; - match layout { + match layout_interner.get(layout) { Struct { field_layouts: sorted_fields, .. } => basic_type_from_record(env, layout_interner, sorted_fields), - LambdaSet(lambda_set) => basic_type_from_layout( - env, - layout_interner, - &lambda_set.runtime_representation(layout_interner), - ), + LambdaSet(lambda_set) => { + basic_type_from_layout(env, layout_interner, lambda_set.runtime_representation()) + } Boxed(inner_layout) => { - let inner_layout = layout_interner.get(*inner_layout); - let inner_type = basic_type_from_layout(env, layout_interner, &inner_layout); + let inner_type = basic_type_from_layout(env, layout_interner, inner_layout); inner_type.ptr_type(AddressSpace::Generic).into() } - Union(union_layout) => basic_type_from_union_layout(env, layout_interner, union_layout), + Union(union_layout) => basic_type_from_union_layout(env, layout_interner, &union_layout), RecursivePointer => env .context .i64_type() .ptr_type(AddressSpace::Generic) .as_basic_type_enum(), - Builtin(builtin) => basic_type_from_builtin(env, builtin), + Builtin(builtin) => basic_type_from_builtin(env, &builtin), } } @@ -148,27 +145,25 @@ pub fn basic_type_from_builtin<'a, 'ctx, 'env>( pub fn argument_type_from_layout<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, - layout: &Layout<'_>, + layout: InLayout<'a>, ) -> BasicTypeEnum<'ctx> { use Layout::*; - match layout { - LambdaSet(lambda_set) => argument_type_from_layout( - env, - layout_interner, - &lambda_set.runtime_representation(layout_interner), - ), - Union(union_layout) => argument_type_from_union_layout(env, layout_interner, union_layout), + match layout_interner.get(layout) { + LambdaSet(lambda_set) => { + argument_type_from_layout(env, layout_interner, lambda_set.runtime_representation()) + } + Union(union_layout) => argument_type_from_union_layout(env, layout_interner, &union_layout), Builtin(_) => { let base = basic_type_from_layout(env, layout_interner, layout); - if layout.is_passed_by_reference(layout_interner, env.target_info) { + if layout_interner.is_passed_by_reference(layout) { base.ptr_type(AddressSpace::Generic).into() } else { base } } - other => basic_type_from_layout(env, layout_interner, other), + _ => basic_type_from_layout(env, layout_interner, layout), } } @@ -301,7 +296,7 @@ impl<'ctx> RocUnion<'ctx> { pub fn tagged_from_slices( interner: &STLayoutInterner, context: &'ctx Context, - layouts: &[&[Layout<'_>]], + layouts: &[&[InLayout<'_>]], target_info: TargetInfo, ) -> Self { let tag_type = match layouts.len() { @@ -318,7 +313,7 @@ impl<'ctx> RocUnion<'ctx> { pub fn untagged_from_slices( interner: &STLayoutInterner, context: &'ctx Context, - layouts: &[&[Layout<'_>]], + layouts: &[&[InLayout<'_>]], target_info: TargetInfo, ) -> Self { let (data_width, data_align) = diff --git a/crates/compiler/gen_llvm/src/llvm/expect.rs b/crates/compiler/gen_llvm/src/llvm/expect.rs index 8175764f15..3a8a6d8717 100644 --- a/crates/compiler/gen_llvm/src/llvm/expect.rs +++ b/crates/compiler/gen_llvm/src/llvm/expect.rs @@ -11,7 +11,9 @@ use inkwell::AddressSpace; use roc_builtins::bitcode; use roc_module::symbol::Symbol; use roc_mono::ir::LookupType; -use roc_mono::layout::{Builtin, Layout, LayoutIds, LayoutInterner, STLayoutInterner, UnionLayout}; +use roc_mono::layout::{ + Builtin, InLayout, Layout, LayoutIds, LayoutInterner, STLayoutInterner, UnionLayout, +}; use roc_region::all::Region; use super::build::BuilderExt; @@ -199,10 +201,9 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx, 'env>( let (value, layout) = load_symbol_and_layout(scope, lookup); - let stack_size = env.ptr_int().const_int( - layout.stack_size(layout_interner, env.target_info) as u64, - false, - ); + let stack_size = env + .ptr_int() + .const_int(layout_interner.stack_size(layout) as u64, false); let mut extra_offset = env.builder.build_int_add(offset, stack_size, "offset"); @@ -218,7 +219,7 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx, 'env>( original_ptr, cursors, value, - *layout, + layout, WhenRecursive::Unreachable, ); @@ -284,10 +285,10 @@ fn build_clone<'a, 'ctx, 'env>( ptr: PointerValue<'ctx>, cursors: Cursors<'ctx>, value: BasicValueEnum<'ctx>, - layout: Layout<'a>, + layout: InLayout<'a>, when_recursive: WhenRecursive<'a>, ) -> IntValue<'ctx> { - match layout { + match layout_interner.get(layout) { Layout::Builtin(builtin) => build_clone_builtin( env, layout_interner, @@ -315,7 +316,7 @@ fn build_clone<'a, 'ctx, 'env>( Layout::LambdaSet(_) => cursors.extra_offset, Layout::Union(union_layout) => { - if layout.safe_to_memcpy(layout_interner) { + if layout_interner.safe_to_memcpy(layout) { let ptr = unsafe { env.builder.new_build_in_bounds_gep( env.context.i8_type(), @@ -352,13 +353,11 @@ fn build_clone<'a, 'ctx, 'env>( build_copy(env, ptr, cursors.offset, cursors.extra_offset.into()); let source = value.into_pointer_value(); - let inner_layout = layout_interner.get(inner_layout); let value = load_roc_value(env, layout_interner, inner_layout, source, "inner"); - let inner_width = env.ptr_int().const_int( - inner_layout.stack_size(layout_interner, env.target_info) as u64, - false, - ); + let inner_width = env + .ptr_int() + .const_int(layout_interner.stack_size(inner_layout) as u64, false); let new_extra = env .builder @@ -387,9 +386,9 @@ fn build_clone<'a, 'ctx, 'env>( } WhenRecursive::Loop(union_layout) => { - let layout = Layout::Union(union_layout); + let layout = layout_interner.insert(Layout::Union(union_layout)); - let bt = basic_type_from_layout(env, layout_interner, &layout); + let bt = basic_type_from_layout(env, layout_interner, layout); // cast the i64 pointer to a pointer to block of memory let field1_cast = env.builder.build_pointer_cast( @@ -420,7 +419,7 @@ fn build_clone_struct<'a, 'ctx, 'env>( ptr: PointerValue<'ctx>, cursors: Cursors<'ctx>, value: BasicValueEnum<'ctx>, - field_layouts: &[Layout<'a>], + field_layouts: &[InLayout<'a>], when_recursive: WhenRecursive<'a>, ) -> IntValue<'ctx> { let layout = Layout::struct_no_name_order(field_layouts); @@ -451,10 +450,9 @@ fn build_clone_struct<'a, 'ctx, 'env>( when_recursive, ); - let field_width = env.ptr_int().const_int( - field_layout.stack_size(layout_interner, env.target_info) as u64, - false, - ); + let field_width = env + .ptr_int() + .const_int(layout_interner.stack_size(*field_layout) as u64, false); cursors.extra_offset = new_extra; cursors.offset = env @@ -476,7 +474,7 @@ fn build_clone_tag<'a, 'ctx, 'env>( union_layout: UnionLayout<'a>, when_recursive: WhenRecursive<'a>, ) -> IntValue<'ctx> { - let layout = Layout::Union(union_layout); + let layout = layout_interner.insert(Layout::Union(union_layout)); let layout_id = layout_ids.get(Symbol::CLONE, &layout); let fn_name = layout_id.to_symbol_string(Symbol::CLONE, &env.interns); @@ -631,12 +629,12 @@ fn build_clone_tag_help<'a, 'ctx, 'env>( let block = env.context.append_basic_block(parent, "tag_id_modify"); env.builder.position_at_end(block); - let layout = Layout::struct_no_name_order(field_layouts); - let layout = Layout::struct_no_name_order( + let layout = layout_interner.insert(Layout::struct_no_name_order(field_layouts)); + let layout = layout_interner.insert(Layout::struct_no_name_order( env.arena.alloc([layout, union_layout.tag_id_layout()]), - ); + )); - let basic_type = basic_type_from_layout(env, layout_interner, &layout); + let basic_type = basic_type_from_layout(env, layout_interner, layout); let data = load_tag_data( env, layout_interner, @@ -690,16 +688,16 @@ fn build_clone_tag_help<'a, 'ctx, 'env>( let tag_value = tag_pointer_clear_tag_id(env, tag_value.into_pointer_value()); - let layout = Layout::struct_no_name_order(field_layouts); + let layout = layout_interner.insert(Layout::struct_no_name_order(field_layouts)); let layout = if union_layout.stores_tag_id_in_pointer(env.target_info) { layout } else { - Layout::struct_no_name_order( + layout_interner.insert(Layout::struct_no_name_order( env.arena.alloc([layout, union_layout.tag_id_layout()]), - ) + )) }; - let basic_type = basic_type_from_layout(env, layout_interner, &layout); + let basic_type = basic_type_from_layout(env, layout_interner, layout); let data = load_tag_data(env, layout_interner, union_layout, tag_value, basic_type); let (width, _) = @@ -748,8 +746,8 @@ fn build_clone_tag_help<'a, 'ctx, 'env>( build_copy(env, ptr, offset, extra_offset.into()); - let layout = Layout::struct_no_name_order(fields); - let basic_type = basic_type_from_layout(env, layout_interner, &layout); + let layout = layout_interner.insert(Layout::struct_no_name_order(fields)); + let basic_type = basic_type_from_layout(env, layout_interner, layout); let (width, _) = union_layout.data_size_and_alignment(layout_interner, env.target_info); @@ -814,8 +812,8 @@ fn build_clone_tag_help<'a, 'ctx, 'env>( other_tags[i] }; - let layout = Layout::struct_no_name_order(fields); - let basic_type = basic_type_from_layout(env, layout_interner, &layout); + let layout = layout_interner.insert(Layout::struct_no_name_order(fields)); + let basic_type = basic_type_from_layout(env, layout_interner, layout); let (width, _) = union_layout.data_size_and_alignment(layout_interner, env.target_info); @@ -898,17 +896,15 @@ fn build_clone_tag_help<'a, 'ctx, 'env>( // write the "pointer" af the current offset build_copy(env, ptr, offset, extra_offset.into()); - let layout = Layout::struct_no_name_order(other_fields); - let basic_type = basic_type_from_layout(env, layout_interner, &layout); + let layout = layout_interner.insert(Layout::struct_no_name_order(other_fields)); + let basic_type = basic_type_from_layout(env, layout_interner, layout); let cursors = Cursors { offset: extra_offset, extra_offset: env.builder.build_int_add( extra_offset, - env.ptr_int().const_int( - layout.stack_size(layout_interner, env.target_info) as _, - false, - ), + env.ptr_int() + .const_int(layout_interner.stack_size(layout) as _, false), "new_offset", ), }; @@ -1041,14 +1037,12 @@ fn build_clone_builtin<'a, 'ctx, 'env>( offset = build_copy(env, ptr, offset, len.into()); offset = build_copy(env, ptr, offset, len.into()); - let elem = layout_interner.get(elem); - let (element_width, _element_align) = - elem.stack_size_and_alignment(layout_interner, env.target_info); + let (element_width, _element_align) = layout_interner.stack_size_and_alignment(elem); let element_width = env.ptr_int().const_int(element_width as _, false); let elements_width = bd.build_int_mul(element_width, len, "elements_width"); - if elem.safe_to_memcpy(layout_interner) { + if layout_interner.safe_to_memcpy(elem) { // NOTE we are not actually sure the dest is properly aligned let dest = pointer_at_offset(bd, env.context.i8_type(), ptr, offset); let src = bd.build_pointer_cast( @@ -1063,7 +1057,7 @@ fn build_clone_builtin<'a, 'ctx, 'env>( // We cloned the elements into the extra_offset address. let elements_start_offset = cursors.extra_offset; - let element_type = basic_type_from_layout(env, layout_interner, &elem); + let element_type = basic_type_from_layout(env, layout_interner, elem); let elements = bd.build_pointer_cast( elements, element_type.ptr_type(AddressSpace::Generic), @@ -1073,10 +1067,9 @@ fn build_clone_builtin<'a, 'ctx, 'env>( // if the element has any pointers, we clone them to this offset let rest_offset = bd.build_alloca(env.ptr_int(), "rest_offset"); - let element_stack_size = env.ptr_int().const_int( - elem.stack_size(layout_interner, env.target_info) as u64, - false, - ); + let element_stack_size = env + .ptr_int() + .const_int(layout_interner.stack_size(elem) as u64, false); let rest_start_offset = bd.build_int_add( cursors.extra_offset, bd.build_int_mul(len, element_stack_size, "elements_width"), diff --git a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs index 040b34db30..759d400e1e 100644 --- a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs +++ b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs @@ -12,7 +12,7 @@ use roc_error_macros::internal_error; use roc_module::{low_level::LowLevel, symbol::Symbol}; use roc_mono::{ ir::HigherOrderLowLevel, - layout::{Builtin, LambdaSet, Layout, LayoutIds, LayoutInterner, STLayoutInterner}, + layout::{Builtin, InLayout, LambdaSet, Layout, LayoutIds, LayoutInterner, STLayoutInterner}, }; use roc_target::PtrWidth; @@ -50,8 +50,8 @@ use super::{ }; macro_rules! list_element_layout { - ($list_layout:expr) => { - match $list_layout { + ($interner:expr, $list_layout:expr) => { + match $interner.get($list_layout) { Layout::Builtin(Builtin::List(list_layout)) => list_layout, _ => unreachable!("invalid list layout"), } @@ -64,7 +64,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( layout_ids: &mut LayoutIds<'a>, scope: &Scope<'a, 'ctx>, parent: FunctionValue<'ctx>, - layout: &Layout<'a>, + layout: InLayout<'a>, op: LowLevel, args: &[Symbol], update_mode: UpdateMode, @@ -200,13 +200,13 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( // Str.toNum : Str -> Result (Num *) {} arguments!(string); - let number_layout = match layout { + let number_layout = match layout_interner.get(layout) { Layout::Struct { field_layouts, .. } => field_layouts[0], // TODO: why is it sometimes a struct? _ => unreachable!(), }; // match on the return layout to figure out which zig builtin we need - let intrinsic = match number_layout { + let intrinsic = match layout_interner.get(number_layout) { Layout::Builtin(Builtin::Int(int_width)) => &bitcode::STR_TO_INT[int_width], Layout::Builtin(Builtin::Float(float_width)) => &bitcode::STR_TO_FLOAT[float_width], Layout::Builtin(Builtin::Decimal) => bitcode::DEC_FROM_STR, @@ -227,7 +227,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( intrinsic, ), None => { - let return_type_name = match number_layout { + let return_type_name = match layout_interner.get(number_layout) { Layout::Builtin(Builtin::Int(int_width)) => int_width.type_name(), Layout::Builtin(Builtin::Decimal) => { // zig picks 128 for dec.RocDec @@ -267,7 +267,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( load_roc_value( env, layout_interner, - *layout, + layout, roc_return_alloca, "str_to_num_result", ) @@ -275,7 +275,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( } } PtrWidth::Bytes8 => { - let cc_return_by_pointer = match number_layout { + let cc_return_by_pointer = match layout_interner.get(number_layout) { Layout::Builtin(Builtin::Int(int_width)) => { (int_width.stack_size() as usize > env.target_info.ptr_size()) .then_some(int_width.type_name()) @@ -321,8 +321,8 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( let (int, int_layout) = load_symbol_and_layout(scope, &args[0]); let int = int.into_int_value(); - let int_width = match int_layout { - Layout::Builtin(Builtin::Int(int_width)) => *int_width, + let int_width = match layout_interner.get(int_layout) { + Layout::Builtin(Builtin::Int(int_width)) => int_width, _ => unreachable!(), }; @@ -340,8 +340,8 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( let (float, float_layout) = load_symbol_and_layout(scope, &args[0]); - let float_width = match float_layout { - Layout::Builtin(Builtin::Float(float_width)) => *float_width, + let float_width = match layout_interner.get(float_layout) { + Layout::Builtin(Builtin::Float(float_width)) => float_width, _ => unreachable!(), }; @@ -649,12 +649,12 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( // List.withCapacity : Nat -> List a arguments!(list_len); - let result_layout = *layout; + let result_layout = layout; list_with_capacity( env, layout_interner, list_len.into_int_value(), - list_element_layout!(result_layout), + list_element_layout!(layout_interner, result_layout), ) } ListConcat => { @@ -664,14 +664,14 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( let second_list = load_symbol(scope, &args[1]); - let element_layout = list_element_layout!(list_layout); + let element_layout = list_element_layout!(layout_interner, list_layout); list_concat( env, layout_interner, first_list, second_list, - *element_layout, + element_layout, ) } ListAppendUnsafe => { @@ -697,7 +697,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( debug_assert_eq!(args.len(), 2); let (list, list_layout) = load_symbol_and_layout(scope, &args[0]); - let element_layout = list_element_layout!(list_layout); + let element_layout = list_element_layout!(layout_interner, list_layout); let spare = load_symbol(scope, &args[1]); list_reserve( @@ -705,7 +705,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( layout_interner, list, spare, - *element_layout, + element_layout, update_mode, ) } @@ -719,14 +719,14 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( let index_1 = load_symbol(scope, &args[1]); let index_2 = load_symbol(scope, &args[2]); - let element_layout = list_element_layout!(list_layout); + let element_layout = list_element_layout!(layout_interner, list_layout); list_swap( env, layout_interner, original_wrapper, index_1.into_int_value(), index_2.into_int_value(), - *element_layout, + element_layout, update_mode, ) } @@ -739,7 +739,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( let start = load_symbol(scope, &args[1]); let len = load_symbol(scope, &args[2]); - let element_layout = list_element_layout!(list_layout); + let element_layout = list_element_layout!(layout_interner, list_layout); list_sublist( env, layout_interner, @@ -747,7 +747,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( original_wrapper, start.into_int_value(), len.into_int_value(), - *element_layout, + element_layout, ) } ListDropAt => { @@ -759,14 +759,14 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( let count = load_symbol(scope, &args[1]); - let element_layout = list_element_layout!(list_layout); + let element_layout = list_element_layout!(layout_interner, list_layout); list_drop_at( env, layout_interner, layout_ids, original_wrapper, count.into_int_value(), - *element_layout, + element_layout, ) } StrGetUnsafe => { @@ -789,7 +789,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( env, layout_interner, layout_ids, - *list_element_layout!(list_layout), + list_element_layout!(layout_interner, list_layout), element_index.into_int_value(), wrapper_struct.into_struct_value(), ) @@ -824,7 +824,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( // Num.toStr : Num a -> Str arguments_with_layouts!((num, num_layout)); - match num_layout { + match layout_interner.get(num_layout) { Layout::Builtin(Builtin::Int(int_width)) => { let int = num.into_int_value(); @@ -833,14 +833,14 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( &[], &[int.into()], BitcodeReturns::Str, - &bitcode::STR_FROM_INT[*int_width], + &bitcode::STR_FROM_INT[int_width], ) } Layout::Builtin(Builtin::Float(_float_width)) => { let (float, float_layout) = load_symbol_and_layout(scope, &args[0]); - let float_width = match float_layout { - Layout::Builtin(Builtin::Float(float_width)) => *float_width, + let float_width = match layout_interner.get(float_layout) { + Layout::Builtin(Builtin::Float(float_width)) => float_width, _ => unreachable!(), }; @@ -861,19 +861,19 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( | NumToIntChecked => { arguments_with_layouts!((arg, arg_layout)); - match arg_layout { + match layout_interner.get(arg_layout) { Layout::Builtin(arg_builtin) => { use roc_mono::layout::Builtin::*; match arg_builtin { Int(int_width) => { - let int_type = convert::int_type_from_int_width(env, *int_width); + let int_type = convert::int_type_from_int_width(env, int_width); build_int_unary_op( env, layout_interner, parent, arg.into_int_value(), - *int_width, + int_width, int_type, op, layout, @@ -881,10 +881,11 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( } Float(float_width) => build_float_unary_op( env, + layout_interner, layout, arg.into_float_value(), op, - *float_width, + float_width, ), _ => { unreachable!("Compiler bug: tried to run numeric operation {:?} on invalid builtin layout: ({:?})", op, arg_layout); @@ -925,7 +926,10 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout)); use inkwell::FloatPredicate; - match (lhs_layout, rhs_layout) { + match ( + layout_interner.get(lhs_layout), + layout_interner.get(rhs_layout), + ) { (Layout::Builtin(lhs_builtin), Layout::Builtin(rhs_builtin)) if lhs_builtin == rhs_builtin => { @@ -1011,13 +1015,22 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( | NumSubChecked | NumSubSaturated | NumMulWrap | NumMulSaturated | NumMulChecked => { arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout)); - build_num_binop(env, parent, lhs_arg, lhs_layout, rhs_arg, rhs_layout, op) + build_num_binop( + env, + layout_interner, + parent, + lhs_arg, + lhs_layout, + rhs_arg, + rhs_layout, + op, + ) } NumBitwiseAnd | NumBitwiseOr | NumBitwiseXor => { arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout)); debug_assert_eq!(lhs_layout, rhs_layout); - let int_width = intwidth_from_layout(*lhs_layout); + let int_width = intwidth_from_layout(lhs_layout); build_int_binop( env, @@ -1031,9 +1044,9 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( NumShiftLeftBy | NumShiftRightBy | NumShiftRightZfBy => { arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout)); - let int_width = intwidth_from_layout(*lhs_layout); + let int_width = intwidth_from_layout(lhs_layout); - debug_assert_eq!(rhs_layout, &Layout::Builtin(Builtin::Int(IntWidth::U8))); + debug_assert_eq!(rhs_layout, Layout::U8); let rhs_arg = if rhs_layout != lhs_layout { // LLVM shift intrinsics expect the left and right sides to have the same type, so // here we cast up `rhs` to the lhs type. Since the rhs was checked to be a U8, @@ -1061,7 +1074,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( arguments!(arg); let to = basic_type_from_layout(env, layout_interner, layout).into_int_type(); - let to_signed = intwidth_from_layout(*layout).is_signed(); + let to_signed = intwidth_from_layout(layout).is_signed(); env.builder .build_int_cast_sign_flag(arg.into_int_value(), to, to_signed, "inc_cast") @@ -1070,7 +1083,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( NumToFloatCast => { arguments_with_layouts!((arg, arg_layout)); - match arg_layout { + match layout_interner.get(arg_layout) { Layout::Builtin(Builtin::Int(width)) => { // Converting from int to float let int_val = arg.into_int_value(); @@ -1198,12 +1211,8 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( } } -fn intwidth_from_layout(layout: Layout) -> IntWidth { - match layout { - Layout::Builtin(Builtin::Int(int_width)) => int_width, - - _ => unreachable!(), - } +fn intwidth_from_layout(layout: InLayout) -> IntWidth { + layout.to_int_width() } fn build_int_binop<'a, 'ctx, 'env>( @@ -1429,14 +1438,18 @@ fn build_int_binop<'a, 'ctx, 'env>( pub fn build_num_binop<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, + layout_interner: &STLayoutInterner<'a>, parent: FunctionValue<'ctx>, lhs_arg: BasicValueEnum<'ctx>, - lhs_layout: &Layout<'a>, + lhs_layout: InLayout<'a>, rhs_arg: BasicValueEnum<'ctx>, - rhs_layout: &Layout<'a>, + rhs_layout: InLayout<'a>, op: LowLevel, ) -> BasicValueEnum<'ctx> { - match (lhs_layout, rhs_layout) { + match ( + layout_interner.get(lhs_layout), + layout_interner.get(rhs_layout), + ) { (Layout::Builtin(lhs_builtin), Layout::Builtin(rhs_builtin)) if lhs_builtin == rhs_builtin => { @@ -1446,7 +1459,7 @@ pub fn build_num_binop<'a, 'ctx, 'env>( Int(int_width) => build_int_binop( env, parent, - *int_width, + int_width, lhs_arg.into_int_value(), rhs_arg.into_int_value(), op, @@ -1454,7 +1467,7 @@ pub fn build_num_binop<'a, 'ctx, 'env>( Float(float_width) => build_float_binop( env, - *float_width, + float_width, lhs_arg.into_float_value(), rhs_arg.into_float_value(), op, @@ -1786,9 +1799,9 @@ fn build_dec_binop<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, parent: FunctionValue<'ctx>, lhs: BasicValueEnum<'ctx>, - _lhs_layout: &Layout<'a>, + _lhs_layout: InLayout<'a>, rhs: BasicValueEnum<'ctx>, - _rhs_layout: &Layout<'a>, + _rhs_layout: InLayout<'a>, op: LowLevel, ) -> BasicValueEnum<'ctx> { use roc_module::low_level::LowLevel::*; @@ -1868,7 +1881,7 @@ fn build_int_unary_op<'a, 'ctx, 'env>( arg_width: IntWidth, arg_int_type: IntType<'ctx>, op: LowLevel, - return_layout: &Layout<'a>, + return_layout: InLayout<'a>, ) -> BasicValueEnum<'ctx> { use roc_module::low_level::LowLevel::*; @@ -1886,9 +1899,9 @@ fn build_int_unary_op<'a, 'ctx, 'env>( NumToFrac => { // This is an Int, so we need to convert it. - let target_float_type = match return_layout { + let target_float_type = match layout_interner.get(return_layout) { Layout::Builtin(Builtin::Float(float_width)) => { - convert::float_type_from_float_width(env, *float_width) + convert::float_type_from_float_width(env, float_width) } _ => internal_error!("There can only be floats here!"), }; @@ -1903,16 +1916,10 @@ fn build_int_unary_op<'a, 'ctx, 'env>( NumToIntChecked => { // return_layout : Result N [OutOfBounds]* ~ { result: N, out_of_bounds: bool } - let target_int_width = match return_layout { + let target_int_width = match layout_interner.get(return_layout) { Layout::Struct { field_layouts, .. } if field_layouts.len() == 2 => { - debug_assert!(matches!(field_layouts[1], Layout::Builtin(Builtin::Bool))); - match field_layouts[0] { - Layout::Builtin(Builtin::Int(iw)) => iw, - layout => internal_error!( - "There can only be an int layout here, found {:?}!", - layout - ), - } + debug_assert!(matches!(field_layouts[1], Layout::BOOL)); + field_layouts[0].to_int_width() } layout => internal_error!( "There can only be a result layout here, found {:?}!", @@ -2017,7 +2024,7 @@ fn build_int_unary_op<'a, 'ctx, 'env>( load_roc_value( env, layout_interner, - *return_layout, + return_layout, roc_return_alloca, "num_to_int", ) @@ -2159,7 +2166,8 @@ fn int_abs_with_overflow<'a, 'ctx, 'env>( fn build_float_unary_op<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, - layout: &Layout<'a>, + layout_interner: &STLayoutInterner<'a>, + layout: InLayout<'a>, arg: FloatValue<'ctx>, op: LowLevel, float_width: FloatWidth, // arg width @@ -2175,8 +2183,8 @@ fn build_float_unary_op<'a, 'ctx, 'env>( NumSqrtUnchecked => env.call_intrinsic(&LLVM_SQRT[float_width], &[arg.into()]), NumLogUnchecked => env.call_intrinsic(&LLVM_LOG[float_width], &[arg.into()]), NumToFrac => { - let return_width = match layout { - Layout::Builtin(Builtin::Float(return_width)) => *return_width, + let return_width = match layout_interner.get(layout) { + Layout::Builtin(Builtin::Float(return_width)) => return_width, _ => internal_error!("Layout for returning is not Float : {:?}", layout), }; match (float_width, return_width) { @@ -2197,10 +2205,10 @@ fn build_float_unary_op<'a, 'ctx, 'env>( } } NumCeiling => { - let (return_signed, return_type) = match layout { + let (return_signed, return_type) = match layout_interner.get(layout) { Layout::Builtin(Builtin::Int(int_width)) => ( int_width.is_signed(), - convert::int_type_from_int_width(env, *int_width), + convert::int_type_from_int_width(env, int_width), ), _ => internal_error!("Ceiling return layout is not int: {:?}", layout), }; @@ -2217,10 +2225,10 @@ fn build_float_unary_op<'a, 'ctx, 'env>( ) } NumFloor => { - let (return_signed, return_type) = match layout { + let (return_signed, return_type) = match layout_interner.get(layout) { Layout::Builtin(Builtin::Int(int_width)) => ( int_width.is_signed(), - convert::int_type_from_int_width(env, *int_width), + convert::int_type_from_int_width(env, int_width), ), _ => internal_error!("Ceiling return layout is not int: {:?}", layout), }; @@ -2237,10 +2245,10 @@ fn build_float_unary_op<'a, 'ctx, 'env>( ) } NumRound => { - let (return_signed, return_type) = match layout { + let (return_signed, return_type) = match layout_interner.get(layout) { Layout::Builtin(Builtin::Int(int_width)) => ( int_width.is_signed(), - convert::int_type_from_int_width(env, *int_width), + convert::int_type_from_int_width(env, int_width), ), _ => internal_error!("Ceiling return layout is not int: {:?}", layout), }; @@ -2277,7 +2285,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>( layout_interner: &mut STLayoutInterner<'a>, layout_ids: &mut LayoutIds<'a>, scope: &Scope<'a, 'ctx>, - return_layout: &Layout<'a>, + return_layout: InLayout<'a>, func_spec: FuncSpec, higher_order: &HigherOrderLowLevel<'a>, ) -> BasicValueEnum<'ctx> { @@ -2312,7 +2320,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>( ); let (closure, closure_layout) = - load_symbol_and_lambda_set(scope, &captured_environment); + load_symbol_and_lambda_set(layout_interner, scope, &captured_environment); (function, closure, closure_layout) }}; @@ -2325,14 +2333,14 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>( let (function, closure, closure_layout) = function_details!(); - match (list_layout, return_layout) { + match ( + layout_interner.get(list_layout), + layout_interner.get(return_layout), + ) { ( Layout::Builtin(Builtin::List(element_layout)), Layout::Builtin(Builtin::List(result_layout)), ) => { - let element_layout = layout_interner.get(*element_layout); - let result_layout = layout_interner.get(*result_layout); - let argument_layouts = &[element_layout]; let roc_function_call = roc_function_call( @@ -2352,8 +2360,8 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>( layout_interner, roc_function_call, list, - &element_layout, - &result_layout, + element_layout, + result_layout, ) } _ => unreachable!("invalid list layout"), @@ -2365,16 +2373,16 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>( let (function, closure, closure_layout) = function_details!(); - match (list1_layout, list2_layout, return_layout) { + match ( + layout_interner.get(list1_layout), + layout_interner.get(list2_layout), + layout_interner.get(return_layout), + ) { ( Layout::Builtin(Builtin::List(element1_layout)), Layout::Builtin(Builtin::List(element2_layout)), Layout::Builtin(Builtin::List(result_layout)), ) => { - let element1_layout = layout_interner.get(*element1_layout); - let element2_layout = layout_interner.get(*element2_layout); - let result_layout = layout_interner.get(*result_layout); - let argument_layouts = &[element1_layout, element2_layout]; let roc_function_call = roc_function_call( @@ -2396,9 +2404,9 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>( roc_function_call, list1, list2, - &element1_layout, - &element2_layout, - &result_layout, + element1_layout, + element2_layout, + result_layout, ) } _ => unreachable!("invalid list layout"), @@ -2411,18 +2419,18 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>( let (function, closure, closure_layout) = function_details!(); - match (list1_layout, list2_layout, list3_layout, return_layout) { + match ( + layout_interner.get(list1_layout), + layout_interner.get(list2_layout), + layout_interner.get(list3_layout), + layout_interner.get(return_layout), + ) { ( Layout::Builtin(Builtin::List(element1_layout)), Layout::Builtin(Builtin::List(element2_layout)), Layout::Builtin(Builtin::List(element3_layout)), Layout::Builtin(Builtin::List(result_layout)), ) => { - let element1_layout = layout_interner.get(*element1_layout); - let element2_layout = layout_interner.get(*element2_layout); - let element3_layout = layout_interner.get(*element3_layout); - let result_layout = layout_interner.get(*result_layout); - let argument_layouts = &[element1_layout, element2_layout, element3_layout]; let roc_function_call = roc_function_call( @@ -2445,10 +2453,10 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>( list1, list2, list3, - &element1_layout, - &element2_layout, - &element3_layout, - &result_layout, + element1_layout, + element2_layout, + element3_layout, + result_layout, ) } _ => unreachable!("invalid list layout"), @@ -2463,11 +2471,11 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>( let (function, closure, closure_layout) = function_details!(); match ( - list1_layout, - list2_layout, - list3_layout, - list4_layout, - return_layout, + layout_interner.get(list1_layout), + layout_interner.get(list2_layout), + layout_interner.get(list3_layout), + layout_interner.get(list4_layout), + layout_interner.get(return_layout), ) { ( Layout::Builtin(Builtin::List(element1_layout)), @@ -2476,12 +2484,6 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>( Layout::Builtin(Builtin::List(element4_layout)), Layout::Builtin(Builtin::List(result_layout)), ) => { - let element1_layout = layout_interner.get(*element1_layout); - let element2_layout = layout_interner.get(*element2_layout); - let element3_layout = layout_interner.get(*element3_layout); - let element4_layout = layout_interner.get(*element4_layout); - let result_layout = layout_interner.get(*result_layout); - let argument_layouts = &[ element1_layout, element2_layout, @@ -2510,11 +2512,11 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>( list2, list3, list4, - &element1_layout, - &element2_layout, - &element3_layout, - &element4_layout, - &result_layout, + element1_layout, + element2_layout, + element3_layout, + element4_layout, + result_layout, ) } _ => unreachable!("invalid list layout"), @@ -2526,12 +2528,10 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>( let (function, closure, closure_layout) = function_details!(); - match list_layout { + match layout_interner.get(list_layout) { Layout::Builtin(Builtin::List(element_layout)) => { use crate::llvm::bitcode::build_compare_wrapper; - let element_layout = layout_interner.get(*element_layout); - let argument_layouts = &[element_layout, element_layout]; let compare_wrapper = build_compare_wrapper( @@ -2539,7 +2539,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>( layout_interner, function, closure_layout, - &element_layout, + element_layout, ) .as_global_value() .as_pointer_value(); @@ -2562,7 +2562,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>( roc_function_call, compare_wrapper, list, - &element_layout, + element_layout, ) } _ => unreachable!("invalid list layout"), @@ -2572,11 +2572,12 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>( } fn load_symbol_and_lambda_set<'a, 'ctx, 'b>( + layout_interner: &STLayoutInterner<'a>, scope: &'b Scope<'a, 'ctx>, symbol: &Symbol, ) -> (BasicValueEnum<'ctx>, LambdaSet<'a>) { - match scope.get(symbol) { - Some((Layout::LambdaSet(lambda_set), ptr)) => (*ptr, *lambda_set), + match scope.get(symbol).map(|(l, v)| (layout_interner.get(*l), v)) { + Some((Layout::LambdaSet(lambda_set), ptr)) => (*ptr, lambda_set), Some((other, ptr)) => panic!("Not a lambda set: {:?}, {:?}", other, ptr), None => panic!("There was no entry for {:?} in scope {:?}", symbol, scope), } diff --git a/crates/compiler/gen_llvm/src/llvm/refcounting.rs b/crates/compiler/gen_llvm/src/llvm/refcounting.rs index 42e0f0a647..5ccc297058 100644 --- a/crates/compiler/gen_llvm/src/llvm/refcounting.rs +++ b/crates/compiler/gen_llvm/src/llvm/refcounting.rs @@ -113,7 +113,7 @@ impl<'ctx> PointerToRefcount<'ctx> { fn modify<'a, 'env>( &self, mode: CallMode<'ctx>, - layout: &Layout<'a>, + layout: InLayout<'a>, env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, ) { @@ -131,10 +131,10 @@ impl<'ctx> PointerToRefcount<'ctx> { &self, env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, - layout: &Layout<'a>, + layout: InLayout<'a>, ) { - let alignment = layout - .allocation_alignment_bytes(layout_interner, env.target_info) + let alignment = layout_interner + .allocation_alignment_bytes(layout) .max(env.target_info.ptr_width() as u32); let context = env.context; @@ -275,28 +275,28 @@ fn modify_refcount_struct<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, layout_ids: &mut LayoutIds<'a>, - layouts: &'a [Layout<'a>], + layouts: &'a [InLayout<'a>], mode: Mode, when_recursive: &WhenRecursive<'a>, ) -> FunctionValue<'ctx> { let block = env.builder.get_insert_block().expect("to be in a function"); let di_location = env.builder.get_current_debug_location().unwrap(); - let layout = Layout::struct_no_name_order(layouts); + let layout = layout_interner.insert(Layout::struct_no_name_order(layouts)); let (_, fn_name) = function_name_from_mode( layout_ids, &env.interns, "increment_struct", "decrement_struct", - &layout, + layout, mode, ); let function = match env.module.get_function(fn_name.as_str()) { Some(function_value) => function_value, None => { - let basic_type = basic_type_from_layout(env, layout_interner, &layout); + let basic_type = basic_type_from_layout(env, layout_interner, layout); let function_value = build_header(env, basic_type, mode, &fn_name); modify_refcount_struct_help( @@ -327,7 +327,7 @@ fn modify_refcount_struct_help<'a, 'ctx, 'env>( layout_ids: &mut LayoutIds<'a>, mode: Mode, when_recursive: &WhenRecursive<'a>, - layouts: &[Layout<'a>], + layouts: &[InLayout<'a>], fn_val: FunctionValue<'ctx>, ) { let builder = env.builder; @@ -349,7 +349,7 @@ fn modify_refcount_struct_help<'a, 'ctx, 'env>( let wrapper_struct = arg_val.into_struct_value(); for (i, field_layout) in layouts.iter().enumerate() { - if field_layout.contains_refcounted(layout_interner) { + if layout_interner.contains_refcounted(*field_layout) { let raw_value = env .builder .build_extract_value(wrapper_struct, i as u32, "decrement_struct_field") @@ -370,7 +370,7 @@ fn modify_refcount_struct_help<'a, 'ctx, 'env>( mode.to_call_mode(fn_val), when_recursive, field_value, - field_layout, + *field_layout, ); } } @@ -384,7 +384,7 @@ pub fn increment_refcount_layout<'a, 'ctx, 'env>( layout_ids: &mut LayoutIds<'a>, inc_amount: u64, value: BasicValueEnum<'ctx>, - layout: &Layout<'a>, + layout: InLayout<'a>, ) { let amount = env.ptr_int().const_int(inc_amount, false); increment_n_refcount_layout(env, layout_interner, layout_ids, amount, value, layout); @@ -396,7 +396,7 @@ pub fn increment_n_refcount_layout<'a, 'ctx, 'env>( layout_ids: &mut LayoutIds<'a>, amount: IntValue<'ctx>, value: BasicValueEnum<'ctx>, - layout: &Layout<'a>, + layout: InLayout<'a>, ) { modify_refcount_layout( env, @@ -413,7 +413,7 @@ pub fn decrement_refcount_layout<'a, 'ctx, 'env>( layout_interner: &mut STLayoutInterner<'a>, layout_ids: &mut LayoutIds<'a>, value: BasicValueEnum<'ctx>, - layout: &Layout<'a>, + layout: InLayout<'a>, ) { modify_refcount_layout( env, @@ -431,7 +431,7 @@ fn modify_refcount_builtin<'a, 'ctx, 'env>( layout_ids: &mut LayoutIds<'a>, mode: Mode, when_recursive: &WhenRecursive<'a>, - layout: &Layout<'a>, + layout: InLayout<'a>, builtin: &Builtin<'a>, ) -> Option> { use Builtin::*; @@ -471,7 +471,7 @@ fn modify_refcount_layout<'a, 'ctx, 'env>( layout_ids: &mut LayoutIds<'a>, call_mode: CallMode<'ctx>, value: BasicValueEnum<'ctx>, - layout: &Layout<'a>, + layout: InLayout<'a>, ) { modify_refcount_layout_help( env, @@ -491,7 +491,7 @@ fn modify_refcount_layout_help<'a, 'ctx, 'env>( call_mode: CallMode<'ctx>, when_recursive: &WhenRecursive<'a>, value: BasicValueEnum<'ctx>, - layout: &Layout<'a>, + layout: InLayout<'a>, ) { let mode = match call_mode { CallMode::Inc(_) => Mode::Inc, @@ -510,15 +510,15 @@ fn modify_refcount_layout_help<'a, 'ctx, 'env>( None => return, }; - match layout { + match layout_interner.get(layout) { Layout::RecursivePointer => match when_recursive { WhenRecursive::Unreachable => { unreachable!("recursion pointers should never be hashed directly") } WhenRecursive::Loop(union_layout) => { - let layout = Layout::Union(*union_layout); + let layout = layout_interner.insert(Layout::Union(*union_layout)); - let bt = basic_type_from_layout(env, layout_interner, &layout); + let bt = basic_type_from_layout(env, layout_interner, layout); // cast the i64 pointer to a pointer to block of memory let field_cast = env.builder.build_pointer_cast( @@ -569,11 +569,11 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>( layout_ids: &mut LayoutIds<'a>, mode: Mode, when_recursive: &WhenRecursive<'a>, - layout: &Layout<'a>, + layout: InLayout<'a>, ) -> Option> { use Layout::*; - match layout { + match layout_interner.get(layout) { Builtin(builtin) => modify_refcount_builtin( env, layout_interner, @@ -581,11 +581,11 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>( mode, when_recursive, layout, - builtin, + &builtin, ), Boxed(inner) => { - let function = modify_refcount_boxed(env, layout_interner, layout_ids, mode, *inner); + let function = modify_refcount_boxed(env, layout_interner, layout_ids, mode, inner); Some(function) } @@ -618,8 +618,8 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>( layout_interner, layout_ids, mode, - &WhenRecursive::Loop(*variant), - *variant, + &WhenRecursive::Loop(variant), + variant, ); Some(function) @@ -645,7 +645,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>( unreachable!("recursion pointers cannot be in/decremented directly") } WhenRecursive::Loop(union_layout) => { - let layout = Layout::Union(*union_layout); + let layout = layout_interner.insert(Layout::Union(*union_layout)); let function = modify_refcount_layout_build_function( env, @@ -653,7 +653,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>( layout_ids, mode, when_recursive, - &layout, + layout, )?; Some(function) @@ -665,7 +665,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>( layout_ids, mode, when_recursive, - &lambda_set.runtime_representation(layout_interner), + lambda_set.runtime_representation(), ), } } @@ -684,7 +684,7 @@ fn modify_refcount_list<'a, 'ctx, 'env>( let element_layout = layout_interner.get(element_layout); let element_layout = when_recursive.unwrap_recursive_pointer(element_layout); let element_layout = layout_interner.insert(element_layout); - let list_layout = &Layout::Builtin(Builtin::List(element_layout)); + let list_layout = layout_interner.insert(Layout::Builtin(Builtin::List(element_layout))); let (_, fn_name) = function_name_from_mode( layout_ids, &env.interns, @@ -735,7 +735,7 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>( layout_ids: &mut LayoutIds<'a>, mode: Mode, when_recursive: &WhenRecursive<'a>, - layout: &Layout<'a>, + layout: InLayout<'a>, element_layout: InLayout<'a>, fn_val: FunctionValue<'ctx>, ) { @@ -775,9 +775,8 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>( builder.position_at_end(modification_block); - let element_layout = layout_interner.get(element_layout); - if element_layout.contains_refcounted(layout_interner) { - let ptr_type = basic_type_from_layout(env, layout_interner, &element_layout) + if layout_interner.contains_refcounted(element_layout) { + let ptr_type = basic_type_from_layout(env, layout_interner, element_layout) .ptr_type(AddressSpace::Generic); let (len, ptr) = load_list(env.builder, original_wrapper, ptr_type); @@ -790,7 +789,7 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>( mode.to_call_mode(fn_val), when_recursive, element, - &element_layout, + element_layout, ); }; @@ -823,7 +822,7 @@ fn modify_refcount_str<'a, 'ctx, 'env>( layout_interner: &mut STLayoutInterner<'a>, layout_ids: &mut LayoutIds<'a>, mode: Mode, - layout: &Layout<'a>, + layout: InLayout<'a>, ) -> FunctionValue<'ctx> { let block = env.builder.get_insert_block().expect("to be in a function"); let di_location = env.builder.get_current_debug_location().unwrap(); @@ -860,7 +859,7 @@ fn modify_refcount_str_help<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &mut STLayoutInterner<'a>, mode: Mode, - layout: &Layout<'a>, + layout: InLayout<'a>, fn_val: FunctionValue<'ctx>, ) { let builder = env.builder; @@ -936,7 +935,7 @@ fn modify_refcount_boxed<'a, 'ctx, 'env>( let block = env.builder.get_insert_block().expect("to be in a function"); let di_location = env.builder.get_current_debug_location().unwrap(); - let boxed_layout = env.arena.alloc(Layout::Boxed(inner_layout)); + let boxed_layout = layout_interner.insert(Layout::Boxed(inner_layout)); let (_, fn_name) = function_name_from_mode( layout_ids, @@ -991,8 +990,8 @@ fn modify_refcount_box_help<'a, 'ctx, 'env>( let boxed = arg_val.into_pointer_value(); let refcount_ptr = PointerToRefcount::from_ptr_to_data(env, boxed); let call_mode = mode_to_call_mode(fn_val, mode); - let boxed_layout = Layout::Boxed(inner_layout); - refcount_ptr.modify(call_mode, &boxed_layout, env, layout_interner); + let boxed_layout = layout_interner.insert(Layout::Boxed(inner_layout)); + refcount_ptr.modify(call_mode, boxed_layout, env, layout_interner); // this function returns void builder.build_return(None); @@ -1097,14 +1096,14 @@ fn build_rec_union<'a, 'ctx, 'env>( when_recursive: &WhenRecursive<'a>, union_layout: UnionLayout<'a>, ) -> FunctionValue<'ctx> { - let layout = Layout::Union(union_layout); + let layout = layout_interner.insert(Layout::Union(union_layout)); let (_, fn_name) = function_name_from_mode( layout_ids, &env.interns, "increment_rec_union", "decrement_rec_union", - &layout, + layout, mode, ); @@ -1114,7 +1113,7 @@ fn build_rec_union<'a, 'ctx, 'env>( let block = env.builder.get_insert_block().expect("to be in a function"); let di_location = env.builder.get_current_debug_location().unwrap(); - let basic_type = basic_type_from_layout(env, layout_interner, &layout); + let basic_type = basic_type_from_layout(env, layout_interner, layout); let function_value = build_header(env, basic_type, mode, &fn_name); build_rec_union_help( @@ -1203,12 +1202,12 @@ fn build_rec_union_help<'a, 'ctx, 'env>( let refcount_ptr = PointerToRefcount::from_ptr_to_data(env, value_ptr); let call_mode = mode_to_call_mode(fn_val, mode); - let layout = Layout::Union(union_layout); + let layout = layout_interner.insert(Layout::Union(union_layout)); match mode { Mode::Inc => { // inc is cheap; we never recurse - refcount_ptr.modify(call_mode, &layout, env, layout_interner); + refcount_ptr.modify(call_mode, layout, env, layout_interner); env.builder.build_return(None); } @@ -1225,7 +1224,7 @@ fn build_rec_union_help<'a, 'ctx, 'env>( { env.builder.position_at_end(no_recurse_block); - refcount_ptr.modify(call_mode, &layout, env, layout_interner); + refcount_ptr.modify(call_mode, layout, env, layout_interner); env.builder.build_return(None); } @@ -1257,10 +1256,11 @@ enum DecOrReuse { Reuse, } -fn fields_need_no_refcounting(interner: &STLayoutInterner, field_layouts: &[Layout]) -> bool { - !field_layouts - .iter() - .any(|x| x.is_refcounted() || x.contains_refcounted(interner)) +fn fields_need_no_refcounting(interner: &STLayoutInterner, field_layouts: &[InLayout]) -> bool { + !field_layouts.iter().any(|x| { + let x = interner.get(*x); + x.is_refcounted() || x.contains_refcounted(interner) + }) } #[allow(clippy::too_many_arguments)] @@ -1289,7 +1289,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>( let mut cases = Vec::with_capacity_in(tags.len(), env.arena); let tag_id_int_type = - basic_type_from_layout(env, layout_interner, &union_layout.tag_id_layout()).into_int_type(); + basic_type_from_layout(env, layout_interner, union_layout.tag_id_layout()).into_int_type(); for (tag_id, field_layouts) in tags.iter().enumerate() { let tag_id = match nullable_id { @@ -1310,11 +1310,8 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>( env.builder.position_at_end(block); - let wrapper_type = basic_type_from_layout( - env, - layout_interner, - &Layout::struct_no_name_order(field_layouts), - ); + let fields_struct = layout_interner.insert(Layout::struct_no_name_order(field_layouts)); + let wrapper_type = basic_type_from_layout(env, layout_interner, fields_struct); // cast the opaque pointer to a pointer of the correct shape let struct_ptr = env.builder.build_pointer_cast( @@ -1329,7 +1326,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>( let mut deferred_nonrec = Vec::new_in(env.arena); for (i, field_layout) in field_layouts.iter().enumerate() { - if let Layout::RecursivePointer = field_layout { + if let Layout::RecursivePointer = layout_interner.get(*field_layout) { // this field has type `*i64`, but is really a pointer to the data we want let elem_pointer = env .builder @@ -1350,12 +1347,12 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>( debug_assert!(ptr_as_i64_ptr.is_pointer_value()); // therefore we must cast it to our desired type - let union_type = - basic_type_from_layout(env, layout_interner, &Layout::Union(union_layout)); + let union_layout = layout_interner.insert(Layout::Union(union_layout)); + let union_type = basic_type_from_layout(env, layout_interner, union_layout); let recursive_field_ptr = cast_basic_basic(env.builder, ptr_as_i64_ptr, union_type); deferred_rec.push(recursive_field_ptr); - } else if field_layout.contains_refcounted(layout_interner) { + } else if layout_interner.contains_refcounted(*field_layout) { let elem_pointer = env .builder .new_build_struct_gep( @@ -1388,12 +1385,8 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>( match decrement_or_reuse { DecOrReuse::Reuse => {} DecOrReuse::Dec => { - refcount_ptr.modify( - call_mode, - &Layout::Union(union_layout), - env, - layout_interner, - ); + let union_layout = layout_interner.insert(Layout::Union(union_layout)); + refcount_ptr.modify(call_mode, union_layout, env, layout_interner); } } @@ -1405,7 +1398,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>( mode.to_call_mode(decrement_fn), when_recursive, field, - field_layout, + *field_layout, ); } @@ -1446,12 +1439,8 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>( // increment/decrement the cons-cell itself if let DecOrReuse::Dec = decrement_or_reuse { - refcount_ptr.modify( - call_mode, - &Layout::Union(union_layout), - env, - layout_interner, - ); + let union_layout = layout_interner.insert(Layout::Union(union_layout)); + refcount_ptr.modify(call_mode, union_layout, env, layout_interner); } } @@ -1462,7 +1451,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>( struct UnionLayoutTags<'a> { nullable_id: Option, - tags: &'a [&'a [Layout<'a>]], + tags: &'a [&'a [InLayout<'a>]], } fn union_layout_tags<'a>( @@ -1509,7 +1498,8 @@ pub fn build_reset<'a, 'ctx, 'env>( ) -> FunctionValue<'ctx> { let mode = Mode::Dec; - let layout_id = layout_ids.get(Symbol::DEC, &Layout::Union(union_layout)); + let union_layout_in = layout_interner.insert(Layout::Union(union_layout)); + let layout_id = layout_ids.get(Symbol::DEC, &union_layout_in); let fn_name = layout_id.to_symbol_string(Symbol::DEC, &env.interns); let fn_name = format!("{}_reset", fn_name); @@ -1529,8 +1519,7 @@ pub fn build_reset<'a, 'ctx, 'env>( let block = env.builder.get_insert_block().expect("to be in a function"); let di_location = env.builder.get_current_debug_location().unwrap(); - let basic_type = - basic_type_from_layout(env, layout_interner, &Layout::Union(union_layout)); + let basic_type = basic_type_from_layout(env, layout_interner, union_layout_in); let function_value = build_header(env, basic_type, mode, &fn_name); build_reuse_rec_union_help( @@ -1616,7 +1605,7 @@ fn build_reuse_rec_union_help<'a, 'ctx, 'env>( env.builder.position_at_end(should_recurse_block); - let layout = Layout::Union(union_layout); + let layout = layout_interner.insert(Layout::Union(union_layout)); let do_recurse_block = env.context.append_basic_block(parent, "do_recurse"); let no_recurse_block = env.context.append_basic_block(parent, "no_recurse"); @@ -1626,7 +1615,7 @@ fn build_reuse_rec_union_help<'a, 'ctx, 'env>( { env.builder.position_at_end(no_recurse_block); - refcount_ptr.modify(call_mode, &layout, env, layout_interner); + refcount_ptr.modify(call_mode, layout, env, layout_interner); env.builder.build_return(None); } @@ -1656,7 +1645,7 @@ fn function_name_from_mode<'a>( interns: &Interns, if_inc: &'static str, if_dec: &'static str, - layout: &Layout<'a>, + layout: InLayout<'a>, mode: Mode, ) -> (&'static str, String) { // NOTE this is not a typo, we always determine the layout ID @@ -1664,7 +1653,7 @@ fn function_name_from_mode<'a>( // decremented, so `dec` is used on more layouts. That can cause the // layout ids of the inc and dec versions to be different, which is // rather confusing, so now `inc_x` always corresponds to `dec_x` - let layout_id = layout_ids.get(Symbol::DEC, layout); + let layout_id = layout_ids.get(Symbol::DEC, &layout); match mode { Mode::Inc => (if_inc, layout_id.to_symbol_string(Symbol::INC, interns)), Mode::Dec => (if_dec, layout_id.to_symbol_string(Symbol::DEC, interns)), @@ -1677,10 +1666,10 @@ fn modify_refcount_nonrecursive<'a, 'ctx, 'env>( layout_ids: &mut LayoutIds<'a>, mode: Mode, when_recursive: &WhenRecursive<'a>, - fields: &'a [&'a [Layout<'a>]], + fields: &'a [&'a [InLayout<'a>]], ) -> FunctionValue<'ctx> { let union_layout = UnionLayout::NonRecursive(fields); - let layout = Layout::Union(union_layout); + let layout = layout_interner.insert(Layout::Union(union_layout)); let block = env.builder.get_insert_block().expect("to be in a function"); let di_location = env.builder.get_current_debug_location().unwrap(); @@ -1690,7 +1679,7 @@ fn modify_refcount_nonrecursive<'a, 'ctx, 'env>( &env.interns, "increment_union", "decrement_union", - &layout, + layout, mode, ); @@ -1727,7 +1716,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>( layout_ids: &mut LayoutIds<'a>, mode: Mode, when_recursive: &WhenRecursive<'a>, - tags: &[&[Layout<'a>]], + tags: &'a [&'a [InLayout<'a>]], fn_val: FunctionValue<'ctx>, ) { debug_assert!(!tags.is_empty()); @@ -1753,9 +1742,8 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>( let before_block = env.builder.get_insert_block().expect("to be in a function"); let union_layout = UnionLayout::NonRecursive(tags); - let layout = Layout::Union(union_layout); - let union_struct_type = - basic_type_from_layout(env, layout_interner, &layout).into_struct_type(); + let layout = layout_interner.insert(Layout::Union(union_layout)); + let union_struct_type = basic_type_from_layout(env, layout_interner, layout).into_struct_type(); // read the tag_id let tag_id_ptr = env @@ -1771,7 +1759,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>( let tag_id = env .builder .new_build_load( - basic_type_from_layout(env, layout_interner, &union_layout.tag_id_layout()), + basic_type_from_layout(env, layout_interner, union_layout.tag_id_layout()), tag_id_ptr, "load_tag_id", ) @@ -1790,21 +1778,18 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>( for (tag_id, field_layouts) in tags.iter().enumerate() { // if none of the fields are or contain anything refcounted, just move on - if !field_layouts - .iter() - .any(|x| x.is_refcounted() || x.contains_refcounted(layout_interner)) - { + if !field_layouts.iter().any(|x| { + let x = layout_interner.get(*x); + x.is_refcounted() || x.contains_refcounted(layout_interner) + }) { continue; } let block = env.context.append_basic_block(parent, "tag_id_modify"); env.builder.position_at_end(block); - let data_struct_type = basic_type_from_layout( - env, - layout_interner, - &Layout::struct_no_name_order(field_layouts), - ); + let fields_struct = layout_interner.insert(Layout::struct_no_name_order(field_layouts)); + let data_struct_type = basic_type_from_layout(env, layout_interner, fields_struct); debug_assert!(data_struct_type.is_struct_type()); let data_struct_type = data_struct_type.into_struct_type(); @@ -1825,7 +1810,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>( ); for (i, field_layout) in field_layouts.iter().enumerate() { - if let Layout::RecursivePointer = field_layout { + if let Layout::RecursivePointer = layout_interner.get(*field_layout) { let recursive_union_layout = match when_recursive { WhenRecursive::Unreachable => { panic!("non-recursive tag unions cannot contain naked recursion pointers!"); @@ -1854,11 +1839,8 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>( debug_assert!(field_value.is_pointer_value()); // therefore we must cast it to our desired type - let union_type = basic_type_from_layout( - env, - layout_interner, - &Layout::Union(*recursive_union_layout), - ); + let union_layout = layout_interner.insert(Layout::Union(*recursive_union_layout)); + let union_type = basic_type_from_layout(env, layout_interner, union_layout); let recursive_ptr_field_value = cast_basic_basic(env.builder, field_value, union_type); @@ -1869,9 +1851,9 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>( mode.to_call_mode(fn_val), when_recursive, recursive_ptr_field_value, - &Layout::RecursivePointer, + Layout::RECURSIVE_PTR, ) - } else if field_layout.contains_refcounted(layout_interner) { + } else if layout_interner.contains_refcounted(*field_layout) { let field_ptr = env .builder .new_build_struct_gep( @@ -1882,16 +1864,15 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>( ) .unwrap(); - let field_value = - if field_layout.is_passed_by_reference(layout_interner, env.target_info) { - field_ptr.into() - } else { - env.builder.new_build_load( - basic_type_from_layout(env, layout_interner, field_layout), - field_ptr, - "field_value", - ) - }; + let field_value = if layout_interner.is_passed_by_reference(*field_layout) { + field_ptr.into() + } else { + env.builder.new_build_load( + basic_type_from_layout(env, layout_interner, *field_layout), + field_ptr, + "field_value", + ) + }; modify_refcount_layout_help( env, @@ -1900,7 +1881,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>( mode.to_call_mode(fn_val), when_recursive, field_value, - field_layout, + *field_layout, ); } } diff --git a/crates/compiler/mono/src/layout/intern.rs b/crates/compiler/mono/src/layout/intern.rs index ae3a5d8f99..54aa41aa91 100644 --- a/crates/compiler/mono/src/layout/intern.rs +++ b/crates/compiler/mono/src/layout/intern.rs @@ -67,6 +67,43 @@ cache_interned_layouts! { ; 18 } +macro_rules! impl_to_from_int_width { + ($($int_width:path => $layout:path,)*) => { + impl<'a> Layout<'a> { + pub const fn int_width(w: IntWidth) -> InLayout<'static> { + match w { + $($int_width => $layout,)* + } + } + } + + impl<'a> InLayout<'a> { + /// # Panics + /// + /// Panics if the layout is not an integer + pub fn to_int_width(&self) -> IntWidth { + match self { + $(&$layout => $int_width,)* + _ => roc_error_macros::internal_error!("not an integer layout!") + } + } + } + }; +} + +impl_to_from_int_width! { + IntWidth::U8 => Layout::U8, + IntWidth::U16 => Layout::U16, + IntWidth::U32 => Layout::U32, + IntWidth::U64 => Layout::U64, + IntWidth::U128 => Layout::U128, + IntWidth::I8 => Layout::I8, + IntWidth::I16 => Layout::I16, + IntWidth::I32 => Layout::I32, + IntWidth::I64 => Layout::I64, + IntWidth::I128 => Layout::I128, +} + impl<'a> Layout<'a> { pub(super) const VOID_NAKED: Self = Layout::Union(UnionLayout::NonRecursive(&[])); pub(super) const UNIT_NAKED: Self = Layout::Struct { @@ -74,20 +111,6 @@ impl<'a> Layout<'a> { field_order_hash: FieldOrderHash::ZERO_FIELD_HASH, }; - pub const fn int_width(w: IntWidth) -> InLayout<'static> { - match w { - IntWidth::U8 => Self::U8, - IntWidth::U16 => Self::U16, - IntWidth::U32 => Self::U32, - IntWidth::U64 => Self::U64, - IntWidth::U128 => Self::U128, - IntWidth::I8 => Self::I8, - IntWidth::I16 => Self::I16, - IntWidth::I32 => Self::I32, - IntWidth::I64 => Self::I64, - IntWidth::I128 => Self::I128, - } - } pub const fn float_width(w: FloatWidth) -> InLayout<'static> { match w { FloatWidth::F32 => Self::F32, @@ -148,6 +171,11 @@ pub trait LayoutInterner<'a>: Sized { self.get(layout).is_refcounted() } + fn is_passed_by_reference(&self, layout: InLayout<'a>) -> bool { + self.get(layout) + .is_passed_by_reference(self, self.target_info()) + } + fn runtime_representation(&self, layout: InLayout<'a>) -> Layout<'a> { self.get(layout).runtime_representation(self) } @@ -156,6 +184,10 @@ pub trait LayoutInterner<'a>: Sized { Layout::runtime_representation_in(layout, self) } + fn safe_to_memcpy(&self, layout: InLayout<'a>) -> bool { + self.get(layout).safe_to_memcpy(self) + } + fn to_doc<'b, D, A>( &self, layout: InLayout<'a>,