Ensure that llvm gen_ wrappers account different recursive pointers

Closes #2551
This commit is contained in:
Ayaz Hafiz 2022-12-02 13:38:32 -06:00
parent 1beb00f490
commit 3685ad2ed2
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
4 changed files with 37 additions and 30 deletions

View file

@ -37,6 +37,7 @@ use roc_collections::all::{ImMap, MutMap, MutSet};
use roc_debug_flags::dbg_do;
#[cfg(debug_assertions)]
use roc_debug_flags::ROC_PRINT_LLVM_FN_VERIFICATION;
use roc_error_macros::internal_error;
use roc_module::symbol::{Interns, ModuleId, Symbol};
use roc_mono::ir::{
BranchInfo, CallType, CrashTag, EntryPoint, JoinPointId, ListLiteralElement, ModifyRc,
@ -5610,3 +5611,23 @@ pub fn add_func<'ctx>(
fn_val
}
#[derive(Clone, Debug, PartialEq)]
pub(crate) enum WhenRecursive<'a> {
Unreachable,
Loop(UnionLayout<'a>),
}
impl<'a> WhenRecursive<'a> {
pub fn unwrap_recursive_pointer(&self, layout: Layout<'a>) -> Layout<'a> {
match layout {
Layout::RecursivePointer => match self {
WhenRecursive::Loop(lay) => Layout::Union(*lay),
WhenRecursive::Unreachable => {
internal_error!("cannot compare recursive pointers outside of a structure")
}
},
_ => layout,
}
}
}

View file

@ -1,4 +1,6 @@
use crate::llvm::build::{get_tag_id, tag_pointer_clear_tag_id, Env, FAST_CALL_CONV};
use crate::llvm::build::{
get_tag_id, tag_pointer_clear_tag_id, Env, WhenRecursive, FAST_CALL_CONV,
};
use crate::llvm::build_list::{list_len, load_list_ptr};
use crate::llvm::build_str::str_equal;
use crate::llvm::convert::basic_type_from_layout;
@ -17,12 +19,6 @@ use super::build::{load_roc_value, use_roc_value};
use super::convert::argument_type_from_union_layout;
use super::lowlevel::dec_binop_with_unchecked;
#[derive(Clone, Debug)]
enum WhenRecursive<'a> {
Unreachable,
Loop(UnionLayout<'a>),
}
pub fn generic_eq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_ids: &mut LayoutIds<'a>,
@ -406,8 +402,9 @@ fn build_list_eq<'a, 'ctx, 'env>(
let di_location = env.builder.get_current_debug_location().unwrap();
let symbol = Symbol::LIST_EQ;
let element_layout = when_recursive.unwrap_recursive_pointer(*element_layout);
let fn_name = layout_ids
.get(symbol, element_layout)
.get(symbol, &element_layout)
.to_symbol_string(symbol, &env.interns);
let function = match env.module.get_function(fn_name.as_str()) {
@ -427,7 +424,7 @@ fn build_list_eq<'a, 'ctx, 'env>(
layout_ids,
when_recursive,
function_value,
element_layout,
&element_layout,
);
function_value

View file

@ -2,7 +2,7 @@ use crate::debug_info_init;
use crate::llvm::bitcode::call_void_bitcode_fn;
use crate::llvm::build::{
add_func, cast_basic_basic, get_tag_id, tag_pointer_clear_tag_id, use_roc_value, Env,
FAST_CALL_CONV,
WhenRecursive, FAST_CALL_CONV,
};
use crate::llvm::build_list::{incrementing_elem_loop, list_len, load_list};
use crate::llvm::convert::{basic_type_from_layout, RocUnion};
@ -399,14 +399,8 @@ fn modify_refcount_builtin<'a, 'ctx, 'env>(
match builtin {
List(element_layout) => {
let function = modify_refcount_list(
env,
layout_ids,
mode,
when_recursive,
layout,
element_layout,
);
let function =
modify_refcount_list(env, layout_ids, mode, when_recursive, element_layout);
Some(function)
}
@ -437,12 +431,6 @@ fn modify_refcount_layout<'a, 'ctx, 'env>(
);
}
#[derive(Clone, Debug, PartialEq)]
enum WhenRecursive<'a> {
Unreachable,
Loop(UnionLayout<'a>),
}
fn modify_refcount_layout_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_ids: &mut LayoutIds<'a>,
@ -609,25 +597,26 @@ fn modify_refcount_list<'a, 'ctx, 'env>(
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
layout: &Layout<'a>,
element_layout: &Layout<'a>,
) -> FunctionValue<'ctx> {
let block = env.builder.get_insert_block().expect("to be in a function");
let di_location = env.builder.get_current_debug_location().unwrap();
let element_layout = when_recursive.unwrap_recursive_pointer(*element_layout);
let list_layout = &Layout::Builtin(Builtin::List(env.arena.alloc(element_layout)));
let (_, fn_name) = function_name_from_mode(
layout_ids,
&env.interns,
"increment_list",
"decrement_list",
layout,
list_layout,
mode,
);
let function = match env.module.get_function(fn_name.as_str()) {
Some(function_value) => function_value,
None => {
let basic_type = argument_type_from_layout(env, layout);
let basic_type = argument_type_from_layout(env, list_layout);
let function_value = build_header(env, basic_type, mode, &fn_name);
modify_refcount_list_help(
@ -635,8 +624,8 @@ fn modify_refcount_list<'a, 'ctx, 'env>(
layout_ids,
mode,
when_recursive,
layout,
element_layout,
list_layout,
&element_layout,
function_value,
);