This commit is contained in:
Folkert 2021-11-27 16:36:43 +01:00
parent a1fd34feef
commit 79d5c82dfb
12 changed files with 186 additions and 70 deletions

View file

@ -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);

View file

@ -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};
@ -810,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);

View file

@ -327,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,
@ -443,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);

View file

@ -585,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>,
@ -607,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!(),
};
@ -651,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!(),
};

View file

@ -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,
@ -521,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(
@ -870,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,
@ -930,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(

View file

@ -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) => {