Toss out when-recursive from llvm backend

This commit is contained in:
Ayaz Hafiz 2023-01-25 12:48:06 -06:00
parent a1ebfa30f8
commit f451ba49f1
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
4 changed files with 160 additions and 377 deletions

View file

@ -37,7 +37,6 @@ 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,
@ -6100,23 +6099,3 @@ pub fn add_func<'ctx>(
fn_val
}
#[derive(Clone, Copy, 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,6 +1,4 @@
use crate::llvm::build::{
get_tag_id, tag_pointer_clear_tag_id, Env, WhenRecursive, FAST_CALL_CONV,
};
use crate::llvm::build::{get_tag_id, tag_pointer_clear_tag_id, Env, 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;
@ -12,6 +10,7 @@ use inkwell::values::{
use inkwell::{AddressSpace, FloatPredicate, IntPredicate};
use roc_builtins::bitcode;
use roc_builtins::bitcode::{FloatWidth, IntWidth};
use roc_error_macros::internal_error;
use roc_module::symbol::Symbol;
use roc_mono::layout::{
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, STLayoutInterner, UnionLayout,
@ -38,7 +37,6 @@ pub fn generic_eq<'a, 'ctx, 'env>(
rhs_val,
lhs_layout,
rhs_layout,
WhenRecursive::Unreachable,
)
}
@ -59,7 +57,6 @@ pub fn generic_neq<'a, 'ctx, 'env>(
rhs_val,
lhs_layout,
rhs_layout,
WhenRecursive::Unreachable,
)
}
@ -70,7 +67,6 @@ fn build_eq_builtin<'a, 'ctx, 'env>(
lhs_val: BasicValueEnum<'ctx>,
rhs_val: BasicValueEnum<'ctx>,
builtin: &Builtin<'a>,
when_recursive: WhenRecursive<'a>,
) -> BasicValueEnum<'ctx> {
let int_cmp = |pred, label| {
let int_val = env.builder.build_int_compare(
@ -139,7 +135,6 @@ fn build_eq_builtin<'a, 'ctx, 'env>(
*elem,
lhs_val.into_struct_value(),
rhs_val.into_struct_value(),
when_recursive,
)
}
}
@ -153,7 +148,6 @@ fn build_eq<'a, 'ctx, 'env>(
rhs_val: BasicValueEnum<'ctx>,
lhs_layout: InLayout<'a>,
rhs_layout: InLayout<'a>,
when_recursive: WhenRecursive<'a>,
) -> BasicValueEnum<'ctx> {
let lhs_layout = &layout_interner.runtime_representation_in(lhs_layout);
let rhs_layout = &layout_interner.runtime_representation_in(rhs_layout);
@ -165,22 +159,15 @@ fn build_eq<'a, 'ctx, 'env>(
}
match layout_interner.get(*lhs_layout) {
Layout::Builtin(builtin) => build_eq_builtin(
env,
layout_interner,
layout_ids,
lhs_val,
rhs_val,
&builtin,
when_recursive,
),
Layout::Builtin(builtin) => {
build_eq_builtin(env, layout_interner, layout_ids, lhs_val, rhs_val, &builtin)
}
Layout::Struct { field_layouts, .. } => build_struct_eq(
env,
layout_interner,
layout_ids,
field_layouts,
when_recursive,
lhs_val.into_struct_value(),
rhs_val.into_struct_value(),
),
@ -191,7 +178,6 @@ fn build_eq<'a, 'ctx, 'env>(
env,
layout_interner,
layout_ids,
when_recursive,
&union_layout,
lhs_val,
rhs_val,
@ -201,47 +187,47 @@ fn build_eq<'a, 'ctx, 'env>(
env,
layout_interner,
layout_ids,
when_recursive,
*lhs_layout,
inner_layout,
lhs_val,
rhs_val,
),
Layout::RecursivePointer(_) => match when_recursive {
WhenRecursive::Unreachable => {
unreachable!("recursion pointers should never be compared directly")
}
Layout::RecursivePointer(rec_layout) => {
let layout = rec_layout;
WhenRecursive::Loop(union_layout) => {
let layout = layout_interner.insert(Layout::Union(union_layout));
let bt = basic_type_from_layout(env, layout_interner, layout);
let bt = basic_type_from_layout(env, layout_interner, layout);
// cast the i64 pointer to a pointer to block of memory
let field1_cast = env.builder.build_pointer_cast(
lhs_val.into_pointer_value(),
bt.into_pointer_type(),
"i64_to_opaque",
);
// cast the i64 pointer to a pointer to block of memory
let field1_cast = env.builder.build_pointer_cast(
lhs_val.into_pointer_value(),
bt.into_pointer_type(),
"i64_to_opaque",
);
let field2_cast = env.builder.build_pointer_cast(
rhs_val.into_pointer_value(),
bt.into_pointer_type(),
"i64_to_opaque",
);
let field2_cast = env.builder.build_pointer_cast(
rhs_val.into_pointer_value(),
bt.into_pointer_type(),
"i64_to_opaque",
);
let union_layout = match layout_interner.get(rec_layout) {
Layout::Union(union_layout) => {
debug_assert!(!matches!(union_layout, UnionLayout::NonRecursive(..)));
union_layout
}
_ => internal_error!(),
};
build_tag_eq(
env,
layout_interner,
layout_ids,
WhenRecursive::Loop(union_layout),
&union_layout,
field1_cast.into(),
field2_cast.into(),
)
}
},
build_tag_eq(
env,
layout_interner,
layout_ids,
&union_layout,
field1_cast.into(),
field2_cast.into(),
)
}
}
}
@ -252,7 +238,6 @@ fn build_neq_builtin<'a, 'ctx, 'env>(
lhs_val: BasicValueEnum<'ctx>,
rhs_val: BasicValueEnum<'ctx>,
builtin: &Builtin<'a>,
when_recursive: WhenRecursive<'a>,
) -> BasicValueEnum<'ctx> {
let int_cmp = |pred, label| {
let int_val = env.builder.build_int_compare(
@ -326,7 +311,6 @@ fn build_neq_builtin<'a, 'ctx, 'env>(
*elem,
lhs_val.into_struct_value(),
rhs_val.into_struct_value(),
when_recursive,
)
.into_int_value();
@ -345,7 +329,6 @@ fn build_neq<'a, 'ctx, 'env>(
rhs_val: BasicValueEnum<'ctx>,
lhs_layout: InLayout<'a>,
rhs_layout: InLayout<'a>,
when_recursive: WhenRecursive<'a>,
) -> BasicValueEnum<'ctx> {
if lhs_layout != rhs_layout {
panic!(
@ -355,15 +338,9 @@ fn build_neq<'a, 'ctx, 'env>(
}
match layout_interner.get(lhs_layout) {
Layout::Builtin(builtin) => build_neq_builtin(
env,
layout_interner,
layout_ids,
lhs_val,
rhs_val,
&builtin,
when_recursive,
),
Layout::Builtin(builtin) => {
build_neq_builtin(env, layout_interner, layout_ids, lhs_val, rhs_val, &builtin)
}
Layout::Struct { field_layouts, .. } => {
let is_equal = build_struct_eq(
@ -371,7 +348,6 @@ fn build_neq<'a, 'ctx, 'env>(
layout_interner,
layout_ids,
field_layouts,
when_recursive,
lhs_val.into_struct_value(),
rhs_val.into_struct_value(),
)
@ -387,7 +363,6 @@ fn build_neq<'a, 'ctx, 'env>(
env,
layout_interner,
layout_ids,
when_recursive,
&union_layout,
lhs_val,
rhs_val,
@ -404,7 +379,6 @@ fn build_neq<'a, 'ctx, 'env>(
env,
layout_interner,
layout_ids,
when_recursive,
lhs_layout,
inner_layout,
lhs_val,
@ -432,15 +406,17 @@ fn build_list_eq<'a, 'ctx, 'env>(
element_layout: InLayout<'a>,
list1: StructValue<'ctx>,
list2: StructValue<'ctx>,
when_recursive: WhenRecursive<'a>,
) -> BasicValueEnum<'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 symbol = Symbol::LIST_EQ;
let element_layout = layout_interner.get(element_layout);
let element_layout = when_recursive.unwrap_recursive_pointer(element_layout);
let element_layout = layout_interner.insert(element_layout);
let element_layout = if let Layout::RecursivePointer(rec) = layout_interner.get(element_layout)
{
rec
} else {
element_layout
};
let fn_name = layout_ids
.get(symbol, &element_layout)
.to_symbol_string(symbol, &env.interns);
@ -461,7 +437,6 @@ fn build_list_eq<'a, 'ctx, 'env>(
env,
layout_interner,
layout_ids,
when_recursive,
function_value,
element_layout,
);
@ -486,7 +461,6 @@ fn build_list_eq_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
when_recursive: WhenRecursive<'a>,
parent: FunctionValue<'ctx>,
element_layout: InLayout<'a>,
) {
@ -605,7 +579,6 @@ fn build_list_eq_help<'a, 'ctx, 'env>(
elem2,
element_layout,
element_layout,
when_recursive,
)
.into_int_value();
@ -647,7 +620,6 @@ fn build_struct_eq<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
field_layouts: &'a [InLayout<'a>],
when_recursive: WhenRecursive<'a>,
struct1: StructValue<'ctx>,
struct2: StructValue<'ctx>,
) -> BasicValueEnum<'ctx> {
@ -678,7 +650,6 @@ fn build_struct_eq<'a, 'ctx, 'env>(
layout_interner,
layout_ids,
function_value,
when_recursive,
field_layouts,
);
@ -703,7 +674,6 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
parent: FunctionValue<'ctx>,
when_recursive: WhenRecursive<'a>,
field_layouts: &[InLayout<'a>],
) {
let ctx = env.context;
@ -761,42 +731,40 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
.build_extract_value(struct2, index as u32, "eq_field")
.unwrap();
let are_equal = if let Layout::RecursivePointer(_) = layout_interner.get(*field_layout) {
match &when_recursive {
WhenRecursive::Unreachable => {
unreachable!("The current layout should not be recursive, but is")
}
WhenRecursive::Loop(union_layout) => {
let field_layout = layout_interner.insert(Layout::Union(*union_layout));
let are_equal = if let Layout::RecursivePointer(rec_layout) =
layout_interner.get(*field_layout)
{
debug_assert!(
matches!(layout_interner.get(rec_layout), Layout::Union(union_layout) if !matches!(union_layout, UnionLayout::NonRecursive(..)))
);
let bt = basic_type_from_layout(env, layout_interner, field_layout);
let field_layout = rec_layout;
// cast the i64 pointer to a pointer to block of memory
let field1_cast = env.builder.build_pointer_cast(
field1.into_pointer_value(),
bt.into_pointer_type(),
"i64_to_opaque",
);
let bt = basic_type_from_layout(env, layout_interner, field_layout);
let field2_cast = env.builder.build_pointer_cast(
field2.into_pointer_value(),
bt.into_pointer_type(),
"i64_to_opaque",
);
// cast the i64 pointer to a pointer to block of memory
let field1_cast = env.builder.build_pointer_cast(
field1.into_pointer_value(),
bt.into_pointer_type(),
"i64_to_opaque",
);
build_eq(
env,
layout_interner,
layout_ids,
field1_cast.into(),
field2_cast.into(),
field_layout,
field_layout,
WhenRecursive::Loop(*union_layout),
)
.into_int_value()
}
}
let field2_cast = env.builder.build_pointer_cast(
field2.into_pointer_value(),
bt.into_pointer_type(),
"i64_to_opaque",
);
build_eq(
env,
layout_interner,
layout_ids,
field1_cast.into(),
field2_cast.into(),
field_layout,
field_layout,
)
.into_int_value()
} else {
let lhs = use_roc_value(env, layout_interner, *field_layout, field1, "field1");
let rhs = use_roc_value(env, layout_interner, *field_layout, field2, "field2");
@ -808,7 +776,6 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
rhs,
*field_layout,
*field_layout,
when_recursive,
)
.into_int_value()
};
@ -839,7 +806,6 @@ fn build_tag_eq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
when_recursive: WhenRecursive<'a>,
union_layout: &UnionLayout<'a>,
tag1: BasicValueEnum<'ctx>,
tag2: BasicValueEnum<'ctx>,
@ -869,7 +835,6 @@ fn build_tag_eq<'a, 'ctx, 'env>(
env,
layout_interner,
layout_ids,
when_recursive,
function_value,
union_layout,
);
@ -894,7 +859,6 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
when_recursive: WhenRecursive<'a>,
parent: FunctionValue<'ctx>,
union_layout: &UnionLayout<'a>,
) {
@ -1004,7 +968,6 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
layout_interner,
layout_ids,
union_layout,
Some(when_recursive),
field_layouts,
tag1,
tag2,
@ -1075,7 +1038,6 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
layout_interner,
layout_ids,
union_layout,
None,
field_layouts,
tag1,
tag2,
@ -1136,7 +1098,6 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
layout_interner,
layout_ids,
union_layout,
None,
other_fields,
tag1.into_pointer_value(),
tag2.into_pointer_value(),
@ -1234,7 +1195,6 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
layout_interner,
layout_ids,
union_layout,
None,
field_layouts,
tag1,
tag2,
@ -1273,7 +1233,6 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
layout_interner,
layout_ids,
union_layout,
None,
field_layouts,
tag1.into_pointer_value(),
tag2.into_pointer_value(),
@ -1289,7 +1248,6 @@ fn eq_ptr_to_struct<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
union_layout: &UnionLayout<'a>,
opt_when_recursive: Option<WhenRecursive<'a>>,
field_layouts: &'a [InLayout<'a>],
tag1: PointerValue<'ctx>,
tag2: PointerValue<'ctx>,
@ -1327,7 +1285,6 @@ fn eq_ptr_to_struct<'a, 'ctx, 'env>(
layout_interner,
layout_ids,
field_layouts,
opt_when_recursive.unwrap_or(WhenRecursive::Loop(*union_layout)),
struct1,
struct2,
)
@ -1340,7 +1297,6 @@ fn build_box_eq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
when_recursive: WhenRecursive<'a>,
box_layout: InLayout<'a>,
inner_layout: InLayout<'a>,
tag1: BasicValueEnum<'ctx>,
@ -1370,7 +1326,6 @@ fn build_box_eq<'a, 'ctx, 'env>(
env,
layout_interner,
layout_ids,
when_recursive,
function_value,
inner_layout,
);
@ -1395,7 +1350,6 @@ fn build_box_eq_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
when_recursive: WhenRecursive<'a>,
parent: FunctionValue<'ctx>,
inner_layout: InLayout<'a>,
) {
@ -1472,7 +1426,6 @@ fn build_box_eq_help<'a, 'ctx, 'env>(
value2,
inner_layout,
inner_layout,
when_recursive,
);
env.builder.build_return(Some(&is_equal));

View file

@ -9,6 +9,7 @@ use inkwell::types::{BasicMetadataTypeEnum, BasicType, BasicTypeEnum};
use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue};
use inkwell::AddressSpace;
use roc_builtins::bitcode;
use roc_error_macros::internal_error;
use roc_module::symbol::Symbol;
use roc_mono::ir::LookupType;
use roc_mono::layout::{
@ -19,7 +20,7 @@ use roc_region::all::Region;
use super::build::BuilderExt;
use super::build::{
add_func, load_roc_value, load_symbol_and_layout, use_roc_value, FunctionSpec, LlvmBackendMode,
Scope, WhenRecursive,
Scope,
};
use super::convert::struct_type_from_union_layout;
@ -220,7 +221,6 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx, 'env>(
cursors,
value,
layout,
WhenRecursive::Unreachable,
);
offset = extra_offset;
@ -286,7 +286,6 @@ fn build_clone<'a, 'ctx, 'env>(
cursors: Cursors<'ctx>,
value: BasicValueEnum<'ctx>,
layout: InLayout<'a>,
when_recursive: WhenRecursive<'a>,
) -> IntValue<'ctx> {
match layout_interner.get(layout) {
Layout::Builtin(builtin) => build_clone_builtin(
@ -297,7 +296,6 @@ fn build_clone<'a, 'ctx, 'env>(
cursors,
value,
builtin,
when_recursive,
),
Layout::Struct { field_layouts, .. } => build_clone_struct(
@ -308,7 +306,6 @@ fn build_clone<'a, 'ctx, 'env>(
cursors,
value,
field_layouts,
when_recursive,
),
// Since we will never actually display functions (and hence lambda sets)
@ -343,7 +340,6 @@ fn build_clone<'a, 'ctx, 'env>(
cursors,
value,
union_layout,
WhenRecursive::Loop(union_layout),
)
}
}
@ -376,39 +372,39 @@ fn build_clone<'a, 'ctx, 'env>(
cursors,
value,
inner_layout,
when_recursive,
)
}
Layout::RecursivePointer(_) => match when_recursive {
WhenRecursive::Unreachable => {
unreachable!("recursion pointers should never be compared directly")
}
Layout::RecursivePointer(rec_layout) => {
let layout = rec_layout;
WhenRecursive::Loop(union_layout) => {
let layout = layout_interner.insert(Layout::Union(union_layout));
let bt = basic_type_from_layout(env, layout_interner, layout);
let bt = basic_type_from_layout(env, layout_interner, layout);
// cast the i64 pointer to a pointer to block of memory
let field1_cast = env.builder.build_pointer_cast(
value.into_pointer_value(),
bt.into_pointer_type(),
"i64_to_opaque",
);
// cast the i64 pointer to a pointer to block of memory
let field1_cast = env.builder.build_pointer_cast(
value.into_pointer_value(),
bt.into_pointer_type(),
"i64_to_opaque",
);
let union_layout = match layout_interner.get(rec_layout) {
Layout::Union(union_layout) => {
debug_assert!(!matches!(union_layout, UnionLayout::NonRecursive(..)));
union_layout
}
_ => internal_error!(),
};
build_clone_tag(
env,
layout_interner,
layout_ids,
ptr,
cursors,
field1_cast.into(),
union_layout,
WhenRecursive::Loop(union_layout),
)
}
},
build_clone_tag(
env,
layout_interner,
layout_ids,
ptr,
cursors,
field1_cast.into(),
union_layout,
)
}
}
}
@ -420,7 +416,6 @@ fn build_clone_struct<'a, 'ctx, 'env>(
cursors: Cursors<'ctx>,
value: BasicValueEnum<'ctx>,
field_layouts: &[InLayout<'a>],
when_recursive: WhenRecursive<'a>,
) -> IntValue<'ctx> {
let layout = Layout::struct_no_name_order(field_layouts);
@ -447,7 +442,6 @@ fn build_clone_struct<'a, 'ctx, 'env>(
cursors,
field,
*field_layout,
when_recursive,
);
let field_width = env
@ -472,7 +466,6 @@ fn build_clone_tag<'a, 'ctx, 'env>(
cursors: Cursors<'ctx>,
value: BasicValueEnum<'ctx>,
union_layout: UnionLayout<'a>,
when_recursive: WhenRecursive<'a>,
) -> IntValue<'ctx> {
let layout = layout_interner.insert(Layout::Union(union_layout));
let layout_id = layout_ids.get(Symbol::CLONE, &layout);
@ -512,7 +505,6 @@ fn build_clone_tag<'a, 'ctx, 'env>(
layout_interner,
layout_ids,
union_layout,
when_recursive,
function_value,
);
@ -575,7 +567,6 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
union_layout: UnionLayout<'a>,
when_recursive: WhenRecursive<'a>,
fn_val: FunctionValue<'ctx>,
) {
use bumpalo::collections::Vec;
@ -643,16 +634,8 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
basic_type,
);
let answer = build_clone(
env,
layout_interner,
layout_ids,
ptr,
cursors,
data,
layout,
when_recursive,
);
let answer =
build_clone(env, layout_interner, layout_ids, ptr, cursors, data, layout);
env.builder.build_return(Some(&answer));
@ -712,17 +695,8 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
),
};
let when_recursive = WhenRecursive::Loop(union_layout);
let answer = build_clone(
env,
layout_interner,
layout_ids,
ptr,
cursors,
data,
layout,
when_recursive,
);
let answer =
build_clone(env, layout_interner, layout_ids, ptr, cursors, data, layout);
env.builder.build_return(Some(&answer));
@ -762,17 +736,7 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
let data = load_tag_data(env, layout_interner, union_layout, tag_value, basic_type);
let when_recursive = WhenRecursive::Loop(union_layout);
let answer = build_clone(
env,
layout_interner,
layout_ids,
ptr,
cursors,
data,
layout,
when_recursive,
);
let answer = build_clone(env, layout_interner, layout_ids, ptr, cursors, data, layout);
env.builder.build_return(Some(&answer));
}
@ -831,17 +795,8 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
let data =
load_tag_data(env, layout_interner, union_layout, tag_value, basic_type);
let when_recursive = WhenRecursive::Loop(union_layout);
let answer = build_clone(
env,
layout_interner,
layout_ids,
ptr,
cursors,
data,
layout,
when_recursive,
);
let answer =
build_clone(env, layout_interner, layout_ids, ptr, cursors, data, layout);
env.builder.build_return(Some(&answer));
@ -917,17 +872,8 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
basic_type,
);
let when_recursive = WhenRecursive::Loop(union_layout);
let answer = build_clone(
env,
layout_interner,
layout_ids,
ptr,
cursors,
data,
layout,
when_recursive,
);
let answer =
build_clone(env, layout_interner, layout_ids, ptr, cursors, data, layout);
env.builder.build_return(Some(&answer));
}
@ -997,7 +943,6 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
cursors: Cursors<'ctx>,
value: BasicValueEnum<'ctx>,
builtin: Builtin<'a>,
when_recursive: WhenRecursive<'a>,
) -> IntValue<'ctx> {
use Builtin::*;
@ -1102,7 +1047,6 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
cursors,
element,
elem,
when_recursive,
);
bd.build_store(rest_offset, new_offset);

View file

@ -3,7 +3,7 @@ use crate::llvm::bitcode::call_void_bitcode_fn;
use crate::llvm::build::BuilderExt;
use crate::llvm::build::{
add_func, cast_basic_basic, get_tag_id, tag_pointer_clear_tag_id, use_roc_value, Env,
WhenRecursive, FAST_CALL_CONV,
FAST_CALL_CONV,
};
use crate::llvm::build_list::{incrementing_elem_loop, list_capacity, load_list};
use crate::llvm::convert::{basic_type_from_layout, zig_str_type, RocUnion};
@ -277,7 +277,6 @@ fn modify_refcount_struct<'a, 'ctx, 'env>(
layout_ids: &mut LayoutIds<'a>,
layouts: &'a [InLayout<'a>],
mode: Mode,
when_recursive: &WhenRecursive<'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();
@ -304,7 +303,6 @@ fn modify_refcount_struct<'a, 'ctx, 'env>(
layout_interner,
layout_ids,
mode,
when_recursive,
layouts,
function_value,
);
@ -326,7 +324,6 @@ fn modify_refcount_struct_help<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
layouts: &[InLayout<'a>],
fn_val: FunctionValue<'ctx>,
) {
@ -368,7 +365,6 @@ fn modify_refcount_struct_help<'a, 'ctx, 'env>(
layout_interner,
layout_ids,
mode.to_call_mode(fn_val),
when_recursive,
field_value,
*field_layout,
);
@ -430,7 +426,6 @@ fn modify_refcount_builtin<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
layout: InLayout<'a>,
builtin: &Builtin<'a>,
) -> Option<FunctionValue<'ctx>> {
@ -438,14 +433,8 @@ fn modify_refcount_builtin<'a, 'ctx, 'env>(
match builtin {
List(element_layout) => {
let function = modify_refcount_list(
env,
layout_interner,
layout_ids,
mode,
when_recursive,
*element_layout,
);
let function =
modify_refcount_list(env, layout_interner, layout_ids, mode, *element_layout);
Some(function)
}
@ -473,15 +462,7 @@ fn modify_refcount_layout<'a, 'ctx, 'env>(
value: BasicValueEnum<'ctx>,
layout: InLayout<'a>,
) {
modify_refcount_layout_help(
env,
layout_interner,
layout_ids,
call_mode,
&WhenRecursive::Unreachable,
value,
layout,
);
modify_refcount_layout_help(env, layout_interner, layout_ids, call_mode, value, layout);
}
fn modify_refcount_layout_help<'a, 'ctx, 'env>(
@ -489,7 +470,6 @@ fn modify_refcount_layout_help<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
call_mode: CallMode<'ctx>,
when_recursive: &WhenRecursive<'a>,
value: BasicValueEnum<'ctx>,
layout: InLayout<'a>,
) {
@ -498,38 +478,28 @@ fn modify_refcount_layout_help<'a, 'ctx, 'env>(
CallMode::Dec => Mode::Dec,
};
let function = match modify_refcount_layout_build_function(
env,
layout_interner,
layout_ids,
mode,
when_recursive,
layout,
) {
Some(f) => f,
None => return,
};
let function =
match modify_refcount_layout_build_function(env, layout_interner, layout_ids, mode, layout)
{
Some(f) => f,
None => return,
};
match layout_interner.get(layout) {
Layout::RecursivePointer(_) => match when_recursive {
WhenRecursive::Unreachable => {
unreachable!("recursion pointers should never be hashed directly")
}
WhenRecursive::Loop(union_layout) => {
let layout = layout_interner.insert(Layout::Union(*union_layout));
Layout::RecursivePointer(rec_layout) => {
let layout = rec_layout;
let bt = basic_type_from_layout(env, layout_interner, layout);
let bt = basic_type_from_layout(env, layout_interner, layout);
// cast the i64 pointer to a pointer to block of memory
let field_cast = env.builder.build_pointer_cast(
value.into_pointer_value(),
bt.into_pointer_type(),
"i64_to_opaque",
);
// cast the i64 pointer to a pointer to block of memory
let field_cast = env.builder.build_pointer_cast(
value.into_pointer_value(),
bt.into_pointer_type(),
"i64_to_opaque",
);
call_help(env, function, call_mode, field_cast.into());
}
},
call_help(env, function, call_mode, field_cast.into());
}
_ => {
call_help(env, function, call_mode, value);
}
@ -568,21 +538,14 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
layout: InLayout<'a>,
) -> Option<FunctionValue<'ctx>> {
use Layout::*;
match layout_interner.get(layout) {
Builtin(builtin) => modify_refcount_builtin(
env,
layout_interner,
layout_ids,
mode,
when_recursive,
layout,
&builtin,
),
Builtin(builtin) => {
modify_refcount_builtin(env, layout_interner, layout_ids, mode, layout, &builtin)
}
Boxed(inner) => {
let function = modify_refcount_boxed(env, layout_interner, layout_ids, mode, inner);
@ -600,27 +563,14 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
}
NonRecursive(tags) => {
let function = modify_refcount_nonrecursive(
env,
layout_interner,
layout_ids,
mode,
when_recursive,
tags,
);
let function =
modify_refcount_nonrecursive(env, layout_interner, layout_ids, mode, tags);
Some(function)
}
_ => {
let function = build_rec_union(
env,
layout_interner,
layout_ids,
mode,
&WhenRecursive::Loop(variant),
variant,
);
let function = build_rec_union(env, layout_interner, layout_ids, mode, variant);
Some(function)
}
@ -628,43 +578,30 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
}
Struct { field_layouts, .. } => {
let function = modify_refcount_struct(
env,
layout_interner,
layout_ids,
field_layouts,
mode,
when_recursive,
);
let function =
modify_refcount_struct(env, layout_interner, layout_ids, field_layouts, mode);
Some(function)
}
Layout::RecursivePointer(_) => match when_recursive {
WhenRecursive::Unreachable => {
unreachable!("recursion pointers cannot be in/decremented directly")
}
WhenRecursive::Loop(union_layout) => {
let layout = layout_interner.insert(Layout::Union(*union_layout));
Layout::RecursivePointer(rec_layout) => {
let layout = rec_layout;
let function = modify_refcount_layout_build_function(
env,
layout_interner,
layout_ids,
mode,
when_recursive,
layout,
)?;
let function = modify_refcount_layout_build_function(
env,
layout_interner,
layout_ids,
mode,
layout,
)?;
Some(function)
}
},
Some(function)
}
LambdaSet(lambda_set) => modify_refcount_layout_build_function(
env,
layout_interner,
layout_ids,
mode,
when_recursive,
lambda_set.runtime_representation(),
),
}
@ -675,15 +612,18 @@ fn modify_refcount_list<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
element_layout: InLayout<'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 = layout_interner.get(element_layout);
let element_layout = when_recursive.unwrap_recursive_pointer(element_layout);
let element_layout = layout_interner.insert(element_layout);
let element_layout = if let Layout::RecursivePointer(rec) = layout_interner.get(element_layout)
{
rec
} else {
element_layout
};
let list_layout = layout_interner.insert(Layout::Builtin(Builtin::List(element_layout)));
let (_, fn_name) = function_name_from_mode(
layout_ids,
@ -705,7 +645,6 @@ fn modify_refcount_list<'a, 'ctx, 'env>(
layout_interner,
layout_ids,
mode,
when_recursive,
list_layout,
element_layout,
function_value,
@ -734,7 +673,6 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
layout: InLayout<'a>,
element_layout: InLayout<'a>,
fn_val: FunctionValue<'ctx>,
@ -787,7 +725,6 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
layout_interner,
layout_ids,
mode.to_call_mode(fn_val),
when_recursive,
element,
element_layout,
);
@ -1093,7 +1030,6 @@ fn build_rec_union<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
union_layout: UnionLayout<'a>,
) -> FunctionValue<'ctx> {
let layout = layout_interner.insert(Layout::Union(union_layout));
@ -1121,7 +1057,6 @@ fn build_rec_union<'a, 'ctx, 'env>(
layout_interner,
layout_ids,
mode,
when_recursive,
union_layout,
function_value,
);
@ -1143,7 +1078,6 @@ fn build_rec_union_help<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
union_layout: UnionLayout<'a>,
fn_val: FunctionValue<'ctx>,
) {
@ -1235,7 +1169,6 @@ fn build_rec_union_help<'a, 'ctx, 'env>(
env,
layout_interner,
layout_ids,
when_recursive,
parent,
fn_val,
union_layout,
@ -1268,7 +1201,6 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
when_recursive: &WhenRecursive<'a>,
parent: FunctionValue<'ctx>,
decrement_fn: FunctionValue<'ctx>,
union_layout: UnionLayout<'a>,
@ -1396,7 +1328,6 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
layout_interner,
layout_ids,
mode.to_call_mode(decrement_fn),
when_recursive,
field,
*field_layout,
);
@ -1503,15 +1434,7 @@ pub fn build_reset<'a, 'ctx, 'env>(
let fn_name = layout_id.to_symbol_string(Symbol::DEC, &env.interns);
let fn_name = format!("{}_reset", fn_name);
let when_recursive = WhenRecursive::Loop(union_layout);
let dec_function = build_rec_union(
env,
layout_interner,
layout_ids,
Mode::Dec,
&when_recursive,
union_layout,
);
let dec_function = build_rec_union(env, layout_interner, layout_ids, Mode::Dec, union_layout);
let function = match env.module.get_function(fn_name.as_str()) {
Some(function_value) => function_value,
@ -1526,7 +1449,6 @@ pub fn build_reset<'a, 'ctx, 'env>(
env,
layout_interner,
layout_ids,
&when_recursive,
union_layout,
function_value,
dec_function,
@ -1548,7 +1470,6 @@ fn build_reuse_rec_union_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
when_recursive: &WhenRecursive<'a>,
union_layout: UnionLayout<'a>,
reset_function: FunctionValue<'ctx>,
dec_function: FunctionValue<'ctx>,
@ -1626,7 +1547,6 @@ fn build_reuse_rec_union_help<'a, 'ctx, 'env>(
env,
layout_interner,
layout_ids,
when_recursive,
parent,
dec_function,
union_layout,
@ -1665,7 +1585,6 @@ fn modify_refcount_nonrecursive<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
fields: &'a [&'a [InLayout<'a>]],
) -> FunctionValue<'ctx> {
let union_layout = UnionLayout::NonRecursive(fields);
@ -1694,7 +1613,6 @@ fn modify_refcount_nonrecursive<'a, 'ctx, 'env>(
layout_interner,
layout_ids,
mode,
when_recursive,
fields,
function_value,
);
@ -1715,7 +1633,6 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
tags: &'a [&'a [InLayout<'a>]],
fn_val: FunctionValue<'ctx>,
) {
@ -1810,14 +1727,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
);
for (i, field_layout) in field_layouts.iter().enumerate() {
if let Layout::RecursivePointer(_) = layout_interner.get(*field_layout) {
let recursive_union_layout = match when_recursive {
WhenRecursive::Unreachable => {
panic!("non-recursive tag unions cannot contain naked recursion pointers!");
}
WhenRecursive::Loop(recursive_union_layout) => recursive_union_layout,
};
if let Layout::RecursivePointer(union_layout) = layout_interner.get(*field_layout) {
// This field is a pointer to the recursive pointer.
let field_ptr = env
.builder
@ -1839,7 +1749,6 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
debug_assert!(field_value.is_pointer_value());
// therefore we must cast it to our desired type
let union_layout = layout_interner.insert(Layout::Union(*recursive_union_layout));
let union_type = basic_type_from_layout(env, layout_interner, union_layout);
let recursive_ptr_field_value =
cast_basic_basic(env.builder, field_value, union_type);
@ -1849,7 +1758,6 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
layout_interner,
layout_ids,
mode.to_call_mode(fn_val),
when_recursive,
recursive_ptr_field_value,
*field_layout,
)
@ -1879,7 +1787,6 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
layout_interner,
layout_ids,
mode.to_call_mode(fn_val),
when_recursive,
field_value,
*field_layout,
);