Push mutable layout interner through llvm backend

This commit is contained in:
Ayaz Hafiz 2022-12-29 10:04:43 -06:00
parent e4b5252e51
commit 512a1721ae
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
8 changed files with 1289 additions and 555 deletions

View file

@ -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()