move all allocas to the entry block

This commit is contained in:
Brendan Hansknecht 2024-07-20 19:17:11 -07:00
parent 70fa3ecdc2
commit ee7f1e39c7
No known key found for this signature in database
GPG Key ID: 0EA784685083E75B
8 changed files with 116 additions and 230 deletions

View File

@ -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<BasicValueEnum<'ctx>> = 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);
}

View File

@ -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);

View File

@ -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>(

View File

@ -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");

View File

@ -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()

View File

@ -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);

View File

@ -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,

View File

@ -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 =