From ee7f1e39c78858c3d06ed01698dbb7902988f017 Mon Sep 17 00:00:00 2001 From: Brendan Hansknecht Date: Sat, 20 Jul 2024 19:17:11 -0700 Subject: [PATCH] move all allocas to the entry block --- crates/compiler/gen_llvm/src/llvm/bitcode.rs | 76 ++------ crates/compiler/gen_llvm/src/llvm/build.rs | 171 +++++++----------- .../compiler/gen_llvm/src/llvm/build_list.rs | 27 +-- crates/compiler/gen_llvm/src/llvm/compare.rs | 8 +- crates/compiler/gen_llvm/src/llvm/expect.rs | 6 +- crates/compiler/gen_llvm/src/llvm/lowlevel.rs | 47 ++--- .../compiler/gen_llvm/src/llvm/refcounting.rs | 7 +- crates/compiler/gen_llvm/src/llvm/struct_.rs | 4 +- 8 files changed, 116 insertions(+), 230 deletions(-) diff --git a/crates/compiler/gen_llvm/src/llvm/bitcode.rs b/crates/compiler/gen_llvm/src/llvm/bitcode.rs index cec013529e..14408ad3fa 100644 --- a/crates/compiler/gen_llvm/src/llvm/bitcode.rs +++ b/crates/compiler/gen_llvm/src/llvm/bitcode.rs @@ -72,18 +72,8 @@ fn call_bitcode_fn_help<'ctx>( .map(|x| { if env.target.operating_system() == roc_target::OperatingSystem::Windows { if x.get_type() == env.context.i128_type().into() { - let parent = env - .builder - .get_insert_block() - .and_then(|b| b.get_parent()) - .unwrap(); - - let alloca = create_entry_block_alloca( - env, - parent, - x.get_type(), - "pass_u128_by_reference", - ); + let alloca = + create_entry_block_alloca(env, x.get_type(), "pass_u128_by_reference"); env.builder.build_store(alloca, *x).unwrap(); @@ -163,7 +153,8 @@ pub fn call_bitcode_fn_fixing_for_convention<'a, 'ctx, 'env>( // when we write an i128 into this (happens in NumToInt), zig expects this pointer to // be 16-byte aligned. Not doing so is UB and will immediately fail on CI - let cc_return_value_ptr = env.builder.new_build_alloca(cc_return_type, "return_value"); + let cc_return_value_ptr = + create_entry_block_alloca(env, cc_return_type, "return_value"); cc_return_value_ptr .as_instruction() .unwrap() @@ -818,14 +809,7 @@ impl BitcodeReturns { BitcodeReturns::List => { let list_type = super::convert::zig_list_type(env); - let parent = env - .builder - .get_insert_block() - .and_then(|b| b.get_parent()) - .unwrap(); - - let result = - create_entry_block_alloca(env, parent, list_type.into(), "list_alloca"); + let result = create_entry_block_alloca(env, list_type, "list_alloca"); arguments.push(result.into()); @@ -834,13 +818,7 @@ impl BitcodeReturns { BitcodeReturns::Str => { let str_type = super::convert::zig_str_type(env); - let parent = env - .builder - .get_insert_block() - .and_then(|b| b.get_parent()) - .unwrap(); - - let result = create_entry_block_alloca(env, parent, str_type.into(), "str_alloca"); + let result = create_entry_block_alloca(env, str_type, "str_alloca"); arguments.push(result.into()); @@ -957,14 +935,8 @@ pub(crate) fn pass_list_to_zig_64bit<'ctx>( env: &Env<'_, 'ctx, '_>, list: BasicValueEnum<'ctx>, ) -> PointerValue<'ctx> { - let parent = env - .builder - .get_insert_block() - .and_then(|b| b.get_parent()) - .unwrap(); - let list_type = super::convert::zig_list_type(env); - let list_alloca = create_entry_block_alloca(env, parent, list_type.into(), "list_alloca"); + let list_alloca = create_entry_block_alloca(env, list_type, "list_alloca"); env.builder.new_build_store(list_alloca, list); @@ -975,14 +947,8 @@ pub(crate) fn pass_list_to_zig_wasm<'ctx>( env: &Env<'_, 'ctx, '_>, list: BasicValueEnum<'ctx>, ) -> PointerValue<'ctx> { - let parent = env - .builder - .get_insert_block() - .and_then(|b| b.get_parent()) - .unwrap(); - let list_type = super::convert::zig_list_type(env); - let list_alloca = create_entry_block_alloca(env, parent, list_type.into(), "list_alloca"); + let list_alloca = create_entry_block_alloca(env, list_type, "list_alloca"); env.builder.new_build_store(list_alloca, list); @@ -993,14 +959,8 @@ pub(crate) fn pass_string_to_zig_wasm<'ctx>( env: &Env<'_, 'ctx, '_>, string: BasicValueEnum<'ctx>, ) -> PointerValue<'ctx> { - let parent = env - .builder - .get_insert_block() - .and_then(|b| b.get_parent()) - .unwrap(); - let string_type = super::convert::zig_str_type(env); - let string_alloca = create_entry_block_alloca(env, parent, string_type.into(), "string_alloca"); + let string_alloca = create_entry_block_alloca(env, string_type, "string_alloca"); env.builder.new_build_store(string_alloca, string); @@ -1225,9 +1185,7 @@ pub(crate) fn call_bitcode_fn_with_record_arg<'ctx>( arg: BasicValueEnum<'ctx>, fn_name: &str, ) -> BasicValueEnum<'ctx> { - let roc_call_alloca = env - .builder - .new_build_alloca(arg.get_type(), "roc_call_alloca"); + let roc_call_alloca = create_entry_block_alloca(env, arg.get_type(), "roc_call_alloca"); env.builder.new_build_store(roc_call_alloca, arg); let fn_val = env.module.get_function(fn_name).unwrap(); @@ -1235,9 +1193,7 @@ pub(crate) fn call_bitcode_fn_with_record_arg<'ctx>( let mut args: Vec> = Vec::with_capacity(fn_val.count_params() as usize); if fn_val.get_first_param().unwrap().is_pointer_value() { // call by pointer - let zig_call_alloca = env - .builder - .new_build_alloca(arg.get_type(), "zig_return_alloca"); + let zig_call_alloca = create_entry_block_alloca(env, arg.get_type(), "zig_return_alloca"); env.builder.new_build_store(zig_call_alloca, arg); args.push(zig_call_alloca.into()); } else if fn_val.count_params() == 1 { @@ -1283,16 +1239,14 @@ pub(crate) fn call_bitcode_fn_returning_record<'ctx>( .module .get_struct_type(bitcode_return_type_name) .unwrap(); - zig_return_alloca = env - .builder - .new_build_alloca(bitcode_return_type, "zig_return_alloca"); + zig_return_alloca = + create_entry_block_alloca(env, bitcode_return_type, "zig_return_alloca"); call_void_bitcode_fn(env, &[zig_return_alloca.into(), arg], fn_name); } else { // direct return let zig_result = call_bitcode_fn(env, &[arg], fn_name); - zig_return_alloca = env - .builder - .new_build_alloca(zig_result.get_type(), "zig_return_alloca"); + zig_return_alloca = + create_entry_block_alloca(env, zig_result.get_type(), "zig_return_alloca"); env.builder.new_build_store(zig_return_alloca, zig_result); } diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index 83d04ab780..f673ab828d 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -936,9 +936,7 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> { match env.target.ptr_width() { PtrWidth::Bytes4 => { // we need to pass the string by reference, but we currently hold the value. - let alloca = env - .builder - .new_build_alloca(string.get_type(), "alloca_string"); + let alloca = create_entry_block_alloca(env, string.get_type(), "alloca_string"); env.builder.new_build_store(alloca, string); alloca.into() } @@ -1345,7 +1343,6 @@ fn float_with_precision<'ctx>( pub fn build_exp_literal<'a, 'ctx>( env: &Env<'a, 'ctx, '_>, layout_interner: &STLayoutInterner<'a>, - parent: FunctionValue<'ctx>, layout: InLayout<'_>, literal: &roc_mono::ir::Literal<'a>, ) -> BasicValueEnum<'ctx> { @@ -1382,18 +1379,14 @@ pub fn build_exp_literal<'a, 'ctx>( } Bool(b) => env.context.bool_type().const_int(*b as u64, false).into(), Byte(b) => env.context.i8_type().const_int(*b as u64, false).into(), - Str(str_literal) => build_string_literal(env, parent, str_literal), + Str(str_literal) => build_string_literal(env, str_literal), } } -fn build_string_literal<'ctx>( - env: &Env<'_, 'ctx, '_>, - parent: FunctionValue<'ctx>, - str_literal: &str, -) -> BasicValueEnum<'ctx> { +fn build_string_literal<'ctx>(env: &Env<'_, 'ctx, '_>, str_literal: &str) -> BasicValueEnum<'ctx> { if str_literal.len() < env.small_str_bytes() as usize { match env.small_str_bytes() { - 24 => small_str_ptr_width_8(env, parent, str_literal).into(), + 24 => small_str_ptr_width_8(env, str_literal).into(), 12 => small_str_ptr_width_4(env, str_literal).into(), _ => unreachable!("incorrect small_str_bytes"), } @@ -1401,7 +1394,7 @@ fn build_string_literal<'ctx>( let ptr = define_global_str_literal_ptr(env, str_literal); let number_of_elements = env.ptr_int().const_int(str_literal.len() as u64, false); - let alloca = const_str_alloca_ptr(env, parent, ptr, number_of_elements, number_of_elements); + let alloca = const_str_alloca_ptr(env, ptr, number_of_elements, number_of_elements); match env.target.ptr_width() { PtrWidth::Bytes4 => { @@ -1415,7 +1408,6 @@ fn build_string_literal<'ctx>( fn const_str_alloca_ptr<'ctx>( env: &Env<'_, 'ctx, '_>, - parent: FunctionValue<'ctx>, ptr: PointerValue<'ctx>, len: IntValue<'ctx>, cap: IntValue<'ctx>, @@ -1424,18 +1416,14 @@ fn const_str_alloca_ptr<'ctx>( let value = typ.const_named_struct(&[ptr.into(), len.into(), cap.into()]); - let alloca = create_entry_block_alloca(env, parent, typ.into(), "const_str_store"); + let alloca = create_entry_block_alloca(env, typ, "const_str_store"); env.builder.new_build_store(alloca, value); alloca } -fn small_str_ptr_width_8<'ctx>( - env: &Env<'_, 'ctx, '_>, - parent: FunctionValue<'ctx>, - str_literal: &str, -) -> PointerValue<'ctx> { +fn small_str_ptr_width_8<'ctx>(env: &Env<'_, 'ctx, '_>, str_literal: &str) -> PointerValue<'ctx> { debug_assert_eq!(env.target.ptr_width() as u8, 8); let mut array = [0u8; 24]; @@ -1456,7 +1444,7 @@ fn small_str_ptr_width_8<'ctx>( let ptr_type = env.context.i8_type().ptr_type(address_space); let ptr = env.builder.new_build_int_to_ptr(ptr, ptr_type, "to_u8_ptr"); - const_str_alloca_ptr(env, parent, ptr, len, cap) + const_str_alloca_ptr(env, ptr, len, cap) } fn small_str_ptr_width_4<'ctx>(env: &Env<'_, 'ctx, '_>, str_literal: &str) -> StructValue<'ctx> { @@ -1653,7 +1641,7 @@ pub(crate) fn build_exp_expr<'a, 'ctx>( use roc_mono::ir::Expr::*; match expr { - Literal(literal) => build_exp_literal(env, layout_interner, parent, layout, literal), + Literal(literal) => build_exp_literal(env, layout_interner, layout, literal), NullPointer => { let basic_type = basic_type_from_layout(env, layout_interner, layout_interner.get_repr(layout)); @@ -1918,7 +1906,7 @@ pub(crate) fn build_exp_expr<'a, 'ctx>( EmptyArray => empty_polymorphic_list(env), Array { elem_layout, elems } => { - list_literal(env, layout_interner, parent, scope, *elem_layout, elems) + list_literal(env, layout_interner, scope, *elem_layout, elems) } RuntimeErrorFunction(_) => todo!(), @@ -2204,7 +2192,7 @@ pub(crate) fn build_exp_expr<'a, 'ctx>( layout_interner, layout_interner.get_repr(*element_layout), ); - let ptr = entry_block_alloca_zerofill(env, element_type, "stack_value"); + let ptr = create_entry_block_alloca(env, element_type, "stack_value"); if let Some(initializer) = initializer { env.builder @@ -2295,21 +2283,6 @@ fn build_wrapped_tag<'a, 'ctx>( } } -pub fn entry_block_alloca_zerofill<'ctx>( - env: &Env<'_, 'ctx, '_>, - basic_type: BasicTypeEnum<'ctx>, - name: &str, -) -> PointerValue<'ctx> { - let parent = env - .builder - .get_insert_block() - .unwrap() - .get_parent() - .unwrap(); - - create_entry_block_alloca(env, parent, basic_type, name) -} - fn build_tag_field_value<'a, 'ctx>( env: &Env<'a, 'ctx, '_>, layout_interner: &STLayoutInterner<'a>, @@ -2395,10 +2368,7 @@ fn build_tag<'a, 'ctx>( let roc_union = RocUnion::tagged_from_slices(layout_interner, env.context, tags); - let tag_alloca = env - .builder - .new_build_alloca(roc_union.struct_type(), "tag_alloca"); - + let tag_alloca = create_entry_block_alloca(env, roc_union.struct_type(), "tag_alloca"); roc_union.write_struct_data( env, layout_interner, @@ -2692,8 +2662,6 @@ pub fn get_tag_id<'a, 'ctx>( union_layout: &UnionLayout<'a>, argument: BasicValueEnum<'ctx>, ) -> IntValue<'ctx> { - let builder = env.builder; - let tag_id_layout = union_layout.tag_id_layout(); let tag_id_int_type = basic_type_from_layout( env, @@ -2728,7 +2696,7 @@ pub fn get_tag_id<'a, 'ctx>( let else_block = ctx.append_basic_block(parent, "else"); let cont_block = ctx.append_basic_block(parent, "cont"); - let result = builder.new_build_alloca(tag_id_int_type, "result"); + let result = create_entry_block_alloca(env, tag_id_int_type, "result"); env.builder .new_build_conditional_branch(is_null, then_block, else_block); @@ -2801,7 +2769,7 @@ fn lookup_at_index_ptr<'a, 'ctx>( // A recursive pointer in the loaded structure is stored as a `i64*`, but the loaded layout // might want a more precise structure. As such, cast it to the refined type if needed. - cast_if_necessary_for_opaque_recursive_pointers(env.builder, result, target_loaded_type) + cast_if_necessary_for_opaque_recursive_pointers(env, result, target_loaded_type) } fn union_field_ptr_at_index_help<'a, 'ctx>( @@ -2858,8 +2826,7 @@ fn union_field_ptr_at_index<'a, 'ctx>( // might want a more precise structure. As such, cast it to the refined type if needed. let from_value: BasicValueEnum = result.into(); let to_type: BasicTypeEnum = target_loaded_type; - cast_if_necessary_for_opaque_recursive_pointers(env.builder, from_value, to_type) - .into_pointer_value() + cast_if_necessary_for_opaque_recursive_pointers(env, from_value, to_type).into_pointer_value() } fn reserve_with_refcount_union_as_block_of_memory<'a, 'ctx>( @@ -2932,7 +2899,6 @@ pub fn allocate_with_refcount_help<'a, 'ctx, 'env>( fn list_literal<'a, 'ctx>( env: &Env<'a, 'ctx, '_>, layout_interner: &STLayoutInterner<'a>, - parent: FunctionValue<'ctx>, scope: &Scope<'a, 'ctx>, element_layout: InLayout<'a>, elems: &[ListLiteralElement], @@ -2989,13 +2955,7 @@ fn list_literal<'a, 'ctx>( for (index, element) in elems.iter().enumerate() { match element { ListLiteralElement::Literal(literal) => { - let val = build_exp_literal( - env, - layout_interner, - parent, - element_layout, - literal, - ); + let val = build_exp_literal(env, layout_interner, element_layout, literal); global_elements.push(val.into_int_value()); } ListLiteralElement::Symbol(symbol) => { @@ -3086,7 +3046,7 @@ fn list_literal<'a, 'ctx>( for (index, element) in elems.iter().enumerate() { let val = match element { ListLiteralElement::Literal(literal) => { - build_exp_literal(env, layout_interner, parent, element_layout, literal) + build_exp_literal(env, layout_interner, element_layout, literal) } ListLiteralElement::Symbol(symbol) => scope.load_symbol(symbol), }; @@ -3118,7 +3078,7 @@ pub fn load_roc_value<'a, 'ctx>( let basic_type = basic_type_from_layout(env, layout_interner, layout); if layout.is_passed_by_reference(layout_interner) { - let alloca = entry_block_alloca_zerofill(env, basic_type, name); + let alloca = create_entry_block_alloca(env, basic_type, name); store_roc_value(env, layout_interner, layout, alloca, source.into()); @@ -3136,7 +3096,7 @@ pub fn use_roc_value<'a, 'ctx>( name: &str, ) -> BasicValueEnum<'ctx> { if layout.is_passed_by_reference(layout_interner) { - let alloca = entry_block_alloca_zerofill( + let alloca = create_entry_block_alloca( env, basic_type_from_layout(env, layout_interner, layout), name, @@ -3576,8 +3536,8 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>( remainder, } => { if env.mode.runs_expects() { - let location = build_string_literal(env, parent, source_location); - let source = build_string_literal(env, parent, source); + let location = build_string_literal(env, source_location); + let source = build_string_literal(env, source); let message = scope.load_symbol(symbol); env.call_dbg(env, location, source, message); } @@ -3644,7 +3604,7 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>( } roc_target::PtrWidth::Bytes4 => { // temporary WASM implementation - throw_internal_exception(env, parent, "An expectation failed!"); + throw_internal_exception(env, "An expectation failed!"); } } } else { @@ -3712,7 +3672,7 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>( } roc_target::PtrWidth::Bytes4 => { // temporary WASM implementation - throw_internal_exception(env, parent, "An expectation failed!"); + throw_internal_exception(env, "An expectation failed!"); } } } else { @@ -3844,7 +3804,7 @@ fn equivalent_type_constructors(t1: &BasicTypeEnum, t2: &BasicTypeEnum) -> bool /// This will no longer be necessary and should be removed after we employ opaque pointers from /// LLVM. pub fn cast_if_necessary_for_opaque_recursive_pointers<'ctx>( - builder: &Builder<'ctx>, + env: &Env<'_, 'ctx, '_>, from_value: BasicValueEnum<'ctx>, to_type: BasicTypeEnum<'ctx>, ) -> BasicValueEnum<'ctx> { @@ -3853,7 +3813,7 @@ pub fn cast_if_necessary_for_opaque_recursive_pointers<'ctx>( && equivalent_type_constructors(&from_value.get_type(), &to_type) { complex_bitcast( - builder, + env, from_value, to_type, "bitcast_for_opaque_recursive_pointer", @@ -3865,39 +3825,33 @@ pub fn cast_if_necessary_for_opaque_recursive_pointers<'ctx>( /// Cast a value to another value of the same (or smaller?) size pub fn cast_basic_basic<'ctx>( - builder: &Builder<'ctx>, + env: &Env<'_, 'ctx, '_>, from_value: BasicValueEnum<'ctx>, to_type: BasicTypeEnum<'ctx>, ) -> BasicValueEnum<'ctx> { - complex_bitcast(builder, from_value, to_type, "cast_basic_basic") + complex_bitcast(env, from_value, to_type, "cast_basic_basic") } pub fn complex_bitcast_struct_struct<'ctx>( - builder: &Builder<'ctx>, + env: &Env<'_, 'ctx, '_>, from_value: StructValue<'ctx>, to_type: StructType<'ctx>, name: &str, ) -> StructValue<'ctx> { - complex_bitcast(builder, from_value.into(), to_type.into(), name).into_struct_value() + complex_bitcast(env, from_value.into(), to_type.into(), name).into_struct_value() } pub fn cast_block_of_memory_to_tag<'ctx>( - builder: &Builder<'ctx>, + env: &Env<'_, 'ctx, '_>, from_value: StructValue<'ctx>, to_type: BasicTypeEnum<'ctx>, ) -> StructValue<'ctx> { - complex_bitcast( - builder, - from_value.into(), - to_type, - "block_of_memory_to_tag", - ) - .into_struct_value() + complex_bitcast(env, from_value.into(), to_type, "block_of_memory_to_tag").into_struct_value() } /// Cast a value to another value of the same (or smaller?) size pub fn complex_bitcast<'ctx>( - builder: &Builder<'ctx>, + env: &Env<'_, 'ctx, '_>, from_value: BasicValueEnum<'ctx>, to_type: BasicTypeEnum<'ctx>, name: &str, @@ -3908,7 +3862,8 @@ pub fn complex_bitcast<'ctx>( // we can't use the more straightforward bitcast in all cases // it seems like a bitcast only works on integers and pointers // and crucially does not work not on arrays - return builder + return env + .builder .new_build_pointer_cast( from_value.into_pointer_value(), to_type.into_pointer_type(), @@ -3917,7 +3872,7 @@ pub fn complex_bitcast<'ctx>( .into(); } - complex_bitcast_from_bigger_than_to(builder, from_value, to_type, name) + complex_bitcast_from_bigger_than_to(env, from_value, to_type, name) } /// Check the size of the input and output types. Pretending we have more bytes at a pointer than @@ -3965,14 +3920,14 @@ pub fn complex_bitcast_check_size<'ctx>( let then_answer = { env.builder.position_at_end(then_block); - let result = complex_bitcast_from_bigger_than_to(env.builder, from_value, to_type, name); + let result = complex_bitcast_from_bigger_than_to(env, from_value, to_type, name); env.builder.new_build_unconditional_branch(cont_block); result }; let else_answer = { env.builder.position_at_end(else_block); - let result = complex_bitcast_to_bigger_than_from(env.builder, from_value, to_type, name); + let result = complex_bitcast_to_bigger_than_from(env, from_value, to_type, name); env.builder.new_build_unconditional_branch(cont_block); result }; @@ -3987,13 +3942,15 @@ pub fn complex_bitcast_check_size<'ctx>( } fn complex_bitcast_from_bigger_than_to<'ctx>( - builder: &Builder<'ctx>, + env: &Env<'_, 'ctx, '_>, from_value: BasicValueEnum<'ctx>, to_type: BasicTypeEnum<'ctx>, name: &str, ) -> BasicValueEnum<'ctx> { + let builder = env.builder; + // store the value in memory - let argument_pointer = builder.new_build_alloca(from_value.get_type(), "cast_alloca"); + let argument_pointer = create_entry_block_alloca(env, from_value.get_type(), "cast_alloca"); builder.new_build_store(argument_pointer, from_value); // then read it back as a different type @@ -4007,15 +3964,16 @@ fn complex_bitcast_from_bigger_than_to<'ctx>( } fn complex_bitcast_to_bigger_than_from<'ctx>( - builder: &Builder<'ctx>, + env: &Env<'_, 'ctx, '_>, from_value: BasicValueEnum<'ctx>, to_type: BasicTypeEnum<'ctx>, name: &str, ) -> BasicValueEnum<'ctx> { + let builder = env.builder; // reserve space in memory with the return type. This way, if the return type is bigger // than the input type, we don't access invalid memory when later taking a pointer to // the cast value - let storage = builder.new_build_alloca(to_type, "cast_alloca"); + let storage = create_entry_block_alloca(env, to_type, "cast_alloca"); // then cast the pointer to our desired type let from_type_pointer = builder.new_build_pointer_cast( @@ -4035,7 +3993,7 @@ fn complex_bitcast_to_bigger_than_from<'ctx>( /// get the tag id out of a pointer to a wrapped (i.e. stores the tag id at runtime) layout fn get_tag_id_wrapped<'a, 'ctx>( - env: &Env<'a, 'ctx, '_>, + env: &Env<'_, 'ctx, '_>, layout_interner: &STLayoutInterner<'a>, union_layout: UnionLayout<'a>, from_value: PointerValue<'ctx>, @@ -4308,12 +4266,18 @@ fn build_switch_ir<'a, 'ctx>( } /// Creates a new stack allocation instruction in the entry block of the function. -pub fn create_entry_block_alloca<'ctx>( +pub fn create_entry_block_alloca<'ctx, T: BasicType<'ctx>>( env: &Env<'_, 'ctx, '_>, - parent: FunctionValue<'_>, - basic_type: BasicTypeEnum<'ctx>, + basic_type: T, name: &str, ) -> PointerValue<'ctx> { + let parent = env + .builder + .get_insert_block() + .expect("builder to be in a block") + .get_parent() + .expect("block to be in a function"); + let builder = env.context.create_builder(); let entry = parent.get_first_basic_block().unwrap(); @@ -5212,7 +5176,7 @@ fn set_jump_and_catch_long_jump<'a, 'ctx>( RocReturn::from_layout(layout_interner, layout) }; let call_result_type = roc_call_result_type(env, return_type.as_basic_type_enum()); - let result_alloca = builder.new_build_alloca(call_result_type, "result"); + let result_alloca = create_entry_block_alloca(env, call_result_type, "result"); let then_block = context.append_basic_block(parent, "then_block"); let catch_block = context.append_basic_block(parent, "catch_block"); @@ -6392,7 +6356,7 @@ fn call_roc_function_help<'a, 'ctx>( arguments.pop(); let result_type = basic_type_from_layout(env, layout_interner, result_layout); - let result_alloca = env.builder.new_build_alloca(result_type, "result_value"); + let result_alloca = create_entry_block_alloca(env, result_type, "result_value"); arguments.push(result_alloca.into()); @@ -6410,7 +6374,7 @@ fn call_roc_function_help<'a, 'ctx>( let mut arguments = Vec::from_iter_in(it, env.arena); let result_type = basic_type_from_layout(env, layout_interner, result_layout); - let result_alloca = entry_block_alloca_zerofill(env, result_type, "result_value"); + let result_alloca = create_entry_block_alloca(env, result_type, "result_value"); arguments.push(result_alloca.into()); @@ -6494,9 +6458,7 @@ pub(crate) fn roc_function_call<'a, 'ctx>( layout_interner.get_repr(lambda_set.runtime_representation()), ); - let closure_data_ptr = env - .builder - .new_build_alloca(closure_data_type, "closure_data_ptr"); + let closure_data_ptr = create_entry_block_alloca(env, closure_data_type, "closure_data_ptr"); store_roc_value( env, @@ -6864,7 +6826,9 @@ fn build_foreign_symbol<'a, 'ctx>( Vec::with_capacity_in(fastcc_parameters.len() + 1, env.arena); let return_pointer = match roc_return { - RocReturn::Return => env.builder.new_build_alloca(return_type, "return_value"), + RocReturn::Return => { + create_entry_block_alloca(env, return_type, "return_value") + } RocReturn::ByPointer => fastcc_parameters.pop().unwrap().into_pointer_value(), }; @@ -6882,9 +6846,8 @@ fn build_foreign_symbol<'a, 'ctx>( // we need to pass this value by-reference; put it into an alloca // and bitcast the reference - let param_alloca = env - .builder - .new_build_alloca(param.get_type(), "param_alloca"); + let param_alloca = + create_entry_block_alloca(env, param.get_type(), "param_alloca"); env.builder.new_build_store(param_alloca, param); let as_cc_type = env.builder.new_build_pointer_cast( @@ -7042,14 +7005,10 @@ fn define_global_str_literal<'ctx>( } } -pub(crate) fn throw_internal_exception<'ctx>( - env: &Env<'_, 'ctx, '_>, - parent: FunctionValue<'ctx>, - message: &str, -) { +pub(crate) fn throw_internal_exception<'ctx>(env: &Env<'_, 'ctx, '_>, message: &str) { let builder = env.builder; - let str = build_string_literal(env, parent, message); + let str = build_string_literal(env, message); env.call_panic(env, str, CrashTag::Roc); diff --git a/crates/compiler/gen_llvm/src/llvm/build_list.rs b/crates/compiler/gen_llvm/src/llvm/build_list.rs index 6bd6cd73db..d2ad307804 100644 --- a/crates/compiler/gen_llvm/src/llvm/build_list.rs +++ b/crates/compiler/gen_llvm/src/llvm/build_list.rs @@ -34,14 +34,8 @@ pub(crate) fn list_symbol_to_c_abi<'a, 'ctx>( scope: &Scope<'a, 'ctx>, symbol: Symbol, ) -> PointerValue<'ctx> { - let parent = env - .builder - .get_insert_block() - .and_then(|b| b.get_parent()) - .unwrap(); - let list_type = zig_list_type(env); - let list_alloca = create_entry_block_alloca(env, parent, list_type.into(), "list_alloca"); + let list_alloca = create_entry_block_alloca(env, list_type, "list_alloca"); let list = scope.load_symbol(&symbol); env.builder.new_build_store(list_alloca, list); @@ -67,9 +61,7 @@ fn pass_element_as_opaque<'a, 'ctx>( ) -> BasicValueEnum<'ctx> { let element_type = basic_type_from_layout(env, layout_interner, layout_interner.get_repr(layout)); - let element_ptr = env - .builder - .new_build_alloca(element_type, "element_to_pass_as_opaque"); + let element_ptr = create_entry_block_alloca(env, element_type, "element_to_pass_as_opaque"); store_roc_value( env, layout_interner, @@ -165,7 +157,7 @@ pub(crate) fn list_get_unsafe<'a, 'ctx>( let elem_index = builder.new_build_int_cast(elem_index, env.ptr_int(), "u64_to_usize"); let ptr_type = elem_type.ptr_type(AddressSpace::default()); // Load the pointer to the array data - let array_data_ptr = load_list_ptr(builder, wrapper_struct, ptr_type); + let array_data_ptr = load_list_ptr(env, wrapper_struct, ptr_type); // Assume the bounds have already been checked earlier // (e.g. by List.get or List.first, which wrap List.#getUnsafe) @@ -404,9 +396,7 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx>( layout_interner, layout_interner.get_repr(element_layout), ); - let element_ptr = env - .builder - .new_build_alloca(element_type, "output_element_as_opaque"); + let element_ptr = create_entry_block_alloca(env, element_type, "output_element_as_opaque"); // Assume the bounds have already been checked earlier // (e.g. by List.replace or List.set, which wrap List.#replaceUnsafe) @@ -657,7 +647,7 @@ where let zero = env.ptr_int().const_zero(); // allocate a stack slot for the current index - let index_alloca = builder.new_build_alloca(env.ptr_int(), index_name); + let index_alloca = create_entry_block_alloca(env, env.ptr_int(), index_name); builder.new_build_store(index_alloca, zero); let loop_bb = ctx.append_basic_block(parent, "loop"); @@ -698,18 +688,19 @@ pub(crate) fn empty_polymorphic_list<'ctx>(env: &Env<'_, 'ctx, '_>) -> BasicValu } pub(crate) fn load_list_ptr<'ctx>( - builder: &Builder<'ctx>, + env: &Env<'_, 'ctx, '_>, wrapper_struct: StructValue<'ctx>, ptr_type: PointerType<'ctx>, ) -> PointerValue<'ctx> { // a `*mut u8` pointer - let generic_ptr = builder + let generic_ptr = env + .builder .build_extract_value(wrapper_struct, Builtin::WRAPPER_PTR, "read_list_ptr") .unwrap() .into_pointer_value(); // cast to the expected pointer type - cast_basic_basic(builder, generic_ptr.into(), ptr_type.into()).into_pointer_value() + cast_basic_basic(env, generic_ptr.into(), ptr_type.into()).into_pointer_value() } pub(crate) fn allocate_list<'a, 'ctx>( diff --git a/crates/compiler/gen_llvm/src/llvm/compare.rs b/crates/compiler/gen_llvm/src/llvm/compare.rs index 3d1b5e771b..976e50aed6 100644 --- a/crates/compiler/gen_llvm/src/llvm/compare.rs +++ b/crates/compiler/gen_llvm/src/llvm/compare.rs @@ -14,7 +14,7 @@ use roc_mono::layout::{ Builtin, InLayout, LayoutIds, LayoutInterner, LayoutRepr, STLayoutInterner, UnionLayout, }; -use super::build::{load_roc_value, BuilderExt}; +use super::build::{create_entry_block_alloca, load_roc_value, BuilderExt}; use super::convert::{argument_type_from_layout, argument_type_from_union_layout}; use super::lowlevel::dec_binop_with_unchecked; use super::struct_; @@ -529,14 +529,14 @@ fn build_list_eq_help<'a, 'ctx>( let builder = env.builder; let element_type = basic_type_from_layout(env, layout_interner, element_layout); let ptr_type = element_type.ptr_type(AddressSpace::default()); - let ptr1 = load_list_ptr(env.builder, list1, ptr_type); - let ptr2 = load_list_ptr(env.builder, list2, ptr_type); + let ptr1 = load_list_ptr(env, list1, ptr_type); + let ptr2 = load_list_ptr(env, list2, ptr_type); // we know that len1 == len2 let end = len1; // allocate a stack slot for the current index - let index_alloca = builder.new_build_alloca(env.ptr_int(), "index"); + let index_alloca = create_entry_block_alloca(env, env.ptr_int(), "index"); builder.new_build_store(index_alloca, env.ptr_int().const_zero()); let loop_bb = ctx.append_basic_block(parent, "loop"); diff --git a/crates/compiler/gen_llvm/src/llvm/expect.rs b/crates/compiler/gen_llvm/src/llvm/expect.rs index 9923531412..a51101906c 100644 --- a/crates/compiler/gen_llvm/src/llvm/expect.rs +++ b/crates/compiler/gen_llvm/src/llvm/expect.rs @@ -1,6 +1,8 @@ use crate::debug_info_init; use crate::llvm::bitcode::call_str_bitcode_fn; -use crate::llvm::build::{get_tag_id, store_roc_value, tag_pointer_clear_tag_id, Env}; +use crate::llvm::build::{ + create_entry_block_alloca, get_tag_id, store_roc_value, tag_pointer_clear_tag_id, Env, +}; use crate::llvm::build_list::{self, incrementing_elem_loop}; use crate::llvm::convert::{basic_type_from_layout, RocUnion}; use inkwell::builder::Builder; @@ -1030,7 +1032,7 @@ fn build_clone_builtin<'a, 'ctx>( ); // if the element has any pointers, we clone them to this offset - let rest_offset = bd.new_build_alloca(env.ptr_int(), "rest_offset"); + let rest_offset = create_entry_block_alloca(env, env.ptr_int(), "rest_offset"); let element_stack_size = env .ptr_int() diff --git a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs index 9e5d9adefe..c1f7b583c3 100644 --- a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs +++ b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs @@ -225,12 +225,8 @@ pub(crate) fn run_low_level<'a, 'ctx>( let return_type = zig_num_parse_result_type(env, return_type_name); - let zig_return_alloca = create_entry_block_alloca( - env, - parent, - return_type.into(), - "str_to_num", - ); + let zig_return_alloca = + create_entry_block_alloca(env, return_type, "str_to_num"); let (a, b) = pass_list_or_string_to_zig_32bit(env, string.into_struct_value()); @@ -324,7 +320,7 @@ pub(crate) fn run_low_level<'a, 'ctx>( let return_type = zig_num_parse_result_type(env, return_type_name); let zig_return_alloca = - create_entry_block_alloca(env, parent, return_type.into(), "str_to_num"); + create_entry_block_alloca(env, return_type, "str_to_num"); call_void_bitcode_fn( env, @@ -411,9 +407,8 @@ pub(crate) fn run_low_level<'a, 'ctx>( } StrFromUtf8 => { let result_type = env.module.get_struct_type("str.FromUtf8Result").unwrap(); - let result_ptr = env - .builder - .new_build_alloca(result_type, "alloca_utf8_validate_bytes_result"); + let result_ptr = + create_entry_block_alloca(env, result_type, "alloca_utf8_validate_bytes_result"); use roc_target::Architecture::*; match env.target.architecture() { @@ -947,7 +942,6 @@ pub(crate) fn run_low_level<'a, 'ctx>( build_int_unary_op( env, layout_interner, - parent, arg.into_int_value(), int_width, int_type, @@ -1396,9 +1390,7 @@ pub(crate) fn run_low_level<'a, 'ctx>( layout_interner, layout_interner.get_repr(layout), ); - let ptr = env - .builder - .new_build_alloca(basic_type, "unreachable_alloca"); + let ptr = create_entry_block_alloca(env, basic_type, "unreachable_alloca"); env.builder.new_build_store(ptr, basic_type.const_zero()); ptr.into() @@ -1933,7 +1925,7 @@ fn throw_because_overflow(env: &Env<'_, '_, '_>, message: &str) { env.builder.position_at_end(entry); // ends in unreachable, so no return is needed - throw_internal_exception(env, function_value, message); + throw_internal_exception(env, message); function_value } @@ -1973,7 +1965,7 @@ fn dec_alloca<'ctx>(env: &Env<'_, 'ctx, '_>, value: IntValue<'ctx>) -> BasicValu Windows => { let dec_type = zig_dec_type(env); - let alloca = env.builder.new_build_alloca(dec_type, "dec_alloca"); + let alloca = create_entry_block_alloca(env, dec_type, "dec_alloca"); let instruction = alloca.as_instruction_value().unwrap(); instruction.set_alignment(16).unwrap(); @@ -2079,11 +2071,7 @@ fn dec_binary_op<'ctx>( fn_name, ); - let block = env.builder.get_insert_block().expect("to be in a function"); - let parent = block.get_parent().expect("to be in a function"); - - let ptr = - create_entry_block_alloca(env, parent, env.context.i128_type().into(), "to_i128"); + let ptr = create_entry_block_alloca(env, env.context.i128_type(), "to_i128"); env.builder.build_store(ptr, lowr_highr).unwrap(); env.builder @@ -2109,7 +2097,7 @@ fn dec_binop_with_overflow<'ctx>( let rhs = rhs.into_int_value(); let return_type = zig_with_overflow_roc_dec(env); - let return_alloca = env.builder.new_build_alloca(return_type, "return_alloca"); + let return_alloca = create_entry_block_alloca(env, return_type, "return_alloca"); match env.target { Target::LinuxX32 | Target::LinuxX64 | Target::MacX64 => { @@ -2195,7 +2183,7 @@ fn change_with_overflow_to_roc_type<'a, 'ctx>( layout_interner, layout_interner.get_repr(return_layout), ); - let casted = cast_basic_basic(env.builder, val.as_basic_value_enum(), return_type); + let casted = cast_basic_basic(env, val.as_basic_value_enum(), return_type); use_roc_value( env, @@ -2341,7 +2329,6 @@ fn int_type_signed_min(int_type: IntType) -> IntValue { fn build_int_unary_op<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, layout_interner: &STLayoutInterner<'a>, - parent: FunctionValue<'ctx>, arg: IntValue<'ctx>, arg_width: IntWidth, arg_int_type: IntType<'ctx>, @@ -2477,12 +2464,8 @@ fn build_int_unary_op<'a, 'ctx, 'env>( target_int_width.type_name(), ); - let zig_return_alloca = create_entry_block_alloca( - env, - parent, - return_type.into(), - "num_to_int", - ); + let zig_return_alloca = + create_entry_block_alloca(env, return_type, "num_to_int"); call_void_bitcode_fn( env, @@ -2584,7 +2567,6 @@ fn int_neg_raise_on_overflow<'ctx>( throw_internal_exception( env, - parent, "Integer negation overflowed because its argument is the minimum value", ); @@ -2615,7 +2597,6 @@ fn int_abs_raise_on_overflow<'ctx>( throw_internal_exception( env, - parent, "Integer absolute overflowed because its argument is the minimum value", ); @@ -2642,7 +2623,7 @@ fn int_abs_with_overflow<'ctx>( let bits_to_shift = int_type.get_bit_width() as u64 - 1; let shift_val = int_type.const_int(bits_to_shift, false); let shifted = bd.new_build_right_shift(arg, shift_val, true, shifted_name); - let alloca = bd.new_build_alloca(int_type, "#int_abs_help"); + let alloca = create_entry_block_alloca(env, int_type, "#int_abs_help"); // shifted = arg >>> 63 bd.new_build_store(alloca, shifted); diff --git a/crates/compiler/gen_llvm/src/llvm/refcounting.rs b/crates/compiler/gen_llvm/src/llvm/refcounting.rs index 204b4de83e..2ab51a3e9f 100644 --- a/crates/compiler/gen_llvm/src/llvm/refcounting.rs +++ b/crates/compiler/gen_llvm/src/llvm/refcounting.rs @@ -646,7 +646,7 @@ fn call_help<'ctx>( value: BasicValueEnum<'ctx>, ) -> inkwell::values::CallSiteValue<'ctx> { let value = cast_if_necessary_for_opaque_recursive_pointers( - env.builder, + env, value, function.get_params()[0].get_type(), ); @@ -1350,7 +1350,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx>( // therefore we must cast it to our desired type let union_layout = LayoutRepr::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); + let recursive_field_ptr = cast_basic_basic(env, ptr_as_i64_ptr, union_type); deferred_rec.push(recursive_field_ptr); } else if layout_interner.contains_refcounted(*field_layout) { @@ -1823,8 +1823,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx>( layout_interner, layout_interner.get_repr(union_layout), ); - let recursive_ptr_field_value = - cast_basic_basic(env.builder, field_value, union_type); + let recursive_ptr_field_value = cast_basic_basic(env, field_value, union_type); modify_refcount_layout_help( env, diff --git a/crates/compiler/gen_llvm/src/llvm/struct_.rs b/crates/compiler/gen_llvm/src/llvm/struct_.rs index caae11494f..3f4f4013d5 100644 --- a/crates/compiler/gen_llvm/src/llvm/struct_.rs +++ b/crates/compiler/gen_llvm/src/llvm/struct_.rs @@ -11,7 +11,7 @@ use roc_mono::layout::{InLayout, LayoutInterner, LayoutRepr, STLayoutInterner}; use crate::llvm::build::{load_roc_value, use_roc_value}; use super::{ - build::{store_roc_value, BuilderExt, Env}, + build::{create_entry_block_alloca, store_roc_value, BuilderExt, Env}, convert::basic_type_from_layout, scope::Scope, }; @@ -253,7 +253,7 @@ fn build_struct_alloca_helper<'a, 'ctx>( // Create the struct_type let struct_type = ctx.struct_type(field_types.into_bump_slice(), false); - let alloca = env.builder.new_build_alloca(struct_type, "struct_alloca"); + let alloca = create_entry_block_alloca(env, struct_type, "struct_alloca"); for (i, (field_expr, field_repr)) in field_expr_repr.into_iter().enumerate() { let dst =