mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 15:21:12 +00:00
prepare to drop tag
This commit is contained in:
parent
c1cf43eda3
commit
897bc41b6b
2 changed files with 111 additions and 84 deletions
|
@ -28,7 +28,7 @@ use inkwell::debug_info::{
|
||||||
use inkwell::memory_buffer::MemoryBuffer;
|
use inkwell::memory_buffer::MemoryBuffer;
|
||||||
use inkwell::module::{Linkage, Module};
|
use inkwell::module::{Linkage, Module};
|
||||||
use inkwell::passes::{PassManager, PassManagerBuilder};
|
use inkwell::passes::{PassManager, PassManagerBuilder};
|
||||||
use inkwell::types::{BasicTypeEnum, FunctionType, IntType, StructType};
|
use inkwell::types::{BasicTypeEnum, FunctionType, IntType, PointerType, StructType};
|
||||||
use inkwell::values::BasicValueEnum::{self, *};
|
use inkwell::values::BasicValueEnum::{self, *};
|
||||||
use inkwell::values::{
|
use inkwell::values::{
|
||||||
BasicValue, CallSiteValue, FloatValue, FunctionValue, InstructionOpcode, InstructionValue,
|
BasicValue, CallSiteValue, FloatValue, FunctionValue, InstructionOpcode, InstructionValue,
|
||||||
|
@ -1158,7 +1158,11 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
||||||
return output_type.const_null().into();
|
return output_type.const_null().into();
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_assert!(*union_size > 1);
|
// this tag id is not the nullable one. For the type to be recursive, the other
|
||||||
|
// constructor must have at least one argument!
|
||||||
|
debug_assert!(!arguments.is_empty());
|
||||||
|
|
||||||
|
debug_assert!(*union_size == 2);
|
||||||
let ptr_size = env.ptr_bytes;
|
let ptr_size = env.ptr_bytes;
|
||||||
|
|
||||||
let ctx = env.context;
|
let ctx = env.context;
|
||||||
|
@ -1169,16 +1173,10 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
||||||
let mut field_types = Vec::with_capacity_in(num_fields, env.arena);
|
let mut field_types = Vec::with_capacity_in(num_fields, env.arena);
|
||||||
let mut field_vals = Vec::with_capacity_in(num_fields, env.arena);
|
let mut field_vals = Vec::with_capacity_in(num_fields, env.arena);
|
||||||
|
|
||||||
let tag_field_layouts = if let TagName::Closure(_) = tag_name {
|
debug_assert!(!matches!(tag_name, TagName::Closure(_)));
|
||||||
// closures ignore (and do not store) the discriminant
|
|
||||||
panic!()
|
let tag_field_layouts = &other_fields[0..];
|
||||||
} else {
|
let arguments = &arguments[0..];
|
||||||
if (*tag_id != 0) == *nullable_id {
|
|
||||||
&[] as &[_]
|
|
||||||
} else {
|
|
||||||
other_fields
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
debug_assert_eq!(arguments.len(), tag_field_layouts.len());
|
debug_assert_eq!(arguments.len(), tag_field_layouts.len());
|
||||||
|
|
||||||
|
@ -1351,8 +1349,7 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PointerValue(value) => {
|
PointerValue(value) => match structure_layout {
|
||||||
match structure_layout {
|
|
||||||
Layout::Union(UnionLayout::NullableWrapped { nullable_id, .. })
|
Layout::Union(UnionLayout::NullableWrapped { nullable_id, .. })
|
||||||
if *index == 0 =>
|
if *index == 0 =>
|
||||||
{
|
{
|
||||||
|
@ -1390,9 +1387,8 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
env.builder.build_load(result, "load_result")
|
env.builder.build_load(result, "load_result")
|
||||||
}
|
}
|
||||||
Layout::Union(UnionLayout::NullableUnwrapped { nullable_id, .. })
|
Layout::Union(UnionLayout::NullableUnwrapped { nullable_id, .. }) => {
|
||||||
if *index == 0 =>
|
if *index == 0 {
|
||||||
{
|
|
||||||
let is_null = env.builder.build_is_null(value, "is_null");
|
let is_null = env.builder.build_is_null(value, "is_null");
|
||||||
|
|
||||||
let ctx = env.context;
|
let ctx = env.context;
|
||||||
|
@ -1406,39 +1402,26 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
||||||
else_value,
|
else_value,
|
||||||
"select_tag_id",
|
"select_tag_id",
|
||||||
)
|
)
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let ptr = cast_basic_basic(
|
|
||||||
builder,
|
|
||||||
value.into(),
|
|
||||||
struct_type.ptr_type(AddressSpace::Generic).into(),
|
|
||||||
)
|
|
||||||
.into_pointer_value();
|
|
||||||
|
|
||||||
let elem_ptr = builder
|
|
||||||
.build_struct_gep(ptr, *index as u32, "at_index_struct_gep")
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let result = builder.build_load(elem_ptr, "load_at_index_ptr");
|
|
||||||
|
|
||||||
if let Some(Layout::RecursivePointer) =
|
|
||||||
field_layouts.get(*index as usize)
|
|
||||||
{
|
|
||||||
// a recursive field is stored as a `i64*`, to use it we must cast it to
|
|
||||||
// a pointer to the block of memory representation
|
|
||||||
cast_basic_basic(
|
|
||||||
builder,
|
|
||||||
result,
|
|
||||||
block_of_memory(env.context, &struct_layout, env.ptr_bytes)
|
|
||||||
.ptr_type(AddressSpace::Generic)
|
|
||||||
.into(),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
result
|
lookup_at_index_ptr(
|
||||||
}
|
env,
|
||||||
}
|
field_layouts,
|
||||||
|
*index as usize,
|
||||||
|
value,
|
||||||
|
&struct_layout,
|
||||||
|
struct_type,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ => lookup_at_index_ptr(
|
||||||
|
env,
|
||||||
|
field_layouts,
|
||||||
|
*index as usize,
|
||||||
|
value,
|
||||||
|
&struct_layout,
|
||||||
|
struct_type,
|
||||||
|
),
|
||||||
|
},
|
||||||
_ => panic!("cannot look up index in {:?}", argument),
|
_ => panic!("cannot look up index in {:?}", argument),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1485,6 +1468,45 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lookup_at_index_ptr<'a, 'ctx, 'env>(
|
||||||
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
|
field_layouts: &[Layout<'_>],
|
||||||
|
index: usize,
|
||||||
|
value: PointerValue<'ctx>,
|
||||||
|
struct_layout: &Layout<'_>,
|
||||||
|
struct_type: StructType<'ctx>,
|
||||||
|
) -> BasicValueEnum<'ctx> {
|
||||||
|
use inkwell::types::BasicType;
|
||||||
|
let builder = env.builder;
|
||||||
|
|
||||||
|
let ptr = cast_basic_basic(
|
||||||
|
builder,
|
||||||
|
value.into(),
|
||||||
|
struct_type.ptr_type(AddressSpace::Generic).into(),
|
||||||
|
)
|
||||||
|
.into_pointer_value();
|
||||||
|
|
||||||
|
let elem_ptr = builder
|
||||||
|
.build_struct_gep(ptr, index as u32, "at_index_struct_gep")
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let result = builder.build_load(elem_ptr, "load_at_index_ptr");
|
||||||
|
|
||||||
|
if let Some(Layout::RecursivePointer) = field_layouts.get(index as usize) {
|
||||||
|
// a recursive field is stored as a `i64*`, to use it we must cast it to
|
||||||
|
// a pointer to the block of memory representation
|
||||||
|
cast_basic_basic(
|
||||||
|
builder,
|
||||||
|
result,
|
||||||
|
block_of_memory(env.context, &struct_layout, env.ptr_bytes)
|
||||||
|
.ptr_type(AddressSpace::Generic)
|
||||||
|
.into(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn reserve_with_refcount<'a, 'ctx, 'env>(
|
pub fn reserve_with_refcount<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
layout: &Layout<'a>,
|
layout: &Layout<'a>,
|
||||||
|
|
|
@ -1006,6 +1006,8 @@ fn path_to_expr_help<'a>(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Some(wrapped) => {
|
Some(wrapped) => {
|
||||||
|
let index = *index;
|
||||||
|
|
||||||
let field_layouts = match &layout {
|
let field_layouts = match &layout {
|
||||||
Layout::Union(variant) => {
|
Layout::Union(variant) => {
|
||||||
use UnionLayout::*;
|
use UnionLayout::*;
|
||||||
|
@ -1037,6 +1039,9 @@ fn path_to_expr_help<'a>(
|
||||||
let tag_id = *tag_id != 0;
|
let tag_id = *tag_id != 0;
|
||||||
|
|
||||||
if tag_id == *nullable_id {
|
if tag_id == *nullable_id {
|
||||||
|
// the nullable tag has no fields; we can only lookup its tag id
|
||||||
|
debug_assert_eq!(index, 0);
|
||||||
|
|
||||||
// the nullable tag is going to pretend it stores a tag id
|
// the nullable tag is going to pretend it stores a tag id
|
||||||
&*env.arena.alloc([Layout::Builtin(crate::layout::TAG_SIZE)])
|
&*env.arena.alloc([Layout::Builtin(crate::layout::TAG_SIZE)])
|
||||||
} else {
|
} else {
|
||||||
|
@ -1051,7 +1056,7 @@ fn path_to_expr_help<'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
*index < field_layouts.len() as u64,
|
index < field_layouts.len() as u64,
|
||||||
"{} {:?} {:?} {:?}",
|
"{} {:?} {:?} {:?}",
|
||||||
index,
|
index,
|
||||||
field_layouts,
|
field_layouts,
|
||||||
|
@ -1059,13 +1064,13 @@ fn path_to_expr_help<'a>(
|
||||||
tag_id,
|
tag_id,
|
||||||
);
|
);
|
||||||
|
|
||||||
let inner_layout = match &field_layouts[*index as usize] {
|
let inner_layout = match &field_layouts[index as usize] {
|
||||||
Layout::RecursivePointer => layout.clone(),
|
Layout::RecursivePointer => layout.clone(),
|
||||||
other => other.clone(),
|
other => other.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let inner_expr = Expr::AccessAtIndex {
|
let inner_expr = Expr::AccessAtIndex {
|
||||||
index: *index,
|
index,
|
||||||
field_layouts,
|
field_layouts,
|
||||||
structure: symbol,
|
structure: symbol,
|
||||||
wrapped,
|
wrapped,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue