mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 00:01:16 +00:00
Merge pull request #2091 from rtfeldman/remove-empty-layouts
Remove empty layouts
This commit is contained in:
commit
f80409800d
17 changed files with 280 additions and 366 deletions
|
@ -1,6 +1,8 @@
|
|||
/// Helpers for interacting with the zig that generates bitcode
|
||||
use crate::debug_info_init;
|
||||
use crate::llvm::build::{struct_from_fields, Env, C_CALL_CONV, FAST_CALL_CONV, TAG_DATA_INDEX};
|
||||
use crate::llvm::build::{
|
||||
load_roc_value, struct_from_fields, Env, C_CALL_CONV, FAST_CALL_CONV, TAG_DATA_INDEX,
|
||||
};
|
||||
use crate::llvm::convert::basic_type_from_layout;
|
||||
use crate::llvm::refcounting::{
|
||||
decrement_refcount_layout, increment_n_refcount_layout, increment_refcount_layout,
|
||||
|
@ -506,8 +508,9 @@ pub fn build_eq_wrapper<'a, 'ctx, 'env>(
|
|||
.build_bitcast(value_ptr2, value_type, "load_opaque")
|
||||
.into_pointer_value();
|
||||
|
||||
let value1 = env.builder.build_load(value_cast1, "load_opaque");
|
||||
let value2 = env.builder.build_load(value_cast2, "load_opaque");
|
||||
// load_roc_value(env, *element_layout, elem_ptr, "get_elem")
|
||||
let value1 = load_roc_value(env, *layout, value_cast1, "load_opaque");
|
||||
let value2 = load_roc_value(env, *layout, value_cast2, "load_opaque");
|
||||
|
||||
let result =
|
||||
crate::llvm::compare::generic_eq(env, layout_ids, value1, value2, layout, layout);
|
||||
|
|
|
@ -8,11 +8,11 @@ use crate::llvm::build_dict::{
|
|||
};
|
||||
use crate::llvm::build_hash::generic_hash;
|
||||
use crate::llvm::build_list::{
|
||||
self, allocate_list, empty_list, empty_polymorphic_list, list_all, list_any, list_append,
|
||||
list_concat, list_contains, list_drop_at, list_find_trivial_not_found, list_find_unsafe,
|
||||
list_get_unsafe, list_join, list_keep_errs, list_keep_if, list_keep_oks, list_len, list_map,
|
||||
list_map2, list_map3, list_map4, list_map_with_index, list_prepend, list_range, list_repeat,
|
||||
list_reverse, list_set, list_single, list_sort_with, list_sublist, list_swap,
|
||||
self, allocate_list, empty_polymorphic_list, list_all, list_any, list_append, list_concat,
|
||||
list_contains, list_drop_at, list_find_unsafe, list_get_unsafe, list_join, list_keep_errs,
|
||||
list_keep_if, list_keep_oks, list_len, list_map, list_map2, list_map3, list_map4,
|
||||
list_map_with_index, list_prepend, list_range, list_repeat, list_reverse, list_set,
|
||||
list_single, list_sort_with, list_sublist, list_swap,
|
||||
};
|
||||
use crate::llvm::build_str::{
|
||||
empty_str, str_concat, str_count_graphemes, str_ends_with, str_from_float, str_from_int,
|
||||
|
@ -4726,7 +4726,6 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
let (function, closure, closure_layout) = function_details!();
|
||||
|
||||
match list_layout {
|
||||
Layout::Builtin(Builtin::EmptyList) => default,
|
||||
Layout::Builtin(Builtin::List(element_layout)) => {
|
||||
let argument_layouts = &[*default_layout, **element_layout];
|
||||
|
||||
|
@ -4765,7 +4764,6 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
let (function, closure, closure_layout) = function_details!();
|
||||
|
||||
match (list_layout, return_layout) {
|
||||
(Layout::Builtin(Builtin::EmptyList), _) => empty_list(env),
|
||||
(
|
||||
Layout::Builtin(Builtin::List(element_layout)),
|
||||
Layout::Builtin(Builtin::List(result_layout)),
|
||||
|
@ -4824,8 +4822,6 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
result_layout,
|
||||
)
|
||||
}
|
||||
(Layout::Builtin(Builtin::EmptyList), _, _)
|
||||
| (_, Layout::Builtin(Builtin::EmptyList), _) => empty_list(env),
|
||||
_ => unreachable!("invalid list layout"),
|
||||
}
|
||||
}
|
||||
|
@ -4870,9 +4866,6 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
result_layout,
|
||||
)
|
||||
}
|
||||
(Layout::Builtin(Builtin::EmptyList), _, _, _)
|
||||
| (_, Layout::Builtin(Builtin::EmptyList), _, _)
|
||||
| (_, _, Layout::Builtin(Builtin::EmptyList), _) => empty_list(env),
|
||||
_ => unreachable!("invalid list layout"),
|
||||
}
|
||||
}
|
||||
|
@ -4931,10 +4924,6 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
result_layout,
|
||||
)
|
||||
}
|
||||
(Layout::Builtin(Builtin::EmptyList), _, _, _, _)
|
||||
| (_, Layout::Builtin(Builtin::EmptyList), _, _, _)
|
||||
| (_, _, Layout::Builtin(Builtin::EmptyList), _, _)
|
||||
| (_, _, _, Layout::Builtin(Builtin::EmptyList), _) => empty_list(env),
|
||||
_ => unreachable!("invalid list layout"),
|
||||
}
|
||||
}
|
||||
|
@ -4945,7 +4934,6 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
let (function, closure, closure_layout) = function_details!();
|
||||
|
||||
match (list_layout, return_layout) {
|
||||
(Layout::Builtin(Builtin::EmptyList), _) => empty_list(env),
|
||||
(
|
||||
Layout::Builtin(Builtin::List(element_layout)),
|
||||
Layout::Builtin(Builtin::List(result_layout)),
|
||||
|
@ -4975,7 +4963,6 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
let (function, closure, closure_layout) = function_details!();
|
||||
|
||||
match list_layout {
|
||||
Layout::Builtin(Builtin::EmptyList) => empty_list(env),
|
||||
Layout::Builtin(Builtin::List(element_layout)) => {
|
||||
let argument_layouts = &[**element_layout];
|
||||
|
||||
|
@ -5002,8 +4989,6 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
let (function, closure, closure_layout) = function_details!();
|
||||
|
||||
match (list_layout, return_layout) {
|
||||
(_, Layout::Builtin(Builtin::EmptyList))
|
||||
| (Layout::Builtin(Builtin::EmptyList), _) => empty_list(env),
|
||||
(
|
||||
Layout::Builtin(Builtin::List(before_layout)),
|
||||
Layout::Builtin(Builtin::List(after_layout)),
|
||||
|
@ -5043,8 +5028,6 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
let (function, closure, closure_layout) = function_details!();
|
||||
|
||||
match (list_layout, return_layout) {
|
||||
(_, Layout::Builtin(Builtin::EmptyList))
|
||||
| (Layout::Builtin(Builtin::EmptyList), _) => empty_list(env),
|
||||
(
|
||||
Layout::Builtin(Builtin::List(before_layout)),
|
||||
Layout::Builtin(Builtin::List(after_layout)),
|
||||
|
@ -5093,7 +5076,6 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
let (function, closure, closure_layout) = function_details!();
|
||||
|
||||
match list_layout {
|
||||
Layout::Builtin(Builtin::EmptyList) => empty_list(env),
|
||||
Layout::Builtin(Builtin::List(element_layout)) => {
|
||||
use crate::llvm::bitcode::build_compare_wrapper;
|
||||
|
||||
|
@ -5131,7 +5113,6 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
let (function, closure, closure_layout) = function_details!();
|
||||
|
||||
match list_layout {
|
||||
Layout::Builtin(Builtin::EmptyList) => env.context.bool_type().const_zero().into(),
|
||||
Layout::Builtin(Builtin::List(element_layout)) => {
|
||||
let argument_layouts = &[**element_layout];
|
||||
|
||||
|
@ -5156,9 +5137,6 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
let (function, closure, closure_layout) = function_details!();
|
||||
|
||||
match list_layout {
|
||||
Layout::Builtin(Builtin::EmptyList) => {
|
||||
env.context.bool_type().const_int(1, false).into()
|
||||
}
|
||||
Layout::Builtin(Builtin::List(element_layout)) => {
|
||||
let argument_layouts = &[**element_layout];
|
||||
|
||||
|
@ -5184,15 +5162,6 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
let (function, closure, closure_layout) = function_details!();
|
||||
|
||||
match list_layout {
|
||||
Layout::Builtin(Builtin::EmptyList) => {
|
||||
// Returns { found: False, elem: \empty }, where the `elem` field is zero-sized.
|
||||
// NB: currently we never hit this case, since the only caller of this
|
||||
// lowlevel, namely List.find, will fail during monomorphization when there is no
|
||||
// concrete list element type. This is because List.find returns a
|
||||
// `Result elem [ NotFound ]*`, and we can't figure out the size of that if
|
||||
// `elem` is not concrete.
|
||||
list_find_trivial_not_found(env)
|
||||
}
|
||||
Layout::Builtin(Builtin::List(element_layout)) => {
|
||||
let argument_layouts = &[**element_layout];
|
||||
let roc_function_call = roc_function_call(
|
||||
|
@ -5217,10 +5186,6 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
let (function, closure, closure_layout) = function_details!();
|
||||
|
||||
match dict_layout {
|
||||
Layout::Builtin(Builtin::EmptyDict) => {
|
||||
// no elements, so `key` is not in here
|
||||
panic!("key type unknown")
|
||||
}
|
||||
Layout::Builtin(Builtin::Dict(key_layout, value_layout)) => {
|
||||
let argument_layouts = &[*default_layout, **key_layout, **value_layout];
|
||||
|
||||
|
@ -5484,7 +5449,6 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
let index_2 = load_symbol(scope, &args[2]);
|
||||
|
||||
match list_layout {
|
||||
Layout::Builtin(Builtin::EmptyList) => empty_list(env),
|
||||
Layout::Builtin(Builtin::List(element_layout)) => list_swap(
|
||||
env,
|
||||
original_wrapper,
|
||||
|
@ -5510,7 +5474,6 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
let len = load_symbol(scope, &args[2]);
|
||||
|
||||
match list_layout {
|
||||
Layout::Builtin(Builtin::EmptyList) => empty_list(env),
|
||||
Layout::Builtin(Builtin::List(element_layout)) => list_sublist(
|
||||
env,
|
||||
layout_ids,
|
||||
|
@ -5532,7 +5495,6 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
let count = load_symbol(scope, &args[1]);
|
||||
|
||||
match list_layout {
|
||||
Layout::Builtin(Builtin::EmptyList) => empty_list(env),
|
||||
Layout::Builtin(Builtin::List(element_layout)) => list_drop_at(
|
||||
env,
|
||||
layout_ids,
|
||||
|
@ -5846,10 +5808,6 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
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,
|
||||
|
@ -5894,10 +5852,6 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
let (key, key_layout) = load_symbol_and_layout(scope, &args[1]);
|
||||
|
||||
match dict_layout {
|
||||
Layout::Builtin(Builtin::EmptyDict) => {
|
||||
// no elements, so nothing to remove
|
||||
dict
|
||||
}
|
||||
Layout::Builtin(Builtin::Dict(_, value_layout)) => {
|
||||
dict_remove(env, layout_ids, dict, key, key_layout, value_layout)
|
||||
}
|
||||
|
@ -5911,10 +5865,6 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
let (key, key_layout) = load_symbol_and_layout(scope, &args[1]);
|
||||
|
||||
match dict_layout {
|
||||
Layout::Builtin(Builtin::EmptyDict) => {
|
||||
// no elements, so `key` is not in here
|
||||
env.context.bool_type().const_zero().into()
|
||||
}
|
||||
Layout::Builtin(Builtin::Dict(_, value_layout)) => {
|
||||
dict_contains(env, layout_ids, dict, key, key_layout, value_layout)
|
||||
}
|
||||
|
@ -5928,10 +5878,6 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
let (key, key_layout) = load_symbol_and_layout(scope, &args[1]);
|
||||
|
||||
match dict_layout {
|
||||
Layout::Builtin(Builtin::EmptyDict) => {
|
||||
unreachable!("we can't make up a layout for the return value");
|
||||
// in other words, make sure to check whether the dict is empty first
|
||||
}
|
||||
Layout::Builtin(Builtin::Dict(_, value_layout)) => {
|
||||
dict_get(env, layout_ids, dict, key, key_layout, value_layout)
|
||||
}
|
||||
|
@ -5944,10 +5890,6 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
let (dict, dict_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||
|
||||
match dict_layout {
|
||||
Layout::Builtin(Builtin::EmptyDict) => {
|
||||
// no elements, so `key` is not in here
|
||||
empty_list(env)
|
||||
}
|
||||
Layout::Builtin(Builtin::Dict(key_layout, value_layout)) => {
|
||||
dict_keys(env, layout_ids, dict, key_layout, value_layout)
|
||||
}
|
||||
|
@ -5960,10 +5902,6 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
let (dict, dict_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||
|
||||
match dict_layout {
|
||||
Layout::Builtin(Builtin::EmptyDict) => {
|
||||
// no elements, so `key` is not in here
|
||||
empty_list(env)
|
||||
}
|
||||
Layout::Builtin(Builtin::Dict(key_layout, value_layout)) => {
|
||||
dict_values(env, layout_ids, dict, key_layout, value_layout)
|
||||
}
|
||||
|
@ -5977,10 +5915,6 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
let (dict2, _) = load_symbol_and_layout(scope, &args[1]);
|
||||
|
||||
match dict_layout {
|
||||
Layout::Builtin(Builtin::EmptyDict) => {
|
||||
// no elements, so `key` is not in here
|
||||
panic!("key type unknown")
|
||||
}
|
||||
Layout::Builtin(Builtin::Dict(key_layout, value_layout)) => {
|
||||
dict_union(env, layout_ids, dict1, dict2, key_layout, value_layout)
|
||||
}
|
||||
|
@ -5994,10 +5928,6 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
let (dict2, _) = load_symbol_and_layout(scope, &args[1]);
|
||||
|
||||
match dict_layout {
|
||||
Layout::Builtin(Builtin::EmptyDict) => {
|
||||
// no elements, so `key` is not in here
|
||||
panic!("key type unknown")
|
||||
}
|
||||
Layout::Builtin(Builtin::Dict(key_layout, value_layout)) => {
|
||||
dict_difference(env, layout_ids, dict1, dict2, key_layout, value_layout)
|
||||
}
|
||||
|
@ -6011,10 +5941,6 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
let (dict2, _) = load_symbol_and_layout(scope, &args[1]);
|
||||
|
||||
match dict_layout {
|
||||
Layout::Builtin(Builtin::EmptyDict) => {
|
||||
// no elements, so `key` is not in here
|
||||
panic!("key type unknown")
|
||||
}
|
||||
Layout::Builtin(Builtin::Dict(key_layout, value_layout)) => {
|
||||
dict_intersection(env, layout_ids, dict1, dict2, key_layout, value_layout)
|
||||
}
|
||||
|
@ -6027,7 +5953,6 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||
|
||||
match list_layout {
|
||||
Layout::Builtin(Builtin::EmptyList) => dict_empty(env),
|
||||
Layout::Builtin(Builtin::List(key_layout)) => {
|
||||
set_from_list(env, layout_ids, list, key_layout)
|
||||
}
|
||||
|
@ -6123,10 +6048,8 @@ fn to_cc_type_builtin<'a, 'ctx, 'env>(
|
|||
Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal => {
|
||||
basic_type_from_builtin(env, builtin)
|
||||
}
|
||||
Builtin::Str | Builtin::EmptyStr | Builtin::List(_) | Builtin::EmptyList => {
|
||||
env.str_list_c_abi().into()
|
||||
}
|
||||
Builtin::Dict(_, _) | Builtin::Set(_) | Builtin::EmptyDict | Builtin::EmptySet => {
|
||||
Builtin::Str | Builtin::List(_) => env.str_list_c_abi().into(),
|
||||
Builtin::Dict(_, _) | Builtin::Set(_) => {
|
||||
// TODO verify this is what actually happens
|
||||
basic_type_from_builtin(env, builtin)
|
||||
}
|
||||
|
|
|
@ -3,7 +3,8 @@ use crate::llvm::bitcode::{
|
|||
build_dec_wrapper, build_eq_wrapper, build_inc_wrapper, call_bitcode_fn, call_void_bitcode_fn,
|
||||
};
|
||||
use crate::llvm::build::{
|
||||
complex_bitcast, load_symbol, load_symbol_and_layout, Env, RocFunctionCall, Scope,
|
||||
complex_bitcast, load_roc_value, load_symbol, load_symbol_and_layout, Env, RocFunctionCall,
|
||||
Scope,
|
||||
};
|
||||
use crate::llvm::build_list::{layout_width, pass_as_opaque};
|
||||
use crate::llvm::convert::{basic_type_from_layout, zig_dict_type, zig_list_type};
|
||||
|
@ -64,7 +65,6 @@ pub fn dict_len<'a, 'ctx, 'env>(
|
|||
.build_int_cast(length_i64.into_int_value(), env.ptr_int(), "to_usize")
|
||||
.into()
|
||||
}
|
||||
Layout::Builtin(Builtin::EmptyDict) => env.ptr_int().const_zero().into(),
|
||||
_ => unreachable!("Invalid layout given to Dict.len : {:?}", dict_layout),
|
||||
}
|
||||
}
|
||||
|
@ -811,7 +811,7 @@ fn build_hash_wrapper<'a, 'ctx, 'env>(
|
|||
.build_bitcast(value_ptr, value_type, "load_opaque")
|
||||
.into_pointer_value();
|
||||
|
||||
let val_arg = env.builder.build_load(value_cast, "load_opaque");
|
||||
let val_arg = load_roc_value(env, *layout, value_cast, "load_opaque");
|
||||
|
||||
let result =
|
||||
crate::llvm::build_hash::generic_hash(env, layout_ids, seed_arg, val_arg, layout);
|
||||
|
|
|
@ -136,9 +136,6 @@ fn hash_builtin<'a, 'ctx, 'env>(
|
|||
)
|
||||
.into_int_value()
|
||||
}
|
||||
Builtin::EmptyStr | Builtin::EmptyDict | Builtin::EmptyList | Builtin::EmptySet => {
|
||||
hash_empty_collection(seed)
|
||||
}
|
||||
|
||||
Builtin::Dict(_, _) => {
|
||||
todo!("Implement hash for Dict")
|
||||
|
@ -330,7 +327,6 @@ fn build_hash_tag<'a, 'ctx, 'env>(
|
|||
let seed_type = env.context.i64_type();
|
||||
|
||||
let arg_type = basic_type_from_layout_1(env, layout);
|
||||
dbg!(layout, arg_type);
|
||||
|
||||
let function_value = crate::llvm::refcounting::build_header_help(
|
||||
env,
|
||||
|
@ -446,9 +442,15 @@ fn hash_tag<'a, 'ctx, 'env>(
|
|||
|
||||
env.builder.position_at_end(entry_block);
|
||||
|
||||
let default = cases.pop().unwrap().1;
|
||||
|
||||
env.builder.build_switch(current_tag_id, default, &cases);
|
||||
match cases.pop() {
|
||||
Some((_, default)) => {
|
||||
env.builder.build_switch(current_tag_id, default, &cases);
|
||||
}
|
||||
None => {
|
||||
// we're hashing empty tag unions; this code is effectively unreachable
|
||||
env.builder.build_unreachable();
|
||||
}
|
||||
}
|
||||
}
|
||||
Recursive(tags) => {
|
||||
let current_tag_id = get_tag_id(env, parent, union_layout, tag);
|
||||
|
@ -793,10 +795,6 @@ fn hash_null(seed: IntValue<'_>) -> IntValue<'_> {
|
|||
seed
|
||||
}
|
||||
|
||||
fn hash_empty_collection(seed: IntValue<'_>) -> IntValue<'_> {
|
||||
seed
|
||||
}
|
||||
|
||||
fn hash_ptr_to_struct<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
|
|
|
@ -150,12 +150,6 @@ pub fn list_join<'a, 'ctx, 'env>(
|
|||
outer_list_layout: &Layout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
match outer_list_layout {
|
||||
Layout::Builtin(Builtin::EmptyList)
|
||||
| Layout::Builtin(Builtin::List(Layout::Builtin(Builtin::EmptyList))) => {
|
||||
// If the input list is empty, or if it is a list of empty lists
|
||||
// then simply return an empty list
|
||||
empty_list(env)
|
||||
}
|
||||
Layout::Builtin(Builtin::List(Layout::Builtin(Builtin::List(element_layout)))) => {
|
||||
call_bitcode_fn_returns_list(
|
||||
env,
|
||||
|
@ -181,11 +175,6 @@ pub fn list_reverse<'a, 'ctx, 'env>(
|
|||
update_mode: UpdateMode,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let element_layout = match *list_layout {
|
||||
Layout::Builtin(Builtin::EmptyList) => {
|
||||
// this pointer will never actually be dereferenced
|
||||
Layout::i64()
|
||||
}
|
||||
|
||||
Layout::Builtin(Builtin::List(elem_layout)) => *elem_layout,
|
||||
|
||||
_ => unreachable!("Invalid layout {:?} in List.reverse", list_layout),
|
||||
|
@ -596,6 +585,14 @@ pub fn list_keep_if<'a, 'ctx, 'env>(
|
|||
)
|
||||
}
|
||||
|
||||
fn empty_list<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> BasicValueEnum<'ctx> {
|
||||
let struct_type = super::convert::zig_list_type(env);
|
||||
|
||||
// The pointer should be null (aka zero) and the length should be zero,
|
||||
// so the whole struct should be a const_zero
|
||||
BasicValueEnum::StructValue(struct_type.const_zero())
|
||||
}
|
||||
|
||||
/// List.keepOks : List before, (before -> Result after *) -> List after
|
||||
pub fn list_keep_oks<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
|
@ -618,6 +615,10 @@ pub fn list_keep_oks<'a, 'ctx, 'env>(
|
|||
|
||||
let has_tag_id = match result_layout {
|
||||
Layout::Union(union_layout) => build_has_tag_id(env, function, *union_layout),
|
||||
Layout::Builtin(Builtin::Bool) => {
|
||||
// a `Result [] whatever`, so there is nothing to keep
|
||||
return empty_list(env);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
|
@ -662,6 +663,10 @@ pub fn list_keep_errs<'a, 'ctx, 'env>(
|
|||
|
||||
let has_tag_id = match result_layout {
|
||||
Layout::Union(union_layout) => build_has_tag_id(env, function, *union_layout),
|
||||
Layout::Builtin(Builtin::Bool) => {
|
||||
// a `Result whatever []`, so there is nothing to keep
|
||||
return empty_list(env);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
|
@ -881,11 +886,6 @@ pub fn list_concat<'a, 'ctx, 'env>(
|
|||
list_layout: &Layout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
match list_layout {
|
||||
Layout::Builtin(Builtin::EmptyList) => {
|
||||
// If the input list is empty, or if it is a list of empty lists
|
||||
// then simply return an empty list
|
||||
empty_list(env)
|
||||
}
|
||||
Layout::Builtin(Builtin::List(elem_layout)) => call_bitcode_fn_returns_list(
|
||||
env,
|
||||
&[
|
||||
|
@ -1038,29 +1038,6 @@ pub fn list_find_unsafe<'a, 'ctx, 'env>(
|
|||
.into()
|
||||
}
|
||||
|
||||
/// Returns { value: \empty, found: False }, representing that no element was found in a call
|
||||
/// to List.find when the layout of the element is also unknown.
|
||||
pub fn list_find_trivial_not_found<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let empty_type = env.context.custom_width_int_type(0);
|
||||
let result = env
|
||||
.context
|
||||
.struct_type(&[empty_type.into(), env.context.bool_type().into()], false)
|
||||
.const_zero();
|
||||
|
||||
env.builder
|
||||
.build_insert_value(
|
||||
result,
|
||||
env.context.bool_type().const_zero(),
|
||||
1,
|
||||
"insert_found",
|
||||
)
|
||||
.unwrap()
|
||||
.into_struct_value()
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn decrementing_elem_loop<'ctx, LoopFn>(
|
||||
builder: &Builder<'ctx>,
|
||||
ctx: &'ctx Context,
|
||||
|
@ -1269,15 +1246,6 @@ pub fn empty_polymorphic_list<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> Basi
|
|||
BasicValueEnum::StructValue(struct_type.const_zero())
|
||||
}
|
||||
|
||||
// TODO investigate: does this cause problems when the layout is known? this value is now not refcounted!
|
||||
pub fn empty_list<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> BasicValueEnum<'ctx> {
|
||||
let struct_type = super::convert::zig_list_type(env);
|
||||
|
||||
// The pointer should be null (aka zero) and the length should be zero,
|
||||
// so the whole struct should be a const_zero
|
||||
BasicValueEnum::StructValue(struct_type.const_zero())
|
||||
}
|
||||
|
||||
pub fn load_list<'ctx>(
|
||||
builder: &Builder<'ctx>,
|
||||
wrapper_struct: StructValue<'ctx>,
|
||||
|
|
|
@ -14,6 +14,8 @@ use roc_builtins::bitcode::{FloatWidth, IntWidth};
|
|||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::layout::{Builtin, Layout, LayoutIds, UnionLayout};
|
||||
|
||||
use super::build::load_roc_value;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum WhenRecursive<'a> {
|
||||
Unreachable,
|
||||
|
@ -135,12 +137,6 @@ fn build_eq_builtin<'a, 'ctx, 'env>(
|
|||
),
|
||||
Builtin::Set(_elem) => todo!("equality on Set"),
|
||||
Builtin::Dict(_key, _value) => todo!("equality on Dict"),
|
||||
|
||||
// empty structures are always equal to themselves
|
||||
Builtin::EmptyStr => env.context.bool_type().const_int(1, false).into(),
|
||||
Builtin::EmptyList => env.context.bool_type().const_int(1, false).into(),
|
||||
Builtin::EmptyDict => env.context.bool_type().const_int(1, false).into(),
|
||||
Builtin::EmptySet => env.context.bool_type().const_int(1, false).into(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -310,12 +306,6 @@ fn build_neq_builtin<'a, 'ctx, 'env>(
|
|||
}
|
||||
Builtin::Set(_elem) => todo!("equality on Set"),
|
||||
Builtin::Dict(_key, _value) => todo!("equality on Dict"),
|
||||
|
||||
// empty structures are always equal to themselves
|
||||
Builtin::EmptyStr => env.context.bool_type().const_int(0, false).into(),
|
||||
Builtin::EmptyList => env.context.bool_type().const_int(0, false).into(),
|
||||
Builtin::EmptyDict => env.context.bool_type().const_int(0, false).into(),
|
||||
Builtin::EmptySet => env.context.bool_type().const_int(0, false).into(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -533,13 +523,13 @@ fn build_list_eq_help<'a, 'ctx, 'env>(
|
|||
let elem1 = {
|
||||
let elem_ptr =
|
||||
unsafe { builder.build_in_bounds_gep(ptr1, &[curr_index], "load_index") };
|
||||
builder.build_load(elem_ptr, "get_elem")
|
||||
load_roc_value(env, *element_layout, elem_ptr, "get_elem")
|
||||
};
|
||||
|
||||
let elem2 = {
|
||||
let elem_ptr =
|
||||
unsafe { builder.build_in_bounds_gep(ptr2, &[curr_index], "load_index") };
|
||||
builder.build_load(elem_ptr, "get_elem")
|
||||
load_roc_value(env, *element_layout, elem_ptr, "get_elem")
|
||||
};
|
||||
|
||||
let are_equal = build_eq(
|
||||
|
@ -882,6 +872,10 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
|
|||
use UnionLayout::*;
|
||||
|
||||
match union_layout {
|
||||
NonRecursive(&[]) => {
|
||||
// we're comparing empty tag unions; this code is effectively unreachable
|
||||
env.builder.build_unreachable();
|
||||
}
|
||||
NonRecursive(tags) => {
|
||||
let ptr_equal = env.builder.build_int_compare(
|
||||
IntPredicate::EQ,
|
||||
|
@ -942,9 +936,15 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
|
|||
|
||||
env.builder.position_at_end(compare_tag_fields);
|
||||
|
||||
let default = cases.pop().unwrap().1;
|
||||
|
||||
env.builder.build_switch(id1, default, &cases);
|
||||
match cases.pop() {
|
||||
Some((_, default)) => {
|
||||
env.builder.build_switch(id1, default, &cases);
|
||||
}
|
||||
None => {
|
||||
// we're comparing empty tag unions; this code is effectively unreachable
|
||||
env.builder.build_unreachable();
|
||||
}
|
||||
}
|
||||
}
|
||||
Recursive(tags) => {
|
||||
let ptr_equal = env.builder.build_int_compare(
|
||||
|
|
|
@ -150,10 +150,10 @@ pub fn basic_type_from_builtin<'a, 'ctx, 'env>(
|
|||
Float(float_width) => float_type_from_float_width(env, *float_width).as_basic_type_enum(),
|
||||
Bool => context.bool_type().as_basic_type_enum(),
|
||||
Decimal => context.i128_type().as_basic_type_enum(),
|
||||
Dict(_, _) | EmptyDict => zig_dict_type(env).into(),
|
||||
Set(_) | EmptySet => zig_dict_type(env).into(),
|
||||
List(_) | EmptyList => zig_list_type(env).into(),
|
||||
Str | EmptyStr => zig_str_type(env).into(),
|
||||
Dict(_, _) => zig_dict_type(env).into(),
|
||||
Set(_) => zig_dict_type(env).into(),
|
||||
List(_) => zig_list_type(env).into(),
|
||||
Str => zig_str_type(env).into(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -593,21 +593,31 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
|
|||
Union(variant) => {
|
||||
use UnionLayout::*;
|
||||
|
||||
if let NonRecursive(tags) = variant {
|
||||
let function = modify_refcount_union(env, layout_ids, mode, when_recursive, tags);
|
||||
match variant {
|
||||
NonRecursive(&[]) => {
|
||||
// void type, nothing to refcount here
|
||||
None
|
||||
}
|
||||
|
||||
return Some(function);
|
||||
NonRecursive(tags) => {
|
||||
let function =
|
||||
modify_refcount_union(env, layout_ids, mode, when_recursive, tags);
|
||||
|
||||
Some(function)
|
||||
}
|
||||
|
||||
_ => {
|
||||
let function = build_rec_union(
|
||||
env,
|
||||
layout_ids,
|
||||
mode,
|
||||
&WhenRecursive::Loop(*variant),
|
||||
*variant,
|
||||
);
|
||||
|
||||
Some(function)
|
||||
}
|
||||
}
|
||||
|
||||
let function = build_rec_union(
|
||||
env,
|
||||
layout_ids,
|
||||
mode,
|
||||
&WhenRecursive::Loop(*variant),
|
||||
*variant,
|
||||
);
|
||||
|
||||
Some(function)
|
||||
}
|
||||
|
||||
Struct(layouts) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue