Push layout interner further through Layout

This commit is contained in:
Ayaz Hafiz 2022-08-31 14:14:34 -05:00
parent ed04c2040a
commit 3b4b1838b8
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
34 changed files with 1279 additions and 634 deletions

View file

@ -312,7 +312,7 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
}
pub fn alignment_intvalue(&self, element_layout: &Layout<'a>) -> BasicValueEnum<'ctx> {
let alignment = element_layout.alignment_bytes(self.target_info);
let alignment = element_layout.alignment_bytes(self.layout_interner, self.target_info);
let alignment_iv = self.alignment_const(alignment);
alignment_iv.into()
@ -881,7 +881,9 @@ fn promote_to_wasm_test_wrapper<'a, 'ctx, 'env>(
let roc_main_fn_result = call_roc_function(env, roc_main_fn, &top_level.result, &[]);
// For consistency, we always return with a heap-allocated value
let (size, alignment) = top_level.result.stack_size_and_alignment(env.target_info);
let (size, alignment) = top_level
.result
.stack_size_and_alignment(env.layout_interner, env.target_info);
let number_of_bytes = env.ptr_int().const_int(size as _, false);
let void_ptr = env.call_alloc(number_of_bytes, alignment);
@ -1250,8 +1252,8 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
let allocation = reserve_with_refcount_help(
env,
basic_type,
layout.stack_size(env.target_info),
layout.alignment_bytes(env.target_info),
layout.stack_size(env.layout_interner, env.target_info),
layout.alignment_bytes(env.layout_interner, env.target_info),
);
store_roc_value(env, *layout, allocation, value);
@ -1329,7 +1331,7 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
let (value, layout) = load_symbol_and_layout(scope, structure);
let layout = if let Layout::LambdaSet(lambda_set) = layout {
lambda_set.runtime_representation()
lambda_set.runtime_representation(env.layout_interner)
} else {
*layout
};
@ -1601,7 +1603,7 @@ fn build_tag_field_value<'a, 'ctx, 'env>(
env.context.i64_type().ptr_type(AddressSpace::Generic),
"cast_recursive_pointer",
)
} else if tag_field_layout.is_passed_by_reference(env.target_info) {
} else if tag_field_layout.is_passed_by_reference(env.layout_interner, env.target_info) {
debug_assert!(value.is_pointer_value());
// NOTE: we rely on this being passed to `store_roc_value` so that
@ -1662,7 +1664,7 @@ fn build_struct<'a, 'ctx, 'env>(
if !field_layout.is_dropped_because_empty() {
field_types.push(basic_type_from_layout(env, field_layout));
if field_layout.is_passed_by_reference(env.target_info) {
if field_layout.is_passed_by_reference(env.layout_interner, env.target_info) {
let field_value = env
.builder
.build_load(field_expr.into_pointer_value(), "load_tag_to_put_in_struct");
@ -1698,7 +1700,12 @@ fn build_tag<'a, 'ctx, 'env>(
let data = build_struct(env, scope, arguments);
let roc_union = RocUnion::tagged_from_slices(env.context, tags, env.target_info);
let roc_union = RocUnion::tagged_from_slices(
env.layout_interner,
env.context,
tags,
env.target_info,
);
let value = roc_union.as_struct_value(env, data, Some(tag_id as _));
let alloca = create_entry_block_alloca(
@ -1789,8 +1796,12 @@ fn build_tag<'a, 'ctx, 'env>(
nullable_id,
other_fields,
} => {
let roc_union =
RocUnion::untagged_from_slices(env.context, &[other_fields], env.target_info);
let roc_union = RocUnion::untagged_from_slices(
env.layout_interner,
env.context,
&[other_fields],
env.target_info,
);
if tag_id == *nullable_id as _ {
let output_type = roc_union.struct_type().ptr_type(AddressSpace::Generic);
@ -2105,8 +2116,8 @@ pub fn reserve_with_refcount<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout: &Layout<'a>,
) -> PointerValue<'ctx> {
let stack_size = layout.stack_size(env.target_info);
let alignment_bytes = layout.alignment_bytes(env.target_info);
let stack_size = layout.stack_size(env.layout_interner, env.target_info);
let alignment_bytes = layout.alignment_bytes(env.layout_interner, env.target_info);
let basic_type = basic_type_from_layout(env, layout);
@ -2121,9 +2132,9 @@ fn reserve_with_refcount_union_as_block_of_memory<'a, 'ctx, 'env>(
let ptr_bytes = env.target_info;
let roc_union = if union_layout.stores_tag_id_as_data(ptr_bytes) {
RocUnion::tagged_from_slices(env.context, fields, env.target_info)
RocUnion::tagged_from_slices(env.layout_interner, env.context, fields, env.target_info)
} else {
RocUnion::untagged_from_slices(env.context, fields, env.target_info)
RocUnion::untagged_from_slices(env.layout_interner, env.context, fields, env.target_info)
};
reserve_with_refcount_help(
@ -2212,10 +2223,10 @@ fn list_literal<'a, 'ctx, 'env>(
// if element_type.is_int_type() {
if false {
let element_type = element_type.into_int_type();
let element_width = element_layout.stack_size(env.target_info);
let element_width = element_layout.stack_size(env.layout_interner, env.target_info);
let size = list_length * element_width as usize;
let alignment = element_layout
.alignment_bytes(env.target_info)
.alignment_bytes(env.layout_interner, env.target_info)
.max(env.target_info.ptr_width() as u32);
let mut is_all_constant = true;
@ -2352,7 +2363,7 @@ pub fn load_roc_value<'a, 'ctx, 'env>(
source: PointerValue<'ctx>,
name: &str,
) -> BasicValueEnum<'ctx> {
if layout.is_passed_by_reference(env.target_info) {
if layout.is_passed_by_reference(env.layout_interner, env.target_info) {
let alloca = entry_block_alloca_zerofill(env, basic_type_from_layout(env, &layout), name);
store_roc_value(env, layout, alloca, source.into());
@ -2369,7 +2380,7 @@ pub fn use_roc_value<'a, 'ctx, 'env>(
source: BasicValueEnum<'ctx>,
name: &str,
) -> BasicValueEnum<'ctx> {
if layout.is_passed_by_reference(env.target_info) {
if layout.is_passed_by_reference(env.layout_interner, env.target_info) {
let alloca = entry_block_alloca_zerofill(env, basic_type_from_layout(env, &layout), name);
env.builder.build_store(alloca, source);
@ -2400,15 +2411,16 @@ pub fn store_roc_value<'a, 'ctx, 'env>(
destination: PointerValue<'ctx>,
value: BasicValueEnum<'ctx>,
) {
if layout.is_passed_by_reference(env.target_info) {
if layout.is_passed_by_reference(env.layout_interner, env.target_info) {
debug_assert!(value.is_pointer_value());
let align_bytes = layout.alignment_bytes(env.target_info);
let align_bytes = layout.alignment_bytes(env.layout_interner, env.target_info);
if align_bytes > 0 {
let size = env
.ptr_int()
.const_int(layout.stack_size(env.target_info) as u64, false);
let size = env.ptr_int().const_int(
layout.stack_size(env.layout_interner, env.target_info) as u64,
false,
);
env.builder
.build_memcpy(
@ -2503,8 +2515,9 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
// store_roc_value(env, *layout, out_parameter.into_pointer_value(), value);
let destination = out_parameter.into_pointer_value();
if layout.is_passed_by_reference(env.target_info) {
let align_bytes = layout.alignment_bytes(env.target_info);
if layout.is_passed_by_reference(env.layout_interner, env.target_info) {
let align_bytes =
layout.alignment_bytes(env.layout_interner, env.target_info);
if align_bytes > 0 {
debug_assert!(
@ -2535,7 +2548,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
// Hence, we explicitly memcpy source to destination, and rely on
// LLVM optimizing away any inefficiencies.
let target_info = env.target_info;
let width = layout.stack_size(target_info);
let width = layout.stack_size(env.layout_interner, target_info);
let size = env.ptr_int().const_int(width as _, false);
env.builder
@ -2615,7 +2628,10 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
for param in parameters.iter() {
let basic_type = basic_type_from_layout(env, &param.layout);
let phi_type = if param.layout.is_passed_by_reference(env.target_info) {
let phi_type = if param
.layout
.is_passed_by_reference(env.layout_interner, env.target_info)
{
basic_type.ptr_type(AddressSpace::Generic).into()
} else {
basic_type
@ -2698,7 +2714,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
let (value, layout) = load_symbol_and_layout(scope, symbol);
let layout = *layout;
if layout.contains_refcounted() {
if layout.contains_refcounted(env.layout_interner) {
increment_refcount_layout(
env,
parent,
@ -2714,7 +2730,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
Dec(symbol) => {
let (value, layout) = load_symbol_and_layout(scope, symbol);
if layout.contains_refcounted() {
if layout.contains_refcounted(env.layout_interner) {
decrement_refcount_layout(env, parent, layout_ids, value, layout);
}
@ -2727,7 +2743,8 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
Layout::Builtin(Builtin::Str) => todo!(),
Layout::Builtin(Builtin::List(element_layout)) => {
debug_assert!(value.is_struct_value());
let alignment = element_layout.alignment_bytes(env.target_info);
let alignment = element_layout
.alignment_bytes(env.layout_interner, env.target_info);
build_list::decref(env, value.into_struct_value(), alignment);
}
@ -4140,7 +4157,7 @@ fn make_good_roc_result<'a, 'ctx, 'env>(
.build_insert_value(v1, context.i64_type().const_zero(), 0, "set_no_error")
.unwrap();
let v3 = if return_layout.is_passed_by_reference(env.target_info) {
let v3 = if return_layout.is_passed_by_reference(env.layout_interner, env.target_info) {
let loaded = env.builder.build_load(
return_value.into_pointer_value(),
"load_call_result_passed_by_ptr",
@ -4403,10 +4420,12 @@ fn build_procedures_help<'a, 'ctx, 'env>(
let it = procedures.iter().map(|x| x.1);
let solutions = match roc_alias_analysis::spec_program(opt_level, opt_entry_point, it) {
Err(e) => panic!("Error in alias analysis: {}", e),
Ok(solutions) => solutions,
};
let solutions =
match roc_alias_analysis::spec_program(env.layout_interner, opt_level, opt_entry_point, it)
{
Err(e) => panic!("Error in alias analysis: {}", e),
Ok(solutions) => solutions,
};
let solutions = env.arena.alloc(solutions);
@ -4672,7 +4691,8 @@ fn build_closure_caller<'a, 'ctx, 'env>(
}
let closure_argument_type = {
let basic_type = basic_type_from_layout(env, &lambda_set.runtime_representation());
let basic_type =
basic_type_from_layout(env, &lambda_set.runtime_representation(env.layout_interner));
basic_type.ptr_type(AddressSpace::Generic)
};
@ -4719,10 +4739,12 @@ fn build_closure_caller<'a, 'ctx, 'env>(
// NOTE this may be incorrect in the long run
// here we load any argument that is a pointer
let closure_layout = lambda_set.runtime_representation();
let closure_layout = lambda_set.runtime_representation(env.layout_interner);
let layouts_it = arguments.iter().chain(std::iter::once(&closure_layout));
for (param, layout) in evaluator_arguments.iter_mut().zip(layouts_it) {
if param.is_pointer_value() && !layout.is_passed_by_reference(env.target_info) {
if param.is_pointer_value()
&& !layout.is_passed_by_reference(env.layout_interner, env.target_info)
{
*param = builder.build_load(param.into_pointer_value(), "load_param");
}
}
@ -4740,13 +4762,14 @@ fn build_closure_caller<'a, 'ctx, 'env>(
} else {
let call_result = call_roc_function(env, evaluator, return_layout, &evaluator_arguments);
if return_layout.is_passed_by_reference(env.target_info) {
let align_bytes = return_layout.alignment_bytes(env.target_info);
if return_layout.is_passed_by_reference(env.layout_interner, env.target_info) {
let align_bytes = return_layout.alignment_bytes(env.layout_interner, env.target_info);
if align_bytes > 0 {
let size = env
.ptr_int()
.const_int(return_layout.stack_size(env.target_info) as u64, false);
let size = env.ptr_int().const_int(
return_layout.stack_size(env.layout_interner, env.target_info) as u64,
false,
);
env.builder
.build_memcpy(
@ -4773,7 +4796,7 @@ fn build_closure_caller<'a, 'ctx, 'env>(
env,
def_name,
alias_symbol,
lambda_set.runtime_representation(),
lambda_set.runtime_representation(env.layout_interner),
);
}
@ -5043,7 +5066,7 @@ pub fn call_roc_function<'a, 'ctx, 'env>(
debug_assert_eq!(roc_function.get_call_conventions(), FAST_CALL_CONV);
call.set_call_convention(FAST_CALL_CONV);
if result_layout.is_passed_by_reference(env.target_info) {
if result_layout.is_passed_by_reference(env.layout_interner, env.target_info) {
result_alloca.into()
} else {
env.builder
@ -5125,10 +5148,13 @@ fn roc_function_call<'a, 'ctx, 'env>(
.as_global_value()
.as_pointer_value();
let inc_closure_data =
build_inc_n_wrapper(env, layout_ids, &lambda_set.runtime_representation())
.as_global_value()
.as_pointer_value();
let inc_closure_data = build_inc_n_wrapper(
env,
layout_ids,
&lambda_set.runtime_representation(env.layout_interner),
)
.as_global_value()
.as_pointer_value();
let closure_data_is_owned = env
.context
@ -6467,7 +6493,7 @@ fn to_cc_type<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout: &Layout<'a>,
) -> BasicTypeEnum<'ctx> {
match layout.runtime_representation() {
match layout.runtime_representation(env.layout_interner) {
Layout::Builtin(builtin) => to_cc_type_builtin(env, &builtin),
layout => {
// TODO this is almost certainly incorrect for bigger structs
@ -6509,7 +6535,11 @@ enum RocReturn {
}
impl RocReturn {
fn roc_return_by_pointer(target_info: TargetInfo, layout: Layout) -> bool {
fn roc_return_by_pointer(
interner: &STLayoutInterner,
target_info: TargetInfo,
layout: Layout,
) -> bool {
match layout {
Layout::Builtin(builtin) => {
use Builtin::*;
@ -6524,15 +6554,17 @@ impl RocReturn {
}
}
Layout::Union(UnionLayout::NonRecursive(_)) => true,
Layout::LambdaSet(lambda_set) => {
RocReturn::roc_return_by_pointer(target_info, lambda_set.runtime_representation())
}
Layout::LambdaSet(lambda_set) => RocReturn::roc_return_by_pointer(
interner,
target_info,
lambda_set.runtime_representation(interner),
),
_ => false,
}
}
fn from_layout<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>, layout: &Layout<'a>) -> Self {
if Self::roc_return_by_pointer(env.target_info, *layout) {
if Self::roc_return_by_pointer(env.layout_interner, env.target_info, *layout) {
RocReturn::ByPointer
} else {
RocReturn::Return
@ -6670,7 +6702,7 @@ impl<'ctx> FunctionSpec<'ctx> {
/// According to the C ABI, how should we return a value with the given layout?
pub fn to_cc_return<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>, layout: &Layout<'a>) -> CCReturn {
let return_size = layout.stack_size(env.target_info);
let return_size = layout.stack_size(env.layout_interner, env.target_info);
let pass_result_by_pointer = return_size > 2 * env.target_info.ptr_width() as u32;
if return_size == 0 {