mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Push mutable layout interner through llvm backend
This commit is contained in:
parent
e4b5252e51
commit
512a1721ae
8 changed files with 1289 additions and 555 deletions
|
@ -12,7 +12,7 @@ use roc_builtins::bitcode;
|
|||
use roc_intern::Interner;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::ir::LookupType;
|
||||
use roc_mono::layout::{Builtin, Layout, LayoutIds, UnionLayout};
|
||||
use roc_mono::layout::{Builtin, Layout, LayoutIds, STLayoutInterner, UnionLayout};
|
||||
use roc_region::all::Region;
|
||||
|
||||
use super::build::BuilderExt;
|
||||
|
@ -167,6 +167,7 @@ pub(crate) fn notify_parent_dbg(env: &Env, shared_memory: &SharedMemoryPointer)
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn clone_to_shared_memory<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
scope: &Scope<'a, 'ctx>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
shared_memory: &SharedMemoryPointer<'ctx>,
|
||||
|
@ -201,7 +202,7 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx, 'env>(
|
|||
let (value, layout) = load_symbol_and_layout(scope, lookup);
|
||||
|
||||
let stack_size = env.ptr_int().const_int(
|
||||
layout.stack_size(env.layout_interner, env.target_info) as u64,
|
||||
layout.stack_size(layout_interner, env.target_info) as u64,
|
||||
false,
|
||||
);
|
||||
|
||||
|
@ -214,6 +215,7 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx, 'env>(
|
|||
|
||||
extra_offset = build_clone(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
original_ptr,
|
||||
cursors,
|
||||
|
@ -280,6 +282,7 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx, 'env>(
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
fn build_clone<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
ptr: PointerValue<'ctx>,
|
||||
cursors: Cursors<'ctx>,
|
||||
|
@ -290,6 +293,7 @@ fn build_clone<'a, 'ctx, 'env>(
|
|||
match layout {
|
||||
Layout::Builtin(builtin) => build_clone_builtin(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
|
@ -300,6 +304,7 @@ fn build_clone<'a, 'ctx, 'env>(
|
|||
|
||||
Layout::Struct { field_layouts, .. } => build_clone_struct(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
|
@ -313,7 +318,7 @@ fn build_clone<'a, 'ctx, 'env>(
|
|||
Layout::LambdaSet(_) => cursors.extra_offset,
|
||||
|
||||
Layout::Union(union_layout) => {
|
||||
if layout.safe_to_memcpy(env.layout_interner) {
|
||||
if layout.safe_to_memcpy(layout_interner) {
|
||||
let ptr = unsafe {
|
||||
env.builder.new_build_in_bounds_gep(
|
||||
env.context.i8_type(),
|
||||
|
@ -328,12 +333,13 @@ fn build_clone<'a, 'ctx, 'env>(
|
|||
.builder
|
||||
.build_pointer_cast(ptr, ptr_type, "cast_ptr_type");
|
||||
|
||||
store_roc_value(env, layout, ptr, value);
|
||||
store_roc_value(env, layout_interner, layout, ptr, value);
|
||||
|
||||
cursors.extra_offset
|
||||
} else {
|
||||
build_clone_tag(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
|
@ -349,11 +355,11 @@ fn build_clone<'a, 'ctx, 'env>(
|
|||
build_copy(env, ptr, cursors.offset, cursors.extra_offset.into());
|
||||
|
||||
let source = value.into_pointer_value();
|
||||
let inner_layout = env.layout_interner.get(inner_layout);
|
||||
let value = load_roc_value(env, *inner_layout, source, "inner");
|
||||
let inner_layout = layout_interner.get(inner_layout);
|
||||
let value = load_roc_value(env, layout_interner, *inner_layout, source, "inner");
|
||||
|
||||
let inner_width = env.ptr_int().const_int(
|
||||
inner_layout.stack_size(env.layout_interner, env.target_info) as u64,
|
||||
inner_layout.stack_size(layout_interner, env.target_info) as u64,
|
||||
false,
|
||||
);
|
||||
|
||||
|
@ -368,6 +374,7 @@ fn build_clone<'a, 'ctx, 'env>(
|
|||
|
||||
build_clone(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
|
@ -385,7 +392,7 @@ fn build_clone<'a, 'ctx, 'env>(
|
|||
WhenRecursive::Loop(union_layout) => {
|
||||
let layout = Layout::Union(union_layout);
|
||||
|
||||
let bt = basic_type_from_layout(env, &layout);
|
||||
let bt = basic_type_from_layout(env, layout_interner, &layout);
|
||||
|
||||
// cast the i64 pointer to a pointer to block of memory
|
||||
let field1_cast = env.builder.build_pointer_cast(
|
||||
|
@ -396,6 +403,7 @@ fn build_clone<'a, 'ctx, 'env>(
|
|||
|
||||
build_clone_tag(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
|
@ -411,6 +419,7 @@ fn build_clone<'a, 'ctx, 'env>(
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
fn build_clone_struct<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
ptr: PointerValue<'ctx>,
|
||||
cursors: Cursors<'ctx>,
|
||||
|
@ -420,7 +429,7 @@ fn build_clone_struct<'a, 'ctx, 'env>(
|
|||
) -> IntValue<'ctx> {
|
||||
let layout = Layout::struct_no_name_order(field_layouts);
|
||||
|
||||
if layout.safe_to_memcpy(env.layout_interner) {
|
||||
if layout.safe_to_memcpy(layout_interner) {
|
||||
build_copy(env, ptr, cursors.offset, value)
|
||||
} else {
|
||||
let mut cursors = cursors;
|
||||
|
@ -433,10 +442,11 @@ fn build_clone_struct<'a, 'ctx, 'env>(
|
|||
.build_extract_value(structure, i as _, "extract")
|
||||
.unwrap();
|
||||
|
||||
let field = use_roc_value(env, *field_layout, field, "field");
|
||||
let field = use_roc_value(env, layout_interner, *field_layout, field, "field");
|
||||
|
||||
let new_extra = build_clone(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
|
@ -446,7 +456,7 @@ fn build_clone_struct<'a, 'ctx, 'env>(
|
|||
);
|
||||
|
||||
let field_width = env.ptr_int().const_int(
|
||||
field_layout.stack_size(env.layout_interner, env.target_info) as u64,
|
||||
field_layout.stack_size(layout_interner, env.target_info) as u64,
|
||||
false,
|
||||
);
|
||||
|
||||
|
@ -463,6 +473,7 @@ fn build_clone_struct<'a, 'ctx, 'env>(
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
fn build_clone_tag<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
ptr: PointerValue<'ctx>,
|
||||
cursors: Cursors<'ctx>,
|
||||
|
@ -505,6 +516,7 @@ fn build_clone_tag<'a, 'ctx, 'env>(
|
|||
|
||||
build_clone_tag_help(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
union_layout,
|
||||
when_recursive,
|
||||
|
@ -539,11 +551,12 @@ fn build_clone_tag<'a, 'ctx, 'env>(
|
|||
|
||||
fn load_tag_data<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
union_layout: UnionLayout<'a>,
|
||||
tag_value: PointerValue<'ctx>,
|
||||
tag_type: BasicTypeEnum<'ctx>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let union_struct_type = struct_type_from_union_layout(env, &union_layout);
|
||||
let union_struct_type = struct_type_from_union_layout(env, layout_interner, &union_layout);
|
||||
|
||||
let raw_data_ptr = env
|
||||
.builder
|
||||
|
@ -567,6 +580,7 @@ fn load_tag_data<'a, 'ctx, 'env>(
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
fn build_clone_tag_help<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
union_layout: UnionLayout<'a>,
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
|
@ -612,7 +626,7 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
env.builder.build_unreachable();
|
||||
}
|
||||
NonRecursive(tags) => {
|
||||
let id = get_tag_id(env, parent, &union_layout, tag_value);
|
||||
let id = get_tag_id(env, layout_interner, parent, &union_layout, tag_value);
|
||||
|
||||
let switch_block = env.context.append_basic_block(parent, "switch_block");
|
||||
env.builder.build_unconditional_branch(switch_block);
|
||||
|
@ -628,16 +642,25 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
env.arena.alloc([layout, union_layout.tag_id_layout()]),
|
||||
);
|
||||
|
||||
let basic_type = basic_type_from_layout(env, &layout);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
|
||||
let data = load_tag_data(
|
||||
env,
|
||||
layout_interner,
|
||||
union_layout,
|
||||
tag_value.into_pointer_value(),
|
||||
basic_type,
|
||||
);
|
||||
|
||||
let answer =
|
||||
build_clone(env, layout_ids, ptr, cursors, data, layout, when_recursive);
|
||||
let answer = build_clone(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
data,
|
||||
layout,
|
||||
when_recursive,
|
||||
);
|
||||
|
||||
env.builder.build_return(Some(&answer));
|
||||
|
||||
|
@ -657,7 +680,7 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
}
|
||||
}
|
||||
Recursive(tags) => {
|
||||
let id = get_tag_id(env, parent, &union_layout, tag_value);
|
||||
let id = get_tag_id(env, layout_interner, parent, &union_layout, tag_value);
|
||||
|
||||
let switch_block = env.context.append_basic_block(parent, "switch_block");
|
||||
env.builder.build_unconditional_branch(switch_block);
|
||||
|
@ -682,11 +705,11 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
)
|
||||
};
|
||||
|
||||
let basic_type = basic_type_from_layout(env, &layout);
|
||||
let data = load_tag_data(env, union_layout, tag_value, basic_type);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
|
||||
let data = load_tag_data(env, layout_interner, union_layout, tag_value, basic_type);
|
||||
|
||||
let (width, _) =
|
||||
union_layout.data_size_and_alignment(env.layout_interner, env.target_info);
|
||||
union_layout.data_size_and_alignment(layout_interner, env.target_info);
|
||||
|
||||
let cursors = Cursors {
|
||||
offset: extra_offset,
|
||||
|
@ -698,8 +721,16 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
};
|
||||
|
||||
let when_recursive = WhenRecursive::Loop(union_layout);
|
||||
let answer =
|
||||
build_clone(env, layout_ids, ptr, cursors, data, layout, when_recursive);
|
||||
let answer = build_clone(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
data,
|
||||
layout,
|
||||
when_recursive,
|
||||
);
|
||||
|
||||
env.builder.build_return(Some(&answer));
|
||||
|
||||
|
@ -724,10 +755,9 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
build_copy(env, ptr, offset, extra_offset.into());
|
||||
|
||||
let layout = Layout::struct_no_name_order(fields);
|
||||
let basic_type = basic_type_from_layout(env, &layout);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
|
||||
|
||||
let (width, _) =
|
||||
union_layout.data_size_and_alignment(env.layout_interner, env.target_info);
|
||||
let (width, _) = union_layout.data_size_and_alignment(layout_interner, env.target_info);
|
||||
|
||||
let cursors = Cursors {
|
||||
offset: extra_offset,
|
||||
|
@ -738,10 +768,19 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
),
|
||||
};
|
||||
|
||||
let data = load_tag_data(env, union_layout, tag_value, basic_type);
|
||||
let data = load_tag_data(env, layout_interner, union_layout, tag_value, basic_type);
|
||||
|
||||
let when_recursive = WhenRecursive::Loop(union_layout);
|
||||
let answer = build_clone(env, layout_ids, ptr, cursors, data, layout, when_recursive);
|
||||
let answer = build_clone(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
data,
|
||||
layout,
|
||||
when_recursive,
|
||||
);
|
||||
|
||||
env.builder.build_return(Some(&answer));
|
||||
}
|
||||
|
@ -752,7 +791,7 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
let switch_block = env.context.append_basic_block(parent, "switch_block");
|
||||
let null_block = env.context.append_basic_block(parent, "null_block");
|
||||
|
||||
let id = get_tag_id(env, parent, &union_layout, tag_value);
|
||||
let id = get_tag_id(env, layout_interner, parent, &union_layout, tag_value);
|
||||
|
||||
let comparison = env
|
||||
.builder
|
||||
|
@ -782,10 +821,10 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
};
|
||||
|
||||
let layout = Layout::struct_no_name_order(fields);
|
||||
let basic_type = basic_type_from_layout(env, &layout);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
|
||||
|
||||
let (width, _) =
|
||||
union_layout.data_size_and_alignment(env.layout_interner, env.target_info);
|
||||
union_layout.data_size_and_alignment(layout_interner, env.target_info);
|
||||
|
||||
let cursors = Cursors {
|
||||
offset: extra_offset,
|
||||
|
@ -797,11 +836,20 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
};
|
||||
|
||||
let tag_value = tag_pointer_clear_tag_id(env, tag_value.into_pointer_value());
|
||||
let data = load_tag_data(env, union_layout, tag_value, basic_type);
|
||||
let data =
|
||||
load_tag_data(env, layout_interner, union_layout, tag_value, basic_type);
|
||||
|
||||
let when_recursive = WhenRecursive::Loop(union_layout);
|
||||
let answer =
|
||||
build_clone(env, layout_ids, ptr, cursors, data, layout, when_recursive);
|
||||
let answer = build_clone(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
data,
|
||||
layout,
|
||||
when_recursive,
|
||||
);
|
||||
|
||||
env.builder.build_return(Some(&answer));
|
||||
|
||||
|
@ -857,14 +905,14 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
build_copy(env, ptr, offset, extra_offset.into());
|
||||
|
||||
let layout = Layout::struct_no_name_order(other_fields);
|
||||
let basic_type = basic_type_from_layout(env, &layout);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
|
||||
|
||||
let cursors = Cursors {
|
||||
offset: extra_offset,
|
||||
extra_offset: env.builder.build_int_add(
|
||||
extra_offset,
|
||||
env.ptr_int().const_int(
|
||||
layout.stack_size(env.layout_interner, env.target_info) as _,
|
||||
layout.stack_size(layout_interner, env.target_info) as _,
|
||||
false,
|
||||
),
|
||||
"new_offset",
|
||||
|
@ -873,14 +921,23 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
|
||||
let data = load_tag_data(
|
||||
env,
|
||||
layout_interner,
|
||||
union_layout,
|
||||
tag_value.into_pointer_value(),
|
||||
basic_type,
|
||||
);
|
||||
|
||||
let when_recursive = WhenRecursive::Loop(union_layout);
|
||||
let answer =
|
||||
build_clone(env, layout_ids, ptr, cursors, data, layout, when_recursive);
|
||||
let answer = build_clone(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
data,
|
||||
layout,
|
||||
when_recursive,
|
||||
);
|
||||
|
||||
env.builder.build_return(Some(&answer));
|
||||
}
|
||||
|
@ -945,6 +1002,7 @@ fn build_copy<'a, 'ctx, 'env>(
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
fn build_clone_builtin<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
ptr: PointerValue<'ctx>,
|
||||
cursors: Cursors<'ctx>,
|
||||
|
@ -990,14 +1048,14 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
|
|||
offset = build_copy(env, ptr, offset, len.into());
|
||||
offset = build_copy(env, ptr, offset, len.into());
|
||||
|
||||
let elem = env.layout_interner.get(elem);
|
||||
let elem = layout_interner.get(elem);
|
||||
let (element_width, _element_align) =
|
||||
elem.stack_size_and_alignment(env.layout_interner, env.target_info);
|
||||
elem.stack_size_and_alignment(layout_interner, env.target_info);
|
||||
let element_width = env.ptr_int().const_int(element_width as _, false);
|
||||
|
||||
let elements_width = bd.build_int_mul(element_width, len, "elements_width");
|
||||
|
||||
if elem.safe_to_memcpy(env.layout_interner) {
|
||||
if elem.safe_to_memcpy(layout_interner) {
|
||||
// NOTE we are not actually sure the dest is properly aligned
|
||||
let dest = pointer_at_offset(bd, env.context.i8_type(), ptr, offset);
|
||||
let src = bd.build_pointer_cast(
|
||||
|
@ -1012,7 +1070,7 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
|
|||
// We cloned the elements into the extra_offset address.
|
||||
let elements_start_offset = cursors.extra_offset;
|
||||
|
||||
let element_type = basic_type_from_layout(env, elem);
|
||||
let element_type = basic_type_from_layout(env, layout_interner, elem);
|
||||
let elements = bd.build_pointer_cast(
|
||||
elements,
|
||||
element_type.ptr_type(AddressSpace::Generic),
|
||||
|
@ -1023,7 +1081,7 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
|
|||
let rest_offset = bd.build_alloca(env.ptr_int(), "rest_offset");
|
||||
|
||||
let element_stack_size = env.ptr_int().const_int(
|
||||
elem.stack_size(env.layout_interner, env.target_info) as u64,
|
||||
elem.stack_size(layout_interner, env.target_info) as u64,
|
||||
false,
|
||||
);
|
||||
let rest_start_offset = bd.build_int_add(
|
||||
|
@ -1033,7 +1091,7 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
|
|||
);
|
||||
bd.build_store(rest_offset, rest_start_offset);
|
||||
|
||||
let body = |index, element| {
|
||||
let body = |layout_interner, index, element| {
|
||||
let current_offset =
|
||||
bd.build_int_mul(element_stack_size, index, "current_offset");
|
||||
let current_offset =
|
||||
|
@ -1051,6 +1109,7 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
|
|||
|
||||
let new_offset = build_clone(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
|
@ -1068,7 +1127,16 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
|
|||
.and_then(|b| b.get_parent())
|
||||
.unwrap();
|
||||
|
||||
incrementing_elem_loop(env, parent, *elem, elements, len, "index", body);
|
||||
incrementing_elem_loop(
|
||||
env,
|
||||
layout_interner,
|
||||
parent,
|
||||
*elem,
|
||||
elements,
|
||||
len,
|
||||
"index",
|
||||
body,
|
||||
);
|
||||
|
||||
bd.new_build_load(env.ptr_int(), rest_offset, "rest_start_offset")
|
||||
.into_int_value()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue