passing tests

This commit is contained in:
Folkert 2021-06-28 22:28:47 +02:00
parent 1d1bcaea63
commit 978cea4b8a
12 changed files with 230 additions and 207 deletions

View file

@ -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));

View file

@ -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,
));
}

View file

@ -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);

View file

@ -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>(

View file

@ -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);