mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 07:14:46 +00:00
passing tests
This commit is contained in:
parent
1d1bcaea63
commit
978cea4b8a
12 changed files with 230 additions and 207 deletions
|
@ -632,6 +632,7 @@ pub fn int_with_precision<'a, 'ctx, 'env>(
|
|||
Builtin::Int32 => env.context.i32_type().const_int(value as u64, false),
|
||||
Builtin::Int16 => env.context.i16_type().const_int(value as u64, false),
|
||||
Builtin::Int8 => env.context.i8_type().const_int(value as u64, false),
|
||||
Builtin::Int1 => env.context.bool_type().const_int(value as u64, false),
|
||||
_ => panic!("Invalid layout for int literal = {:?}", precision),
|
||||
}
|
||||
}
|
||||
|
@ -1081,11 +1082,8 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
|||
|
||||
let field_layouts = tag_layouts[*tag_id as usize];
|
||||
|
||||
let tag_id_type = basic_type_from_layout(
|
||||
env,
|
||||
&UnionLayout::tag_id_layout_from_slices(tag_layouts),
|
||||
)
|
||||
.into_int_type();
|
||||
let tag_id_type =
|
||||
basic_type_from_layout(env, &union_layout.tag_id_layout()).into_int_type();
|
||||
|
||||
lookup_at_index_ptr2(
|
||||
env,
|
||||
|
@ -1124,11 +1122,8 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
|||
|
||||
let field_layouts = other_tags[tag_index as usize];
|
||||
|
||||
let tag_id_type = basic_type_from_layout(
|
||||
env,
|
||||
&UnionLayout::tag_id_layout_from_slices(other_tags),
|
||||
)
|
||||
.into_int_type();
|
||||
let tag_id_type =
|
||||
basic_type_from_layout(env, &union_layout.tag_id_layout()).into_int_type();
|
||||
|
||||
lookup_at_index_ptr2(
|
||||
env,
|
||||
|
@ -1183,6 +1178,8 @@ pub fn build_tag<'a, 'ctx, 'env>(
|
|||
tag_id: u8,
|
||||
arguments: &[Symbol],
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let tag_id_layout = union_layout.tag_id_layout();
|
||||
|
||||
match union_layout {
|
||||
UnionLayout::NonRecursive(tags) => {
|
||||
debug_assert!(union_size > 1);
|
||||
|
@ -1254,9 +1251,7 @@ pub fn build_tag<'a, 'ctx, 'env>(
|
|||
let internal_type = block_of_memory_slices(env.context, tags, env.ptr_bytes);
|
||||
|
||||
let data = cast_tag_to_block_of_memory(builder, struct_val, internal_type);
|
||||
let tag_id_type =
|
||||
basic_type_from_layout(env, &UnionLayout::tag_id_layout_from_slices(tags))
|
||||
.into_int_type();
|
||||
let tag_id_type = basic_type_from_layout(env, &tag_id_layout).into_int_type();
|
||||
let wrapper_type = env
|
||||
.context
|
||||
.struct_type(&[data.get_type(), tag_id_type.into()], false);
|
||||
|
@ -1264,8 +1259,8 @@ pub fn build_tag<'a, 'ctx, 'env>(
|
|||
let tag_id_intval = tag_id_type.const_int(tag_id as u64, false);
|
||||
|
||||
let field_vals = [
|
||||
(TAG_ID_INDEX as usize, tag_id_intval.into()),
|
||||
(TAG_DATA_INDEX as usize, data),
|
||||
(TAG_ID_INDEX as usize, tag_id_intval.into()),
|
||||
];
|
||||
|
||||
struct_from_fields(env, wrapper_type, field_vals.iter().copied()).into()
|
||||
|
@ -1317,9 +1312,7 @@ pub fn build_tag<'a, 'ctx, 'env>(
|
|||
.build_struct_gep(raw_data_ptr, TAG_ID_INDEX, "tag_id_index")
|
||||
.unwrap();
|
||||
|
||||
let tag_id_type =
|
||||
basic_type_from_layout(env, &UnionLayout::tag_id_layout_from_slices(tags))
|
||||
.into_int_type();
|
||||
let tag_id_type = basic_type_from_layout(env, &tag_id_layout).into_int_type();
|
||||
|
||||
env.builder
|
||||
.build_store(tag_id_ptr, tag_id_type.const_int(tag_id as u64, false));
|
||||
|
@ -1482,9 +1475,7 @@ pub fn build_tag<'a, 'ctx, 'env>(
|
|||
.build_struct_gep(raw_data_ptr, TAG_ID_INDEX, "tag_id_index")
|
||||
.unwrap();
|
||||
|
||||
let tag_id_type =
|
||||
basic_type_from_layout(env, &UnionLayout::tag_id_layout_from_slices(tags))
|
||||
.into_int_type();
|
||||
let tag_id_type = basic_type_from_layout(env, &tag_id_layout).into_int_type();
|
||||
|
||||
env.builder
|
||||
.build_store(tag_id_ptr, tag_id_type.const_int(tag_id as u64, false));
|
||||
|
@ -1608,6 +1599,10 @@ pub fn get_tag_id<'a, 'ctx, 'env>(
|
|||
argument: BasicValueEnum<'ctx>,
|
||||
) -> IntValue<'ctx> {
|
||||
let builder = env.builder;
|
||||
|
||||
let tag_id_layout = union_layout.tag_id_layout();
|
||||
let tag_id_int_type = basic_type_from_layout(env, &tag_id_layout).into_int_type();
|
||||
|
||||
match union_layout {
|
||||
UnionLayout::NonRecursive(_) => {
|
||||
let tag = argument.into_struct_value();
|
||||
|
@ -1615,7 +1610,7 @@ pub fn get_tag_id<'a, 'ctx, 'env>(
|
|||
get_tag_id_non_recursive(env, tag)
|
||||
}
|
||||
UnionLayout::Recursive(_) => get_tag_id_wrapped(env, argument.into_pointer_value()),
|
||||
UnionLayout::NonNullableUnwrapped(_) => env.context.i64_type().const_zero(),
|
||||
UnionLayout::NonNullableUnwrapped(_) => tag_id_int_type.const_zero(),
|
||||
UnionLayout::NullableWrapped { nullable_id, .. } => {
|
||||
let argument_ptr = argument.into_pointer_value();
|
||||
let is_null = env.builder.build_is_null(argument_ptr, "is_null");
|
||||
|
@ -1625,14 +1620,14 @@ pub fn get_tag_id<'a, 'ctx, 'env>(
|
|||
let else_block = ctx.append_basic_block(parent, "else");
|
||||
let cont_block = ctx.append_basic_block(parent, "cont");
|
||||
|
||||
let result = builder.build_alloca(ctx.i64_type(), "result");
|
||||
let result = builder.build_alloca(tag_id_int_type, "result");
|
||||
|
||||
env.builder
|
||||
.build_conditional_branch(is_null, then_block, else_block);
|
||||
|
||||
{
|
||||
env.builder.position_at_end(then_block);
|
||||
let tag_id = ctx.i64_type().const_int(*nullable_id as u64, false);
|
||||
let tag_id = tag_id_int_type.const_int(*nullable_id as u64, false);
|
||||
env.builder.build_store(result, tag_id);
|
||||
env.builder.build_unconditional_branch(cont_block);
|
||||
}
|
||||
|
@ -1654,10 +1649,8 @@ pub fn get_tag_id<'a, 'ctx, 'env>(
|
|||
let argument_ptr = argument.into_pointer_value();
|
||||
let is_null = env.builder.build_is_null(argument_ptr, "is_null");
|
||||
|
||||
let ctx = env.context;
|
||||
|
||||
let then_value = ctx.i64_type().const_int(*nullable_id as u64, false);
|
||||
let else_value = ctx.i64_type().const_int(!*nullable_id as u64, false);
|
||||
let then_value = tag_id_int_type.const_int(*nullable_id as u64, false);
|
||||
let else_value = tag_id_int_type.const_int(!*nullable_id as u64, false);
|
||||
|
||||
env.builder
|
||||
.build_select(is_null, then_value, else_value, "select_tag_id")
|
||||
|
@ -1746,10 +1739,10 @@ fn lookup_at_index_ptr2<'a, 'ctx, 'env>(
|
|||
|
||||
let tags = &[field_layouts];
|
||||
let struct_type = block_of_memory_slices(env.context, tags, env.ptr_bytes);
|
||||
let tag_id_type =
|
||||
basic_type_from_layout(env, &UnionLayout::tag_id_layout_from_slices(tags));
|
||||
|
||||
let opaque_wrapper_type = env.context.struct_type(&[struct_type, tag_id_type], false);
|
||||
let opaque_wrapper_type = env
|
||||
.context
|
||||
.struct_type(&[struct_type, tag_id_type.into()], false);
|
||||
|
||||
builder.build_bitcast(
|
||||
result,
|
||||
|
@ -2741,18 +2734,14 @@ fn build_switch_ir<'a, 'ctx, 'env>(
|
|||
// ]
|
||||
//
|
||||
// they either need to all be i8, or i64
|
||||
let int_val = match cond_layout {
|
||||
Layout::Builtin(Builtin::Usize) => {
|
||||
ptr_int(env.context, env.ptr_bytes).const_int(*int as u64, false)
|
||||
}
|
||||
Layout::Builtin(Builtin::Int64) => context.i64_type().const_int(*int as u64, false),
|
||||
Layout::Builtin(Builtin::Int128) => const_i128(env, *int as i128),
|
||||
Layout::Builtin(Builtin::Int32) => context.i32_type().const_int(*int as u64, false),
|
||||
Layout::Builtin(Builtin::Int16) => context.i16_type().const_int(*int as u64, false),
|
||||
Layout::Builtin(Builtin::Int8) => context.i8_type().const_int(*int as u64, false),
|
||||
Layout::Builtin(Builtin::Int1) => context.bool_type().const_int(*int as u64, false),
|
||||
_ => panic!("Can't cast to cond_layout = {:?}", cond_layout),
|
||||
let condition_int_type = cond.get_type();
|
||||
|
||||
let int_val = if condition_int_type == context.i128_type() {
|
||||
const_i128(env, *int as i128)
|
||||
} else {
|
||||
condition_int_type.const_int(*int as u64, false)
|
||||
};
|
||||
|
||||
let block = context.append_basic_block(parent, format!("branch{}", int).as_str());
|
||||
|
||||
cases.push((int_val, block));
|
||||
|
|
|
@ -401,12 +401,14 @@ fn hash_tag<'a, 'ctx, 'env>(
|
|||
let merge_block = env.context.append_basic_block(parent, "merge_block");
|
||||
env.builder.position_at_end(merge_block);
|
||||
|
||||
let merge_phi = env.builder.build_phi(env.context.i64_type(), "merge_hash");
|
||||
let tag_id_basic_type = basic_type_from_layout(env, &union_layout.tag_id_layout());
|
||||
|
||||
let merge_phi = env.builder.build_phi(seed.get_type(), "merge_hash");
|
||||
|
||||
env.builder.position_at_end(entry_block);
|
||||
match union_layout {
|
||||
NonRecursive(tags) => {
|
||||
let tag_id = get_tag_id(env, parent, union_layout, tag);
|
||||
let current_tag_id = get_tag_id(env, parent, union_layout, tag);
|
||||
|
||||
let mut cases = Vec::with_capacity_in(tags.len(), env.arena);
|
||||
|
||||
|
@ -414,7 +416,6 @@ fn hash_tag<'a, 'ctx, 'env>(
|
|||
let block = env.context.append_basic_block(parent, "tag_id_modify");
|
||||
env.builder.position_at_end(block);
|
||||
|
||||
// TODO drop tag id?
|
||||
let struct_layout = Layout::Struct(field_layouts);
|
||||
|
||||
let wrapper_type = basic_type_from_layout(env, &struct_layout);
|
||||
|
@ -436,7 +437,7 @@ fn hash_tag<'a, 'ctx, 'env>(
|
|||
env.builder.build_unconditional_branch(merge_block);
|
||||
|
||||
cases.push((
|
||||
env.context.i64_type().const_int(tag_id as u64, false),
|
||||
current_tag_id.get_type().const_int(tag_id as u64, false),
|
||||
block,
|
||||
));
|
||||
}
|
||||
|
@ -445,10 +446,10 @@ fn hash_tag<'a, 'ctx, 'env>(
|
|||
|
||||
let default = cases.pop().unwrap().1;
|
||||
|
||||
env.builder.build_switch(tag_id, default, &cases);
|
||||
env.builder.build_switch(current_tag_id, default, &cases);
|
||||
}
|
||||
Recursive(tags) => {
|
||||
let tag_id = get_tag_id(env, parent, union_layout, tag);
|
||||
let current_tag_id = get_tag_id(env, parent, union_layout, tag);
|
||||
|
||||
let mut cases = Vec::with_capacity_in(tags.len(), env.arena);
|
||||
|
||||
|
@ -469,7 +470,7 @@ fn hash_tag<'a, 'ctx, 'env>(
|
|||
env.builder.build_unconditional_branch(merge_block);
|
||||
|
||||
cases.push((
|
||||
env.context.i64_type().const_int(tag_id as u64, false),
|
||||
current_tag_id.get_type().const_int(tag_id as u64, false),
|
||||
block,
|
||||
));
|
||||
}
|
||||
|
@ -478,7 +479,7 @@ fn hash_tag<'a, 'ctx, 'env>(
|
|||
|
||||
let default = cases.pop().unwrap().1;
|
||||
|
||||
env.builder.build_switch(tag_id, default, &cases);
|
||||
env.builder.build_switch(current_tag_id, default, &cases);
|
||||
}
|
||||
NullableUnwrapped { other_fields, .. } => {
|
||||
let tag = tag.into_pointer_value();
|
||||
|
@ -544,7 +545,9 @@ fn hash_tag<'a, 'ctx, 'env>(
|
|||
env.builder.build_unconditional_branch(merge_block);
|
||||
|
||||
cases.push((
|
||||
env.context.i64_type().const_int(tag_id as u64, false),
|
||||
tag_id_basic_type
|
||||
.into_int_type()
|
||||
.const_int(tag_id as u64, false),
|
||||
block,
|
||||
));
|
||||
}
|
||||
|
|
|
@ -896,10 +896,7 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
|
|||
|
||||
env.builder.build_return(Some(&answer));
|
||||
|
||||
cases.push((
|
||||
env.context.i64_type().const_int(tag_id as u64, false),
|
||||
block,
|
||||
));
|
||||
cases.push((id1.get_type().const_int(tag_id as u64, false), block));
|
||||
}
|
||||
|
||||
env.builder.position_at_end(compare_tag_fields);
|
||||
|
@ -958,10 +955,7 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
|
|||
|
||||
env.builder.build_return(Some(&answer));
|
||||
|
||||
cases.push((
|
||||
env.context.i64_type().const_int(tag_id as u64, false),
|
||||
block,
|
||||
));
|
||||
cases.push((id1.get_type().const_int(tag_id as u64, false), block));
|
||||
}
|
||||
|
||||
env.builder.position_at_end(compare_tag_fields);
|
||||
|
@ -1110,10 +1104,7 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
|
|||
|
||||
env.builder.build_return(Some(&answer));
|
||||
|
||||
cases.push((
|
||||
env.context.i64_type().const_int(tag_id as u64, false),
|
||||
block,
|
||||
));
|
||||
cases.push((id1.get_type().const_int(tag_id as u64, false), block));
|
||||
}
|
||||
|
||||
env.builder.position_at_end(compare_tag_fields);
|
||||
|
|
|
@ -33,6 +33,9 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>(
|
|||
Struct(sorted_fields) => basic_type_from_record(env, sorted_fields),
|
||||
Union(variant) => {
|
||||
use UnionLayout::*;
|
||||
|
||||
let tag_id_type = basic_type_from_layout(env, &variant.tag_id_layout());
|
||||
|
||||
match variant {
|
||||
NullableWrapped {
|
||||
other_tags: tags, ..
|
||||
|
@ -40,7 +43,7 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>(
|
|||
let data = block_of_memory_slices(env.context, tags, env.ptr_bytes);
|
||||
|
||||
env.context
|
||||
.struct_type(&[data, env.context.i64_type().into()], false)
|
||||
.struct_type(&[data, tag_id_type], false)
|
||||
.ptr_type(AddressSpace::Generic)
|
||||
.into()
|
||||
}
|
||||
|
@ -57,16 +60,14 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>(
|
|||
let data = block_of_memory_slices(env.context, tags, env.ptr_bytes);
|
||||
|
||||
env.context
|
||||
.struct_type(&[data, env.context.i64_type().into()], false)
|
||||
.struct_type(&[data, tag_id_type], false)
|
||||
.ptr_type(AddressSpace::Generic)
|
||||
.into()
|
||||
}
|
||||
NonRecursive(tags) => {
|
||||
let data = block_of_memory_slices(env.context, tags, env.ptr_bytes);
|
||||
|
||||
env.context
|
||||
.struct_type(&[data, env.context.i64_type().into()], false)
|
||||
.into()
|
||||
env.context.struct_type(&[data, tag_id_type], false).into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -146,12 +147,12 @@ pub fn union_data_is_struct_type<'ctx>(
|
|||
|
||||
pub fn union_data_block_of_memory<'ctx>(
|
||||
context: &'ctx Context,
|
||||
tag_id_int_type: IntType<'ctx>,
|
||||
layouts: &[&[Layout<'_>]],
|
||||
ptr_bytes: u32,
|
||||
) -> StructType<'ctx> {
|
||||
let tag_id_type = context.i64_type();
|
||||
let data_type = block_of_memory_slices(context, layouts, ptr_bytes);
|
||||
context.struct_type(&[data_type, tag_id_type.into()], false)
|
||||
context.struct_type(&[data_type, tag_id_int_type.into()], false)
|
||||
}
|
||||
|
||||
pub fn block_of_memory<'ctx>(
|
||||
|
|
|
@ -1394,6 +1394,9 @@ fn build_rec_union_recursive_decrement<'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 tag_id_int_type =
|
||||
basic_type_from_layout(env, &union_layout.tag_id_layout()).into_int_type();
|
||||
|
||||
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
|
||||
|
@ -1439,11 +1442,16 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
|
|||
debug_assert!(ptr_as_i64_ptr.is_pointer_value());
|
||||
|
||||
// therefore we must cast it to our desired type
|
||||
|
||||
let union_type = match union_layout {
|
||||
UnionLayout::NonRecursive(_) => unreachable!(),
|
||||
UnionLayout::Recursive(_) | UnionLayout::NullableWrapped { .. } => {
|
||||
union_data_block_of_memory(env.context, tags, env.ptr_bytes).into()
|
||||
union_data_block_of_memory(
|
||||
env.context,
|
||||
tag_id_int_type,
|
||||
tags,
|
||||
env.ptr_bytes,
|
||||
)
|
||||
.into()
|
||||
}
|
||||
UnionLayout::NonNullableUnwrapped { .. }
|
||||
| UnionLayout::NullableUnwrapped { .. } => {
|
||||
|
@ -1501,10 +1509,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
|
|||
// this function returns void
|
||||
builder.build_return(None);
|
||||
|
||||
cases.push((
|
||||
env.context.i64_type().const_int(tag_id as u64, false),
|
||||
block,
|
||||
));
|
||||
cases.push((tag_id_int_type.const_int(tag_id as u64, false), block));
|
||||
}
|
||||
|
||||
env.builder.position_at_end(match_block);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue