mirror of
https://github.com/roc-lang/roc.git
synced 2025-07-24 15:03:46 +00:00
WIP
This commit is contained in:
parent
4a9514d2c4
commit
0247237fe8
16 changed files with 625 additions and 163 deletions
|
@ -23,7 +23,7 @@ use inkwell::passes::{PassManager, PassManagerBuilder};
|
|||
use inkwell::types::{
|
||||
AnyType, BasicMetadataTypeEnum, BasicType, BasicTypeEnum, FunctionType, IntType, StructType,
|
||||
};
|
||||
use inkwell::values::BasicValueEnum::{self};
|
||||
use inkwell::values::BasicValueEnum;
|
||||
use inkwell::values::{
|
||||
BasicMetadataValueEnum, CallSiteValue, FunctionValue, InstructionValue, IntValue, PointerValue,
|
||||
StructValue,
|
||||
|
@ -1379,12 +1379,13 @@ pub(crate) fn build_exp_expr<'a, 'ctx>(
|
|||
layout_interner.get_repr(layout),
|
||||
);
|
||||
|
||||
lookup_at_index_ptr2(
|
||||
lookup_at_index_ptr(
|
||||
env,
|
||||
layout_interner,
|
||||
field_layouts,
|
||||
*index as usize,
|
||||
ptr,
|
||||
None,
|
||||
target_loaded_type,
|
||||
)
|
||||
}
|
||||
|
@ -1404,7 +1405,7 @@ pub(crate) fn build_exp_expr<'a, 'ctx>(
|
|||
field_layouts,
|
||||
*index as usize,
|
||||
argument.into_pointer_value(),
|
||||
struct_type.into_struct_type(),
|
||||
Some(struct_type.into_struct_type()),
|
||||
target_loaded_type,
|
||||
)
|
||||
}
|
||||
|
@ -1430,12 +1431,13 @@ pub(crate) fn build_exp_expr<'a, 'ctx>(
|
|||
layout_interner.get_repr(layout),
|
||||
);
|
||||
|
||||
lookup_at_index_ptr2(
|
||||
lookup_at_index_ptr(
|
||||
env,
|
||||
layout_interner,
|
||||
field_layouts,
|
||||
*index as usize,
|
||||
ptr,
|
||||
None,
|
||||
target_loaded_type,
|
||||
)
|
||||
}
|
||||
|
@ -1463,13 +1465,117 @@ pub(crate) fn build_exp_expr<'a, 'ctx>(
|
|||
// the tag id is not stored
|
||||
*index as usize,
|
||||
argument.into_pointer_value(),
|
||||
struct_type.into_struct_type(),
|
||||
Some(struct_type.into_struct_type()),
|
||||
target_loaded_type,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UnionFieldPtrAtIndex {
|
||||
tag_id,
|
||||
structure,
|
||||
index,
|
||||
union_layout,
|
||||
} => {
|
||||
// cast the argument bytes into the desired shape for this tag
|
||||
let (argument, structure_layout) = scope.load_symbol_and_layout(structure);
|
||||
let ret_repr = layout_interner.get_repr(layout);
|
||||
|
||||
let pointer_value = match union_layout {
|
||||
UnionLayout::NonRecursive(_) => unreachable!(),
|
||||
UnionLayout::Recursive(tag_layouts) => {
|
||||
debug_assert!(argument.is_pointer_value());
|
||||
|
||||
let field_layouts = tag_layouts[*tag_id as usize];
|
||||
|
||||
let ptr = tag_pointer_clear_tag_id(env, argument.into_pointer_value());
|
||||
let target_loaded_type = basic_type_from_layout(env, layout_interner, ret_repr);
|
||||
|
||||
union_field_at_index(
|
||||
env,
|
||||
layout_interner,
|
||||
field_layouts,
|
||||
None,
|
||||
*index as usize,
|
||||
ptr,
|
||||
target_loaded_type,
|
||||
)
|
||||
}
|
||||
UnionLayout::NonNullableUnwrapped(field_layouts) => {
|
||||
let struct_layout = LayoutRepr::struct_(field_layouts);
|
||||
|
||||
let struct_type = basic_type_from_layout(env, layout_interner, struct_layout);
|
||||
let target_loaded_type = basic_type_from_layout(env, layout_interner, ret_repr);
|
||||
|
||||
union_field_at_index(
|
||||
env,
|
||||
layout_interner,
|
||||
field_layouts,
|
||||
Some(struct_type.into_struct_type()),
|
||||
*index as usize,
|
||||
argument.into_pointer_value(),
|
||||
target_loaded_type,
|
||||
)
|
||||
}
|
||||
UnionLayout::NullableWrapped {
|
||||
nullable_id,
|
||||
other_tags,
|
||||
} => {
|
||||
debug_assert!(argument.is_pointer_value());
|
||||
debug_assert_ne!(*tag_id, *nullable_id);
|
||||
|
||||
let tag_index = if *tag_id < *nullable_id {
|
||||
*tag_id
|
||||
} else {
|
||||
tag_id - 1
|
||||
};
|
||||
|
||||
let field_layouts = other_tags[tag_index as usize];
|
||||
|
||||
let ptr = tag_pointer_clear_tag_id(env, argument.into_pointer_value());
|
||||
let target_loaded_type = basic_type_from_layout(env, layout_interner, ret_repr);
|
||||
|
||||
union_field_at_index(
|
||||
env,
|
||||
layout_interner,
|
||||
field_layouts,
|
||||
None,
|
||||
*index as usize,
|
||||
ptr,
|
||||
target_loaded_type,
|
||||
)
|
||||
.into()
|
||||
}
|
||||
UnionLayout::NullableUnwrapped {
|
||||
nullable_id,
|
||||
other_fields,
|
||||
} => {
|
||||
debug_assert!(argument.is_pointer_value());
|
||||
debug_assert_ne!(*tag_id != 0, *nullable_id);
|
||||
|
||||
let field_layouts = other_fields;
|
||||
let struct_layout = LayoutRepr::struct_(field_layouts);
|
||||
|
||||
let struct_type = basic_type_from_layout(env, layout_interner, struct_layout);
|
||||
let target_loaded_type = basic_type_from_layout(env, layout_interner, ret_repr);
|
||||
|
||||
union_field_at_index(
|
||||
env,
|
||||
layout_interner,
|
||||
field_layouts,
|
||||
Some(struct_type.into_struct_type()),
|
||||
// the tag id is not stored
|
||||
*index as usize,
|
||||
argument.into_pointer_value(),
|
||||
target_loaded_type,
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
pointer_value.into()
|
||||
}
|
||||
|
||||
GetTagId {
|
||||
structure,
|
||||
union_layout,
|
||||
|
@ -2025,21 +2131,20 @@ fn lookup_at_index_ptr<'a, 'ctx>(
|
|||
field_layouts: &[InLayout<'a>],
|
||||
index: usize,
|
||||
value: PointerValue<'ctx>,
|
||||
struct_type: StructType<'ctx>,
|
||||
struct_type: Option<StructType<'ctx>>,
|
||||
target_loaded_type: BasicTypeEnum<'ctx>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let builder = env.builder;
|
||||
|
||||
let ptr = env.builder.build_pointer_cast(
|
||||
let elem_ptr = union_field_at_index_help(
|
||||
env,
|
||||
layout_interner,
|
||||
field_layouts,
|
||||
struct_type,
|
||||
index,
|
||||
value,
|
||||
struct_type.ptr_type(AddressSpace::default()),
|
||||
"cast_lookup_at_index_ptr",
|
||||
);
|
||||
|
||||
let elem_ptr = builder
|
||||
.new_build_struct_gep(struct_type, ptr, index as u32, "at_index_struct_gep")
|
||||
.unwrap();
|
||||
|
||||
let field_layout = field_layouts[index];
|
||||
let result = load_roc_value(
|
||||
env,
|
||||
|
@ -2054,19 +2159,23 @@ fn lookup_at_index_ptr<'a, 'ctx>(
|
|||
cast_if_necessary_for_opaque_recursive_pointers(env.builder, result, target_loaded_type)
|
||||
}
|
||||
|
||||
fn lookup_at_index_ptr2<'a, 'ctx>(
|
||||
fn union_field_at_index_help<'a, 'ctx>(
|
||||
env: &Env<'a, 'ctx, '_>,
|
||||
layout_interner: &STLayoutInterner<'a>,
|
||||
field_layouts: &'a [InLayout<'a>],
|
||||
opt_struct_type: Option<StructType<'ctx>>,
|
||||
index: usize,
|
||||
value: PointerValue<'ctx>,
|
||||
target_loaded_type: BasicTypeEnum<'ctx>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
) -> PointerValue<'ctx> {
|
||||
let builder = env.builder;
|
||||
|
||||
let struct_layout = LayoutRepr::struct_(field_layouts);
|
||||
let struct_type =
|
||||
basic_type_from_layout(env, layout_interner, struct_layout).into_struct_type();
|
||||
let struct_type = match opt_struct_type {
|
||||
Some(st) => st,
|
||||
None => {
|
||||
let struct_layout = LayoutRepr::struct_(field_layouts);
|
||||
basic_type_from_layout(env, layout_interner, struct_layout).into_struct_type()
|
||||
}
|
||||
};
|
||||
|
||||
let data_ptr = env.builder.build_pointer_cast(
|
||||
value,
|
||||
|
@ -2074,27 +2183,40 @@ fn lookup_at_index_ptr2<'a, 'ctx>(
|
|||
"cast_lookup_at_index_ptr",
|
||||
);
|
||||
|
||||
let elem_ptr = builder
|
||||
builder
|
||||
.new_build_struct_gep(
|
||||
struct_type,
|
||||
data_ptr,
|
||||
index as u32,
|
||||
"at_index_struct_gep_data",
|
||||
)
|
||||
.unwrap();
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
let field_layout = field_layouts[index];
|
||||
let result = load_roc_value(
|
||||
fn union_field_at_index<'a, 'ctx>(
|
||||
env: &Env<'a, 'ctx, '_>,
|
||||
layout_interner: &STLayoutInterner<'a>,
|
||||
field_layouts: &'a [InLayout<'a>],
|
||||
opt_struct_type: Option<StructType<'ctx>>,
|
||||
index: usize,
|
||||
value: PointerValue<'ctx>,
|
||||
target_loaded_type: BasicTypeEnum<'ctx>,
|
||||
) -> PointerValue<'ctx> {
|
||||
let result = union_field_at_index_help(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_interner.get_repr(field_layout),
|
||||
elem_ptr,
|
||||
"load_at_index_ptr",
|
||||
field_layouts,
|
||||
opt_struct_type,
|
||||
index,
|
||||
value,
|
||||
);
|
||||
|
||||
// A recursive pointer in the loaded structure is stored as a `i64*`, but the loaded layout
|
||||
// might want a more precise structure. As such, cast it to the refined type if needed.
|
||||
cast_if_necessary_for_opaque_recursive_pointers(env.builder, result, target_loaded_type)
|
||||
let from_value: BasicValueEnum = result.into();
|
||||
let to_type: BasicTypeEnum = target_loaded_type;
|
||||
cast_if_necessary_for_opaque_recursive_pointers(env.builder, from_value, to_type)
|
||||
.into_pointer_value()
|
||||
}
|
||||
|
||||
pub fn reserve_with_refcount<'a, 'ctx>(
|
||||
|
@ -3071,7 +3193,7 @@ pub fn cast_if_necessary_for_opaque_recursive_pointers<'ctx>(
|
|||
to_type: BasicTypeEnum<'ctx>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
if from_value.get_type() != to_type
|
||||
// Only perform the cast if the target types are transumatble.
|
||||
// Only perform the cast if the target types are transmutable.
|
||||
&& equivalent_type_constructors(&from_value.get_type(), &to_type)
|
||||
{
|
||||
complex_bitcast(
|
||||
|
|
|
@ -1304,8 +1304,28 @@ pub(crate) fn run_low_level<'a, 'ctx>(
|
|||
.into()
|
||||
}
|
||||
|
||||
PtrStore | PtrLoad | PtrToZeroed | RefCountIncRcPtr | RefCountDecRcPtr
|
||||
| RefCountIncDataPtr | RefCountDecDataPtr => {
|
||||
PtrStore => {
|
||||
arguments!(ptr, value);
|
||||
|
||||
env.builder.build_store(ptr.into_pointer_value(), value);
|
||||
|
||||
// ptr
|
||||
env.context.struct_type(&[], false).const_zero().into()
|
||||
}
|
||||
|
||||
PtrLoad => {
|
||||
arguments!(ptr);
|
||||
|
||||
let ret_repr = layout_interner.get_repr(layout);
|
||||
let element_type = basic_type_from_layout(env, layout_interner, ret_repr);
|
||||
|
||||
env.builder
|
||||
.new_build_load(element_type, ptr.into_pointer_value(), "ptr_load")
|
||||
}
|
||||
|
||||
PtrToZeroed => todo!(),
|
||||
|
||||
RefCountIncRcPtr | RefCountDecRcPtr | RefCountIncDataPtr | RefCountDecDataPtr => {
|
||||
unreachable!("Not used in LLVM backend: {:?}", op);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue