fix list functions

This commit is contained in:
Folkert 2022-04-06 18:43:48 +02:00
parent 5e0b724854
commit 653d2d2a72
No known key found for this signature in database
GPG Key ID: 1F17F6FFD112B97C
5 changed files with 50 additions and 19 deletions

View File

@ -5215,6 +5215,7 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
argument_layouts,
Layout::Builtin(Builtin::Bool),
);
list_find_unsafe(env, layout_ids, roc_function_call, list, element_layout)
}
_ => unreachable!("invalid list layout"),

View File

@ -494,7 +494,7 @@ pub fn list_walk_generic<'a, 'ctx, 'env>(
layout_width(env, element_layout),
layout_width(env, function_call_return_layout),
layout_width(env, default_layout),
has_tag_id.as_global_value().as_pointer_value().into(),
has_tag_id_helper(env, has_tag_id).into(),
dec_element_fn.as_global_value().as_pointer_value().into(),
pass_as_opaque(env, result_ptr),
],
@ -603,6 +603,30 @@ fn empty_list<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> BasicValueEnum<'ctx>
BasicValueEnum::StructValue(struct_type.const_zero())
}
fn has_tag_id_helper<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
has_tag_id: FunctionValue<'ctx>,
) -> PointerValue<'ctx> {
let u8_t = env.context.i8_type();
let u16_t = env.context.i16_type();
let u8_ptr_t = u8_t.ptr_type(AddressSpace::Generic);
let struct_t = env
.context
.struct_type(&[u8_t.into(), env.ptr_int().into()], false);
let has_tag_id_type = struct_t
.fn_type(&[u16_t.into(), u8_ptr_t.into()], false)
.ptr_type(AddressSpace::Generic);
env.builder.build_pointer_cast(
has_tag_id.as_global_value().as_pointer_value(),
has_tag_id_type,
"has_tag_id_cast",
)
}
/// List.keepOks : List before, (before -> Result after *) -> List after
pub fn list_keep_oks<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
@ -626,7 +650,7 @@ pub fn list_keep_oks<'a, 'ctx, 'env>(
let has_tag_id = match result_layout {
Layout::Union(union_layout) => build_has_tag_id(env, function, *union_layout),
Layout::Builtin(Builtin::Bool) => {
// a `Result [] whatever`, so there is nothing to keep
// a `Result whatever []`, so there is nothing to keep
return empty_list(env);
}
_ => unreachable!(),
@ -644,7 +668,7 @@ pub fn list_keep_oks<'a, 'ctx, 'env>(
layout_width(env, before_layout),
layout_width(env, result_layout),
layout_width(env, after_layout),
has_tag_id.as_global_value().as_pointer_value().into(),
has_tag_id_helper(env, has_tag_id).into(),
dec_result_fn.as_global_value().as_pointer_value().into(),
],
bitcode::LIST_KEEP_OKS,
@ -692,7 +716,7 @@ pub fn list_keep_errs<'a, 'ctx, 'env>(
layout_width(env, before_layout),
layout_width(env, result_layout),
layout_width(env, after_layout),
has_tag_id.as_global_value().as_pointer_value().into(),
has_tag_id_helper(env, has_tag_id).into(),
dec_result_fn.as_global_value().as_pointer_value().into(),
],
bitcode::LIST_KEEP_ERRS,
@ -981,18 +1005,22 @@ pub fn list_find_unsafe<'a, 'ctx, 'env>(
// in the Zig definition called above, because we don't know the size of the
// element until user compile time, which is later than the compile time of bitcode defs.
let value_u8_ptr = env
let value_u8_ptr_int = env
.builder
.build_extract_value(result, 0, "get_value_ptr")
.build_extract_value(result, 0, "get_value_ptr_int")
.unwrap()
.into_pointer_value();
.into_int_value();
let found = env
let found_u8 = env
.builder
.build_extract_value(result, 1, "get_found")
.unwrap()
.into_int_value();
let found = env
.builder
.build_int_cast(found_u8, env.context.bool_type(), "found_as_bool");
let start_block = env.builder.get_insert_block().unwrap();
let parent = start_block.get_parent().unwrap();
@ -1006,14 +1034,13 @@ pub fn list_find_unsafe<'a, 'ctx, 'env>(
.build_conditional_branch(found, if_not_null, done_block);
env.builder.position_at_end(if_not_null);
let value_ptr = env
.builder
.build_bitcast(
value_u8_ptr,
value_bt.ptr_type(AddressSpace::Generic),
"from_opaque",
)
.into_pointer_value();
let value_ptr = env.builder.build_int_to_ptr(
value_u8_ptr_int,
value_bt.ptr_type(AddressSpace::Generic),
"get_value_ptr",
);
let loaded = env.builder.build_load(value_ptr, "load_value");
env.builder.build_unconditional_branch(done_block);

View File

@ -1,5 +1,5 @@
use crate::llvm::bitcode::{call_bitcode_fn, call_str_bitcode_fn, call_void_bitcode_fn};
use crate::llvm::build::{complex_bitcast, Env, Scope};
use crate::llvm::build::{Env, Scope};
use crate::llvm::build_list::{allocate_list, pass_update_mode, store_list};
use inkwell::builder::Builder;
use inkwell::values::{BasicValueEnum, IntValue, PointerValue, StructValue};

View File

@ -273,7 +273,10 @@ pub fn zig_str_type<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> StructType<'ct
}
pub fn zig_has_tag_id_type<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> StructType<'ctx> {
env.module.get_struct_type("list.HasTagId").unwrap()
let u8_ptr_t = env.context.i8_type().ptr_type(AddressSpace::Generic);
env.context
.struct_type(&[env.context.bool_type().into(), u8_ptr_t.into()], false)
}
pub fn zig_with_overflow_roc_dec<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> StructType<'ctx> {

View File

@ -800,7 +800,7 @@ fn list_walk_until_sum() {
#[test]
#[cfg(any(feature = "gen-llvm"))]
fn list_walk_imlements_position() {
fn list_walk_implements_position() {
assert_evals_to!(
r#"
Option a : [ Some a, None ]