all tests passing

This commit is contained in:
Folkert 2021-11-07 14:56:24 +01:00
parent bd0f02c542
commit 180575852a
4 changed files with 65 additions and 14 deletions

View file

@ -2372,6 +2372,25 @@ fn list_literal<'a, 'ctx, 'env>(
}
}
pub fn load_roc_value<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout: Layout<'a>,
source: PointerValue<'ctx>,
name: &str,
) -> BasicValueEnum<'ctx> {
if layout.is_passed_by_reference() {
let alloca = env
.builder
.build_alloca(basic_type_from_layout(env, &layout), name);
store_roc_value(env, layout, alloca, source.into());
alloca.into()
} else {
env.builder.build_load(source, name)
}
}
pub fn store_roc_value_opaque<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout: Layout<'a>,
@ -3318,7 +3337,7 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx, 'env>(
.unwrap()
.into_pointer_value();
builder.build_store(output_arg, call_result);
store_roc_value(env, return_layout, output_arg, call_result);
builder.build_return(None);
c_function
@ -4218,8 +4237,10 @@ pub fn build_closure_caller<'a, 'ctx, 'env>(
// NOTE this may be incorrect in the long run
// here we load any argument that is a pointer
for param in evaluator_arguments.iter_mut() {
if param.is_pointer_value() {
let closure_layout = lambda_set.runtime_representation();
let layouts_it = arguments.iter().chain(std::iter::once(&closure_layout));
for (param, layout) in evaluator_arguments.iter_mut().zip(layouts_it) {
if param.is_pointer_value() && !layout.is_passed_by_reference() {
*param = builder.build_load(param.into_pointer_value(), "load_param");
}
}

View file

@ -780,7 +780,15 @@ fn hash_list<'a, 'ctx, 'env>(
env.builder.build_store(result, answer);
};
incrementing_elem_loop(env, parent, ptr, length, "current_index", loop_fn);
incrementing_elem_loop(
env,
parent,
*element_layout,
ptr,
length,
"current_index",
loop_fn,
);
env.builder.build_unconditional_branch(done_block);

View file

@ -17,6 +17,8 @@ use morphic_lib::UpdateMode;
use roc_builtins::bitcode;
use roc_mono::layout::{Builtin, Layout, LayoutIds};
use super::build::load_roc_value;
pub fn pass_update_mode<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
update_mode: UpdateMode,
@ -216,10 +218,15 @@ pub fn list_get_unsafe<'a, 'ctx, 'env>(
// Assume the bounds have already been checked earlier
// (e.g. by List.get or List.first, which wrap List.#getUnsafe)
let elem_ptr =
unsafe { builder.build_in_bounds_gep(array_data_ptr, &[elem_index], "elem") };
let elem_ptr = unsafe {
builder.build_in_bounds_gep(array_data_ptr, &[elem_index], "list_get_element")
};
let result = builder.build_load(elem_ptr, "List.get");
let result = if elem_layout.is_passed_by_reference() {
elem_ptr.into()
} else {
builder.build_load(elem_ptr, "list_get_load_element")
};
increment_refcount_layout(env, parent, layout_ids, 1, result, elem_layout);
@ -975,6 +982,7 @@ where
pub fn incrementing_elem_loop<'a, 'ctx, 'env, LoopFn>(
env: &Env<'a, 'ctx, 'env>,
parent: FunctionValue<'ctx>,
element_layout: Layout<'a>,
ptr: PointerValue<'ctx>,
len: IntValue<'ctx>,
index_name: &str,
@ -987,9 +995,14 @@ where
incrementing_index_loop(env, parent, len, index_name, |index| {
// The pointer to the element in the list
let elem_ptr = unsafe { builder.build_in_bounds_gep(ptr, &[index], "load_index") };
let element_ptr = unsafe { builder.build_in_bounds_gep(ptr, &[index], "load_index") };
let elem = builder.build_load(elem_ptr, "get_elem");
let elem = load_roc_value(
env,
element_layout,
element_ptr,
"incrementing_element_loop_load",
);
loop_fn(index, elem);
})

View file

@ -765,7 +765,15 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
);
};
incrementing_elem_loop(env, parent, ptr, len, "modify_rc_index", loop_fn);
incrementing_elem_loop(
env,
parent,
*element_layout,
ptr,
len,
"modify_rc_index",
loop_fn,
);
}
let refcount_ptr = PointerToRefcount::from_list_wrapper(env, original_wrapper);
@ -1616,7 +1624,6 @@ fn modify_refcount_union<'a, 'ctx, 'env>(
None => {
let basic_type = basic_type_from_layout_1(env, &layout);
let function_value = build_header(env, basic_type, mode, &fn_name);
dbg!(function_value);
modify_refcount_union_help(
env,
@ -1668,8 +1675,6 @@ fn modify_refcount_union_help<'a, 'ctx, 'env>(
let before_block = env.builder.get_insert_block().expect("to be in a function");
dbg!(fn_val, arg_ptr);
// read the tag_id
let tag_id_ptr = env
.builder
@ -1729,7 +1734,11 @@ fn modify_refcount_union_help<'a, 'ctx, 'env>(
.build_struct_gep(cast_tag_data_pointer, i as u32, "modify_tag_field")
.unwrap();
let field_value = env.builder.build_load(field_ptr, "field_value");
let field_value = if field_layout.is_passed_by_reference() {
field_ptr.into()
} else {
env.builder.build_load(field_ptr, "field_value")
};
modify_refcount_layout_help(
env,