switch to passing the copy function into zig (implement llvm)

This commit is contained in:
Brendan Hansknecht 2024-07-21 19:04:57 -07:00
parent d028aa3c74
commit 82764dc697
No known key found for this signature in database
GPG key ID: 0EA784685083E75B
5 changed files with 173 additions and 102 deletions

View file

@ -5,6 +5,7 @@ use crate::llvm::build::{
FAST_CALL_CONV,
};
use crate::llvm::convert::basic_type_from_layout;
use crate::llvm::memcpy::build_memcpy;
use crate::llvm::refcounting::{
decrement_refcount_layout, increment_n_refcount_layout, increment_refcount_layout,
};
@ -736,6 +737,78 @@ pub fn build_compare_wrapper<'a, 'ctx>(
function_value
}
pub fn build_copy_wrapper<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
layout: InLayout<'a>,
) -> FunctionValue<'ctx> {
let block = env.builder.get_insert_block().expect("to be in a function");
let di_location = env.builder.get_current_debug_location().unwrap();
let symbol = Symbol::GENERIC_COPY_REF;
let fn_name = layout_ids
.get(symbol, &layout_interner.get_repr(layout))
.to_symbol_string(symbol, &env.interns);
let function_value = match env.module.get_function(fn_name.as_str()) {
Some(function_value) => function_value,
None => {
let arg_type = env.context.i8_type().ptr_type(AddressSpace::default());
let function_value = crate::llvm::refcounting::build_header_help(
env,
&fn_name,
env.context.void_type().into(),
&[arg_type.into(), arg_type.into()],
);
// called from zig, must use C calling convention
function_value.set_call_conventions(C_CALL_CONV);
let kind_id = Attribute::get_named_enum_kind_id("alwaysinline");
debug_assert!(kind_id > 0);
let attr = env.context.create_enum_attribute(kind_id, 0);
function_value.add_attribute(AttributeLoc::Function, attr);
let entry = env.context.append_basic_block(function_value, "entry");
env.builder.position_at_end(entry);
debug_info_init!(env, function_value);
let mut it = function_value.get_param_iter();
let dst_ptr = it.next().unwrap().into_pointer_value();
let src_ptr = it.next().unwrap().into_pointer_value();
dst_ptr.set_name(Symbol::ARG_1.as_str(&env.interns));
src_ptr.set_name(Symbol::ARG_2.as_str(&env.interns));
let repr = layout_interner.get_repr(layout);
let value_type = basic_type_from_layout(env, layout_interner, repr)
.ptr_type(AddressSpace::default());
let dst_cast = env
.builder
.new_build_pointer_cast(dst_ptr, value_type, "load_opaque");
let src_cast = env
.builder
.new_build_pointer_cast(src_ptr, value_type, "load_opaque");
build_memcpy(env, layout_interner, repr, dst_cast, src_cast);
env.builder.new_build_return(None);
function_value
}
};
env.builder.position_at_end(block);
env.builder.set_current_debug_location(di_location);
function_value
}
enum BitcodeReturnValue<'ctx> {
List(PointerValue<'ctx>),
Str(PointerValue<'ctx>),

View file

@ -12,7 +12,7 @@ use roc_mono::layout::{
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, LayoutRepr, STLayoutInterner,
};
use super::bitcode::{build_inc_wrapper, call_list_bitcode_fn, BitcodeReturns};
use super::bitcode::{build_copy_wrapper, build_inc_wrapper, call_list_bitcode_fn, BitcodeReturns};
use super::build::{
create_entry_block_alloca, load_roc_value, store_roc_value, use_roc_value, BuilderExt,
};
@ -235,16 +235,19 @@ pub(crate) fn list_release_excess_capacity<'a, 'ctx>(
pub(crate) fn list_append_unsafe<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
original_wrapper: StructValue<'ctx>,
element: BasicValueEnum<'ctx>,
element_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
let copy_fn = build_copy_wrapper(env, layout_interner, layout_ids, element_layout);
call_list_bitcode_fn_1(
env,
original_wrapper,
&[
pass_element_as_opaque(env, layout_interner, element, element_layout),
layout_width(env, layout_interner, element_layout),
copy_fn.as_global_value().as_pointer_value().into(),
],
bitcode::LIST_APPEND_UNSAFE,
)
@ -260,6 +263,7 @@ pub(crate) fn list_prepend<'a, 'ctx>(
element_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
let inc_element_fn = build_inc_wrapper(env, layout_interner, layout_ids, element_layout);
let copy_fn = build_copy_wrapper(env, layout_interner, layout_ids, element_layout);
call_list_bitcode_fn_1(
env,
original_wrapper,
@ -269,6 +273,7 @@ pub(crate) fn list_prepend<'a, 'ctx>(
layout_width(env, layout_interner, element_layout),
layout_refcounted(env, layout_interner, element_layout),
inc_element_fn.as_global_value().as_pointer_value().into(),
copy_fn.as_global_value().as_pointer_value().into(),
],
bitcode::LIST_PREPEND,
)
@ -310,6 +315,7 @@ pub(crate) fn list_swap<'a, 'ctx>(
) -> BasicValueEnum<'ctx> {
let inc_element_fn = build_inc_wrapper(env, layout_interner, layout_ids, element_layout);
let dec_element_fn = build_dec_wrapper(env, layout_interner, layout_ids, element_layout);
let copy_fn = build_copy_wrapper(env, layout_interner, layout_ids, element_layout);
call_list_bitcode_fn_1(
env,
@ -323,6 +329,7 @@ pub(crate) fn list_swap<'a, 'ctx>(
inc_element_fn.as_global_value().as_pointer_value().into(),
dec_element_fn.as_global_value().as_pointer_value().into(),
pass_update_mode(env, update_mode),
copy_fn.as_global_value().as_pointer_value().into(),
],
bitcode::LIST_SWAP,
)
@ -397,6 +404,7 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx>(
layout_interner.get_repr(element_layout),
);
let element_ptr = create_entry_block_alloca(env, element_type, "output_element_as_opaque");
let copy_fn = build_copy_wrapper(env, layout_interner, layout_ids, element_layout);
// Assume the bounds have already been checked earlier
// (e.g. by List.replace or List.set, which wrap List.#replaceUnsafe)
@ -409,6 +417,7 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx>(
pass_element_as_opaque(env, layout_interner, element, element_layout),
layout_width(env, layout_interner, element_layout),
pass_as_opaque(env, element_ptr),
copy_fn.as_global_value().as_pointer_value().into(),
],
bitcode::LIST_REPLACE_IN_PLACE,
),
@ -429,6 +438,7 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx>(
inc_element_fn.as_global_value().as_pointer_value().into(),
dec_element_fn.as_global_value().as_pointer_value().into(),
pass_as_opaque(env, element_ptr),
copy_fn.as_global_value().as_pointer_value().into(),
],
bitcode::LIST_REPLACE,
)
@ -536,6 +546,7 @@ pub(crate) fn list_sort_with<'a, 'ctx>(
) -> BasicValueEnum<'ctx> {
let inc_element_fn = build_inc_wrapper(env, layout_interner, layout_ids, element_layout);
let dec_element_fn = build_dec_wrapper(env, layout_interner, layout_ids, element_layout);
let copy_fn = build_copy_wrapper(env, layout_interner, layout_ids, element_layout);
call_list_bitcode_fn_1(
env,
list.into_struct_value(),
@ -549,6 +560,7 @@ pub(crate) fn list_sort_with<'a, 'ctx>(
layout_refcounted(env, layout_interner, element_layout),
inc_element_fn.as_global_value().as_pointer_value().into(),
dec_element_fn.as_global_value().as_pointer_value().into(),
copy_fn.as_global_value().as_pointer_value().into(),
],
bitcode::LIST_SORT_WITH,
)

View file

@ -670,7 +670,14 @@ pub(crate) fn run_low_level<'a, 'ctx>(
let original_wrapper = scope.load_symbol(&args[0]).into_struct_value();
let (elem, elem_layout) = scope.load_symbol_and_layout(&args[1]);
list_append_unsafe(env, layout_interner, original_wrapper, elem, elem_layout)
list_append_unsafe(
env,
layout_interner,
layout_ids,
original_wrapper,
elem,
elem_layout,
)
}
ListPrepend => {
// List.prepend : List elem, elem -> List elem