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| { .map(|x| {
if env.target.operating_system() == roc_target::OperatingSystem::Windows { if env.target.operating_system() == roc_target::OperatingSystem::Windows {
if x.get_type() == env.context.i128_type().into() { if x.get_type() == env.context.i128_type().into() {
let parent = env let alloca =
.builder create_entry_block_alloca(env, x.get_type(), "pass_u128_by_reference");
.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",
);
env.builder.build_store(alloca, *x).unwrap(); 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 // 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 // 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 cc_return_value_ptr
.as_instruction() .as_instruction()
.unwrap() .unwrap()
@ -818,14 +809,7 @@ impl BitcodeReturns {
BitcodeReturns::List => { BitcodeReturns::List => {
let list_type = super::convert::zig_list_type(env); let list_type = super::convert::zig_list_type(env);
let parent = env let result = create_entry_block_alloca(env, list_type, "list_alloca");
.builder
.get_insert_block()
.and_then(|b| b.get_parent())
.unwrap();
let result =
create_entry_block_alloca(env, parent, list_type.into(), "list_alloca");
arguments.push(result.into()); arguments.push(result.into());
@ -834,13 +818,7 @@ impl BitcodeReturns {
BitcodeReturns::Str => { BitcodeReturns::Str => {
let str_type = super::convert::zig_str_type(env); let str_type = super::convert::zig_str_type(env);
let parent = env let result = create_entry_block_alloca(env, str_type, "str_alloca");
.builder
.get_insert_block()
.and_then(|b| b.get_parent())
.unwrap();
let result = create_entry_block_alloca(env, parent, str_type.into(), "str_alloca");
arguments.push(result.into()); arguments.push(result.into());
@ -957,14 +935,8 @@ pub(crate) fn pass_list_to_zig_64bit<'ctx>(
env: &Env<'_, 'ctx, '_>, env: &Env<'_, 'ctx, '_>,
list: BasicValueEnum<'ctx>, list: BasicValueEnum<'ctx>,
) -> PointerValue<'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_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); env.builder.new_build_store(list_alloca, list);
@ -975,14 +947,8 @@ pub(crate) fn pass_list_to_zig_wasm<'ctx>(
env: &Env<'_, 'ctx, '_>, env: &Env<'_, 'ctx, '_>,
list: BasicValueEnum<'ctx>, list: BasicValueEnum<'ctx>,
) -> PointerValue<'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_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); env.builder.new_build_store(list_alloca, list);
@ -993,14 +959,8 @@ pub(crate) fn pass_string_to_zig_wasm<'ctx>(
env: &Env<'_, 'ctx, '_>, env: &Env<'_, 'ctx, '_>,
string: BasicValueEnum<'ctx>, string: BasicValueEnum<'ctx>,
) -> PointerValue<'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_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); 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>, arg: BasicValueEnum<'ctx>,
fn_name: &str, fn_name: &str,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let roc_call_alloca = env let roc_call_alloca = create_entry_block_alloca(env, arg.get_type(), "roc_call_alloca");
.builder
.new_build_alloca(arg.get_type(), "roc_call_alloca");
env.builder.new_build_store(roc_call_alloca, arg); env.builder.new_build_store(roc_call_alloca, arg);
let fn_val = env.module.get_function(fn_name).unwrap(); 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); 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() { if fn_val.get_first_param().unwrap().is_pointer_value() {
// call by pointer // call by pointer
let zig_call_alloca = env let zig_call_alloca = create_entry_block_alloca(env, arg.get_type(), "zig_return_alloca");
.builder
.new_build_alloca(arg.get_type(), "zig_return_alloca");
env.builder.new_build_store(zig_call_alloca, arg); env.builder.new_build_store(zig_call_alloca, arg);
args.push(zig_call_alloca.into()); args.push(zig_call_alloca.into());
} else if fn_val.count_params() == 1 { } else if fn_val.count_params() == 1 {
@ -1283,16 +1239,14 @@ pub(crate) fn call_bitcode_fn_returning_record<'ctx>(
.module .module
.get_struct_type(bitcode_return_type_name) .get_struct_type(bitcode_return_type_name)
.unwrap(); .unwrap();
zig_return_alloca = env zig_return_alloca =
.builder create_entry_block_alloca(env, bitcode_return_type, "zig_return_alloca");
.new_build_alloca(bitcode_return_type, "zig_return_alloca");
call_void_bitcode_fn(env, &[zig_return_alloca.into(), arg], fn_name); call_void_bitcode_fn(env, &[zig_return_alloca.into(), arg], fn_name);
} else { } else {
// direct return // direct return
let zig_result = call_bitcode_fn(env, &[arg], fn_name); let zig_result = call_bitcode_fn(env, &[arg], fn_name);
zig_return_alloca = env zig_return_alloca =
.builder create_entry_block_alloca(env, zig_result.get_type(), "zig_return_alloca");
.new_build_alloca(zig_result.get_type(), "zig_return_alloca");
env.builder.new_build_store(zig_return_alloca, zig_result); 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() { match env.target.ptr_width() {
PtrWidth::Bytes4 => { PtrWidth::Bytes4 => {
// we need to pass the string by reference, but we currently hold the value. // we need to pass the string by reference, but we currently hold the value.
let alloca = env let alloca = create_entry_block_alloca(env, string.get_type(), "alloca_string");
.builder
.new_build_alloca(string.get_type(), "alloca_string");
env.builder.new_build_store(alloca, string); env.builder.new_build_store(alloca, string);
alloca.into() alloca.into()
} }
@ -1345,7 +1343,6 @@ fn float_with_precision<'ctx>(
pub fn build_exp_literal<'a, 'ctx>( pub fn build_exp_literal<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>, env: &Env<'a, 'ctx, '_>,
layout_interner: &STLayoutInterner<'a>, layout_interner: &STLayoutInterner<'a>,
parent: FunctionValue<'ctx>,
layout: InLayout<'_>, layout: InLayout<'_>,
literal: &roc_mono::ir::Literal<'a>, literal: &roc_mono::ir::Literal<'a>,
) -> BasicValueEnum<'ctx> { ) -> 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(), 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(), 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>( fn build_string_literal<'ctx>(env: &Env<'_, 'ctx, '_>, str_literal: &str) -> BasicValueEnum<'ctx> {
env: &Env<'_, 'ctx, '_>,
parent: FunctionValue<'ctx>,
str_literal: &str,
) -> BasicValueEnum<'ctx> {
if str_literal.len() < env.small_str_bytes() as usize { if str_literal.len() < env.small_str_bytes() as usize {
match env.small_str_bytes() { 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(), 12 => small_str_ptr_width_4(env, str_literal).into(),
_ => unreachable!("incorrect small_str_bytes"), _ => 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 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 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() { match env.target.ptr_width() {
PtrWidth::Bytes4 => { PtrWidth::Bytes4 => {
@ -1415,7 +1408,6 @@ fn build_string_literal<'ctx>(
fn const_str_alloca_ptr<'ctx>( fn const_str_alloca_ptr<'ctx>(
env: &Env<'_, 'ctx, '_>, env: &Env<'_, 'ctx, '_>,
parent: FunctionValue<'ctx>,
ptr: PointerValue<'ctx>, ptr: PointerValue<'ctx>,
len: IntValue<'ctx>, len: IntValue<'ctx>,
cap: 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 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); env.builder.new_build_store(alloca, value);
alloca alloca
} }
fn small_str_ptr_width_8<'ctx>( fn small_str_ptr_width_8<'ctx>(env: &Env<'_, 'ctx, '_>, str_literal: &str) -> PointerValue<'ctx> {
env: &Env<'_, 'ctx, '_>,
parent: FunctionValue<'ctx>,
str_literal: &str,
) -> PointerValue<'ctx> {
debug_assert_eq!(env.target.ptr_width() as u8, 8); debug_assert_eq!(env.target.ptr_width() as u8, 8);
let mut array = [0u8; 24]; 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_type = env.context.i8_type().ptr_type(address_space);
let ptr = env.builder.new_build_int_to_ptr(ptr, ptr_type, "to_u8_ptr"); 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> { 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::*; use roc_mono::ir::Expr::*;
match 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 => { NullPointer => {
let basic_type = let basic_type =
basic_type_from_layout(env, layout_interner, layout_interner.get_repr(layout)); 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), EmptyArray => empty_polymorphic_list(env),
Array { elem_layout, elems } => { 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!(), RuntimeErrorFunction(_) => todo!(),
@ -2204,7 +2192,7 @@ pub(crate) fn build_exp_expr<'a, 'ctx>(
layout_interner, layout_interner,
layout_interner.get_repr(*element_layout), 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 { if let Some(initializer) = initializer {
env.builder 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>( fn build_tag_field_value<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>, env: &Env<'a, 'ctx, '_>,
layout_interner: &STLayoutInterner<'a>, 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 roc_union = RocUnion::tagged_from_slices(layout_interner, env.context, tags);
let tag_alloca = env let tag_alloca = create_entry_block_alloca(env, roc_union.struct_type(), "tag_alloca");
.builder
.new_build_alloca(roc_union.struct_type(), "tag_alloca");
roc_union.write_struct_data( roc_union.write_struct_data(
env, env,
layout_interner, layout_interner,
@ -2692,8 +2662,6 @@ pub fn get_tag_id<'a, 'ctx>(
union_layout: &UnionLayout<'a>, union_layout: &UnionLayout<'a>,
argument: BasicValueEnum<'ctx>, argument: BasicValueEnum<'ctx>,
) -> IntValue<'ctx> { ) -> IntValue<'ctx> {
let builder = env.builder;
let tag_id_layout = union_layout.tag_id_layout(); let tag_id_layout = union_layout.tag_id_layout();
let tag_id_int_type = basic_type_from_layout( let tag_id_int_type = basic_type_from_layout(
env, env,
@ -2728,7 +2696,7 @@ pub fn get_tag_id<'a, 'ctx>(
let else_block = ctx.append_basic_block(parent, "else"); let else_block = ctx.append_basic_block(parent, "else");
let cont_block = ctx.append_basic_block(parent, "cont"); 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 env.builder
.new_build_conditional_branch(is_null, then_block, else_block); .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 // 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. // 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>( 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. // might want a more precise structure. As such, cast it to the refined type if needed.
let from_value: BasicValueEnum = result.into(); let from_value: BasicValueEnum = result.into();
let to_type: BasicTypeEnum = target_loaded_type; let to_type: BasicTypeEnum = target_loaded_type;
cast_if_necessary_for_opaque_recursive_pointers(env.builder, from_value, to_type) cast_if_necessary_for_opaque_recursive_pointers(env, from_value, to_type).into_pointer_value()
.into_pointer_value()
} }
fn reserve_with_refcount_union_as_block_of_memory<'a, 'ctx>( 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>( fn list_literal<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>, env: &Env<'a, 'ctx, '_>,
layout_interner: &STLayoutInterner<'a>, layout_interner: &STLayoutInterner<'a>,
parent: FunctionValue<'ctx>,
scope: &Scope<'a, 'ctx>, scope: &Scope<'a, 'ctx>,
element_layout: InLayout<'a>, element_layout: InLayout<'a>,
elems: &[ListLiteralElement], elems: &[ListLiteralElement],
@ -2989,13 +2955,7 @@ fn list_literal<'a, 'ctx>(
for (index, element) in elems.iter().enumerate() { for (index, element) in elems.iter().enumerate() {
match element { match element {
ListLiteralElement::Literal(literal) => { ListLiteralElement::Literal(literal) => {
let val = build_exp_literal( let val = build_exp_literal(env, layout_interner, element_layout, literal);
env,
layout_interner,
parent,
element_layout,
literal,
);
global_elements.push(val.into_int_value()); global_elements.push(val.into_int_value());
} }
ListLiteralElement::Symbol(symbol) => { ListLiteralElement::Symbol(symbol) => {
@ -3086,7 +3046,7 @@ fn list_literal<'a, 'ctx>(
for (index, element) in elems.iter().enumerate() { for (index, element) in elems.iter().enumerate() {
let val = match element { let val = match element {
ListLiteralElement::Literal(literal) => { 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), 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); let basic_type = basic_type_from_layout(env, layout_interner, layout);
if layout.is_passed_by_reference(layout_interner) { 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()); store_roc_value(env, layout_interner, layout, alloca, source.into());
@ -3136,7 +3096,7 @@ pub fn use_roc_value<'a, 'ctx>(
name: &str, name: &str,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
if layout.is_passed_by_reference(layout_interner) { if layout.is_passed_by_reference(layout_interner) {
let alloca = entry_block_alloca_zerofill( let alloca = create_entry_block_alloca(
env, env,
basic_type_from_layout(env, layout_interner, layout), basic_type_from_layout(env, layout_interner, layout),
name, name,
@ -3576,8 +3536,8 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>(
remainder, remainder,
} => { } => {
if env.mode.runs_expects() { if env.mode.runs_expects() {
let location = build_string_literal(env, parent, source_location); let location = build_string_literal(env, source_location);
let source = build_string_literal(env, parent, source); let source = build_string_literal(env, source);
let message = scope.load_symbol(symbol); let message = scope.load_symbol(symbol);
env.call_dbg(env, location, source, message); env.call_dbg(env, location, source, message);
} }
@ -3644,7 +3604,7 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>(
} }
roc_target::PtrWidth::Bytes4 => { roc_target::PtrWidth::Bytes4 => {
// temporary WASM implementation // temporary WASM implementation
throw_internal_exception(env, parent, "An expectation failed!"); throw_internal_exception(env, "An expectation failed!");
} }
} }
} else { } else {
@ -3712,7 +3672,7 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>(
} }
roc_target::PtrWidth::Bytes4 => { roc_target::PtrWidth::Bytes4 => {
// temporary WASM implementation // temporary WASM implementation
throw_internal_exception(env, parent, "An expectation failed!"); throw_internal_exception(env, "An expectation failed!");
} }
} }
} else { } 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 /// This will no longer be necessary and should be removed after we employ opaque pointers from
/// LLVM. /// LLVM.
pub fn cast_if_necessary_for_opaque_recursive_pointers<'ctx>( pub fn cast_if_necessary_for_opaque_recursive_pointers<'ctx>(
builder: &Builder<'ctx>, env: &Env<'_, 'ctx, '_>,
from_value: BasicValueEnum<'ctx>, from_value: BasicValueEnum<'ctx>,
to_type: BasicTypeEnum<'ctx>, to_type: BasicTypeEnum<'ctx>,
) -> BasicValueEnum<'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) && equivalent_type_constructors(&from_value.get_type(), &to_type)
{ {
complex_bitcast( complex_bitcast(
builder, env,
from_value, from_value,
to_type, to_type,
"bitcast_for_opaque_recursive_pointer", "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 /// Cast a value to another value of the same (or smaller?) size
pub fn cast_basic_basic<'ctx>( pub fn cast_basic_basic<'ctx>(
builder: &Builder<'ctx>, env: &Env<'_, 'ctx, '_>,
from_value: BasicValueEnum<'ctx>, from_value: BasicValueEnum<'ctx>,
to_type: BasicTypeEnum<'ctx>, to_type: BasicTypeEnum<'ctx>,
) -> BasicValueEnum<'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>( pub fn complex_bitcast_struct_struct<'ctx>(
builder: &Builder<'ctx>, env: &Env<'_, 'ctx, '_>,
from_value: StructValue<'ctx>, from_value: StructValue<'ctx>,
to_type: StructType<'ctx>, to_type: StructType<'ctx>,
name: &str, name: &str,
) -> StructValue<'ctx> { ) -> 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>( pub fn cast_block_of_memory_to_tag<'ctx>(
builder: &Builder<'ctx>, env: &Env<'_, 'ctx, '_>,
from_value: StructValue<'ctx>, from_value: StructValue<'ctx>,
to_type: BasicTypeEnum<'ctx>, to_type: BasicTypeEnum<'ctx>,
) -> StructValue<'ctx> { ) -> StructValue<'ctx> {
complex_bitcast( complex_bitcast(env, from_value.into(), to_type, "block_of_memory_to_tag").into_struct_value()
builder,
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 /// Cast a value to another value of the same (or smaller?) size
pub fn complex_bitcast<'ctx>( pub fn complex_bitcast<'ctx>(
builder: &Builder<'ctx>, env: &Env<'_, 'ctx, '_>,
from_value: BasicValueEnum<'ctx>, from_value: BasicValueEnum<'ctx>,
to_type: BasicTypeEnum<'ctx>, to_type: BasicTypeEnum<'ctx>,
name: &str, name: &str,
@ -3908,7 +3862,8 @@ pub fn complex_bitcast<'ctx>(
// we can't use the more straightforward bitcast in all cases // we can't use the more straightforward bitcast in all cases
// it seems like a bitcast only works on integers and pointers // it seems like a bitcast only works on integers and pointers
// and crucially does not work not on arrays // and crucially does not work not on arrays
return builder return env
.builder
.new_build_pointer_cast( .new_build_pointer_cast(
from_value.into_pointer_value(), from_value.into_pointer_value(),
to_type.into_pointer_type(), to_type.into_pointer_type(),
@ -3917,7 +3872,7 @@ pub fn complex_bitcast<'ctx>(
.into(); .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 /// 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 = { let then_answer = {
env.builder.position_at_end(then_block); 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); env.builder.new_build_unconditional_branch(cont_block);
result result
}; };
let else_answer = { let else_answer = {
env.builder.position_at_end(else_block); 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); env.builder.new_build_unconditional_branch(cont_block);
result result
}; };
@ -3987,13 +3942,15 @@ pub fn complex_bitcast_check_size<'ctx>(
} }
fn complex_bitcast_from_bigger_than_to<'ctx>( fn complex_bitcast_from_bigger_than_to<'ctx>(
builder: &Builder<'ctx>, env: &Env<'_, 'ctx, '_>,
from_value: BasicValueEnum<'ctx>, from_value: BasicValueEnum<'ctx>,
to_type: BasicTypeEnum<'ctx>, to_type: BasicTypeEnum<'ctx>,
name: &str, name: &str,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let builder = env.builder;
// store the value in memory // 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); builder.new_build_store(argument_pointer, from_value);
// then read it back as a different type // 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>( fn complex_bitcast_to_bigger_than_from<'ctx>(
builder: &Builder<'ctx>, env: &Env<'_, 'ctx, '_>,
from_value: BasicValueEnum<'ctx>, from_value: BasicValueEnum<'ctx>,
to_type: BasicTypeEnum<'ctx>, to_type: BasicTypeEnum<'ctx>,
name: &str, name: &str,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let builder = env.builder;
// reserve space in memory with the return type. This way, if the return type is bigger // 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 // than the input type, we don't access invalid memory when later taking a pointer to
// the cast value // 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 // then cast the pointer to our desired type
let from_type_pointer = builder.new_build_pointer_cast( 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 /// 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>( fn get_tag_id_wrapped<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>, env: &Env<'_, 'ctx, '_>,
layout_interner: &STLayoutInterner<'a>, layout_interner: &STLayoutInterner<'a>,
union_layout: UnionLayout<'a>, union_layout: UnionLayout<'a>,
from_value: PointerValue<'ctx>, 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. /// 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, '_>, env: &Env<'_, 'ctx, '_>,
parent: FunctionValue<'_>, basic_type: T,
basic_type: BasicTypeEnum<'ctx>,
name: &str, name: &str,
) -> PointerValue<'ctx> { ) -> 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 builder = env.context.create_builder();
let entry = parent.get_first_basic_block().unwrap(); 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) RocReturn::from_layout(layout_interner, layout)
}; };
let call_result_type = roc_call_result_type(env, return_type.as_basic_type_enum()); 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 then_block = context.append_basic_block(parent, "then_block");
let catch_block = context.append_basic_block(parent, "catch_block"); let catch_block = context.append_basic_block(parent, "catch_block");
@ -6392,7 +6356,7 @@ fn call_roc_function_help<'a, 'ctx>(
arguments.pop(); arguments.pop();
let result_type = basic_type_from_layout(env, layout_interner, result_layout); 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()); 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 mut arguments = Vec::from_iter_in(it, env.arena);
let result_type = basic_type_from_layout(env, layout_interner, result_layout); 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()); 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()), layout_interner.get_repr(lambda_set.runtime_representation()),
); );
let closure_data_ptr = env let closure_data_ptr = create_entry_block_alloca(env, closure_data_type, "closure_data_ptr");
.builder
.new_build_alloca(closure_data_type, "closure_data_ptr");
store_roc_value( store_roc_value(
env, env,
@ -6864,7 +6826,9 @@ fn build_foreign_symbol<'a, 'ctx>(
Vec::with_capacity_in(fastcc_parameters.len() + 1, env.arena); Vec::with_capacity_in(fastcc_parameters.len() + 1, env.arena);
let return_pointer = match roc_return { 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(), 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 // we need to pass this value by-reference; put it into an alloca
// and bitcast the reference // and bitcast the reference
let param_alloca = env let param_alloca =
.builder create_entry_block_alloca(env, param.get_type(), "param_alloca");
.new_build_alloca(param.get_type(), "param_alloca");
env.builder.new_build_store(param_alloca, param); env.builder.new_build_store(param_alloca, param);
let as_cc_type = env.builder.new_build_pointer_cast( 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>( pub(crate) fn throw_internal_exception<'ctx>(env: &Env<'_, 'ctx, '_>, message: &str) {
env: &Env<'_, 'ctx, '_>,
parent: FunctionValue<'ctx>,
message: &str,
) {
let builder = env.builder; 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); 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>, scope: &Scope<'a, 'ctx>,
symbol: Symbol, symbol: Symbol,
) -> PointerValue<'ctx> { ) -> 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_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); let list = scope.load_symbol(&symbol);
env.builder.new_build_store(list_alloca, list); env.builder.new_build_store(list_alloca, list);
@ -67,9 +61,7 @@ fn pass_element_as_opaque<'a, 'ctx>(
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let element_type = let element_type =
basic_type_from_layout(env, layout_interner, layout_interner.get_repr(layout)); basic_type_from_layout(env, layout_interner, layout_interner.get_repr(layout));
let element_ptr = env let element_ptr = create_entry_block_alloca(env, element_type, "element_to_pass_as_opaque");
.builder
.new_build_alloca(element_type, "element_to_pass_as_opaque");
store_roc_value( store_roc_value(
env, env,
layout_interner, 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 elem_index = builder.new_build_int_cast(elem_index, env.ptr_int(), "u64_to_usize");
let ptr_type = elem_type.ptr_type(AddressSpace::default()); let ptr_type = elem_type.ptr_type(AddressSpace::default());
// Load the pointer to the array data // 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 // Assume the bounds have already been checked earlier
// (e.g. by List.get or List.first, which wrap List.#getUnsafe) // (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,
layout_interner.get_repr(element_layout), layout_interner.get_repr(element_layout),
); );
let element_ptr = env let element_ptr = create_entry_block_alloca(env, element_type, "output_element_as_opaque");
.builder
.new_build_alloca(element_type, "output_element_as_opaque");
// Assume the bounds have already been checked earlier // Assume the bounds have already been checked earlier
// (e.g. by List.replace or List.set, which wrap List.#replaceUnsafe) // (e.g. by List.replace or List.set, which wrap List.#replaceUnsafe)
@ -657,7 +647,7 @@ where
let zero = env.ptr_int().const_zero(); let zero = env.ptr_int().const_zero();
// allocate a stack slot for the current index // 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); builder.new_build_store(index_alloca, zero);
let loop_bb = ctx.append_basic_block(parent, "loop"); 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>( pub(crate) fn load_list_ptr<'ctx>(
builder: &Builder<'ctx>, env: &Env<'_, 'ctx, '_>,
wrapper_struct: StructValue<'ctx>, wrapper_struct: StructValue<'ctx>,
ptr_type: PointerType<'ctx>, ptr_type: PointerType<'ctx>,
) -> PointerValue<'ctx> { ) -> PointerValue<'ctx> {
// a `*mut u8` pointer // a `*mut u8` pointer
let generic_ptr = builder let generic_ptr = env
.builder
.build_extract_value(wrapper_struct, Builtin::WRAPPER_PTR, "read_list_ptr") .build_extract_value(wrapper_struct, Builtin::WRAPPER_PTR, "read_list_ptr")
.unwrap() .unwrap()
.into_pointer_value(); .into_pointer_value();
// cast to the expected pointer type // 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>( pub(crate) fn allocate_list<'a, 'ctx>(

View File

@ -14,7 +14,7 @@ use roc_mono::layout::{
Builtin, InLayout, LayoutIds, LayoutInterner, LayoutRepr, STLayoutInterner, UnionLayout, 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::convert::{argument_type_from_layout, argument_type_from_union_layout};
use super::lowlevel::dec_binop_with_unchecked; use super::lowlevel::dec_binop_with_unchecked;
use super::struct_; use super::struct_;
@ -529,14 +529,14 @@ fn build_list_eq_help<'a, 'ctx>(
let builder = env.builder; let builder = env.builder;
let element_type = basic_type_from_layout(env, layout_interner, element_layout); let element_type = basic_type_from_layout(env, layout_interner, element_layout);
let ptr_type = element_type.ptr_type(AddressSpace::default()); let ptr_type = element_type.ptr_type(AddressSpace::default());
let ptr1 = load_list_ptr(env.builder, list1, ptr_type); let ptr1 = load_list_ptr(env, list1, ptr_type);
let ptr2 = load_list_ptr(env.builder, list2, ptr_type); let ptr2 = load_list_ptr(env, list2, ptr_type);
// we know that len1 == len2 // we know that len1 == len2
let end = len1; let end = len1;
// allocate a stack slot for the current index // 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()); builder.new_build_store(index_alloca, env.ptr_int().const_zero());
let loop_bb = ctx.append_basic_block(parent, "loop"); let loop_bb = ctx.append_basic_block(parent, "loop");

View File

@ -1,6 +1,8 @@
use crate::debug_info_init; use crate::debug_info_init;
use crate::llvm::bitcode::call_str_bitcode_fn; 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::build_list::{self, incrementing_elem_loop};
use crate::llvm::convert::{basic_type_from_layout, RocUnion}; use crate::llvm::convert::{basic_type_from_layout, RocUnion};
use inkwell::builder::Builder; 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 // 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 let element_stack_size = env
.ptr_int() .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 return_type = zig_num_parse_result_type(env, return_type_name);
let zig_return_alloca = create_entry_block_alloca( let zig_return_alloca =
env, create_entry_block_alloca(env, return_type, "str_to_num");
parent,
return_type.into(),
"str_to_num",
);
let (a, b) = let (a, b) =
pass_list_or_string_to_zig_32bit(env, string.into_struct_value()); 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 return_type = zig_num_parse_result_type(env, return_type_name);
let zig_return_alloca = 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( call_void_bitcode_fn(
env, env,
@ -411,9 +407,8 @@ pub(crate) fn run_low_level<'a, 'ctx>(
} }
StrFromUtf8 => { StrFromUtf8 => {
let result_type = env.module.get_struct_type("str.FromUtf8Result").unwrap(); let result_type = env.module.get_struct_type("str.FromUtf8Result").unwrap();
let result_ptr = env let result_ptr =
.builder create_entry_block_alloca(env, result_type, "alloca_utf8_validate_bytes_result");
.new_build_alloca(result_type, "alloca_utf8_validate_bytes_result");
use roc_target::Architecture::*; use roc_target::Architecture::*;
match env.target.architecture() { match env.target.architecture() {
@ -947,7 +942,6 @@ pub(crate) fn run_low_level<'a, 'ctx>(
build_int_unary_op( build_int_unary_op(
env, env,
layout_interner, layout_interner,
parent,
arg.into_int_value(), arg.into_int_value(),
int_width, int_width,
int_type, int_type,
@ -1396,9 +1390,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
layout_interner, layout_interner,
layout_interner.get_repr(layout), layout_interner.get_repr(layout),
); );
let ptr = env let ptr = create_entry_block_alloca(env, basic_type, "unreachable_alloca");
.builder
.new_build_alloca(basic_type, "unreachable_alloca");
env.builder.new_build_store(ptr, basic_type.const_zero()); env.builder.new_build_store(ptr, basic_type.const_zero());
ptr.into() ptr.into()
@ -1933,7 +1925,7 @@ fn throw_because_overflow(env: &Env<'_, '_, '_>, message: &str) {
env.builder.position_at_end(entry); env.builder.position_at_end(entry);
// ends in unreachable, so no return is needed // ends in unreachable, so no return is needed
throw_internal_exception(env, function_value, message); throw_internal_exception(env, message);
function_value function_value
} }
@ -1973,7 +1965,7 @@ fn dec_alloca<'ctx>(env: &Env<'_, 'ctx, '_>, value: IntValue<'ctx>) -> BasicValu
Windows => { Windows => {
let dec_type = zig_dec_type(env); 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(); let instruction = alloca.as_instruction_value().unwrap();
instruction.set_alignment(16).unwrap(); instruction.set_alignment(16).unwrap();
@ -2079,11 +2071,7 @@ fn dec_binary_op<'ctx>(
fn_name, fn_name,
); );
let block = env.builder.get_insert_block().expect("to be in a function"); let ptr = create_entry_block_alloca(env, env.context.i128_type(), "to_i128");
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");
env.builder.build_store(ptr, lowr_highr).unwrap(); env.builder.build_store(ptr, lowr_highr).unwrap();
env.builder env.builder
@ -2109,7 +2097,7 @@ fn dec_binop_with_overflow<'ctx>(
let rhs = rhs.into_int_value(); let rhs = rhs.into_int_value();
let return_type = zig_with_overflow_roc_dec(env); 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 { match env.target {
Target::LinuxX32 | Target::LinuxX64 | Target::MacX64 => { Target::LinuxX32 | Target::LinuxX64 | Target::MacX64 => {
@ -2195,7 +2183,7 @@ fn change_with_overflow_to_roc_type<'a, 'ctx>(
layout_interner, layout_interner,
layout_interner.get_repr(return_layout), 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( use_roc_value(
env, env,
@ -2341,7 +2329,6 @@ fn int_type_signed_min(int_type: IntType) -> IntValue {
fn build_int_unary_op<'a, 'ctx, 'env>( fn build_int_unary_op<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &STLayoutInterner<'a>, layout_interner: &STLayoutInterner<'a>,
parent: FunctionValue<'ctx>,
arg: IntValue<'ctx>, arg: IntValue<'ctx>,
arg_width: IntWidth, arg_width: IntWidth,
arg_int_type: IntType<'ctx>, arg_int_type: IntType<'ctx>,
@ -2477,12 +2464,8 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
target_int_width.type_name(), target_int_width.type_name(),
); );
let zig_return_alloca = create_entry_block_alloca( let zig_return_alloca =
env, create_entry_block_alloca(env, return_type, "num_to_int");
parent,
return_type.into(),
"num_to_int",
);
call_void_bitcode_fn( call_void_bitcode_fn(
env, env,
@ -2584,7 +2567,6 @@ fn int_neg_raise_on_overflow<'ctx>(
throw_internal_exception( throw_internal_exception(
env, env,
parent,
"Integer negation overflowed because its argument is the minimum value", "Integer negation overflowed because its argument is the minimum value",
); );
@ -2615,7 +2597,6 @@ fn int_abs_raise_on_overflow<'ctx>(
throw_internal_exception( throw_internal_exception(
env, env,
parent,
"Integer absolute overflowed because its argument is the minimum value", "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 bits_to_shift = int_type.get_bit_width() as u64 - 1;
let shift_val = int_type.const_int(bits_to_shift, false); 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 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 // shifted = arg >>> 63
bd.new_build_store(alloca, shifted); bd.new_build_store(alloca, shifted);

View File

@ -646,7 +646,7 @@ fn call_help<'ctx>(
value: BasicValueEnum<'ctx>, value: BasicValueEnum<'ctx>,
) -> inkwell::values::CallSiteValue<'ctx> { ) -> inkwell::values::CallSiteValue<'ctx> {
let value = cast_if_necessary_for_opaque_recursive_pointers( let value = cast_if_necessary_for_opaque_recursive_pointers(
env.builder, env,
value, value,
function.get_params()[0].get_type(), 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 // therefore we must cast it to our desired type
let union_layout = LayoutRepr::Union(union_layout); let union_layout = LayoutRepr::Union(union_layout);
let union_type = basic_type_from_layout(env, layout_interner, 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); deferred_rec.push(recursive_field_ptr);
} else if layout_interner.contains_refcounted(*field_layout) { } else if layout_interner.contains_refcounted(*field_layout) {
@ -1823,8 +1823,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx>(
layout_interner, layout_interner,
layout_interner.get_repr(union_layout), layout_interner.get_repr(union_layout),
); );
let recursive_ptr_field_value = let recursive_ptr_field_value = cast_basic_basic(env, field_value, union_type);
cast_basic_basic(env.builder, field_value, union_type);
modify_refcount_layout_help( modify_refcount_layout_help(
env, 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 crate::llvm::build::{load_roc_value, use_roc_value};
use super::{ use super::{
build::{store_roc_value, BuilderExt, Env}, build::{create_entry_block_alloca, store_roc_value, BuilderExt, Env},
convert::basic_type_from_layout, convert::basic_type_from_layout,
scope::Scope, scope::Scope,
}; };
@ -253,7 +253,7 @@ fn build_struct_alloca_helper<'a, 'ctx>(
// Create the struct_type // Create the struct_type
let struct_type = ctx.struct_type(field_types.into_bump_slice(), false); 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() { for (i, (field_expr, field_repr)) in field_expr_repr.into_iter().enumerate() {
let dst = let dst =