mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 07:41:12 +00:00
Merge remote-tracking branch 'origin/trunk' into expect-dont-panic
This commit is contained in:
commit
a55ff62e6c
501 changed files with 26570 additions and 12276 deletions
File diff suppressed because it is too large
Load diff
|
@ -17,17 +17,20 @@ use inkwell::AddressSpace;
|
|||
use roc_builtins::bitcode;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::layout::{Builtin, Layout, LayoutIds};
|
||||
use roc_target::TargetInfo;
|
||||
|
||||
#[repr(transparent)]
|
||||
struct Alignment(u8);
|
||||
|
||||
impl Alignment {
|
||||
fn from_key_value_layout(key: &Layout, value: &Layout, ptr_bytes: u32) -> Alignment {
|
||||
let key_align = key.alignment_bytes(ptr_bytes);
|
||||
let value_align = value.alignment_bytes(ptr_bytes);
|
||||
fn from_key_value_layout(key: &Layout, value: &Layout, target_info: TargetInfo) -> Alignment {
|
||||
let key_align = key.alignment_bytes(target_info);
|
||||
let value_align = value.alignment_bytes(target_info);
|
||||
|
||||
let mut bits = key_align.max(value_align) as u8;
|
||||
debug_assert!(bits == 4 || bits == 8 || bits == 16);
|
||||
|
||||
// alignment must be a power of 2
|
||||
debug_assert!(bits.is_power_of_two());
|
||||
|
||||
let value_before_key_flag = 0b1000_0000;
|
||||
|
||||
|
@ -103,15 +106,15 @@ pub fn dict_insert<'a, 'ctx, 'env>(
|
|||
|
||||
let key_width = env
|
||||
.ptr_int()
|
||||
.const_int(key_layout.stack_size(env.ptr_bytes) as u64, false);
|
||||
.const_int(key_layout.stack_size(env.target_info) as u64, false);
|
||||
|
||||
let value_width = env
|
||||
.ptr_int()
|
||||
.const_int(value_layout.stack_size(env.ptr_bytes) as u64, false);
|
||||
.const_int(value_layout.stack_size(env.target_info) as u64, false);
|
||||
|
||||
let result_ptr = builder.build_alloca(zig_dict_type(env), "result_ptr");
|
||||
|
||||
let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.ptr_bytes);
|
||||
let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.target_info);
|
||||
let alignment_iv = alignment.as_int_value(env.context);
|
||||
|
||||
let hash_fn = build_hash_wrapper(env, layout_ids, key_layout);
|
||||
|
@ -160,15 +163,15 @@ pub fn dict_remove<'a, 'ctx, 'env>(
|
|||
|
||||
let key_width = env
|
||||
.ptr_int()
|
||||
.const_int(key_layout.stack_size(env.ptr_bytes) as u64, false);
|
||||
.const_int(key_layout.stack_size(env.target_info) as u64, false);
|
||||
|
||||
let value_width = env
|
||||
.ptr_int()
|
||||
.const_int(value_layout.stack_size(env.ptr_bytes) as u64, false);
|
||||
.const_int(value_layout.stack_size(env.target_info) as u64, false);
|
||||
|
||||
let result_ptr = builder.build_alloca(zig_dict_type(env), "result_ptr");
|
||||
|
||||
let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.ptr_bytes);
|
||||
let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.target_info);
|
||||
let alignment_iv = alignment.as_int_value(env.context);
|
||||
|
||||
let hash_fn = build_hash_wrapper(env, layout_ids, key_layout);
|
||||
|
@ -216,13 +219,13 @@ pub fn dict_contains<'a, 'ctx, 'env>(
|
|||
|
||||
let key_width = env
|
||||
.ptr_int()
|
||||
.const_int(key_layout.stack_size(env.ptr_bytes) as u64, false);
|
||||
.const_int(key_layout.stack_size(env.target_info) as u64, false);
|
||||
|
||||
let value_width = env
|
||||
.ptr_int()
|
||||
.const_int(value_layout.stack_size(env.ptr_bytes) as u64, false);
|
||||
.const_int(value_layout.stack_size(env.target_info) as u64, false);
|
||||
|
||||
let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.ptr_bytes);
|
||||
let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.target_info);
|
||||
let alignment_iv = alignment.as_int_value(env.context);
|
||||
|
||||
let hash_fn = build_hash_wrapper(env, layout_ids, key_layout);
|
||||
|
@ -262,13 +265,13 @@ pub fn dict_get<'a, 'ctx, 'env>(
|
|||
|
||||
let key_width = env
|
||||
.ptr_int()
|
||||
.const_int(key_layout.stack_size(env.ptr_bytes) as u64, false);
|
||||
.const_int(key_layout.stack_size(env.target_info) as u64, false);
|
||||
|
||||
let value_width = env
|
||||
.ptr_int()
|
||||
.const_int(value_layout.stack_size(env.ptr_bytes) as u64, false);
|
||||
.const_int(value_layout.stack_size(env.target_info) as u64, false);
|
||||
|
||||
let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.ptr_bytes);
|
||||
let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.target_info);
|
||||
let alignment_iv = alignment.as_int_value(env.context);
|
||||
|
||||
let hash_fn = build_hash_wrapper(env, layout_ids, key_layout);
|
||||
|
@ -364,13 +367,13 @@ pub fn dict_elements_rc<'a, 'ctx, 'env>(
|
|||
) {
|
||||
let key_width = env
|
||||
.ptr_int()
|
||||
.const_int(key_layout.stack_size(env.ptr_bytes) as u64, false);
|
||||
.const_int(key_layout.stack_size(env.target_info) as u64, false);
|
||||
|
||||
let value_width = env
|
||||
.ptr_int()
|
||||
.const_int(value_layout.stack_size(env.ptr_bytes) as u64, false);
|
||||
.const_int(value_layout.stack_size(env.target_info) as u64, false);
|
||||
|
||||
let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.ptr_bytes);
|
||||
let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.target_info);
|
||||
let alignment_iv = alignment.as_int_value(env.context);
|
||||
|
||||
let (key_fn, value_fn) = match rc_operation {
|
||||
|
@ -410,13 +413,13 @@ pub fn dict_keys<'a, 'ctx, 'env>(
|
|||
|
||||
let key_width = env
|
||||
.ptr_int()
|
||||
.const_int(key_layout.stack_size(env.ptr_bytes) as u64, false);
|
||||
.const_int(key_layout.stack_size(env.target_info) as u64, false);
|
||||
|
||||
let value_width = env
|
||||
.ptr_int()
|
||||
.const_int(value_layout.stack_size(env.ptr_bytes) as u64, false);
|
||||
.const_int(value_layout.stack_size(env.target_info) as u64, false);
|
||||
|
||||
let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.ptr_bytes);
|
||||
let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.target_info);
|
||||
let alignment_iv = alignment.as_int_value(env.context);
|
||||
|
||||
let inc_key_fn = build_inc_wrapper(env, layout_ids, key_layout);
|
||||
|
@ -452,19 +455,18 @@ fn pass_dict_c_abi<'a, 'ctx, 'env>(
|
|||
env: &Env<'a, 'ctx, 'env>,
|
||||
dict: BasicValueEnum<'ctx>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
match env.ptr_bytes {
|
||||
4 => {
|
||||
match env.target_info.ptr_width() {
|
||||
roc_target::PtrWidth::Bytes4 => {
|
||||
let target_type = env.context.custom_width_int_type(96).into();
|
||||
|
||||
complex_bitcast(env.builder, dict, target_type, "to_i96")
|
||||
}
|
||||
8 => {
|
||||
roc_target::PtrWidth::Bytes8 => {
|
||||
let dict_ptr = env.builder.build_alloca(zig_dict_type(env), "dict_ptr");
|
||||
env.builder.build_store(dict_ptr, dict);
|
||||
|
||||
dict_ptr.into()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -481,13 +483,13 @@ pub fn dict_union<'a, 'ctx, 'env>(
|
|||
|
||||
let key_width = env
|
||||
.ptr_int()
|
||||
.const_int(key_layout.stack_size(env.ptr_bytes) as u64, false);
|
||||
.const_int(key_layout.stack_size(env.target_info) as u64, false);
|
||||
|
||||
let value_width = env
|
||||
.ptr_int()
|
||||
.const_int(value_layout.stack_size(env.ptr_bytes) as u64, false);
|
||||
.const_int(value_layout.stack_size(env.target_info) as u64, false);
|
||||
|
||||
let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.ptr_bytes);
|
||||
let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.target_info);
|
||||
let alignment_iv = alignment.as_int_value(env.context);
|
||||
|
||||
let hash_fn = build_hash_wrapper(env, layout_ids, key_layout);
|
||||
|
@ -574,13 +576,13 @@ fn dict_intersect_or_difference<'a, 'ctx, 'env>(
|
|||
|
||||
let key_width = env
|
||||
.ptr_int()
|
||||
.const_int(key_layout.stack_size(env.ptr_bytes) as u64, false);
|
||||
.const_int(key_layout.stack_size(env.target_info) as u64, false);
|
||||
|
||||
let value_width = env
|
||||
.ptr_int()
|
||||
.const_int(value_layout.stack_size(env.ptr_bytes) as u64, false);
|
||||
.const_int(value_layout.stack_size(env.target_info) as u64, false);
|
||||
|
||||
let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.ptr_bytes);
|
||||
let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.target_info);
|
||||
let alignment_iv = alignment.as_int_value(env.context);
|
||||
|
||||
let hash_fn = build_hash_wrapper(env, layout_ids, key_layout);
|
||||
|
@ -629,7 +631,7 @@ pub fn dict_walk<'a, 'ctx, 'env>(
|
|||
let accum_ptr = builder.build_alloca(accum_bt, "accum_ptr");
|
||||
env.builder.build_store(accum_ptr, accum);
|
||||
|
||||
let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.ptr_bytes);
|
||||
let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.target_info);
|
||||
let alignment_iv = alignment.as_int_value(env.context);
|
||||
|
||||
let output_ptr = builder.build_alloca(accum_bt, "output_ptr");
|
||||
|
@ -669,13 +671,13 @@ pub fn dict_values<'a, 'ctx, 'env>(
|
|||
|
||||
let key_width = env
|
||||
.ptr_int()
|
||||
.const_int(key_layout.stack_size(env.ptr_bytes) as u64, false);
|
||||
.const_int(key_layout.stack_size(env.target_info) as u64, false);
|
||||
|
||||
let value_width = env
|
||||
.ptr_int()
|
||||
.const_int(value_layout.stack_size(env.ptr_bytes) as u64, false);
|
||||
.const_int(value_layout.stack_size(env.target_info) as u64, false);
|
||||
|
||||
let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.ptr_bytes);
|
||||
let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.target_info);
|
||||
let alignment_iv = alignment.as_int_value(env.context);
|
||||
|
||||
let inc_value_fn = build_inc_wrapper(env, layout_ids, value_layout);
|
||||
|
@ -727,14 +729,14 @@ pub fn set_from_list<'a, 'ctx, 'env>(
|
|||
|
||||
let key_width = env
|
||||
.ptr_int()
|
||||
.const_int(key_layout.stack_size(env.ptr_bytes) as u64, false);
|
||||
.const_int(key_layout.stack_size(env.target_info) as u64, false);
|
||||
|
||||
let value_width = env.ptr_int().const_zero();
|
||||
|
||||
let result_alloca = builder.build_alloca(zig_dict_type(env), "result_alloca");
|
||||
|
||||
let alignment =
|
||||
Alignment::from_key_value_layout(key_layout, &Layout::Struct(&[]), env.ptr_bytes);
|
||||
Alignment::from_key_value_layout(key_layout, &Layout::Struct(&[]), env.target_info);
|
||||
let alignment_iv = alignment.as_int_value(env.context);
|
||||
|
||||
let hash_fn = build_hash_wrapper(env, layout_ids, key_layout);
|
||||
|
|
|
@ -120,7 +120,7 @@ fn hash_builtin<'a, 'ctx, 'env>(
|
|||
builtin: &Builtin<'a>,
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
) -> IntValue<'ctx> {
|
||||
let ptr_bytes = env.ptr_bytes;
|
||||
let ptr_bytes = env.target_info;
|
||||
|
||||
match builtin {
|
||||
Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal => {
|
||||
|
@ -246,7 +246,7 @@ fn hash_struct<'a, 'ctx, 'env>(
|
|||
when_recursive: WhenRecursive<'a>,
|
||||
field_layouts: &[Layout<'a>],
|
||||
) -> IntValue<'ctx> {
|
||||
let ptr_bytes = env.ptr_bytes;
|
||||
let ptr_bytes = env.target_info;
|
||||
|
||||
let layout = Layout::Struct(field_layouts);
|
||||
|
||||
|
@ -423,7 +423,7 @@ fn hash_tag<'a, 'ctx, 'env>(
|
|||
env,
|
||||
seed,
|
||||
hash_bytes,
|
||||
tag_id_layout.stack_size(env.ptr_bytes),
|
||||
tag_id_layout.stack_size(env.target_info),
|
||||
);
|
||||
|
||||
// hash the tag data
|
||||
|
@ -474,7 +474,7 @@ fn hash_tag<'a, 'ctx, 'env>(
|
|||
env,
|
||||
seed,
|
||||
hash_bytes,
|
||||
tag_id_layout.stack_size(env.ptr_bytes),
|
||||
tag_id_layout.stack_size(env.target_info),
|
||||
);
|
||||
|
||||
// hash the tag data
|
||||
|
@ -574,7 +574,7 @@ fn hash_tag<'a, 'ctx, 'env>(
|
|||
env,
|
||||
seed,
|
||||
hash_bytes,
|
||||
tag_id_layout.stack_size(env.ptr_bytes),
|
||||
tag_id_layout.stack_size(env.target_info),
|
||||
);
|
||||
|
||||
// hash tag data
|
||||
|
|
|
@ -87,7 +87,7 @@ pub fn layout_width<'a, 'ctx, 'env>(
|
|||
layout: &Layout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
env.ptr_int()
|
||||
.const_int(layout.stack_size(env.ptr_bytes) as u64, false)
|
||||
.const_int(layout.stack_size(env.target_info) as u64, false)
|
||||
.into()
|
||||
}
|
||||
|
||||
|
@ -1254,17 +1254,17 @@ pub fn allocate_list<'a, 'ctx, 'env>(
|
|||
let ctx = env.context;
|
||||
|
||||
let len_type = env.ptr_int();
|
||||
let elem_bytes = elem_layout.stack_size(env.ptr_bytes) as u64;
|
||||
let elem_bytes = elem_layout.stack_size(env.target_info) as u64;
|
||||
let bytes_per_element = len_type.const_int(elem_bytes, false);
|
||||
let number_of_data_bytes =
|
||||
builder.build_int_mul(bytes_per_element, number_of_elements, "data_length");
|
||||
|
||||
// the refcount of a new list is initially 1
|
||||
// we assume that the list is indeed used (dead variables are eliminated)
|
||||
let rc1 = crate::llvm::refcounting::refcount_1(ctx, env.ptr_bytes);
|
||||
let rc1 = crate::llvm::refcounting::refcount_1(ctx, env.target_info);
|
||||
|
||||
let basic_type = basic_type_from_layout(env, elem_layout);
|
||||
let alignment_bytes = elem_layout.alignment_bytes(env.ptr_bytes);
|
||||
let alignment_bytes = elem_layout.alignment_bytes(env.target_info);
|
||||
allocate_with_refcount_help(env, basic_type, alignment_bytes, number_of_data_bytes, rc1)
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ use morphic_lib::UpdateMode;
|
|||
use roc_builtins::bitcode::{self, IntWidth};
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::layout::{Builtin, Layout};
|
||||
use roc_target::PtrWidth;
|
||||
|
||||
use super::build::load_symbol;
|
||||
|
||||
|
@ -79,10 +80,9 @@ fn str_symbol_to_c_abi<'a, 'ctx, 'env>(
|
|||
) -> IntValue<'ctx> {
|
||||
let string = load_symbol(scope, &symbol);
|
||||
|
||||
let target_type = match env.ptr_bytes {
|
||||
8 => env.context.i128_type().into(),
|
||||
4 => env.context.i64_type().into(),
|
||||
_ => unreachable!(),
|
||||
let target_type = match env.target_info.ptr_width() {
|
||||
PtrWidth::Bytes8 => env.context.i128_type().into(),
|
||||
PtrWidth::Bytes4 => env.context.i64_type().into(),
|
||||
};
|
||||
|
||||
complex_bitcast(env.builder, string, target_type, "str_to_c_abi").into_int_value()
|
||||
|
@ -96,10 +96,9 @@ pub fn str_to_c_abi<'a, 'ctx, 'env>(
|
|||
|
||||
env.builder.build_store(cell, value);
|
||||
|
||||
let target_type = match env.ptr_bytes {
|
||||
8 => env.context.i128_type(),
|
||||
4 => env.context.i64_type(),
|
||||
_ => unreachable!(),
|
||||
let target_type = match env.target_info.ptr_width() {
|
||||
PtrWidth::Bytes8 => env.context.i128_type(),
|
||||
PtrWidth::Bytes4 => env.context.i64_type(),
|
||||
};
|
||||
|
||||
let target_type_ptr = env
|
||||
|
@ -310,20 +309,19 @@ fn decode_from_utf8_result<'a, 'ctx, 'env>(
|
|||
let builder = env.builder;
|
||||
let ctx = env.context;
|
||||
|
||||
let fields = match env.ptr_bytes {
|
||||
8 | 4 => [
|
||||
let fields = match env.target_info.ptr_width() {
|
||||
PtrWidth::Bytes4 | PtrWidth::Bytes8 => [
|
||||
env.ptr_int().into(),
|
||||
super::convert::zig_str_type(env).into(),
|
||||
env.context.bool_type().into(),
|
||||
ctx.i8_type().into(),
|
||||
],
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let record_type = env.context.struct_type(&fields, false);
|
||||
|
||||
match env.ptr_bytes {
|
||||
8 | 4 => {
|
||||
match env.target_info.ptr_width() {
|
||||
PtrWidth::Bytes4 | PtrWidth::Bytes8 => {
|
||||
let result_ptr_cast = env
|
||||
.builder
|
||||
.build_bitcast(
|
||||
|
@ -337,7 +335,6 @@ fn decode_from_utf8_result<'a, 'ctx, 'env>(
|
|||
.build_load(result_ptr_cast, "load_utf8_validate_bytes_result")
|
||||
.into_struct_value()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -432,12 +429,3 @@ pub fn str_equal<'a, 'ctx, 'env>(
|
|||
bitcode::STR_EQUAL,
|
||||
)
|
||||
}
|
||||
|
||||
// TODO investigate: does this cause problems when the layout is known? this value is now not refcounted!
|
||||
pub fn empty_str<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> BasicValueEnum<'ctx> {
|
||||
let struct_type = super::convert::zig_str_type(env);
|
||||
|
||||
// The pointer should be null (aka zero) and the length should be zero,
|
||||
// so the whole struct should be a const_zero
|
||||
BasicValueEnum::StructValue(struct_type.const_zero())
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ use inkwell::types::{BasicType, BasicTypeEnum, FloatType, IntType, StructType};
|
|||
use inkwell::AddressSpace;
|
||||
use roc_builtins::bitcode::{FloatWidth, IntWidth};
|
||||
use roc_mono::layout::{Builtin, Layout, UnionLayout};
|
||||
use roc_target::TargetInfo;
|
||||
|
||||
fn basic_type_from_record<'a, 'ctx, 'env>(
|
||||
env: &crate::llvm::build::Env<'a, 'ctx, 'env>,
|
||||
|
@ -36,7 +37,7 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>(
|
|||
|
||||
match union_layout {
|
||||
NonRecursive(tags) => {
|
||||
let data = block_of_memory_slices(env.context, tags, env.ptr_bytes);
|
||||
let data = block_of_memory_slices(env.context, tags, env.target_info);
|
||||
|
||||
env.context.struct_type(&[data, tag_id_type], false).into()
|
||||
}
|
||||
|
@ -44,9 +45,9 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>(
|
|||
| NullableWrapped {
|
||||
other_tags: tags, ..
|
||||
} => {
|
||||
let data = block_of_memory_slices(env.context, tags, env.ptr_bytes);
|
||||
let data = block_of_memory_slices(env.context, tags, env.target_info);
|
||||
|
||||
if union_layout.stores_tag_id_as_data(env.ptr_bytes) {
|
||||
if union_layout.stores_tag_id_as_data(env.target_info) {
|
||||
env.context
|
||||
.struct_type(&[data, tag_id_type], false)
|
||||
.ptr_type(AddressSpace::Generic)
|
||||
|
@ -56,11 +57,12 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>(
|
|||
}
|
||||
}
|
||||
NullableUnwrapped { other_fields, .. } => {
|
||||
let block = block_of_memory_slices(env.context, &[other_fields], env.ptr_bytes);
|
||||
let block =
|
||||
block_of_memory_slices(env.context, &[other_fields], env.target_info);
|
||||
block.ptr_type(AddressSpace::Generic).into()
|
||||
}
|
||||
NonNullableUnwrapped(fields) => {
|
||||
let block = block_of_memory_slices(env.context, &[fields], env.ptr_bytes);
|
||||
let block = block_of_memory_slices(env.context, &[fields], env.target_info);
|
||||
block.ptr_type(AddressSpace::Generic).into()
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +97,7 @@ pub fn basic_type_from_layout_1<'a, 'ctx, 'env>(
|
|||
|
||||
match union_layout {
|
||||
NonRecursive(tags) => {
|
||||
let data = block_of_memory_slices(env.context, tags, env.ptr_bytes);
|
||||
let data = block_of_memory_slices(env.context, tags, env.target_info);
|
||||
let struct_type = env.context.struct_type(&[data, tag_id_type], false);
|
||||
|
||||
struct_type.ptr_type(AddressSpace::Generic).into()
|
||||
|
@ -104,9 +106,9 @@ pub fn basic_type_from_layout_1<'a, 'ctx, 'env>(
|
|||
| NullableWrapped {
|
||||
other_tags: tags, ..
|
||||
} => {
|
||||
let data = block_of_memory_slices(env.context, tags, env.ptr_bytes);
|
||||
let data = block_of_memory_slices(env.context, tags, env.target_info);
|
||||
|
||||
if union_layout.stores_tag_id_as_data(env.ptr_bytes) {
|
||||
if union_layout.stores_tag_id_as_data(env.target_info) {
|
||||
env.context
|
||||
.struct_type(&[data, tag_id_type], false)
|
||||
.ptr_type(AddressSpace::Generic)
|
||||
|
@ -116,11 +118,12 @@ pub fn basic_type_from_layout_1<'a, 'ctx, 'env>(
|
|||
}
|
||||
}
|
||||
NullableUnwrapped { other_fields, .. } => {
|
||||
let block = block_of_memory_slices(env.context, &[other_fields], env.ptr_bytes);
|
||||
let block =
|
||||
block_of_memory_slices(env.context, &[other_fields], env.target_info);
|
||||
block.ptr_type(AddressSpace::Generic).into()
|
||||
}
|
||||
NonNullableUnwrapped(fields) => {
|
||||
let block = block_of_memory_slices(env.context, &[fields], env.ptr_bytes);
|
||||
let block = block_of_memory_slices(env.context, &[fields], env.target_info);
|
||||
block.ptr_type(AddressSpace::Generic).into()
|
||||
}
|
||||
}
|
||||
|
@ -188,13 +191,13 @@ pub fn float_type_from_float_width<'a, 'ctx, 'env>(
|
|||
pub fn block_of_memory_slices<'ctx>(
|
||||
context: &'ctx Context,
|
||||
layouts: &[&[Layout<'_>]],
|
||||
ptr_bytes: u32,
|
||||
target_info: TargetInfo,
|
||||
) -> BasicTypeEnum<'ctx> {
|
||||
let mut union_size = 0;
|
||||
for tag in layouts {
|
||||
let mut total = 0;
|
||||
for layout in tag.iter() {
|
||||
total += layout.stack_size(ptr_bytes as u32);
|
||||
total += layout.stack_size(target_info);
|
||||
}
|
||||
|
||||
union_size = union_size.max(total);
|
||||
|
@ -203,32 +206,16 @@ pub fn block_of_memory_slices<'ctx>(
|
|||
block_of_memory_help(context, union_size)
|
||||
}
|
||||
|
||||
pub fn union_data_is_struct<'a, 'ctx, 'env>(
|
||||
env: &crate::llvm::build::Env<'a, 'ctx, 'env>,
|
||||
layouts: &[Layout<'_>],
|
||||
) -> StructType<'ctx> {
|
||||
let data_type = basic_type_from_record(env, layouts);
|
||||
union_data_is_struct_type(env.context, data_type.into_struct_type())
|
||||
}
|
||||
|
||||
pub fn union_data_is_struct_type<'ctx>(
|
||||
context: &'ctx Context,
|
||||
struct_type: StructType<'ctx>,
|
||||
) -> StructType<'ctx> {
|
||||
let tag_id_type = context.i64_type();
|
||||
context.struct_type(&[struct_type.into(), tag_id_type.into()], false)
|
||||
}
|
||||
|
||||
pub fn block_of_memory<'ctx>(
|
||||
context: &'ctx Context,
|
||||
layout: &Layout<'_>,
|
||||
ptr_bytes: u32,
|
||||
target_info: TargetInfo,
|
||||
) -> BasicTypeEnum<'ctx> {
|
||||
// TODO make this dynamic
|
||||
let mut union_size = layout.stack_size(ptr_bytes as u32);
|
||||
let mut union_size = layout.stack_size(target_info);
|
||||
|
||||
if let Layout::Union(UnionLayout::NonRecursive { .. }) = layout {
|
||||
union_size -= ptr_bytes;
|
||||
union_size -= target_info.ptr_width() as u32;
|
||||
}
|
||||
|
||||
block_of_memory_help(context, union_size)
|
||||
|
@ -246,14 +233,18 @@ fn block_of_memory_help(context: &Context, union_size: u32) -> BasicTypeEnum<'_>
|
|||
let num_i64 = union_size / 8;
|
||||
let num_i8 = union_size % 8;
|
||||
|
||||
let i8_array_type = context.i8_type().array_type(num_i8).as_basic_type_enum();
|
||||
let i64_array_type = context.i64_type().array_type(num_i64).as_basic_type_enum();
|
||||
|
||||
if num_i8 == 0 {
|
||||
// the object fits perfectly in some number of i64's
|
||||
if num_i64 == 0 {
|
||||
// The object fits perfectly in some number of i8s
|
||||
context.struct_type(&[i8_array_type], false).into()
|
||||
} else if num_i8 == 0 {
|
||||
// The object fits perfectly in some number of i64s
|
||||
// (i.e. the size is a multiple of 8 bytes)
|
||||
context.struct_type(&[i64_array_type], false).into()
|
||||
} else {
|
||||
// there are some trailing bytes at the end
|
||||
// There are some trailing bytes at the end
|
||||
let i8_array_type = context.i8_type().array_type(num_i8).as_basic_type_enum();
|
||||
|
||||
context
|
||||
|
@ -263,16 +254,10 @@ fn block_of_memory_help(context: &Context, union_size: u32) -> BasicTypeEnum<'_>
|
|||
}
|
||||
|
||||
/// The int type that the C ABI turns our RocList/RocStr into
|
||||
pub fn str_list_int(ctx: &Context, ptr_bytes: u32) -> IntType<'_> {
|
||||
match ptr_bytes {
|
||||
1 => ctx.i16_type(),
|
||||
2 => ctx.i32_type(),
|
||||
4 => ctx.i64_type(),
|
||||
8 => ctx.i128_type(),
|
||||
_ => panic!(
|
||||
"Invalid target: Roc does't support compiling to {}-bit systems.",
|
||||
ptr_bytes * 8
|
||||
),
|
||||
pub fn str_list_int(ctx: &Context, target_info: TargetInfo) -> IntType<'_> {
|
||||
match target_info.ptr_width() {
|
||||
roc_target::PtrWidth::Bytes4 => ctx.i64_type(),
|
||||
roc_target::PtrWidth::Bytes8 => ctx.i128_type(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -212,7 +212,9 @@ pub fn add_sjlj_roc_panic(env: &Env<'_, '_, '_>) {
|
|||
let buffer = crate::llvm::build::get_sjlj_buffer(env);
|
||||
|
||||
// write our error message pointer
|
||||
let index = env.ptr_int().const_int(3 * env.ptr_bytes as u64, false);
|
||||
let index = env
|
||||
.ptr_int()
|
||||
.const_int(3 * env.target_info.ptr_width() as u64, false);
|
||||
let message_buffer_raw =
|
||||
unsafe { builder.build_gep(buffer, &[index], "raw_msg_buffer_ptr") };
|
||||
let message_buffer = builder.build_bitcast(
|
||||
|
|
|
@ -18,21 +18,16 @@ use inkwell::{AddressSpace, IntPredicate};
|
|||
use roc_module::symbol::Interns;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::layout::{Builtin, Layout, LayoutIds, UnionLayout};
|
||||
use roc_target::TargetInfo;
|
||||
|
||||
/// "Infinite" reference count, for static values
|
||||
/// Ref counts are encoded as negative numbers where isize::MIN represents 1
|
||||
pub const REFCOUNT_MAX: usize = 0_usize;
|
||||
|
||||
pub fn refcount_1(ctx: &Context, ptr_bytes: u32) -> IntValue<'_> {
|
||||
match ptr_bytes {
|
||||
1 => ctx.i8_type().const_int(i8::MIN as u64, false),
|
||||
2 => ctx.i16_type().const_int(i16::MIN as u64, false),
|
||||
4 => ctx.i32_type().const_int(i32::MIN as u64, false),
|
||||
8 => ctx.i64_type().const_int(i64::MIN as u64, false),
|
||||
_ => panic!(
|
||||
"Invalid target: Roc does't support compiling to {}-bit systems.",
|
||||
ptr_bytes * 8
|
||||
),
|
||||
pub fn refcount_1(ctx: &Context, target_info: TargetInfo) -> IntValue<'_> {
|
||||
match target_info.ptr_width() {
|
||||
roc_target::PtrWidth::Bytes4 => ctx.i32_type().const_int(i32::MIN as u64, false),
|
||||
roc_target::PtrWidth::Bytes8 => ctx.i64_type().const_int(i64::MIN as u64, false),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,7 +93,7 @@ impl<'ctx> PointerToRefcount<'ctx> {
|
|||
|
||||
pub fn is_1<'a, 'env>(&self, env: &Env<'a, 'ctx, 'env>) -> IntValue<'ctx> {
|
||||
let current = self.get_refcount(env);
|
||||
let one = refcount_1(env.context, env.ptr_bytes);
|
||||
let one = refcount_1(env.context, env.target_info);
|
||||
|
||||
env.builder
|
||||
.build_int_compare(IntPredicate::EQ, current, one, "is_one")
|
||||
|
@ -163,8 +158,8 @@ impl<'ctx> PointerToRefcount<'ctx> {
|
|||
|
||||
pub fn decrement<'a, 'env>(&self, env: &Env<'a, 'ctx, 'env>, layout: &Layout<'a>) {
|
||||
let alignment = layout
|
||||
.allocation_alignment_bytes(env.ptr_bytes)
|
||||
.max(env.ptr_bytes);
|
||||
.allocation_alignment_bytes(env.target_info)
|
||||
.max(env.target_info.ptr_width() as u32);
|
||||
|
||||
let context = env.context;
|
||||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
|
@ -1192,7 +1187,7 @@ fn build_rec_union_help<'a, 'ctx, 'env>(
|
|||
|
||||
debug_assert!(arg_val.is_pointer_value());
|
||||
let current_tag_id = get_tag_id(env, fn_val, &union_layout, arg_val);
|
||||
let value_ptr = if union_layout.stores_tag_id_in_pointer(env.ptr_bytes) {
|
||||
let value_ptr = if union_layout.stores_tag_id_in_pointer(env.target_info) {
|
||||
tag_pointer_clear_tag_id(env, arg_val.into_pointer_value())
|
||||
} else {
|
||||
arg_val.into_pointer_value()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue