mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 11:52:19 +00:00
Merge pull request #4963 from roc-lang/recursive-ptr-propogate
Get rid of WhenRecursive
This commit is contained in:
commit
212dfdf842
7 changed files with 250 additions and 622 deletions
|
@ -8,6 +8,7 @@ version = "0.0.1"
|
|||
[dependencies]
|
||||
morphic_lib = {path = "../../vendor/morphic_lib"}
|
||||
roc_collections = {path = "../collections"}
|
||||
roc_error_macros = {path = "../../error_macros"}
|
||||
roc_module = {path = "../module"}
|
||||
roc_mono = {path = "../mono"}
|
||||
roc_debug_flags = {path = "../debug_flags"}
|
||||
|
|
|
@ -9,6 +9,7 @@ use morphic_lib::{
|
|||
TypeDefBuilder, TypeId, TypeName, UpdateModeVar, ValueId,
|
||||
};
|
||||
use roc_collections::all::{MutMap, MutSet};
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_module::low_level::LowLevel;
|
||||
use roc_module::symbol::Symbol;
|
||||
|
||||
|
@ -365,13 +366,7 @@ fn build_entry_point<'a>(
|
|||
let block = builder.add_block();
|
||||
|
||||
// to the modelling language, the arguments appear out of thin air
|
||||
let argument_type = build_tuple_type(
|
||||
env,
|
||||
&mut builder,
|
||||
interner,
|
||||
layout.arguments,
|
||||
&WhenRecursive::Unreachable,
|
||||
)?;
|
||||
let argument_type = build_tuple_type(env, &mut builder, interner, layout.arguments)?;
|
||||
|
||||
// does not make any assumptions about the input
|
||||
// let argument = builder.add_unknown_with(block, &[], argument_type)?;
|
||||
|
@ -401,13 +396,7 @@ fn build_entry_point<'a>(
|
|||
let block = builder.add_block();
|
||||
|
||||
let struct_layout = interner.insert(Layout::struct_no_name_order(layouts));
|
||||
let type_id = layout_spec(
|
||||
env,
|
||||
&mut builder,
|
||||
interner,
|
||||
struct_layout,
|
||||
&WhenRecursive::Unreachable,
|
||||
)?;
|
||||
let type_id = layout_spec(env, &mut builder, interner, struct_layout)?;
|
||||
|
||||
let argument = builder.add_unknown_with(block, &[], type_id)?;
|
||||
|
||||
|
@ -466,20 +455,8 @@ fn proc_spec<'a>(
|
|||
let args_struct_layout = interner.insert(Layout::struct_no_name_order(
|
||||
argument_layouts.into_bump_slice(),
|
||||
));
|
||||
let arg_type_id = layout_spec(
|
||||
&mut env,
|
||||
&mut builder,
|
||||
interner,
|
||||
args_struct_layout,
|
||||
&WhenRecursive::Unreachable,
|
||||
)?;
|
||||
let ret_type_id = layout_spec(
|
||||
&mut env,
|
||||
&mut builder,
|
||||
interner,
|
||||
proc.ret_layout,
|
||||
&WhenRecursive::Unreachable,
|
||||
)?;
|
||||
let arg_type_id = layout_spec(&mut env, &mut builder, interner, args_struct_layout)?;
|
||||
let ret_type_id = layout_spec(&mut env, &mut builder, interner, proc.ret_layout)?;
|
||||
|
||||
let spec = builder.build(arg_type_id, ret_type_id, root)?;
|
||||
|
||||
|
@ -617,17 +594,10 @@ fn stmt_spec<'a>(
|
|||
let mut type_ids = Vec::new();
|
||||
|
||||
for p in parameters.iter() {
|
||||
type_ids.push(layout_spec(
|
||||
env,
|
||||
builder,
|
||||
interner,
|
||||
p.layout,
|
||||
&WhenRecursive::Unreachable,
|
||||
)?);
|
||||
type_ids.push(layout_spec(env, builder, interner, p.layout)?);
|
||||
}
|
||||
|
||||
let ret_type_id =
|
||||
layout_spec(env, builder, interner, layout, &WhenRecursive::Unreachable)?;
|
||||
let ret_type_id = layout_spec(env, builder, interner, layout)?;
|
||||
|
||||
let jp_arg_type_id = builder.add_tuple_type(&type_ids)?;
|
||||
|
||||
|
@ -668,8 +638,7 @@ fn stmt_spec<'a>(
|
|||
builder.add_sub_block(block, BlockExpr(cont_block, cont_value_id))
|
||||
}
|
||||
Jump(id, symbols) => {
|
||||
let ret_type_id =
|
||||
layout_spec(env, builder, interner, layout, &WhenRecursive::Unreachable)?;
|
||||
let ret_type_id = layout_spec(env, builder, interner, layout)?;
|
||||
let argument = build_tuple_value(builder, env, block, symbols)?;
|
||||
|
||||
let jpid = env.join_points[id];
|
||||
|
@ -678,8 +647,7 @@ fn stmt_spec<'a>(
|
|||
Crash(msg, _) => {
|
||||
// Model this as a foreign call rather than TERMINATE because
|
||||
// we want ownership of the message.
|
||||
let result_type =
|
||||
layout_spec(env, builder, interner, layout, &WhenRecursive::Unreachable)?;
|
||||
let result_type = layout_spec(env, builder, interner, layout)?;
|
||||
|
||||
builder.add_unknown_with(block, &[env.symbols[msg]], result_type)
|
||||
}
|
||||
|
@ -708,23 +676,16 @@ fn build_tuple_value(
|
|||
builder.add_make_tuple(block, &value_ids)
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
enum WhenRecursive<'a> {
|
||||
Unreachable,
|
||||
Loop(UnionLayout<'a>),
|
||||
}
|
||||
|
||||
fn build_recursive_tuple_type<'a>(
|
||||
env: &mut Env<'a>,
|
||||
builder: &mut impl TypeContext,
|
||||
interner: &STLayoutInterner<'a>,
|
||||
layouts: &[InLayout<'a>],
|
||||
when_recursive: &WhenRecursive,
|
||||
) -> Result<TypeId> {
|
||||
let mut field_types = Vec::new();
|
||||
|
||||
for field in layouts.iter() {
|
||||
let type_id = layout_spec_help(env, builder, interner, *field, when_recursive)?;
|
||||
let type_id = layout_spec_help(env, builder, interner, *field)?;
|
||||
field_types.push(type_id);
|
||||
}
|
||||
|
||||
|
@ -736,12 +697,11 @@ fn build_tuple_type<'a>(
|
|||
builder: &mut impl TypeContext,
|
||||
interner: &STLayoutInterner<'a>,
|
||||
layouts: &[InLayout<'a>],
|
||||
when_recursive: &WhenRecursive,
|
||||
) -> Result<TypeId> {
|
||||
let mut field_types = Vec::new();
|
||||
|
||||
for field in layouts.iter() {
|
||||
field_types.push(layout_spec(env, builder, interner, *field, when_recursive)?);
|
||||
field_types.push(layout_spec(env, builder, interner, *field)?);
|
||||
}
|
||||
|
||||
builder.add_tuple_type(&field_types)
|
||||
|
@ -811,13 +771,7 @@ fn call_spec<'a>(
|
|||
.map(|symbol| env.symbols[symbol])
|
||||
.collect();
|
||||
|
||||
let result_type = layout_spec(
|
||||
env,
|
||||
builder,
|
||||
interner,
|
||||
*ret_layout,
|
||||
&WhenRecursive::Unreachable,
|
||||
)?;
|
||||
let result_type = layout_spec(env, builder, interner, *ret_layout)?;
|
||||
|
||||
builder.add_unknown_with(block, &arguments, result_type)
|
||||
}
|
||||
|
@ -888,23 +842,11 @@ fn call_spec<'a>(
|
|||
list_append(builder, block, update_mode_var, state, new_element)
|
||||
};
|
||||
|
||||
let output_element_type = layout_spec(
|
||||
env,
|
||||
builder,
|
||||
interner,
|
||||
*return_layout,
|
||||
&WhenRecursive::Unreachable,
|
||||
)?;
|
||||
let output_element_type = layout_spec(env, builder, interner, *return_layout)?;
|
||||
|
||||
let state_layout =
|
||||
interner.insert(Layout::Builtin(Builtin::List(*return_layout)));
|
||||
let state_type = layout_spec(
|
||||
env,
|
||||
builder,
|
||||
interner,
|
||||
state_layout,
|
||||
&WhenRecursive::Unreachable,
|
||||
)?;
|
||||
let state_type = layout_spec(env, builder, interner, state_layout)?;
|
||||
|
||||
let init_state = new_list(builder, block, output_element_type)?;
|
||||
|
||||
|
@ -931,13 +873,7 @@ fn call_spec<'a>(
|
|||
let arg0_layout = argument_layouts[0];
|
||||
|
||||
let state_layout = interner.insert(Layout::Builtin(Builtin::List(arg0_layout)));
|
||||
let state_type = layout_spec(
|
||||
env,
|
||||
builder,
|
||||
interner,
|
||||
state_layout,
|
||||
&WhenRecursive::Unreachable,
|
||||
)?;
|
||||
let state_type = layout_spec(env, builder, interner, state_layout)?;
|
||||
let init_state = list;
|
||||
|
||||
add_loop(builder, block, state_type, init_state, loop_body)
|
||||
|
@ -961,23 +897,11 @@ fn call_spec<'a>(
|
|||
list_append(builder, block, update_mode_var, state, new_element)
|
||||
};
|
||||
|
||||
let output_element_type = layout_spec(
|
||||
env,
|
||||
builder,
|
||||
interner,
|
||||
*return_layout,
|
||||
&WhenRecursive::Unreachable,
|
||||
)?;
|
||||
let output_element_type = layout_spec(env, builder, interner, *return_layout)?;
|
||||
|
||||
let state_layout =
|
||||
interner.insert(Layout::Builtin(Builtin::List(*return_layout)));
|
||||
let state_type = layout_spec(
|
||||
env,
|
||||
builder,
|
||||
interner,
|
||||
state_layout,
|
||||
&WhenRecursive::Unreachable,
|
||||
)?;
|
||||
let state_type = layout_spec(env, builder, interner, state_layout)?;
|
||||
|
||||
let init_state = new_list(builder, block, output_element_type)?;
|
||||
|
||||
|
@ -1007,23 +931,11 @@ fn call_spec<'a>(
|
|||
list_append(builder, block, update_mode_var, state, new_element)
|
||||
};
|
||||
|
||||
let output_element_type = layout_spec(
|
||||
env,
|
||||
builder,
|
||||
interner,
|
||||
*return_layout,
|
||||
&WhenRecursive::Unreachable,
|
||||
)?;
|
||||
let output_element_type = layout_spec(env, builder, interner, *return_layout)?;
|
||||
|
||||
let state_layout =
|
||||
interner.insert(Layout::Builtin(Builtin::List(*return_layout)));
|
||||
let state_type = layout_spec(
|
||||
env,
|
||||
builder,
|
||||
interner,
|
||||
state_layout,
|
||||
&WhenRecursive::Unreachable,
|
||||
)?;
|
||||
let state_type = layout_spec(env, builder, interner, state_layout)?;
|
||||
|
||||
let init_state = new_list(builder, block, output_element_type)?;
|
||||
|
||||
|
@ -1059,23 +971,11 @@ fn call_spec<'a>(
|
|||
list_append(builder, block, update_mode_var, state, new_element)
|
||||
};
|
||||
|
||||
let output_element_type = layout_spec(
|
||||
env,
|
||||
builder,
|
||||
interner,
|
||||
*return_layout,
|
||||
&WhenRecursive::Unreachable,
|
||||
)?;
|
||||
let output_element_type = layout_spec(env, builder, interner, *return_layout)?;
|
||||
|
||||
let state_layout =
|
||||
interner.insert(Layout::Builtin(Builtin::List(*return_layout)));
|
||||
let state_type = layout_spec(
|
||||
env,
|
||||
builder,
|
||||
interner,
|
||||
state_layout,
|
||||
&WhenRecursive::Unreachable,
|
||||
)?;
|
||||
let state_type = layout_spec(env, builder, interner, state_layout)?;
|
||||
|
||||
let init_state = new_list(builder, block, output_element_type)?;
|
||||
|
||||
|
@ -1130,7 +1030,7 @@ fn lowlevel_spec<'a>(
|
|||
) -> Result<ValueId> {
|
||||
use LowLevel::*;
|
||||
|
||||
let type_id = layout_spec(env, builder, interner, layout, &WhenRecursive::Unreachable)?;
|
||||
let type_id = layout_spec(env, builder, interner, layout)?;
|
||||
let mode = update_mode.to_bytes();
|
||||
let update_mode_var = UpdateModeVar(&mode);
|
||||
|
||||
|
@ -1238,13 +1138,7 @@ fn lowlevel_spec<'a>(
|
|||
|
||||
match interner.get(layout) {
|
||||
Layout::Builtin(Builtin::List(element_layout)) => {
|
||||
let type_id = layout_spec(
|
||||
env,
|
||||
builder,
|
||||
interner,
|
||||
element_layout,
|
||||
&WhenRecursive::Unreachable,
|
||||
)?;
|
||||
let type_id = layout_spec(env, builder, interner, element_layout)?;
|
||||
new_list(builder, block, type_id)
|
||||
}
|
||||
_ => unreachable!("empty array does not have a list layout"),
|
||||
|
@ -1287,8 +1181,7 @@ fn lowlevel_spec<'a>(
|
|||
// TODO overly pessimstic
|
||||
let arguments: Vec<_> = arguments.iter().map(|symbol| env.symbols[symbol]).collect();
|
||||
|
||||
let result_type =
|
||||
layout_spec(env, builder, interner, layout, &WhenRecursive::Unreachable)?;
|
||||
let result_type = layout_spec(env, builder, interner, layout)?;
|
||||
|
||||
builder.add_unknown_with(block, &arguments, result_type)
|
||||
}
|
||||
|
@ -1299,12 +1192,9 @@ fn recursive_tag_variant<'a>(
|
|||
env: &mut Env<'a>,
|
||||
builder: &mut impl TypeContext,
|
||||
interner: &STLayoutInterner<'a>,
|
||||
union_layout: &UnionLayout,
|
||||
fields: &[InLayout<'a>],
|
||||
) -> Result<TypeId> {
|
||||
let when_recursive = WhenRecursive::Loop(*union_layout);
|
||||
|
||||
build_recursive_tuple_type(env, builder, interner, fields, &when_recursive)
|
||||
build_recursive_tuple_type(env, builder, interner, fields)
|
||||
}
|
||||
|
||||
fn recursive_variant_types<'a>(
|
||||
|
@ -1325,23 +1215,11 @@ fn recursive_variant_types<'a>(
|
|||
result = Vec::with_capacity(tags.len());
|
||||
|
||||
for tag in tags.iter() {
|
||||
result.push(recursive_tag_variant(
|
||||
env,
|
||||
builder,
|
||||
interner,
|
||||
union_layout,
|
||||
tag,
|
||||
)?);
|
||||
result.push(recursive_tag_variant(env, builder, interner, tag)?);
|
||||
}
|
||||
}
|
||||
NonNullableUnwrapped(fields) => {
|
||||
result = vec![recursive_tag_variant(
|
||||
env,
|
||||
builder,
|
||||
interner,
|
||||
union_layout,
|
||||
fields,
|
||||
)?];
|
||||
result = vec![recursive_tag_variant(env, builder, interner, fields)?];
|
||||
}
|
||||
NullableWrapped {
|
||||
nullable_id,
|
||||
|
@ -1352,39 +1230,21 @@ fn recursive_variant_types<'a>(
|
|||
let cutoff = *nullable_id as usize;
|
||||
|
||||
for tag in tags[..cutoff].iter() {
|
||||
result.push(recursive_tag_variant(
|
||||
env,
|
||||
builder,
|
||||
interner,
|
||||
union_layout,
|
||||
tag,
|
||||
)?);
|
||||
result.push(recursive_tag_variant(env, builder, interner, tag)?);
|
||||
}
|
||||
|
||||
result.push(recursive_tag_variant(
|
||||
env,
|
||||
builder,
|
||||
interner,
|
||||
union_layout,
|
||||
&[],
|
||||
)?);
|
||||
result.push(recursive_tag_variant(env, builder, interner, &[])?);
|
||||
|
||||
for tag in tags[cutoff..].iter() {
|
||||
result.push(recursive_tag_variant(
|
||||
env,
|
||||
builder,
|
||||
interner,
|
||||
union_layout,
|
||||
tag,
|
||||
)?);
|
||||
result.push(recursive_tag_variant(env, builder, interner, tag)?);
|
||||
}
|
||||
}
|
||||
NullableUnwrapped {
|
||||
nullable_id,
|
||||
other_fields: fields,
|
||||
} => {
|
||||
let unit = recursive_tag_variant(env, builder, interner, union_layout, &[])?;
|
||||
let other_type = recursive_tag_variant(env, builder, interner, union_layout, fields)?;
|
||||
let unit = recursive_tag_variant(env, builder, interner, &[])?;
|
||||
let other_type = recursive_tag_variant(env, builder, interner, fields)?;
|
||||
|
||||
if *nullable_id {
|
||||
// nullable_id == 1
|
||||
|
@ -1432,13 +1292,7 @@ fn expr_spec<'a>(
|
|||
|
||||
let value_id = match tag_layout {
|
||||
UnionLayout::NonRecursive(tags) => {
|
||||
let variant_types = non_recursive_variant_types(
|
||||
env,
|
||||
builder,
|
||||
interner,
|
||||
tags,
|
||||
&WhenRecursive::Unreachable,
|
||||
)?;
|
||||
let variant_types = non_recursive_variant_types(env, builder, interner, tags)?;
|
||||
let value_id = build_tuple_value(builder, env, block, arguments)?;
|
||||
return builder.add_make_union(block, &variant_types, *tag_id as u32, value_id);
|
||||
}
|
||||
|
@ -1543,13 +1397,7 @@ fn expr_spec<'a>(
|
|||
builder.add_get_tuple_field(block, value_id, *index as u32)
|
||||
}
|
||||
Array { elem_layout, elems } => {
|
||||
let type_id = layout_spec(
|
||||
env,
|
||||
builder,
|
||||
interner,
|
||||
*elem_layout,
|
||||
&WhenRecursive::Unreachable,
|
||||
)?;
|
||||
let type_id = layout_spec(env, builder, interner, *elem_layout)?;
|
||||
|
||||
let list = new_list(builder, block, type_id)?;
|
||||
|
||||
|
@ -1576,13 +1424,7 @@ fn expr_spec<'a>(
|
|||
|
||||
EmptyArray => match interner.get(layout) {
|
||||
Layout::Builtin(Builtin::List(element_layout)) => {
|
||||
let type_id = layout_spec(
|
||||
env,
|
||||
builder,
|
||||
interner,
|
||||
element_layout,
|
||||
&WhenRecursive::Unreachable,
|
||||
)?;
|
||||
let type_id = layout_spec(env, builder, interner, element_layout)?;
|
||||
new_list(builder, block, type_id)
|
||||
}
|
||||
_ => unreachable!("empty array does not have a list layout"),
|
||||
|
@ -1615,7 +1457,7 @@ fn expr_spec<'a>(
|
|||
with_new_heap_cell(builder, block, union_data)
|
||||
}
|
||||
RuntimeErrorFunction(_) => {
|
||||
let type_id = layout_spec(env, builder, interner, layout, &WhenRecursive::Unreachable)?;
|
||||
let type_id = layout_spec(env, builder, interner, layout)?;
|
||||
|
||||
builder.add_terminate(block, type_id)
|
||||
}
|
||||
|
@ -1647,9 +1489,8 @@ fn layout_spec<'a>(
|
|||
builder: &mut impl TypeContext,
|
||||
interner: &STLayoutInterner<'a>,
|
||||
layout: InLayout<'a>,
|
||||
when_recursive: &WhenRecursive,
|
||||
) -> Result<TypeId> {
|
||||
layout_spec_help(env, builder, interner, layout, when_recursive)
|
||||
layout_spec_help(env, builder, interner, layout)
|
||||
}
|
||||
|
||||
fn non_recursive_variant_types<'a>(
|
||||
|
@ -1657,19 +1498,11 @@ fn non_recursive_variant_types<'a>(
|
|||
builder: &mut impl TypeContext,
|
||||
interner: &STLayoutInterner<'a>,
|
||||
tags: &[&[InLayout<'a>]],
|
||||
// If there is a recursive pointer latent within this layout, coming from a containing layout.
|
||||
when_recursive: &WhenRecursive,
|
||||
) -> Result<Vec<TypeId>> {
|
||||
let mut result = Vec::with_capacity(tags.len());
|
||||
|
||||
for tag in tags.iter() {
|
||||
result.push(build_tuple_type(
|
||||
env,
|
||||
builder,
|
||||
interner,
|
||||
tag,
|
||||
when_recursive,
|
||||
)?);
|
||||
result.push(build_tuple_type(env, builder, interner, tag)?);
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
|
@ -1680,22 +1513,17 @@ fn layout_spec_help<'a>(
|
|||
builder: &mut impl TypeContext,
|
||||
interner: &STLayoutInterner<'a>,
|
||||
layout: InLayout<'a>,
|
||||
when_recursive: &WhenRecursive,
|
||||
) -> Result<TypeId> {
|
||||
use Layout::*;
|
||||
|
||||
match interner.get(layout) {
|
||||
Builtin(builtin) => builtin_spec(env, builder, interner, &builtin, when_recursive),
|
||||
Builtin(builtin) => builtin_spec(env, builder, interner, &builtin),
|
||||
Struct { field_layouts, .. } => {
|
||||
build_recursive_tuple_type(env, builder, interner, field_layouts, when_recursive)
|
||||
build_recursive_tuple_type(env, builder, interner, field_layouts)
|
||||
}
|
||||
LambdaSet(lambda_set) => {
|
||||
layout_spec_help(env, builder, interner, lambda_set.runtime_representation())
|
||||
}
|
||||
LambdaSet(lambda_set) => layout_spec_help(
|
||||
env,
|
||||
builder,
|
||||
interner,
|
||||
lambda_set.runtime_representation(),
|
||||
when_recursive,
|
||||
),
|
||||
Union(union_layout) => {
|
||||
match union_layout {
|
||||
UnionLayout::NonRecursive(&[]) => {
|
||||
|
@ -1705,8 +1533,7 @@ fn layout_spec_help<'a>(
|
|||
builder.add_tuple_type(&[])
|
||||
}
|
||||
UnionLayout::NonRecursive(tags) => {
|
||||
let variant_types =
|
||||
non_recursive_variant_types(env, builder, interner, tags, when_recursive)?;
|
||||
let variant_types = non_recursive_variant_types(env, builder, interner, tags)?;
|
||||
builder.add_union_type(&variant_types)
|
||||
}
|
||||
UnionLayout::Recursive(_)
|
||||
|
@ -1724,29 +1551,21 @@ fn layout_spec_help<'a>(
|
|||
}
|
||||
|
||||
Boxed(inner_layout) => {
|
||||
let inner_type =
|
||||
layout_spec_help(env, builder, interner, inner_layout, when_recursive)?;
|
||||
let inner_type = layout_spec_help(env, builder, interner, inner_layout)?;
|
||||
let cell_type = builder.add_heap_cell_type();
|
||||
|
||||
builder.add_tuple_type(&[cell_type, inner_type])
|
||||
}
|
||||
// TODO(recursive-layouts): update once we have recursive pointer loops
|
||||
RecursivePointer(_) => match when_recursive {
|
||||
WhenRecursive::Unreachable => {
|
||||
unreachable!()
|
||||
}
|
||||
WhenRecursive::Loop(union_layout) => match union_layout {
|
||||
UnionLayout::NonRecursive(_) => unreachable!(),
|
||||
UnionLayout::Recursive(_)
|
||||
| UnionLayout::NullableUnwrapped { .. }
|
||||
| UnionLayout::NullableWrapped { .. }
|
||||
| UnionLayout::NonNullableUnwrapped(_) => {
|
||||
let type_name_bytes = recursive_tag_union_name_bytes(union_layout).as_bytes();
|
||||
let type_name = TypeName(&type_name_bytes);
|
||||
RecursivePointer(union_layout) => match interner.get(union_layout) {
|
||||
Layout::Union(union_layout) => {
|
||||
assert!(!matches!(union_layout, UnionLayout::NonRecursive(..)));
|
||||
let type_name_bytes = recursive_tag_union_name_bytes(&union_layout).as_bytes();
|
||||
let type_name = TypeName(&type_name_bytes);
|
||||
|
||||
Ok(builder.add_named_type(MOD_APP, type_name))
|
||||
}
|
||||
},
|
||||
Ok(builder.add_named_type(MOD_APP, type_name))
|
||||
}
|
||||
_ => internal_error!("somehow, a non-recursive layout is under a recursive pointer"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1756,7 +1575,6 @@ fn builtin_spec<'a>(
|
|||
builder: &mut impl TypeContext,
|
||||
interner: &STLayoutInterner<'a>,
|
||||
builtin: &Builtin<'a>,
|
||||
when_recursive: &WhenRecursive,
|
||||
) -> Result<TypeId> {
|
||||
use Builtin::*;
|
||||
|
||||
|
@ -1765,8 +1583,7 @@ fn builtin_spec<'a>(
|
|||
Decimal | Float(_) => builder.add_tuple_type(&[]),
|
||||
Str => str_type(builder),
|
||||
List(element_layout) => {
|
||||
let element_type =
|
||||
layout_spec_help(env, builder, interner, *element_layout, when_recursive)?;
|
||||
let element_type = layout_spec_help(env, builder, interner, *element_layout)?;
|
||||
|
||||
let cell = builder.add_heap_cell_type();
|
||||
let bag = builder.add_bag_type(element_type)?;
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -69,8 +66,8 @@ fn build_eq_builtin<'a, 'ctx, 'env>(
|
|||
layout_ids: &mut LayoutIds<'a>,
|
||||
lhs_val: BasicValueEnum<'ctx>,
|
||||
rhs_val: BasicValueEnum<'ctx>,
|
||||
builtin_layout: InLayout<'a>,
|
||||
builtin: &Builtin<'a>,
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let int_cmp = |pred, label| {
|
||||
let int_val = env.builder.build_int_compare(
|
||||
|
@ -129,19 +126,15 @@ fn build_eq_builtin<'a, 'ctx, 'env>(
|
|||
Builtin::Decimal => dec_binop_with_unchecked(env, bitcode::DEC_EQ, lhs_val, rhs_val),
|
||||
|
||||
Builtin::Str => str_equal(env, lhs_val, rhs_val),
|
||||
Builtin::List(elem) => {
|
||||
let list_layout = layout_interner.insert(Layout::Builtin(*builtin));
|
||||
build_list_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
list_layout,
|
||||
*elem,
|
||||
lhs_val.into_struct_value(),
|
||||
rhs_val.into_struct_value(),
|
||||
when_recursive,
|
||||
)
|
||||
}
|
||||
Builtin::List(elem) => build_list_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
builtin_layout,
|
||||
*elem,
|
||||
lhs_val.into_struct_value(),
|
||||
rhs_val.into_struct_value(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,7 +146,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);
|
||||
|
@ -171,16 +163,16 @@ fn build_eq<'a, 'ctx, 'env>(
|
|||
layout_ids,
|
||||
lhs_val,
|
||||
rhs_val,
|
||||
*lhs_layout,
|
||||
&builtin,
|
||||
when_recursive,
|
||||
),
|
||||
|
||||
Layout::Struct { field_layouts, .. } => build_struct_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
*lhs_layout,
|
||||
field_layouts,
|
||||
when_recursive,
|
||||
lhs_val.into_struct_value(),
|
||||
rhs_val.into_struct_value(),
|
||||
),
|
||||
|
@ -191,7 +183,7 @@ fn build_eq<'a, 'ctx, 'env>(
|
|||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
when_recursive,
|
||||
*lhs_layout,
|
||||
&union_layout,
|
||||
lhs_val,
|
||||
rhs_val,
|
||||
|
@ -201,47 +193,48 @@ 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,
|
||||
rec_layout,
|
||||
&union_layout,
|
||||
field1_cast.into(),
|
||||
field2_cast.into(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -251,8 +244,8 @@ fn build_neq_builtin<'a, 'ctx, 'env>(
|
|||
layout_ids: &mut LayoutIds<'a>,
|
||||
lhs_val: BasicValueEnum<'ctx>,
|
||||
rhs_val: BasicValueEnum<'ctx>,
|
||||
builtin_layout: InLayout<'a>,
|
||||
builtin: &Builtin<'a>,
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let int_cmp = |pred, label| {
|
||||
let int_val = env.builder.build_int_compare(
|
||||
|
@ -317,7 +310,6 @@ fn build_neq_builtin<'a, 'ctx, 'env>(
|
|||
result.into()
|
||||
}
|
||||
Builtin::List(elem) => {
|
||||
let builtin_layout = layout_interner.insert(Layout::Builtin(*builtin));
|
||||
let is_equal = build_list_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
|
@ -326,7 +318,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 +336,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!(
|
||||
|
@ -361,8 +351,8 @@ fn build_neq<'a, 'ctx, 'env>(
|
|||
layout_ids,
|
||||
lhs_val,
|
||||
rhs_val,
|
||||
lhs_layout,
|
||||
&builtin,
|
||||
when_recursive,
|
||||
),
|
||||
|
||||
Layout::Struct { field_layouts, .. } => {
|
||||
|
@ -370,8 +360,8 @@ fn build_neq<'a, 'ctx, 'env>(
|
|||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
lhs_layout,
|
||||
field_layouts,
|
||||
when_recursive,
|
||||
lhs_val.into_struct_value(),
|
||||
rhs_val.into_struct_value(),
|
||||
)
|
||||
|
@ -387,7 +377,7 @@ fn build_neq<'a, 'ctx, 'env>(
|
|||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
when_recursive,
|
||||
lhs_layout,
|
||||
&union_layout,
|
||||
lhs_val,
|
||||
rhs_val,
|
||||
|
@ -404,7 +394,6 @@ fn build_neq<'a, 'ctx, 'env>(
|
|||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
when_recursive,
|
||||
lhs_layout,
|
||||
inner_layout,
|
||||
lhs_val,
|
||||
|
@ -432,15 +421,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 +452,6 @@ fn build_list_eq<'a, 'ctx, 'env>(
|
|||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
when_recursive,
|
||||
function_value,
|
||||
element_layout,
|
||||
);
|
||||
|
@ -486,7 +476,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 +594,6 @@ fn build_list_eq_help<'a, 'ctx, 'env>(
|
|||
elem2,
|
||||
element_layout,
|
||||
element_layout,
|
||||
when_recursive,
|
||||
)
|
||||
.into_int_value();
|
||||
|
||||
|
@ -646,16 +634,14 @@ fn build_struct_eq<'a, 'ctx, 'env>(
|
|||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
struct_layout: InLayout<'a>,
|
||||
field_layouts: &'a [InLayout<'a>],
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
struct1: StructValue<'ctx>,
|
||||
struct2: StructValue<'ctx>,
|
||||
) -> 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 struct_layout = layout_interner.insert(Layout::struct_no_name_order(field_layouts));
|
||||
|
||||
let symbol = Symbol::GENERIC_EQ;
|
||||
let fn_name = layout_ids
|
||||
.get(symbol, &struct_layout)
|
||||
|
@ -678,7 +664,6 @@ fn build_struct_eq<'a, 'ctx, 'env>(
|
|||
layout_interner,
|
||||
layout_ids,
|
||||
function_value,
|
||||
when_recursive,
|
||||
field_layouts,
|
||||
);
|
||||
|
||||
|
@ -703,7 +688,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 +745,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 +790,6 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
|
|||
rhs,
|
||||
*field_layout,
|
||||
*field_layout,
|
||||
when_recursive,
|
||||
)
|
||||
.into_int_value()
|
||||
};
|
||||
|
@ -839,7 +820,7 @@ 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>,
|
||||
tag_layout: InLayout<'a>,
|
||||
union_layout: &UnionLayout<'a>,
|
||||
tag1: BasicValueEnum<'ctx>,
|
||||
tag2: BasicValueEnum<'ctx>,
|
||||
|
@ -847,7 +828,6 @@ fn build_tag_eq<'a, 'ctx, 'env>(
|
|||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let tag_layout = layout_interner.insert(Layout::Union(*union_layout));
|
||||
let symbol = Symbol::GENERIC_EQ;
|
||||
let fn_name = layout_ids
|
||||
.get(symbol, &tag_layout)
|
||||
|
@ -869,7 +849,6 @@ fn build_tag_eq<'a, 'ctx, 'env>(
|
|||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
when_recursive,
|
||||
function_value,
|
||||
union_layout,
|
||||
);
|
||||
|
@ -894,7 +873,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>,
|
||||
) {
|
||||
|
@ -999,12 +977,14 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
|
|||
let block = env.context.append_basic_block(parent, "tag_id_modify");
|
||||
env.builder.position_at_end(block);
|
||||
|
||||
let struct_layout =
|
||||
layout_interner.insert(Layout::struct_no_name_order(field_layouts));
|
||||
|
||||
let answer = eq_ptr_to_struct(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
union_layout,
|
||||
Some(when_recursive),
|
||||
struct_layout,
|
||||
field_layouts,
|
||||
tag1,
|
||||
tag2,
|
||||
|
@ -1070,12 +1050,14 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
|
|||
let block = env.context.append_basic_block(parent, "tag_id_modify");
|
||||
env.builder.position_at_end(block);
|
||||
|
||||
let struct_layout =
|
||||
layout_interner.insert(Layout::struct_no_name_order(field_layouts));
|
||||
|
||||
let answer = eq_ptr_to_struct(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
union_layout,
|
||||
None,
|
||||
struct_layout,
|
||||
field_layouts,
|
||||
tag1,
|
||||
tag2,
|
||||
|
@ -1131,12 +1113,13 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
|
|||
|
||||
env.builder.position_at_end(compare_other);
|
||||
|
||||
let struct_layout = layout_interner.insert(Layout::struct_no_name_order(other_fields));
|
||||
|
||||
let answer = eq_ptr_to_struct(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
union_layout,
|
||||
None,
|
||||
struct_layout,
|
||||
other_fields,
|
||||
tag1.into_pointer_value(),
|
||||
tag2.into_pointer_value(),
|
||||
|
@ -1229,12 +1212,14 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
|
|||
let block = env.context.append_basic_block(parent, "tag_id_modify");
|
||||
env.builder.position_at_end(block);
|
||||
|
||||
let struct_layout =
|
||||
layout_interner.insert(Layout::struct_no_name_order(field_layouts));
|
||||
|
||||
let answer = eq_ptr_to_struct(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
union_layout,
|
||||
None,
|
||||
struct_layout,
|
||||
field_layouts,
|
||||
tag1,
|
||||
tag2,
|
||||
|
@ -1268,12 +1253,13 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
|
|||
|
||||
env.builder.position_at_end(compare_fields);
|
||||
|
||||
let struct_layout = layout_interner.insert(Layout::struct_no_name_order(field_layouts));
|
||||
|
||||
let answer = eq_ptr_to_struct(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
union_layout,
|
||||
None,
|
||||
struct_layout,
|
||||
field_layouts,
|
||||
tag1.into_pointer_value(),
|
||||
tag2.into_pointer_value(),
|
||||
|
@ -1288,14 +1274,11 @@ fn eq_ptr_to_struct<'a, 'ctx, 'env>(
|
|||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
union_layout: &UnionLayout<'a>,
|
||||
opt_when_recursive: Option<WhenRecursive<'a>>,
|
||||
struct_layout: InLayout<'a>,
|
||||
field_layouts: &'a [InLayout<'a>],
|
||||
tag1: PointerValue<'ctx>,
|
||||
tag2: PointerValue<'ctx>,
|
||||
) -> IntValue<'ctx> {
|
||||
let struct_layout = layout_interner.insert(Layout::struct_no_name_order(field_layouts));
|
||||
|
||||
let wrapper_type = basic_type_from_layout(env, layout_interner, struct_layout);
|
||||
debug_assert!(wrapper_type.is_struct_type());
|
||||
|
||||
|
@ -1326,8 +1309,8 @@ fn eq_ptr_to_struct<'a, 'ctx, 'env>(
|
|||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
struct_layout,
|
||||
field_layouts,
|
||||
opt_when_recursive.unwrap_or(WhenRecursive::Loop(*union_layout)),
|
||||
struct1,
|
||||
struct2,
|
||||
)
|
||||
|
@ -1340,7 +1323,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 +1352,6 @@ fn build_box_eq<'a, 'ctx, 'env>(
|
|||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
when_recursive,
|
||||
function_value,
|
||||
inner_layout,
|
||||
);
|
||||
|
@ -1395,7 +1376,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 +1452,6 @@ fn build_box_eq_help<'a, 'ctx, 'env>(
|
|||
value2,
|
||||
inner_layout,
|
||||
inner_layout,
|
||||
when_recursive,
|
||||
);
|
||||
|
||||
env.builder.build_return(Some(&is_equal));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue