Merge remote-tracking branch 'origin/trunk' into list-str-capacity

This commit is contained in:
Folkert 2022-03-09 14:36:34 +01:00
commit 07063a8e18
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
458 changed files with 20371 additions and 8316 deletions

View file

@ -318,52 +318,70 @@ pub fn list_drop_at<'a, 'ctx, 'env>(
)
}
/// List.set : List elem, Nat, elem -> List elem
pub fn list_set<'a, 'ctx, 'env>(
/// List.replace_unsafe : List elem, Nat, elem -> { list: List elem, value: elem }
pub fn list_replace_unsafe<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_ids: &mut LayoutIds<'a>,
_layout_ids: &mut LayoutIds<'a>,
list: BasicValueEnum<'ctx>,
index: IntValue<'ctx>,
element: BasicValueEnum<'ctx>,
element_layout: &Layout<'a>,
update_mode: UpdateMode,
) -> BasicValueEnum<'ctx> {
let dec_element_fn = build_dec_wrapper(env, layout_ids, element_layout);
let element_type = basic_type_from_layout(env, element_layout);
let element_ptr = env
.builder
.build_alloca(element_type, "output_element_as_opaque");
let (length, bytes) = load_list(
env.builder,
list.into_struct_value(),
env.context.i8_type().ptr_type(AddressSpace::Generic),
);
let new_bytes = match update_mode {
UpdateMode::InPlace => call_bitcode_fn(
// Assume the bounds have already been checked earlier
// (e.g. by List.replace or List.set, which wrap List.#replaceUnsafe)
let new_list = match update_mode {
UpdateMode::InPlace => call_list_bitcode_fn(
env,
&[
bytes.into(),
list_to_c_abi(env, list).into(),
index.into(),
pass_element_as_opaque(env, element, *element_layout),
layout_width(env, element_layout),
dec_element_fn.as_global_value().as_pointer_value().into(),
pass_as_opaque(env, element_ptr),
],
bitcode::LIST_SET_IN_PLACE,
bitcode::LIST_REPLACE_IN_PLACE,
),
UpdateMode::Immutable => call_bitcode_fn(
UpdateMode::Immutable => call_list_bitcode_fn(
env,
&[
bytes.into(),
length.into(),
list_to_c_abi(env, list).into(),
env.alignment_intvalue(element_layout),
index.into(),
pass_element_as_opaque(env, element, *element_layout),
layout_width(env, element_layout),
dec_element_fn.as_global_value().as_pointer_value().into(),
pass_as_opaque(env, element_ptr),
],
bitcode::LIST_SET,
bitcode::LIST_REPLACE,
),
};
store_list(env, new_bytes.into_pointer_value(), length)
// Load the element and returned list into a struct.
let old_element = env.builder.build_load(element_ptr, "load_element");
let result = env
.context
.struct_type(
&[super::convert::zig_list_type(env).into(), element_type],
false,
)
.const_zero();
let result = env
.builder
.build_insert_value(result, new_list, 0, "insert_list")
.unwrap();
env.builder
.build_insert_value(result, old_element, 1, "insert_value")
.unwrap()
.into_struct_value()
.into()
}
fn bounds_check_comparison<'ctx>(