wasm: implement List.sortWith

This commit is contained in:
Brian Carroll 2022-07-06 00:26:17 +01:00
parent 88bcb82fef
commit f132350ef3
No known key found for this signature in database
GPG key ID: 9CF4E3BF9C4722C7
4 changed files with 146 additions and 45 deletions

View file

@ -2018,7 +2018,7 @@ pub fn call_higher_order_lowlevel<'a>(
// We create a wrapper around the passed function, which just unboxes the arguments.
// This allows Zig builtins to have a generic pointer-based interface.
let source = {
let helper_proc_source = {
let passed_proc_layout = ProcLayout {
arguments: argument_layouts,
result: *result_layout,
@ -2031,7 +2031,10 @@ pub fn call_higher_order_lowlevel<'a>(
*name == fn_name.name() && layout == &passed_proc_layout
})
.unwrap();
ProcSource::HigherOrderWrapper(passed_proc_index)
match op {
ListSortWith { .. } => ProcSource::HigherOrderCompare(passed_proc_index),
_ => ProcSource::HigherOrderMapper(passed_proc_index),
}
};
let wrapper_sym = backend.create_symbol(&format!("#wrap#{:?}", fn_name));
let wrapper_layout = {
@ -2051,16 +2054,26 @@ pub fn call_higher_order_lowlevel<'a>(
.take(n_non_closure_args)
.map(Layout::Boxed),
);
wrapper_arg_layouts.push(Layout::Boxed(result_layout));
ProcLayout {
arguments: wrapper_arg_layouts.into_bump_slice(),
result: Layout::UNIT,
captures_niche: fn_name.captures_niche(),
if let ProcSource::HigherOrderMapper(_) = helper_proc_source {
// Our convention for mappers is that they write to the heap via the last argument
wrapper_arg_layouts.push(Layout::Boxed(result_layout));
ProcLayout {
arguments: wrapper_arg_layouts.into_bump_slice(),
result: Layout::UNIT,
captures_niche: fn_name.captures_niche(),
}
} else {
ProcLayout {
arguments: wrapper_arg_layouts.into_bump_slice(),
result: *result_layout,
captures_niche: fn_name.captures_niche(),
}
}
};
let wrapper_fn_idx = backend.register_helper_proc(wrapper_sym, wrapper_layout, source);
let wrapper_fn_idx =
backend.register_helper_proc(wrapper_sym, wrapper_layout, helper_proc_source);
let wrapper_fn_ptr = backend.get_fn_ptr(wrapper_fn_idx);
let inc_fn_ptr = match closure_data_layout {
Layout::Struct {
@ -2132,7 +2145,40 @@ pub fn call_higher_order_lowlevel<'a>(
*owns_captured_environment,
),
ListSortWith { .. } | DictWalk { .. } => todo!("{:?}", op),
ListSortWith { xs } => {
let elem_layout = unwrap_list_elem_layout(backend.storage.symbol_layouts[xs]);
let (element_width, alignment) = elem_layout.stack_size_and_alignment(TARGET_INFO);
let cb = &mut backend.code_builder;
// (return pointer) i32
// input: RocList, i64, i32
// caller: CompareFn, i32
// data: Opaque, i32
// inc_n_data: IncN, i32
// data_is_owned: bool, i32
// alignment: u32, i32
// element_width: usize, i32
backend.storage.load_symbols(cb, &[return_sym]);
backend.storage.load_symbol_zig(cb, *xs);
cb.i32_const(wrapper_fn_ptr);
if closure_data_exists {
backend.storage.load_symbols(cb, &[*captured_environment]);
} else {
// load_symbols assumes that a zero-size arg should be eliminated in code gen,
// but that's a specialization that our Zig code doesn't have! Pass a null pointer.
cb.i32_const(0);
}
cb.i32_const(inc_fn_ptr);
cb.i32_const(*owns_captured_environment as i32);
cb.i32_const(alignment as i32);
cb.i32_const(element_width as i32);
backend.call_host_fn_after_loading_args(bitcode::LIST_SORT_WITH, 9, false);
}
DictWalk { .. } => todo!("{:?}", op),
}
}