This commit is contained in:
Folkert 2021-07-18 00:04:10 +02:00
parent e0b9377dcf
commit e19b03f290
7 changed files with 157 additions and 159 deletions

View file

@ -170,15 +170,6 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
self.ptr_bytes * 2
}
pub fn tag_id_bits(&self) -> u32 {
match self.ptr_bytes {
4 => 2,
8 => 3,
16 => 4,
_ => 0,
}
}
pub fn build_intrinsic_call(
&self,
intrinsic_name: &'static str,
@ -902,7 +893,7 @@ pub fn build_exp_call<'a, 'ctx, 'env>(
}
}
pub const TAG_ID_INDEX: u32 = 1;
const TAG_ID_INDEX: u32 = 1;
pub const TAG_DATA_INDEX: u32 = 0;
pub fn struct_from_fields<'a, 'ctx, 'env, I>(
@ -1253,14 +1244,8 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
}
}
#[allow(clippy::too_many_arguments)]
fn build_wrapped_tag<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
arguments: &[Symbol],
) -> BasicValueEnum<'ctx> {
todo!()
}
fn build_wrapped_tag_store_id<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
scope: &Scope<'a, 'ctx>,
union_layout: &UnionLayout<'a>,
@ -1310,39 +1295,62 @@ fn build_wrapped_tag_store_id<'a, 'ctx, 'env>(
// Create the struct_type
let raw_data_ptr = allocate_tag(env, parent, reuse_allocation, union_layout, tags);
let tag_id_ptr = builder
.build_struct_gep(raw_data_ptr, TAG_ID_INDEX, "tag_id_index")
.unwrap();
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));
let opaque_struct_ptr = builder
.build_struct_gep(raw_data_ptr, TAG_DATA_INDEX, "tag_data_index")
.unwrap();
let struct_type = env.context.struct_type(&field_types, false);
let struct_ptr = env
.builder
.build_bitcast(
opaque_struct_ptr,
struct_type.ptr_type(AddressSpace::Generic),
"struct_ptr",
)
.into_pointer_value();
// Insert field exprs into struct_val
for (index, field_val) in field_vals.into_iter().enumerate() {
let field_ptr = builder
.build_struct_gep(struct_ptr, index as u32, "field_struct_gep")
if union_layout.stores_tag_id_as_data(env.ptr_bytes) {
let tag_id_ptr = builder
.build_struct_gep(raw_data_ptr, TAG_ID_INDEX, "tag_id_index")
.unwrap();
builder.build_store(field_ptr, field_val);
}
let tag_id_type = basic_type_from_layout(env, &tag_id_layout).into_int_type();
tag_pointer_set_tag_id(env, tag_id, raw_data_ptr).into()
env.builder
.build_store(tag_id_ptr, tag_id_type.const_int(tag_id as u64, false));
let opaque_struct_ptr = builder
.build_struct_gep(raw_data_ptr, TAG_DATA_INDEX, "tag_data_index")
.unwrap();
let struct_type = env.context.struct_type(&field_types, false);
let struct_ptr = env
.builder
.build_bitcast(
opaque_struct_ptr,
struct_type.ptr_type(AddressSpace::Generic),
"struct_ptr",
)
.into_pointer_value();
// Insert field exprs into struct_val
for (index, field_val) in field_vals.into_iter().enumerate() {
let field_ptr = builder
.build_struct_gep(struct_ptr, index as u32, "field_struct_gep")
.unwrap();
builder.build_store(field_ptr, field_val);
}
raw_data_ptr.into()
} else {
let struct_type = env.context.struct_type(&field_types, false);
let struct_ptr = env
.builder
.build_bitcast(
raw_data_ptr,
struct_type.ptr_type(AddressSpace::Generic),
"struct_ptr",
)
.into_pointer_value();
// Insert field exprs into struct_val
for (index, field_val) in field_vals.into_iter().enumerate() {
let field_ptr = builder
.build_struct_gep(struct_ptr, index as u32, "field_struct_gep")
.unwrap();
builder.build_store(field_ptr, field_val);
}
tag_pointer_set_tag_id(env, tag_id, raw_data_ptr).into()
}
}
pub fn build_tag<'a, 'ctx, 'env>(
@ -1447,7 +1455,39 @@ pub fn build_tag<'a, 'ctx, 'env>(
let tag_field_layouts = &tags[tag_id as usize];
build_wrapped_tag_store_id(
build_wrapped_tag(
env,
scope,
union_layout,
tag_id,
arguments,
&tag_field_layouts,
tags,
reuse_allocation,
parent,
)
}
UnionLayout::NullableWrapped {
nullable_id,
other_tags: tags,
} => {
let tag_field_layouts = {
use std::cmp::Ordering::*;
match tag_id.cmp(&(*nullable_id as u8)) {
Equal => {
let layout = Layout::Union(*union_layout);
return basic_type_from_layout(env, &layout)
.into_pointer_type()
.const_null()
.into();
}
Less => &tags[tag_id as usize],
Greater => &tags[tag_id as usize - 1],
}
};
build_wrapped_tag(
env,
scope,
union_layout,
@ -1522,42 +1562,6 @@ pub fn build_tag<'a, 'ctx, 'env>(
data_ptr.into()
}
UnionLayout::NullableWrapped {
nullable_id,
other_tags: tags,
} => {
if tag_id == *nullable_id as u8 {
let layout = Layout::Union(*union_layout);
return basic_type_from_layout(env, &layout)
.into_pointer_type()
.const_null()
.into();
}
debug_assert!(union_size > 1);
let tag_field_layouts = {
use std::cmp::Ordering::*;
match tag_id.cmp(&(*nullable_id as u8)) {
Equal => unreachable!("early return above"),
Less => &tags[tag_id as usize],
Greater => &tags[tag_id as usize - 1],
}
};
build_wrapped_tag_store_id(
env,
scope,
union_layout,
tag_id,
arguments,
&tag_field_layouts,
tags,
reuse_allocation,
parent,
)
}
UnionLayout::NullableUnwrapped {
nullable_id,
other_fields,
@ -1769,9 +1773,13 @@ pub fn get_tag_id<'a, 'ctx, 'env>(
get_tag_id_non_recursive(env, tag)
}
UnionLayout::Recursive(_) => {
// TODO check that all tag ids fit into 2/3 bits
// get_tag_id_wrapped( env, tag_pointer_clear_tag_id(env, argument.into_pointer_value()),)
tag_pointer_read_tag_id(env, argument.into_pointer_value())
let argument_ptr = argument.into_pointer_value();
if union_layout.stores_tag_id_as_data(env.ptr_bytes) {
get_tag_id_wrapped(env, argument_ptr)
} else {
tag_pointer_read_tag_id(env, argument_ptr)
}
}
UnionLayout::NonNullableUnwrapped(_) => tag_id_int_type.const_zero(),
UnionLayout::NullableWrapped { nullable_id, .. } => {
@ -1797,7 +1805,12 @@ pub fn get_tag_id<'a, 'ctx, 'env>(
{
env.builder.position_at_end(else_block);
let tag_id = get_tag_id_wrapped(env, argument_ptr);
let tag_id = if union_layout.stores_tag_id_as_data(env.ptr_bytes) {
get_tag_id_wrapped(env, argument_ptr)
} else {
tag_pointer_read_tag_id(env, argument_ptr)
};
env.builder.build_store(result, tag_id);
env.builder.build_unconditional_branch(cont_block);
}
@ -1933,9 +1946,11 @@ fn reserve_with_refcount_union_as_block_of_memory<'a, 'ctx, 'env>(
union_layout: UnionLayout<'a>,
fields: &[&[Layout<'a>]],
) -> PointerValue<'ctx> {
let ptr_bytes = env.ptr_bytes;
let block_type = block_of_memory_slices(env.context, fields, env.ptr_bytes);
let basic_type = if union_layout.stores_tag_id() {
let basic_type = if union_layout.stores_tag_id_as_data(ptr_bytes) {
let tag_id_type = basic_type_from_layout(env, &union_layout.tag_id_layout());
env.context
@ -1951,7 +1966,7 @@ fn reserve_with_refcount_union_as_block_of_memory<'a, 'ctx, 'env>(
.max()
.unwrap_or_default();
if union_layout.stores_tag_id() {
if union_layout.stores_tag_id_as_data(ptr_bytes) {
stack_size += union_layout.tag_id_layout().stack_size(env.ptr_bytes);
}

View file

@ -19,6 +19,9 @@ fn basic_type_from_record<'a, 'ctx, 'env>(
.as_basic_type_enum()
}
//pub const fn store_tag_id_in_pointer<'a, 'ctx, 'env>(
// env: &crate::llvm::build::Env<'a, 'ctx, 'env>,
pub fn basic_type_from_layout<'a, 'ctx, 'env>(
env: &crate::llvm::build::Env<'a, 'ctx, 'env>,
layout: &Layout<'_>,
@ -31,21 +34,31 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>(
basic_type_from_layout(env, &closure_data_layout)
}
Struct(sorted_fields) => basic_type_from_record(env, sorted_fields),
Union(variant) => {
Union(union_layout) => {
use UnionLayout::*;
let tag_id_type = basic_type_from_layout(env, &variant.tag_id_layout());
let tag_id_type = basic_type_from_layout(env, &union_layout.tag_id_layout());
match variant {
NullableWrapped {
match union_layout {
NonRecursive(tags) => {
let data = block_of_memory_slices(env.context, tags, env.ptr_bytes);
env.context.struct_type(&[data, tag_id_type], false).into()
}
Recursive(tags)
| NullableWrapped {
other_tags: tags, ..
} => {
let data = block_of_memory_slices(env.context, tags, env.ptr_bytes);
env.context
.struct_type(&[data, tag_id_type], false)
.ptr_type(AddressSpace::Generic)
.into()
if union_layout.stores_tag_id_as_data(env.ptr_bytes) {
env.context
.struct_type(&[data, tag_id_type], false)
.ptr_type(AddressSpace::Generic)
.into()
} else {
data.ptr_type(AddressSpace::Generic).into()
}
}
NullableUnwrapped { other_fields, .. } => {
let block =
@ -56,19 +69,6 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>(
let block = block_of_memory_slices(env.context, &[fields], env.ptr_bytes);
block.ptr_type(AddressSpace::Generic).into()
}
Recursive(tags) => {
let data = block_of_memory_slices(env.context, tags, env.ptr_bytes);
env.context
.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, tag_id_type], false).into()
}
}
}
RecursivePointer => {
@ -145,16 +145,6 @@ pub fn union_data_is_struct_type<'ctx>(
context.struct_type(&[struct_type.into(), tag_id_type.into()], false)
}
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 data_type = block_of_memory_slices(context, layouts, ptr_bytes);
context.struct_type(&[data_type, tag_id_int_type.into()], false)
}
pub fn block_of_memory<'ctx>(
context: &'ctx Context,
layout: &Layout<'_>,

View file

@ -4,9 +4,7 @@ use crate::llvm::build::{
tag_pointer_clear_tag_id, Env, FAST_CALL_CONV, LLVM_SADD_WITH_OVERFLOW_I64, TAG_DATA_INDEX,
};
use crate::llvm::build_list::{incrementing_elem_loop, list_len, load_list};
use crate::llvm::convert::{
basic_type_from_layout, block_of_memory_slices, ptr_int, union_data_block_of_memory,
};
use crate::llvm::convert::{basic_type_from_layout, ptr_int};
use bumpalo::collections::Vec;
use inkwell::basic_block::BasicBlock;
use inkwell::context::Context;
@ -1399,28 +1397,8 @@ 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,
tag_id_int_type,
tags,
env.ptr_bytes,
)
.into()
}
UnionLayout::NonNullableUnwrapped { .. }
| UnionLayout::NullableUnwrapped { .. } => {
block_of_memory_slices(env.context, tags, env.ptr_bytes)
}
};
let recursive_field_ptr = cast_basic_basic(
env.builder,
ptr_as_i64_ptr,
union_type.ptr_type(AddressSpace::Generic).into(),
);
let union_type = basic_type_from_layout(env, &Layout::Union(union_layout));
let recursive_field_ptr = cast_basic_basic(env.builder, ptr_as_i64_ptr, union_type);
deferred_rec.push(recursive_field_ptr);
} else if field_layout.contains_refcounted() {
@ -1487,9 +1465,6 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
let (_, only_branch) = cases.pop().unwrap();
env.builder.build_unconditional_branch(only_branch);
} else {
// read the tag_id
// let current_tag_id = get_tag_id(env, parent, &union_layout, value_ptr.into());
let default_block = env.context.append_basic_block(parent, "switch_default");
// switch on it