diff --git a/compiler/gen/src/llvm/build_dict.rs b/compiler/gen/src/llvm/build_dict.rs index cda4316fc1..06e0dd4e14 100644 --- a/compiler/gen/src/llvm/build_dict.rs +++ b/compiler/gen/src/llvm/build_dict.rs @@ -336,35 +336,13 @@ fn zig_dict_to_struct<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, zig_dict: StructValue<'ctx>, ) -> StructValue<'ctx> { - let builder = env.builder; - - // get the RocStr type defined by zig - let zig_str_type = env.module.get_struct_type("dict.RocDict").unwrap(); - - let ret_type = BasicTypeEnum::StructType(collection(env.context, env.ptr_bytes)); - - // a roundabout way of casting (LLVM does not accept a standard bitcast) - let allocation = builder.build_alloca(zig_str_type, "zig_result"); - - builder.build_store(allocation, zig_dict); - - let ptr3 = builder - .build_bitcast( - allocation, - env.context.i128_type().ptr_type(AddressSpace::Generic), - "cast", - ) - .into_pointer_value(); - - let ptr4 = builder - .build_bitcast( - ptr3, - ret_type.into_struct_type().ptr_type(AddressSpace::Generic), - "cast", - ) - .into_pointer_value(); - - builder.build_load(ptr4, "load").into_struct_value() + complex_bitcast( + env.builder, + zig_dict.into(), + crate::llvm::convert::dict(env.context, env.ptr_bytes).into(), + "to_zig_dict", + ) + .into_struct_value() } fn struct_to_zig_dict<'a, 'ctx, 'env>( diff --git a/compiler/gen/src/llvm/convert.rs b/compiler/gen/src/llvm/convert.rs index 5687e32b52..590776bcbf 100644 --- a/compiler/gen/src/llvm/convert.rs +++ b/compiler/gen/src/llvm/convert.rs @@ -185,7 +185,7 @@ pub fn basic_type_from_builtin<'ctx>( Float64 => context.f64_type().as_basic_type_enum(), Float32 => context.f32_type().as_basic_type_enum(), Float16 => context.f16_type().as_basic_type_enum(), - Dict(_, _) | EmptyDict => collection(context, ptr_bytes).into(), + Dict(_, _) | EmptyDict => dict(context, ptr_bytes).into(), Set(_) | EmptySet => panic!("TODO layout_to_basic_type for Builtin::Set"), List(_, _) | Str | EmptyStr => collection(context, ptr_bytes).into(), EmptyList => BasicTypeEnum::StructType(collection(context, ptr_bytes)), @@ -260,6 +260,16 @@ pub fn collection(ctx: &Context, ptr_bytes: u32) -> StructType<'_> { ctx.struct_type(&[u8_ptr.into(), usize_type.into()], false) } +pub fn dict(ctx: &Context, ptr_bytes: u32) -> StructType<'_> { + let usize_type = ptr_int(ctx, ptr_bytes); + let u8_ptr = ctx.i8_type().ptr_type(AddressSpace::Generic); + + ctx.struct_type( + &[u8_ptr.into(), usize_type.into(), usize_type.into()], + false, + ) +} + pub fn ptr_int(ctx: &Context, ptr_bytes: u32) -> IntType<'_> { match ptr_bytes { 1 => ctx.i8_type(),