mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
Merge pull request #1432 from rtfeldman/morphic-lowlevel
Morphic lowlevel
This commit is contained in:
commit
4a5df543a5
7 changed files with 73 additions and 44 deletions
|
@ -1009,7 +1009,25 @@ pub fn listConcat(list_a: RocList, list_b: RocList, alignment: u32, element_widt
|
|||
return output;
|
||||
}
|
||||
|
||||
// input: RocList,
|
||||
pub fn listSetInPlace(
|
||||
bytes: ?[*]u8,
|
||||
length: usize,
|
||||
alignment: u32,
|
||||
index: usize,
|
||||
element: Opaque,
|
||||
element_width: usize,
|
||||
dec: Dec,
|
||||
) callconv(.C) ?[*]u8 {
|
||||
// INVARIANT: bounds checking happens on the roc side
|
||||
//
|
||||
// at the time of writing, the function is implemented roughly as
|
||||
// `if inBounds then LowLevelListGet input index item else input`
|
||||
// so we don't do a bounds check here. Hence, the list is also non-empty,
|
||||
// because inserting into an empty list is always out of bounds
|
||||
|
||||
return listSetInPlaceHelp(bytes, length, alignment, index, element, element_width, dec);
|
||||
}
|
||||
|
||||
pub fn listSet(
|
||||
bytes: ?[*]u8,
|
||||
length: usize,
|
||||
|
@ -1028,7 +1046,21 @@ pub fn listSet(
|
|||
const ptr: [*]usize = @ptrCast([*]usize, @alignCast(8, bytes));
|
||||
|
||||
if ((ptr - 1)[0] == utils.REFCOUNT_ONE) {
|
||||
return listSetInPlaceHelp(bytes, length, alignment, index, element, element_width, dec);
|
||||
} else {
|
||||
return listSetImmutable(bytes, length, alignment, index, element, element_width, dec);
|
||||
}
|
||||
}
|
||||
|
||||
inline fn listSetInPlaceHelp(
|
||||
bytes: ?[*]u8,
|
||||
length: usize,
|
||||
alignment: u32,
|
||||
index: usize,
|
||||
element: Opaque,
|
||||
element_width: usize,
|
||||
dec: Dec,
|
||||
) ?[*]u8 {
|
||||
// the element we will replace
|
||||
var element_at_index = (bytes orelse undefined) + (index * element_width);
|
||||
|
||||
|
@ -1039,12 +1071,9 @@ pub fn listSet(
|
|||
@memcpy(element_at_index, element orelse undefined, element_width);
|
||||
|
||||
return bytes;
|
||||
} else {
|
||||
return listSetClone(bytes, length, alignment, index, element, element_width, dec);
|
||||
}
|
||||
}
|
||||
|
||||
inline fn listSetClone(
|
||||
inline fn listSetImmutable(
|
||||
old_bytes: ?[*]u8,
|
||||
length: usize,
|
||||
alignment: u32,
|
||||
|
@ -1053,8 +1082,6 @@ inline fn listSetClone(
|
|||
element_width: usize,
|
||||
dec: Dec,
|
||||
) ?[*]u8 {
|
||||
@setCold(true);
|
||||
|
||||
const data_bytes = length * element_width;
|
||||
|
||||
var new_bytes = utils.allocateWithRefcount(data_bytes, alignment);
|
||||
|
|
|
@ -30,6 +30,7 @@ comptime {
|
|||
exportListFn(list.listConcat, "concat");
|
||||
exportListFn(list.listDrop, "drop");
|
||||
exportListFn(list.listSet, "set");
|
||||
exportListFn(list.listSetInPlace, "set_in_place");
|
||||
exportListFn(list.listSwap, "swap");
|
||||
}
|
||||
|
||||
|
|
|
@ -65,3 +65,4 @@ pub const LIST_REVERSE: &str = "roc_builtins.list.reverse";
|
|||
pub const LIST_SORT_WITH: &str = "roc_builtins.list.sort_with";
|
||||
pub const LIST_CONCAT: &str = "roc_builtins.list.concat";
|
||||
pub const LIST_SET: &str = "roc_builtins.list.set";
|
||||
pub const LIST_SET_IN_PLACE: &str = "roc_builtins.list.set_in_place";
|
||||
|
|
|
@ -42,7 +42,9 @@ use inkwell::values::{
|
|||
};
|
||||
use inkwell::OptimizationLevel;
|
||||
use inkwell::{AddressSpace, IntPredicate};
|
||||
use morphic_lib::{CalleeSpecVar, FuncName, FuncSpec, FuncSpecSolutions, ModSolutions};
|
||||
use morphic_lib::{
|
||||
CalleeSpecVar, FuncName, FuncSpec, FuncSpecSolutions, ModSolutions, UpdateMode, UpdateModeVar,
|
||||
};
|
||||
use roc_builtins::bitcode;
|
||||
use roc_collections::all::{ImMap, MutMap, MutSet};
|
||||
use roc_module::ident::TagName;
|
||||
|
@ -826,8 +828,21 @@ pub fn build_exp_call<'a, 'ctx, 'env>(
|
|||
)
|
||||
}
|
||||
|
||||
CallType::LowLevel { op, update_mode: _ } => {
|
||||
run_low_level(env, layout_ids, scope, parent, layout, *op, arguments)
|
||||
CallType::LowLevel { op, update_mode } => {
|
||||
let bytes = update_mode.to_bytes();
|
||||
let update_var = UpdateModeVar(&bytes);
|
||||
let update_mode = func_spec_solutions.update_mode(update_var).ok();
|
||||
|
||||
run_low_level(
|
||||
env,
|
||||
layout_ids,
|
||||
scope,
|
||||
parent,
|
||||
layout,
|
||||
*op,
|
||||
arguments,
|
||||
update_mode,
|
||||
)
|
||||
}
|
||||
|
||||
CallType::HigherOrderLowLevel {
|
||||
|
@ -4190,6 +4205,7 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
layout: &Layout<'a>,
|
||||
op: LowLevel,
|
||||
args: &[Symbol],
|
||||
update_mode: Option<UpdateMode>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
use LowLevel::*;
|
||||
|
||||
|
@ -4648,27 +4664,6 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
wrapper_struct,
|
||||
)
|
||||
}
|
||||
ListSetInPlace => {
|
||||
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||
let (index, _) = load_symbol_and_layout(scope, &args[1]);
|
||||
let (element, _) = load_symbol_and_layout(scope, &args[2]);
|
||||
|
||||
match list_layout {
|
||||
Layout::Builtin(Builtin::EmptyList) => {
|
||||
// no elements, so nothing to remove
|
||||
empty_list(env)
|
||||
}
|
||||
Layout::Builtin(Builtin::List(element_layout)) => list_set(
|
||||
env,
|
||||
layout_ids,
|
||||
list,
|
||||
index.into_int_value(),
|
||||
element,
|
||||
element_layout,
|
||||
),
|
||||
_ => unreachable!("invalid dict layout"),
|
||||
}
|
||||
}
|
||||
ListSet => {
|
||||
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||
let (index, _) = load_symbol_and_layout(scope, &args[1]);
|
||||
|
@ -4686,6 +4681,7 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
index.into_int_value(),
|
||||
element,
|
||||
element_layout,
|
||||
update_mode.unwrap(),
|
||||
),
|
||||
_ => unreachable!("invalid dict layout"),
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ use inkwell::context::Context;
|
|||
use inkwell::types::{BasicType, BasicTypeEnum, PointerType};
|
||||
use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue, StructValue};
|
||||
use inkwell::{AddressSpace, IntPredicate};
|
||||
use morphic_lib::UpdateMode;
|
||||
use roc_builtins::bitcode;
|
||||
use roc_mono::layout::{Builtin, Layout, LayoutIds};
|
||||
|
||||
|
@ -350,6 +351,7 @@ pub fn list_set<'a, 'ctx, 'env>(
|
|||
index: IntValue<'ctx>,
|
||||
element: BasicValueEnum<'ctx>,
|
||||
element_layout: &'a Layout<'a>,
|
||||
update_mode: UpdateMode,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let dec_element_fn = build_dec_wrapper(env, layout_ids, element_layout);
|
||||
|
||||
|
@ -359,6 +361,11 @@ pub fn list_set<'a, 'ctx, 'env>(
|
|||
env.context.i8_type().ptr_type(AddressSpace::Generic),
|
||||
);
|
||||
|
||||
let symbol = match update_mode {
|
||||
UpdateMode::InPlace => bitcode::LIST_SET_IN_PLACE,
|
||||
UpdateMode::Immutable => bitcode::LIST_SET,
|
||||
};
|
||||
|
||||
let new_bytes = call_bitcode_fn(
|
||||
env,
|
||||
&[
|
||||
|
@ -370,7 +377,7 @@ pub fn list_set<'a, 'ctx, 'env>(
|
|||
layout_width(env, element_layout),
|
||||
dec_element_fn.as_global_value().as_pointer_value().into(),
|
||||
],
|
||||
&bitcode::LIST_SET,
|
||||
&symbol,
|
||||
);
|
||||
|
||||
store_list(env, new_bytes.into_pointer_value(), length)
|
||||
|
|
|
@ -18,7 +18,6 @@ pub enum LowLevel {
|
|||
ListLen,
|
||||
ListGetUnsafe,
|
||||
ListSet,
|
||||
ListSetInPlace,
|
||||
ListSingle,
|
||||
ListRepeat,
|
||||
ListReverse,
|
||||
|
@ -125,7 +124,6 @@ impl LowLevel {
|
|||
| ListLen
|
||||
| ListGetUnsafe
|
||||
| ListSet
|
||||
| ListSetInPlace
|
||||
| ListDrop
|
||||
| ListSingle
|
||||
| ListRepeat
|
||||
|
|
|
@ -760,7 +760,6 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] {
|
|||
match op {
|
||||
ListLen | StrIsEmpty | StrCountGraphemes => arena.alloc_slice_copy(&[borrowed]),
|
||||
ListSet => arena.alloc_slice_copy(&[owned, irrelevant, irrelevant]),
|
||||
ListSetInPlace => arena.alloc_slice_copy(&[owned, irrelevant, irrelevant]),
|
||||
ListGetUnsafe => arena.alloc_slice_copy(&[borrowed, irrelevant]),
|
||||
ListConcat => arena.alloc_slice_copy(&[owned, owned]),
|
||||
StrConcat => arena.alloc_slice_copy(&[owned, borrowed]),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue