mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 16:44:33 +00:00
get RBTree.balance to compile
This commit is contained in:
parent
ec3868ed7e
commit
154b5cc29f
5 changed files with 104 additions and 83 deletions
|
@ -89,46 +89,7 @@ pub fn decrement_refcount_layout<'a, 'ctx, 'env>(
|
|||
RecursivePointer => todo!("TODO implement decrement layout of recursive tag union"),
|
||||
|
||||
Union(tags) => {
|
||||
debug_assert!(!tags.is_empty());
|
||||
let wrapper_struct = value.into_struct_value();
|
||||
|
||||
// read the tag_id
|
||||
let tag_id = env
|
||||
.builder
|
||||
.build_extract_value(wrapper_struct, 0, "read_tag_id")
|
||||
.unwrap()
|
||||
.into_int_value();
|
||||
|
||||
// next, make a jump table for all possible values of the tag_id
|
||||
let mut cases = Vec::with_capacity_in(tags.len(), env.arena);
|
||||
|
||||
let merge_block = env.context.append_basic_block(parent, "decrement_merge");
|
||||
|
||||
for (tag_id, field_layouts) in tags.iter().enumerate() {
|
||||
let block = env.context.append_basic_block(parent, "tag_id_decrement");
|
||||
env.builder.position_at_end(block);
|
||||
|
||||
for (i, field_layout) in field_layouts.iter().enumerate() {
|
||||
if field_layout.contains_refcounted() {
|
||||
let field_ptr = env
|
||||
.builder
|
||||
.build_extract_value(wrapper_struct, i as u32, "decrement_struct_field")
|
||||
.unwrap();
|
||||
|
||||
decrement_refcount_layout(env, parent, layout_ids, field_ptr, field_layout)
|
||||
}
|
||||
}
|
||||
|
||||
env.builder.build_unconditional_branch(merge_block);
|
||||
|
||||
cases.push((env.context.i8_type().const_int(tag_id as u64, false), block));
|
||||
}
|
||||
|
||||
let (_, default_block) = cases.pop().unwrap();
|
||||
|
||||
env.builder.build_switch(tag_id, default_block, &cases);
|
||||
|
||||
env.builder.position_at_end(merge_block);
|
||||
build_dec_union(env, layout_ids, tags, value);
|
||||
}
|
||||
|
||||
RecursiveUnion(tags) => {
|
||||
|
@ -906,14 +867,20 @@ pub fn build_dec_union_help<'a, 'ctx, 'env>(
|
|||
|
||||
let wrapper_struct = arg_val.into_struct_value();
|
||||
|
||||
// let tag_id_u8 = cast_basic_basic(env.builder, tag_id.into(), env.context.i8_type().into());
|
||||
|
||||
// next, make a jump table for all possible values of the tag_id
|
||||
let mut cases = Vec::with_capacity_in(tags.len(), env.arena);
|
||||
|
||||
let merge_block = env.context.append_basic_block(parent, "decrement_merge");
|
||||
|
||||
for (tag_id, field_layouts) in tags.iter().enumerate() {
|
||||
// if none of the fields are or contain anything refcounted, just move on
|
||||
if !field_layouts
|
||||
.iter()
|
||||
.any(|x| x.is_refcounted() || x.contains_refcounted())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let block = env.context.append_basic_block(parent, "tag_id_decrement");
|
||||
env.builder.position_at_end(block);
|
||||
|
||||
|
@ -981,8 +948,6 @@ pub fn build_dec_union_help<'a, 'ctx, 'env>(
|
|||
|
||||
cases.reverse();
|
||||
|
||||
let (_, default_block) = cases.pop().unwrap();
|
||||
|
||||
env.builder.position_at_end(before_block);
|
||||
|
||||
// read the tag_id
|
||||
|
@ -1002,7 +967,7 @@ pub fn build_dec_union_help<'a, 'ctx, 'env>(
|
|||
|
||||
// switch on it
|
||||
env.builder
|
||||
.build_switch(current_tag_id, default_block, &cases);
|
||||
.build_switch(current_tag_id, merge_block, &cases);
|
||||
|
||||
env.builder.position_at_end(merge_block);
|
||||
|
||||
|
@ -1109,10 +1074,18 @@ pub fn build_inc_union_help<'a, 'ctx, 'env>(
|
|||
// next, make a jump table for all possible values of the tag_id
|
||||
let mut cases = Vec::with_capacity_in(tags.len(), env.arena);
|
||||
|
||||
let merge_block = env.context.append_basic_block(parent, "decrement_merge");
|
||||
let merge_block = env.context.append_basic_block(parent, "increment_merge");
|
||||
|
||||
for (tag_id, field_layouts) in tags.iter().enumerate() {
|
||||
let block = env.context.append_basic_block(parent, "tag_id_decrement");
|
||||
// if none of the fields are or contain anything refcounted, just move on
|
||||
if !field_layouts
|
||||
.iter()
|
||||
.any(|x| x.is_refcounted() || x.contains_refcounted())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let block = env.context.append_basic_block(parent, "tag_id_increment");
|
||||
env.builder.position_at_end(block);
|
||||
|
||||
let wrapper_type = basic_type_from_layout(
|
||||
|
@ -1127,18 +1100,19 @@ pub fn build_inc_union_help<'a, 'ctx, 'env>(
|
|||
|
||||
for (i, field_layout) in field_layouts.iter().enumerate() {
|
||||
if let Layout::RecursivePointer = field_layout {
|
||||
// a *i64 pointer to the recursive data
|
||||
// we need to cast this pointer to the appropriate type
|
||||
let field_ptr = env
|
||||
// this field has type `*i64`, but is really a pointer to the data we want
|
||||
let ptr_as_i64_ptr = env
|
||||
.builder
|
||||
.build_extract_value(wrapper_struct, i as u32, "decrement_struct_field")
|
||||
.build_extract_value(wrapper_struct, i as u32, "increment_struct_field")
|
||||
.unwrap();
|
||||
|
||||
// recursively increment
|
||||
debug_assert!(ptr_as_i64_ptr.is_pointer_value());
|
||||
|
||||
// therefore we must cast it to our desired type
|
||||
let union_type = block_of_memory(env.context, &layout, env.ptr_bytes);
|
||||
let recursive_field_ptr = cast_basic_basic(
|
||||
env.builder,
|
||||
field_ptr,
|
||||
ptr_as_i64_ptr,
|
||||
union_type.ptr_type(AddressSpace::Generic).into(),
|
||||
)
|
||||
.into_pointer_value();
|
||||
|
@ -1155,9 +1129,9 @@ pub fn build_inc_union_help<'a, 'ctx, 'env>(
|
|||
// Because it's an internal-only function, use the fast calling convention.
|
||||
call.set_call_convention(FAST_CALL_CONV);
|
||||
|
||||
// TODO do this increment before the recursive call?
|
||||
// TODO do this decrement before the recursive call?
|
||||
// Then the recursive call is potentially TCE'd
|
||||
increment_refcount_ptr(env, &layout, field_ptr.into_pointer_value());
|
||||
increment_refcount_ptr(env, &layout, recursive_field_ptr);
|
||||
} else if field_layout.contains_refcounted() {
|
||||
let field_ptr = env
|
||||
.builder
|
||||
|
@ -1173,12 +1147,10 @@ pub fn build_inc_union_help<'a, 'ctx, 'env>(
|
|||
cases.push((env.context.i8_type().const_int(tag_id as u64, false), block));
|
||||
}
|
||||
|
||||
let (_, default_block) = cases.pop().unwrap();
|
||||
|
||||
env.builder.position_at_end(before_block);
|
||||
|
||||
env.builder
|
||||
.build_switch(tag_id_u8.into_int_value(), default_block, &cases);
|
||||
.build_switch(tag_id_u8.into_int_value(), merge_block, &cases);
|
||||
|
||||
env.builder.position_at_end(merge_block);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue