mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 15:21:12 +00:00
WIP
This commit is contained in:
parent
e0b9377dcf
commit
e19b03f290
7 changed files with 157 additions and 159 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<'_>,
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue