Merge pull request #2153 from rtfeldman/llvm-build-macros

Cleanup dict/list element layout matches
This commit is contained in:
Richard Feldman 2021-12-12 17:50:29 -05:00 committed by GitHub
commit ae755d81fa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 154 additions and 207 deletions

View file

@ -2218,6 +2218,24 @@ pub fn allocate_with_refcount_help<'a, 'ctx, 'env>(
data_ptr
}
macro_rules! dict_key_value_layout {
($dict_layout:expr) => {
match $dict_layout {
Layout::Builtin(Builtin::Dict(key_layout, value_layout)) => (key_layout, value_layout),
_ => unreachable!("invalid dict layout"),
}
};
}
macro_rules! list_element_layout {
($list_layout:expr) => {
match $list_layout {
Layout::Builtin(Builtin::List(list_layout)) => *list_layout,
_ => unreachable!("invalid list layout"),
}
};
}
fn list_literal<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
scope: &Scope<'a, 'ctx>,
@ -5444,7 +5462,9 @@ fn run_low_level<'a, 'ctx, 'env>(
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
list_reverse(env, list, list_layout, update_mode)
let element_layout = list_element_layout!(list_layout);
list_reverse(env, list, element_layout, update_mode)
}
ListConcat => {
debug_assert_eq!(args.len(), 2);
@ -5453,7 +5473,9 @@ fn run_low_level<'a, 'ctx, 'env>(
let second_list = load_symbol(scope, &args[1]);
list_concat(env, parent, first_list, second_list, list_layout)
let element_layout = list_element_layout!(list_layout);
list_concat(env, first_list, second_list, element_layout)
}
ListContains => {
// List.contains : List elem, elem -> Bool
@ -5498,17 +5520,15 @@ fn run_low_level<'a, 'ctx, 'env>(
let index_1 = load_symbol(scope, &args[1]);
let index_2 = load_symbol(scope, &args[2]);
match list_layout {
Layout::Builtin(Builtin::List(element_layout)) => list_swap(
env,
original_wrapper,
index_1.into_int_value(),
index_2.into_int_value(),
element_layout,
update_mode,
),
_ => unreachable!("Invalid layout {:?} in List.swap", list_layout),
}
let element_layout = list_element_layout!(list_layout);
list_swap(
env,
original_wrapper,
index_1.into_int_value(),
index_2.into_int_value(),
element_layout,
update_mode,
)
}
ListSublist => {
// List.sublist : List elem, { start : Nat, len : Nat } -> List elem
@ -5523,17 +5543,15 @@ fn run_low_level<'a, 'ctx, 'env>(
let start = load_symbol(scope, &args[1]);
let len = load_symbol(scope, &args[2]);
match list_layout {
Layout::Builtin(Builtin::List(element_layout)) => list_sublist(
env,
layout_ids,
original_wrapper,
start.into_int_value(),
len.into_int_value(),
element_layout,
),
_ => unreachable!("Invalid layout {:?} in List.sublist", list_layout),
}
let element_layout = list_element_layout!(list_layout);
list_sublist(
env,
layout_ids,
original_wrapper,
start.into_int_value(),
len.into_int_value(),
element_layout,
)
}
ListDropAt => {
// List.dropAt : List elem, Nat -> List elem
@ -5544,16 +5562,14 @@ fn run_low_level<'a, 'ctx, 'env>(
let count = load_symbol(scope, &args[1]);
match list_layout {
Layout::Builtin(Builtin::List(element_layout)) => list_drop_at(
env,
layout_ids,
original_wrapper,
count.into_int_value(),
element_layout,
),
_ => unreachable!("Invalid layout {:?} in List.dropAt", list_layout),
}
let element_layout = list_element_layout!(list_layout);
list_drop_at(
env,
layout_ids,
original_wrapper,
count.into_int_value(),
element_layout,
)
}
ListPrepend => {
// List.prepend : List elem, elem -> List elem
@ -5570,7 +5586,44 @@ fn run_low_level<'a, 'ctx, 'env>(
let (list, outer_list_layout) = load_symbol_and_layout(scope, &args[0]);
list_join(env, parent, list, outer_list_layout)
let inner_list_layout = list_element_layout!(outer_list_layout);
let element_layout = list_element_layout!(inner_list_layout);
list_join(env, list, element_layout)
}
ListGetUnsafe => {
// List.get : List elem, Nat -> [ Ok elem, OutOfBounds ]*
debug_assert_eq!(args.len(), 2);
let (wrapper_struct, list_layout) = load_symbol_and_layout(scope, &args[0]);
let wrapper_struct = wrapper_struct.into_struct_value();
let elem_index = load_symbol(scope, &args[1]).into_int_value();
let element_layout = list_element_layout!(list_layout);
list_get_unsafe(
env,
layout_ids,
parent,
element_layout,
elem_index,
wrapper_struct,
)
}
ListSet => {
let list = load_symbol(scope, &args[0]);
let index = load_symbol(scope, &args[1]);
let (element, element_layout) = load_symbol_and_layout(scope, &args[2]);
list_set(
env,
layout_ids,
list,
index.into_int_value(),
element,
element_layout,
update_mode,
)
}
NumToStr => {
// Num.toStr : Num a -> Str
@ -5857,41 +5910,6 @@ fn run_low_level<'a, 'ctx, 'env>(
BasicValueEnum::IntValue(bool_val)
}
ListGetUnsafe => {
// List.get : List elem, Nat -> [ Ok elem, OutOfBounds ]*
debug_assert_eq!(args.len(), 2);
let (wrapper_struct, list_layout) = load_symbol_and_layout(scope, &args[0]);
let wrapper_struct = wrapper_struct.into_struct_value();
let elem_index = load_symbol(scope, &args[1]).into_int_value();
list_get_unsafe(
env,
layout_ids,
parent,
list_layout,
elem_index,
wrapper_struct,
)
}
ListSet => {
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::List(element_layout)) => list_set(
env,
layout_ids,
list,
index.into_int_value(),
element,
element_layout,
update_mode,
),
_ => unreachable!("invalid dict layout"),
}
}
Hash => {
debug_assert_eq!(args.len(), 2);
let seed = load_symbol(scope, &args[0]);
@ -5921,64 +5939,44 @@ fn run_low_level<'a, 'ctx, 'env>(
debug_assert_eq!(args.len(), 2);
let (dict, dict_layout) = load_symbol_and_layout(scope, &args[0]);
let (key, key_layout) = load_symbol_and_layout(scope, &args[1]);
let key = load_symbol(scope, &args[1]);
match dict_layout {
Layout::Builtin(Builtin::Dict(_, value_layout)) => {
dict_remove(env, layout_ids, dict, key, key_layout, value_layout)
}
_ => unreachable!("invalid dict layout"),
}
let (key_layout, value_layout) = dict_key_value_layout!(dict_layout);
dict_remove(env, layout_ids, dict, key, key_layout, value_layout)
}
DictContains => {
debug_assert_eq!(args.len(), 2);
let (dict, dict_layout) = load_symbol_and_layout(scope, &args[0]);
let (key, key_layout) = load_symbol_and_layout(scope, &args[1]);
let key = load_symbol(scope, &args[1]);
match dict_layout {
Layout::Builtin(Builtin::Dict(_, value_layout)) => {
dict_contains(env, layout_ids, dict, key, key_layout, value_layout)
}
_ => unreachable!("invalid dict layout"),
}
let (key_layout, value_layout) = dict_key_value_layout!(dict_layout);
dict_contains(env, layout_ids, dict, key, key_layout, value_layout)
}
DictGetUnsafe => {
debug_assert_eq!(args.len(), 2);
let (dict, dict_layout) = load_symbol_and_layout(scope, &args[0]);
let (key, key_layout) = load_symbol_and_layout(scope, &args[1]);
let key = load_symbol(scope, &args[1]);
match dict_layout {
Layout::Builtin(Builtin::Dict(_, value_layout)) => {
dict_get(env, layout_ids, dict, key, key_layout, value_layout)
}
_ => unreachable!("invalid dict layout"),
}
let (key_layout, value_layout) = dict_key_value_layout!(dict_layout);
dict_get(env, layout_ids, dict, key, key_layout, value_layout)
}
DictKeys => {
debug_assert_eq!(args.len(), 1);
let (dict, dict_layout) = load_symbol_and_layout(scope, &args[0]);
match dict_layout {
Layout::Builtin(Builtin::Dict(key_layout, value_layout)) => {
dict_keys(env, layout_ids, dict, key_layout, value_layout)
}
_ => unreachable!("invalid dict layout"),
}
let (key_layout, value_layout) = dict_key_value_layout!(dict_layout);
dict_keys(env, layout_ids, dict, key_layout, value_layout)
}
DictValues => {
debug_assert_eq!(args.len(), 1);
let (dict, dict_layout) = load_symbol_and_layout(scope, &args[0]);
match dict_layout {
Layout::Builtin(Builtin::Dict(key_layout, value_layout)) => {
dict_values(env, layout_ids, dict, key_layout, value_layout)
}
_ => unreachable!("invalid dict layout"),
}
let (key_layout, value_layout) = dict_key_value_layout!(dict_layout);
dict_values(env, layout_ids, dict, key_layout, value_layout)
}
DictUnion => {
debug_assert_eq!(args.len(), 2);
@ -5986,12 +5984,8 @@ fn run_low_level<'a, 'ctx, 'env>(
let (dict1, dict_layout) = load_symbol_and_layout(scope, &args[0]);
let (dict2, _) = load_symbol_and_layout(scope, &args[1]);
match dict_layout {
Layout::Builtin(Builtin::Dict(key_layout, value_layout)) => {
dict_union(env, layout_ids, dict1, dict2, key_layout, value_layout)
}
_ => unreachable!("invalid dict layout"),
}
let (key_layout, value_layout) = dict_key_value_layout!(dict_layout);
dict_union(env, layout_ids, dict1, dict2, key_layout, value_layout)
}
DictDifference => {
debug_assert_eq!(args.len(), 2);
@ -5999,12 +5993,8 @@ fn run_low_level<'a, 'ctx, 'env>(
let (dict1, dict_layout) = load_symbol_and_layout(scope, &args[0]);
let (dict2, _) = load_symbol_and_layout(scope, &args[1]);
match dict_layout {
Layout::Builtin(Builtin::Dict(key_layout, value_layout)) => {
dict_difference(env, layout_ids, dict1, dict2, key_layout, value_layout)
}
_ => unreachable!("invalid dict layout"),
}
let (key_layout, value_layout) = dict_key_value_layout!(dict_layout);
dict_difference(env, layout_ids, dict1, dict2, key_layout, value_layout)
}
DictIntersection => {
debug_assert_eq!(args.len(), 2);
@ -6012,24 +6002,16 @@ fn run_low_level<'a, 'ctx, 'env>(
let (dict1, dict_layout) = load_symbol_and_layout(scope, &args[0]);
let (dict2, _) = load_symbol_and_layout(scope, &args[1]);
match dict_layout {
Layout::Builtin(Builtin::Dict(key_layout, value_layout)) => {
dict_intersection(env, layout_ids, dict1, dict2, key_layout, value_layout)
}
_ => unreachable!("invalid dict layout"),
}
let (key_layout, value_layout) = dict_key_value_layout!(dict_layout);
dict_intersection(env, layout_ids, dict1, dict2, key_layout, value_layout)
}
SetFromList => {
debug_assert_eq!(args.len(), 1);
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
match list_layout {
Layout::Builtin(Builtin::List(key_layout)) => {
set_from_list(env, layout_ids, list, key_layout)
}
_ => unreachable!("invalid dict layout"),
}
let key_layout = list_element_layout!(list_layout);
set_from_list(env, layout_ids, list, key_layout)
}
ExpectTrue => {
debug_assert_eq!(args.len(), 1);
@ -6548,17 +6530,6 @@ pub fn build_num_binop<'a, 'ctx, 'env>(
{
use roc_mono::layout::Builtin::*;
let float_binop = |float_width| {
build_float_binop(
env,
parent,
float_width,
lhs_arg.into_float_value(),
rhs_arg.into_float_value(),
op,
)
};
match lhs_builtin {
Int(int_width) => build_int_binop(
env,
@ -6569,7 +6540,14 @@ pub fn build_num_binop<'a, 'ctx, 'env>(
op,
),
Float(float_width) => float_binop(*float_width),
Float(float_width) => build_float_binop(
env,
parent,
*float_width,
lhs_arg.into_float_value(),
rhs_arg.into_float_value(),
op,
),
Decimal => {
build_dec_binop(env, parent, lhs_arg, lhs_layout, rhs_arg, rhs_layout, op)

View file

@ -145,47 +145,33 @@ pub fn list_repeat<'a, 'ctx, 'env>(
/// List.join : List (List elem) -> List elem
pub fn list_join<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
_parent: FunctionValue<'ctx>,
outer_list: BasicValueEnum<'ctx>,
outer_list_layout: &Layout<'a>,
element_layout: &Layout<'a>,
) -> BasicValueEnum<'ctx> {
match outer_list_layout {
Layout::Builtin(Builtin::List(Layout::Builtin(Builtin::List(element_layout)))) => {
call_bitcode_fn_returns_list(
env,
&[
pass_list_cc(env, outer_list),
env.alignment_intvalue(element_layout),
layout_width(env, element_layout),
],
bitcode::LIST_JOIN,
)
}
_ => {
unreachable!("Invalid List layout for List.join {:?}", outer_list_layout);
}
}
call_bitcode_fn_returns_list(
env,
&[
pass_list_cc(env, outer_list),
env.alignment_intvalue(element_layout),
layout_width(env, element_layout),
],
bitcode::LIST_JOIN,
)
}
/// List.reverse : List elem -> List elem
pub fn list_reverse<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
list: BasicValueEnum<'ctx>,
list_layout: &Layout<'a>,
element_layout: &Layout<'a>,
update_mode: UpdateMode,
) -> BasicValueEnum<'ctx> {
let element_layout = match *list_layout {
Layout::Builtin(Builtin::List(elem_layout)) => *elem_layout,
_ => unreachable!("Invalid layout {:?} in List.reverse", list_layout),
};
call_bitcode_fn_returns_list(
env,
&[
pass_list_cc(env, list),
env.alignment_intvalue(&element_layout),
layout_width(env, &element_layout),
env.alignment_intvalue(element_layout),
layout_width(env, element_layout),
pass_update_mode(env, update_mode),
],
bitcode::LIST_REVERSE,
@ -196,38 +182,27 @@ pub fn list_get_unsafe<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_ids: &mut LayoutIds<'a>,
parent: FunctionValue<'ctx>,
list_layout: &Layout<'a>,
element_layout: &Layout<'a>,
elem_index: IntValue<'ctx>,
wrapper_struct: StructValue<'ctx>,
) -> BasicValueEnum<'ctx> {
let builder = env.builder;
match list_layout {
Layout::Builtin(Builtin::List(elem_layout)) => {
let elem_type = basic_type_from_layout(env, elem_layout);
let ptr_type = elem_type.ptr_type(AddressSpace::Generic);
// Load the pointer to the array data
let array_data_ptr = load_list_ptr(builder, wrapper_struct, ptr_type);
let elem_type = basic_type_from_layout(env, element_layout);
let ptr_type = elem_type.ptr_type(AddressSpace::Generic);
// Load the pointer to the array data
let array_data_ptr = load_list_ptr(builder, wrapper_struct, ptr_type);
// 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], "list_get_element")
};
// 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], "list_get_element") };
let result = load_roc_value(env, **elem_layout, elem_ptr, "list_get_load_element");
let result = load_roc_value(env, *element_layout, elem_ptr, "list_get_load_element");
increment_refcount_layout(env, parent, layout_ids, 1, result, elem_layout);
increment_refcount_layout(env, parent, layout_ids, 1, result, element_layout);
result
}
_ => {
unreachable!(
"Invalid List layout for ListGetUnsafe operation: {:?}",
list_layout
);
}
}
result
}
/// List.append : List elem, elem -> List elem
@ -346,7 +321,7 @@ pub fn list_set<'a, 'ctx, 'env>(
list: BasicValueEnum<'ctx>,
index: IntValue<'ctx>,
element: BasicValueEnum<'ctx>,
element_layout: &'a Layout<'a>,
element_layout: &Layout<'a>,
update_mode: UpdateMode,
) -> BasicValueEnum<'ctx> {
let dec_element_fn = build_dec_wrapper(env, layout_ids, element_layout);
@ -880,26 +855,20 @@ pub fn list_map4<'a, 'ctx, 'env>(
/// List.concat : List elem, List elem -> List elem
pub fn list_concat<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
_parent: FunctionValue<'ctx>,
first_list: BasicValueEnum<'ctx>,
second_list: BasicValueEnum<'ctx>,
list_layout: &Layout<'a>,
element_layout: &Layout<'a>,
) -> BasicValueEnum<'ctx> {
match list_layout {
Layout::Builtin(Builtin::List(elem_layout)) => call_bitcode_fn_returns_list(
env,
&[
pass_list_cc(env, first_list),
pass_list_cc(env, second_list),
env.alignment_intvalue(elem_layout),
layout_width(env, elem_layout),
],
bitcode::LIST_CONCAT,
),
_ => {
unreachable!("Invalid List layout for List.concat {:?}", list_layout);
}
}
call_bitcode_fn_returns_list(
env,
&[
pass_list_cc(env, first_list),
pass_list_cc(env, second_list),
env.alignment_intvalue(element_layout),
layout_width(env, element_layout),
],
bitcode::LIST_CONCAT,
)
}
/// List.any : List elem, \(elem -> Bool) -> Bool