mirror of
https://github.com/roc-lang/roc.git
synced 2024-10-04 14:17:28 +03:00
move all allocas to the entry block
This commit is contained in:
parent
70fa3ecdc2
commit
ee7f1e39c7
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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>(
|
||||||
|
@ -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");
|
||||||
|
@ -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()
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
|
@ -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 =
|
||||||
|
Loading…
Reference in New Issue
Block a user