diff --git a/compiler/gen_llvm/src/llvm/build_dict.rs b/compiler/gen_llvm/src/llvm/build_dict.rs index a134c0486c..84c4a951f5 100644 --- a/compiler/gen_llvm/src/llvm/build_dict.rs +++ b/compiler/gen_llvm/src/llvm/build_dict.rs @@ -6,7 +6,7 @@ use crate::llvm::build::{ complex_bitcast, load_symbol, load_symbol_and_layout, Env, RocFunctionCall, Scope, }; use crate::llvm::build_list::{layout_width, pass_as_opaque}; -use crate::llvm::convert::basic_type_from_layout; +use crate::llvm::convert::{basic_type_from_layout, zig_dict_type, zig_list_type}; use crate::llvm::refcounting::Mode; use inkwell::attributes::{Attribute, AttributeLoc}; use inkwell::types::BasicType; @@ -59,12 +59,11 @@ pub fn dict_len<'a, 'ctx, 'env>( // let dict_as_int = dict_symbol_to_i128(env, scope, dict_symbol); let dict_as_zig_dict = dict_symbol_to_zig_dict(env, scope, dict_symbol); - let dict_ptr = env - .builder - .build_alloca(dict_as_zig_dict.get_type(), "dict_ptr"); - env.builder.build_store(dict_ptr, dict_as_zig_dict); - - call_bitcode_fn(env, &[dict_ptr.into()], bitcode::DICT_LEN) + call_bitcode_fn( + env, + &[pass_dict_c_abi(env, dict_as_zig_dict.into())], + bitcode::DICT_LEN, + ) } Layout::Builtin(Builtin::EmptyDict) => ctx.i64_type().const_zero().into(), _ => unreachable!("Invalid layout given to Dict.len : {:?}", dict_layout), @@ -95,14 +94,11 @@ pub fn dict_insert<'a, 'ctx, 'env>( ) -> BasicValueEnum<'ctx> { let builder = env.builder; - let zig_dict_type = env.module.get_struct_type("dict.RocDict").unwrap(); let u8_ptr = env.context.i8_type().ptr_type(AddressSpace::Generic); - let dict_ptr = builder.build_alloca(zig_dict_type, "dict_ptr"); let key_ptr = builder.build_alloca(key.get_type(), "key_ptr"); let value_ptr = builder.build_alloca(value.get_type(), "value_ptr"); - env.builder.build_store(dict_ptr, dict); env.builder.build_store(key_ptr, key); env.builder.build_store(value_ptr, value); @@ -114,7 +110,7 @@ pub fn dict_insert<'a, 'ctx, 'env>( .ptr_int() .const_int(value_layout.stack_size(env.ptr_bytes) as u64, false); - let result_ptr = builder.build_alloca(zig_dict_type, "result_ptr"); + let result_ptr = builder.build_alloca(zig_dict_type(env), "result_ptr"); let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.ptr_bytes); let alignment_iv = env.context.i8_type().const_int(alignment as u64, false); @@ -128,7 +124,7 @@ pub fn dict_insert<'a, 'ctx, 'env>( call_void_bitcode_fn( env, &[ - dict_ptr.into(), + pass_dict_c_abi(env, dict), alignment_iv.into(), env.builder.build_bitcast(key_ptr, u8_ptr, "to_u8_ptr"), key_width.into(), @@ -157,13 +153,10 @@ pub fn dict_remove<'a, 'ctx, 'env>( ) -> BasicValueEnum<'ctx> { let builder = env.builder; - let zig_dict_type = env.module.get_struct_type("dict.RocDict").unwrap(); let u8_ptr = env.context.i8_type().ptr_type(AddressSpace::Generic); - let dict_ptr = builder.build_alloca(zig_dict_type, "dict_ptr"); let key_ptr = builder.build_alloca(key.get_type(), "key_ptr"); - env.builder.build_store(dict_ptr, dict); env.builder.build_store(key_ptr, key); let key_width = env @@ -174,7 +167,7 @@ pub fn dict_remove<'a, 'ctx, 'env>( .ptr_int() .const_int(value_layout.stack_size(env.ptr_bytes) as u64, false); - let result_ptr = builder.build_alloca(zig_dict_type, "result_ptr"); + let result_ptr = builder.build_alloca(zig_dict_type(env), "result_ptr"); let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.ptr_bytes); let alignment_iv = env.context.i8_type().const_int(alignment as u64, false); @@ -188,7 +181,7 @@ pub fn dict_remove<'a, 'ctx, 'env>( call_void_bitcode_fn( env, &[ - dict_ptr.into(), + pass_dict_c_abi(env, dict), alignment_iv.into(), env.builder.build_bitcast(key_ptr, u8_ptr, "to_u8_ptr"), key_width.into(), @@ -216,13 +209,10 @@ pub fn dict_contains<'a, 'ctx, 'env>( ) -> BasicValueEnum<'ctx> { let builder = env.builder; - let zig_dict_type = env.module.get_struct_type("dict.RocDict").unwrap(); let u8_ptr = env.context.i8_type().ptr_type(AddressSpace::Generic); - let dict_ptr = builder.build_alloca(zig_dict_type, "dict_ptr"); let key_ptr = builder.build_alloca(key.get_type(), "key_ptr"); - env.builder.build_store(dict_ptr, dict); env.builder.build_store(key_ptr, key); let key_width = env @@ -242,7 +232,7 @@ pub fn dict_contains<'a, 'ctx, 'env>( call_bitcode_fn( env, &[ - dict_ptr.into(), + pass_dict_c_abi(env, dict), alignment_iv.into(), env.builder.build_bitcast(key_ptr, u8_ptr, "to_u8_ptr"), key_width.into(), @@ -265,13 +255,10 @@ pub fn dict_get<'a, 'ctx, 'env>( ) -> BasicValueEnum<'ctx> { let builder = env.builder; - let zig_dict_type = env.module.get_struct_type("dict.RocDict").unwrap(); let u8_ptr = env.context.i8_type().ptr_type(AddressSpace::Generic); - let dict_ptr = builder.build_alloca(zig_dict_type, "dict_ptr"); let key_ptr = builder.build_alloca(key.get_type(), "key_ptr"); - env.builder.build_store(dict_ptr, dict); env.builder.build_store(key_ptr, key); let key_width = env @@ -294,7 +281,7 @@ pub fn dict_get<'a, 'ctx, 'env>( let result = call_bitcode_fn( env, &[ - dict_ptr.into(), + pass_dict_c_abi(env, dict), alignment_iv.into(), env.builder.build_bitcast(key_ptr, u8_ptr, "to_u8_ptr"), key_width.into(), @@ -376,13 +363,6 @@ pub fn dict_elements_rc<'a, 'ctx, 'env>( value_layout: &Layout<'a>, rc_operation: Mode, ) { - let builder = env.builder; - - let zig_dict_type = env.module.get_struct_type("dict.RocDict").unwrap(); - - let dict_ptr = builder.build_alloca(zig_dict_type, "dict_ptr"); - env.builder.build_store(dict_ptr, dict); - let key_width = env .ptr_int() .const_int(key_layout.stack_size(env.ptr_bytes) as u64, false); @@ -408,7 +388,7 @@ pub fn dict_elements_rc<'a, 'ctx, 'env>( call_void_bitcode_fn( env, &[ - dict_ptr.into(), + pass_dict_c_abi(env, dict), alignment_iv.into(), key_width.into(), value_width.into(), @@ -429,12 +409,6 @@ pub fn dict_keys<'a, 'ctx, 'env>( ) -> BasicValueEnum<'ctx> { let builder = env.builder; - let zig_dict_type = env.module.get_struct_type("dict.RocDict").unwrap(); - let zig_list_type = env.module.get_struct_type("list.RocList").unwrap(); - - let dict_ptr = builder.build_alloca(zig_dict_type, "dict_ptr"); - env.builder.build_store(dict_ptr, dict); - let key_width = env .ptr_int() .const_int(key_layout.stack_size(env.ptr_bytes) as u64, false); @@ -448,12 +422,12 @@ pub fn dict_keys<'a, 'ctx, 'env>( let inc_key_fn = build_inc_wrapper(env, layout_ids, key_layout); - let list_ptr = builder.build_alloca(zig_list_type, "list_ptr"); + let list_ptr = builder.build_alloca(zig_list_type(env), "list_ptr"); call_void_bitcode_fn( env, &[ - dict_ptr.into(), + pass_dict_c_abi(env, dict), alignment_iv.into(), key_width.into(), value_width.into(), @@ -475,6 +449,26 @@ pub fn dict_keys<'a, 'ctx, 'env>( env.builder.build_load(list_ptr, "load_keys_list") } +fn pass_dict_c_abi<'a, 'ctx, 'env>( + env: &Env<'a, 'ctx, 'env>, + dict: BasicValueEnum<'ctx>, +) -> BasicValueEnum<'ctx> { + match env.ptr_bytes { + 4 => { + let target_type = env.context.custom_width_int_type(96).into(); + + complex_bitcast(env.builder, dict, target_type, "to_i96") + } + 8 => { + let dict_ptr = env.builder.build_alloca(zig_dict_type(env), "dict_ptr"); + env.builder.build_store(dict_ptr, dict); + + dict_ptr.into() + } + _ => unreachable!(), + } +} + #[allow(clippy::too_many_arguments)] pub fn dict_union<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, @@ -486,14 +480,6 @@ pub fn dict_union<'a, 'ctx, 'env>( ) -> BasicValueEnum<'ctx> { let builder = env.builder; - let zig_dict_type = env.module.get_struct_type("dict.RocDict").unwrap(); - - let dict1_ptr = builder.build_alloca(zig_dict_type, "dict_ptr"); - let dict2_ptr = builder.build_alloca(zig_dict_type, "dict_ptr"); - - env.builder.build_store(dict1_ptr, dict1); - env.builder.build_store(dict2_ptr, dict2); - let key_width = env .ptr_int() .const_int(key_layout.stack_size(env.ptr_bytes) as u64, false); @@ -511,13 +497,13 @@ pub fn dict_union<'a, 'ctx, 'env>( let inc_key_fn = build_inc_wrapper(env, layout_ids, key_layout); let inc_value_fn = build_inc_wrapper(env, layout_ids, value_layout); - let output_ptr = builder.build_alloca(zig_dict_type, "output_ptr"); + let output_ptr = builder.build_alloca(zig_dict_type(env), "output_ptr"); call_void_bitcode_fn( env, &[ - dict1_ptr.into(), - dict2_ptr.into(), + pass_dict_c_abi(env, dict1), + pass_dict_c_abi(env, dict2), alignment_iv.into(), key_width.into(), value_width.into(), @@ -587,12 +573,6 @@ fn dict_intersect_or_difference<'a, 'ctx, 'env>( let zig_dict_type = env.module.get_struct_type("dict.RocDict").unwrap(); - let dict1_ptr = builder.build_alloca(zig_dict_type, "dict_ptr"); - let dict2_ptr = builder.build_alloca(zig_dict_type, "dict_ptr"); - - env.builder.build_store(dict1_ptr, dict1); - env.builder.build_store(dict2_ptr, dict2); - let key_width = env .ptr_int() .const_int(key_layout.stack_size(env.ptr_bytes) as u64, false); @@ -615,8 +595,8 @@ fn dict_intersect_or_difference<'a, 'ctx, 'env>( call_void_bitcode_fn( env, &[ - dict1_ptr.into(), - dict2_ptr.into(), + pass_dict_c_abi(env, dict1), + pass_dict_c_abi(env, dict2), alignment_iv.into(), key_width.into(), value_width.into(), @@ -645,10 +625,6 @@ pub fn dict_walk<'a, 'ctx, 'env>( let builder = env.builder; let u8_ptr = env.context.i8_type().ptr_type(AddressSpace::Generic); - let zig_dict_type = env.module.get_struct_type("dict.RocDict").unwrap(); - - let dict_ptr = builder.build_alloca(zig_dict_type, "dict_ptr"); - env.builder.build_store(dict_ptr, dict); let accum_bt = basic_type_from_layout(env, accum_layout); let accum_ptr = builder.build_alloca(accum_bt, "accum_ptr"); @@ -662,7 +638,7 @@ pub fn dict_walk<'a, 'ctx, 'env>( call_void_bitcode_fn( env, &[ - dict_ptr.into(), + pass_dict_c_abi(env, dict), roc_function_call.caller.into(), pass_as_opaque(env, roc_function_call.data), roc_function_call.inc_n_data.into(), @@ -690,12 +666,8 @@ pub fn dict_values<'a, 'ctx, 'env>( ) -> BasicValueEnum<'ctx> { let builder = env.builder; - let zig_dict_type = super::convert::zig_dict_type(env); let zig_list_type = super::convert::zig_list_type(env); - let dict_ptr = builder.build_alloca(zig_dict_type, "dict_ptr"); - env.builder.build_store(dict_ptr, dict); - let key_width = env .ptr_int() .const_int(key_layout.stack_size(env.ptr_bytes) as u64, false); @@ -714,7 +686,7 @@ pub fn dict_values<'a, 'ctx, 'env>( call_void_bitcode_fn( env, &[ - dict_ptr.into(), + pass_dict_c_abi(env, dict), alignment_iv.into(), key_width.into(), value_width.into(), @@ -748,7 +720,7 @@ pub fn set_from_list<'a, 'ctx, 'env>( let list_alloca = builder.build_alloca(list.get_type(), "list_alloca"); let list_ptr = env.builder.build_bitcast( list_alloca, - env.context.i128_type().ptr_type(AddressSpace::Generic), + env.str_list_c_abi().ptr_type(AddressSpace::Generic), "to_zig_list", ); @@ -865,11 +837,11 @@ fn dict_symbol_to_zig_dict<'a, 'ctx, 'env>( ) -> StructValue<'ctx> { let dict = load_symbol(scope, &symbol); - let zig_dict_type = env.module.get_struct_type("dict.RocDict").unwrap(); - - complex_bitcast(env.builder, dict, zig_dict_type.into(), "dict_to_zig_dict").into_struct_value() -} - -fn zig_dict_type<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> inkwell::types::StructType<'ctx> { - env.module.get_struct_type("dict.RocDict").unwrap() + complex_bitcast( + env.builder, + dict, + crate::llvm::convert::zig_dict_type(env).into(), + "dict_to_zig_dict", + ) + .into_struct_value() }