change over nullable wrapped

This commit is contained in:
Folkert 2021-06-27 01:35:15 +02:00
parent 71857e83d0
commit 8add147dcf
5 changed files with 230 additions and 152 deletions

View file

@ -4,7 +4,9 @@ use crate::llvm::build::{
LLVM_SADD_WITH_OVERFLOW_I64, TAG_DATA_INDEX, TAG_ID_INDEX,
};
use crate::llvm::build_list::{incrementing_elem_loop, list_len, load_list};
use crate::llvm::convert::{basic_type_from_layout, block_of_memory_slices, ptr_int};
use crate::llvm::convert::{
basic_type_from_layout, block_of_memory_slices, ptr_int, union_data_block_of_memory,
};
use bumpalo::collections::Vec;
use inkwell::basic_block::BasicBlock;
use inkwell::context::Context;
@ -651,6 +653,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
layout_ids,
mode,
&WhenRecursive::Loop(*variant),
*variant,
tags,
true,
);
@ -666,6 +669,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
layout_ids,
mode,
&WhenRecursive::Loop(*variant),
*variant,
&*env.arena.alloc([other_fields]),
true,
);
@ -679,6 +683,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
layout_ids,
mode,
&WhenRecursive::Loop(*variant),
*variant,
&*env.arena.alloc([*fields]),
true,
);
@ -691,6 +696,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
layout_ids,
mode,
&WhenRecursive::Loop(*variant),
*variant,
tags,
false,
);
@ -1203,10 +1209,11 @@ fn build_rec_union<'a, 'ctx, 'env>(
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
fields: &'a [&'a [Layout<'a>]],
union_layout: UnionLayout<'a>,
tags: &'a [&'a [Layout<'a>]],
is_nullable: bool,
) -> FunctionValue<'ctx> {
let layout = Layout::Union(UnionLayout::Recursive(fields));
let layout = Layout::Union(UnionLayout::Recursive(tags));
let (_, fn_name) = function_name_from_mode(
layout_ids,
@ -1223,9 +1230,7 @@ fn build_rec_union<'a, 'ctx, 'env>(
let block = env.builder.get_insert_block().expect("to be in a function");
let di_location = env.builder.get_current_debug_location().unwrap();
let basic_type = block_of_memory_slices(env.context, fields, env.ptr_bytes)
.ptr_type(AddressSpace::Generic)
.into();
let basic_type = basic_type_from_layout(env, &Layout::Union(union_layout));
let function_value = build_header(env, basic_type, mode, &fn_name);
build_rec_union_help(
@ -1233,7 +1238,8 @@ fn build_rec_union<'a, 'ctx, 'env>(
layout_ids,
mode,
when_recursive,
fields,
union_layout,
tags,
function_value,
is_nullable,
);
@ -1249,11 +1255,13 @@ fn build_rec_union<'a, 'ctx, 'env>(
function
}
#[allow(clippy::too_many_arguments)]
fn build_rec_union_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
union_layout: UnionLayout<'a>,
tags: &'a [&'a [roc_mono::layout::Layout<'a>]],
fn_val: FunctionValue<'ctx>,
is_nullable: bool,
@ -1279,8 +1287,6 @@ fn build_rec_union_help<'a, 'ctx, 'env>(
let parent = fn_val;
let layout = Layout::Union(UnionLayout::Recursive(tags));
debug_assert!(arg_val.is_pointer_value());
let value_ptr = arg_val.into_pointer_value();
@ -1309,6 +1315,8 @@ fn build_rec_union_help<'a, 'ctx, 'env>(
env.builder.position_at_end(should_recurse_block);
let layout = Layout::Union(union_layout);
match mode {
Mode::Inc => {
// inc is cheap; we never recurse
@ -1342,7 +1350,7 @@ fn build_rec_union_help<'a, 'ctx, 'env>(
when_recursive,
parent,
fn_val,
layout,
union_layout,
tags,
value_ptr,
refcount_ptr,
@ -1360,7 +1368,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
when_recursive: &WhenRecursive<'a>,
parent: FunctionValue<'ctx>,
decrement_fn: FunctionValue<'ctx>,
layout: Layout<'a>,
union_layout: UnionLayout<'a>,
tags: &[&[Layout<'a>]],
value_ptr: PointerValue<'ctx>,
refcount_ptr: PointerToRefcount<'ctx>,
@ -1433,7 +1441,15 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
debug_assert!(ptr_as_i64_ptr.is_pointer_value());
// therefore we must cast it to our desired type
let union_type = block_of_memory_slices(env.context, tags, env.ptr_bytes);
let union_type = match union_layout {
UnionLayout::Recursive(_) | UnionLayout::NullableWrapped { .. } => {
union_data_block_of_memory(env.context, tags, env.ptr_bytes).into()
}
UnionLayout::NonRecursive(_) => unreachable!(),
_ => block_of_memory_slices(env.context, tags, env.ptr_bytes),
};
let recursive_field_ptr = cast_basic_basic(
env.builder,
ptr_as_i64_ptr,
@ -1461,7 +1477,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
// lists. To achieve it, we must first load all fields that we want to inc/dec (done above)
// and store them on the stack, then modify (and potentially free) the current cell, then
// actually inc/dec the fields.
refcount_ptr.modify(call_mode, &layout, env);
refcount_ptr.modify(call_mode, &Layout::Union(union_layout), env);
for (field, field_layout) in deferred_nonrec {
modify_refcount_layout_help(
@ -1514,7 +1530,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
env.builder.position_at_end(merge_block);
// increment/decrement the cons-cell itself
refcount_ptr.modify(call_mode, &layout, env);
refcount_ptr.modify(call_mode, &Layout::Union(union_layout), env);
// this function returns void
builder.build_return(None);