diff --git a/cli/src/repl/gen.rs b/cli/src/repl/gen.rs index 200941919d..3e789da85b 100644 --- a/cli/src/repl/gen.rs +++ b/cli/src/repl/gen.rs @@ -218,8 +218,8 @@ pub fn gen_and_eval<'a>( // Verify the module if let Err(errors) = env.module.verify() { panic!( - "Errors defining module: {}\n\nUncomment things nearby to see more details.", - errors + "Errors defining module:\n{}\n\nUncomment things nearby to see more details.", + errors.to_string() ); } diff --git a/compiler/gen_llvm/src/llvm/bitcode.rs b/compiler/gen_llvm/src/llvm/bitcode.rs index 0fad482fef..2afb1c7159 100644 --- a/compiler/gen_llvm/src/llvm/bitcode.rs +++ b/compiler/gen_llvm/src/llvm/bitcode.rs @@ -154,18 +154,11 @@ fn build_has_tag_id_help<'a, 'ctx, 'env>( ); let tag_data_ptr = { - let data_index = env - .context - .i64_type() - .const_int(TAG_DATA_INDEX as u64, false); + let ptr = env + .builder + .build_struct_gep(tag_value, TAG_DATA_INDEX, "get_data_ptr") + .unwrap(); - let ptr = unsafe { - env.builder.build_gep( - tag_value_ptr.into_pointer_value(), - &[data_index], - "get_data_ptr", - ) - }; env.builder.build_bitcast(ptr, i8_ptr_type, "to_opaque") }; diff --git a/compiler/gen_llvm/src/llvm/build.rs b/compiler/gen_llvm/src/llvm/build.rs index b89096f4a5..711116bc80 100644 --- a/compiler/gen_llvm/src/llvm/build.rs +++ b/compiler/gen_llvm/src/llvm/build.rs @@ -2532,7 +2532,10 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>( if align_bytes > 0 { let value_ptr = value.into_pointer_value(); - if true { + // We can only do this if the function itself writes data into this + // pointer. If the pointer is passed as an argument, then we must copy + // from one pointer to our destination pointer + if value_ptr.get_first_use().is_some() { value_ptr.replace_all_uses_with(destination); } else { let size = env @@ -3382,8 +3385,7 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx, 'env>( // a tagged union to indicate to the test loader that a panic occurred. // especially when running 32-bit binaries on a 64-bit machine, there // does not seem to be a smarter solution - let wrapper_return_type = - roc_result_type(env, roc_function.get_type().get_return_type().unwrap()); + let wrapper_return_type = roc_result_type(env, basic_type_from_layout(env, &return_layout)); let mut cc_argument_types = Vec::with_capacity_in(arguments.len(), env.arena); for layout in arguments { @@ -3861,7 +3863,7 @@ fn make_good_roc_result<'a, 'ctx, 'env>( let context = env.context; let builder = env.builder; - let v1 = roc_result_type(env, return_value.get_type()).const_zero(); + let v1 = roc_result_type(env, basic_type_from_layout(env, &return_layout)).const_zero(); let v2 = builder .build_insert_value(v1, context.i64_type().const_zero(), 0, "set_no_error") @@ -3906,8 +3908,7 @@ fn make_exception_catching_wrapper<'a, 'ctx, 'env>( } }; - let wrapper_return_type = - roc_result_type(env, roc_function.get_type().get_return_type().unwrap()); + let wrapper_return_type = roc_result_type(env, basic_type_from_layout(env, &return_layout)); // argument_types.push(wrapper_return_type.ptr_type(AddressSpace::Generic).into()); diff --git a/compiler/gen_llvm/src/llvm/refcounting.rs b/compiler/gen_llvm/src/llvm/refcounting.rs index de55b101ff..0a956f8bce 100644 --- a/compiler/gen_llvm/src/llvm/refcounting.rs +++ b/compiler/gen_llvm/src/llvm/refcounting.rs @@ -139,8 +139,10 @@ impl<'ctx> PointerToRefcount<'ctx> { let block = env.builder.get_insert_block().expect("to be in a function"); let parent = block.get_parent().unwrap(); - let modify_block = env.context.append_basic_block(parent, "inc_str_modify"); - let cont_block = env.context.append_basic_block(parent, "inc_str_cont"); + let modify_block = env + .context + .append_basic_block(parent, "inc_refcount_modify"); + let cont_block = env.context.append_basic_block(parent, "inc_refcount_cont"); env.builder .build_conditional_branch(is_static_allocation, cont_block, modify_block); @@ -1718,12 +1720,25 @@ fn modify_refcount_union_help<'a, 'ctx, 'env>( "cast_to_concrete_tag", ); - // let wrapper_struct = cast_block_of_memory_to_tag(env.builder, data_bytes, wrapper_type); - for (i, field_layout) in field_layouts.iter().enumerate() { if let Layout::RecursivePointer = field_layout { panic!("non-recursive tag unions cannot contain naked recursion pointers!"); } else if field_layout.contains_refcounted() { + // crazy hack + match field_layout { + Layout::Builtin(Builtin::Str | Builtin::List(_)) => { + use inkwell::attributes::{Attribute, AttributeLoc}; + let kind_id = Attribute::get_named_enum_kind_id("noinline"); + debug_assert!(kind_id > 0); + let enum_attr = env.context.create_enum_attribute(kind_id, 1); + + fn_val.add_attribute(AttributeLoc::Function, enum_attr); + } + _ => { + // do nothing + } + } + let field_ptr = env .builder .build_struct_gep(cast_tag_data_pointer, i as u32, "modify_tag_field")