Add FunctionPointer layout

This commit is contained in:
Ayaz Hafiz 2023-06-25 15:35:03 -05:00
parent a9e3f967a8
commit 6312d75ee0
No known key found for this signature in database
GPG Key ID: 0E2A37416A25EF58
18 changed files with 111 additions and 14 deletions

View File

@ -1632,6 +1632,8 @@ fn layout_spec_help<'a>(
}
_ => internal_error!("somehow, a non-recursive layout is under a recursive pointer"),
},
FunctionPointer(_) => todo_lambda_erasure!(),
}
}

View File

@ -4527,5 +4527,6 @@ macro_rules! pointer_layouts {
| UnionLayout::NullableWrapped { .. }
| UnionLayout::NullableUnwrapped { .. },
)
| LayoutRepr::FunctionPointer(_)
};
}

View File

@ -830,7 +830,14 @@ impl<
self.copy_to_stack_offset(buf, size, from_offset, to_offset)
}
<<<<<<< HEAD
pointer_layouts!() => {
=======
LayoutRepr::RecursivePointer(_)
| LayoutRepr::Boxed(_)
| LayoutRepr::Union(_)
| LayoutRepr::FunctionPointer(_) => {
>>>>>>> 1e4ebab07 (Add FunctionPointer layout)
// like a 64-bit integer
debug_assert_eq!(to_offset % 8, 0);
let reg = self.load_to_general_reg(buf, sym);

View File

@ -119,8 +119,9 @@ impl<'a> LlvmAlignment<'a> for LayoutRepr<'a> {
.runtime_representation()
.llvm_alignment_bytes(interner),
Builtin(builtin) => builtin.llvm_alignment_bytes(interner),
RecursivePointer(_) => interner.target_info().ptr_width() as u32,
Ptr(_) => interner.target_info().ptr_width() as u32,
RecursivePointer(_) | Ptr(_) | FunctionPointer(_) => {
interner.target_info().ptr_width() as u32
}
}
}
}

View File

@ -8,7 +8,7 @@ use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue, Str
use inkwell::{AddressSpace, FloatPredicate, IntPredicate};
use roc_builtins::bitcode;
use roc_builtins::bitcode::{FloatWidth, IntWidth};
use roc_error_macros::internal_error;
use roc_error_macros::{internal_error, todo_lambda_erasure};
use roc_module::symbol::Symbol;
use roc_mono::layout::{
Builtin, InLayout, LayoutIds, LayoutInterner, LayoutRepr, STLayoutInterner, UnionLayout,
@ -225,6 +225,8 @@ fn build_eq<'a, 'ctx>(
field2_cast.into(),
)
}
LayoutRepr::FunctionPointer(_) => todo_lambda_erasure!(),
}
}
@ -399,6 +401,8 @@ fn build_neq<'a, 'ctx>(
unreachable!("recursion pointers should never be compared directly")
}
LayoutRepr::LambdaSet(_) => unreachable!("cannot compare closure"),
LayoutRepr::FunctionPointer(_) => todo_lambda_erasure!(),
}
}

View File

@ -6,6 +6,7 @@ use inkwell::types::{BasicType, BasicTypeEnum, FloatType, IntType, StructType};
use inkwell::values::PointerValue;
use inkwell::AddressSpace;
use roc_builtins::bitcode::{FloatWidth, IntWidth};
use roc_error_macros::todo_lambda_erasure;
use roc_mono::layout::{
round_up_to_alignment, Builtin, InLayout, Layout, LayoutInterner, LayoutRepr, STLayoutInterner,
UnionLayout,
@ -48,6 +49,8 @@ pub fn basic_type_from_layout<'a, 'ctx>(
.ptr_type(AddressSpace::default())
.as_basic_type_enum(),
FunctionPointer(_) => todo_lambda_erasure!(),
Builtin(builtin) => basic_type_from_builtin(env, &builtin),
}
}

View File

@ -9,7 +9,7 @@ use inkwell::types::{BasicMetadataTypeEnum, BasicType, BasicTypeEnum};
use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue};
use inkwell::AddressSpace;
use roc_builtins::bitcode;
use roc_error_macros::internal_error;
use roc_error_macros::{internal_error, todo_lambda_erasure};
use roc_module::symbol::Symbol;
use roc_mono::ir::LookupType;
use roc_mono::layout::{
@ -387,6 +387,7 @@ fn build_clone<'a, 'ctx>(
union_layout,
)
}
LayoutRepr::FunctionPointer(_) => todo_lambda_erasure!(),
}
}

View File

@ -16,6 +16,7 @@ use inkwell::module::Linkage;
use inkwell::types::{AnyTypeEnum, BasicMetadataTypeEnum, BasicType, BasicTypeEnum};
use inkwell::values::{BasicValueEnum, FunctionValue, InstructionValue, IntValue, PointerValue};
use inkwell::{AddressSpace, IntPredicate};
use roc_error_macros::todo_lambda_erasure;
use roc_module::symbol::Interns;
use roc_module::symbol::Symbol;
use roc_mono::layout::{
@ -624,6 +625,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx>(
mode,
lambda_set.runtime_representation(),
),
FunctionPointer(_) => todo_lambda_erasure!(),
}
}

View File

@ -1,4 +1,5 @@
use roc_builtins::bitcode::{FloatWidth, IntWidth};
use roc_error_macros::todo_lambda_erasure;
use roc_mono::layout::{InLayout, LayoutInterner, LayoutRepr, STLayoutInterner, UnionLayout};
use crate::{PTR_SIZE, PTR_TYPE};
@ -99,6 +100,7 @@ impl WasmLayout {
)
| LayoutRepr::Ptr(_)
| LayoutRepr::RecursivePointer(_) => Self::Primitive(PTR_TYPE, PTR_SIZE),
LayoutRepr::FunctionPointer(_) => todo_lambda_erasure!(),
}
}

View File

@ -1,7 +1,7 @@
use bumpalo::collections::Vec;
use bumpalo::Bump;
use roc_builtins::bitcode::{self, FloatWidth, IntWidth};
use roc_error_macros::internal_error;
use roc_error_macros::{internal_error, todo_lambda_erasure};
use roc_module::low_level::LowLevel;
use roc_module::symbol::Symbol;
use roc_mono::code_gen_help::HelperOp;
@ -2120,6 +2120,8 @@ impl<'a> LowLevelCall<'a> {
self.arguments,
)
}
LayoutRepr::FunctionPointer(_) => todo_lambda_erasure!(),
}
}

View File

@ -25,7 +25,7 @@ pub fn eq_generic<'a>(
use crate::layout::Builtin::*;
use LayoutRepr::*;
let main_body = match layout_interner.get_repr(layout) {
Builtin(Int(_) | Float(_) | Bool | Decimal) => {
Builtin(Int(_) | Float(_) | Bool | Decimal) | FunctionPointer(_) => {
unreachable!(
"No generated proc for `==`. Use direct code gen for {:?}",
layout

View File

@ -582,6 +582,8 @@ impl<'a> CodeGenHelp<'a> {
// This line is the whole point of the function
LayoutRepr::RecursivePointer(_) => LayoutRepr::Union(ctx.recursive_union.unwrap()),
LayoutRepr::FunctionPointer(_) => return layout,
};
layout_interner.insert(Layout::new(LayoutWrapper::Direct(repr), semantic))
@ -838,5 +840,6 @@ fn layout_needs_helper_proc<'a>(
LayoutRepr::LambdaSet(_) => true,
LayoutRepr::RecursivePointer(_) => false,
LayoutRepr::Ptr(_) => false,
LayoutRepr::FunctionPointer(_) => false,
}
}

View File

@ -188,7 +188,8 @@ pub fn refcount_generic<'a>(
match layout_interner.get_repr(layout) {
LayoutRepr::Builtin(
Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal,
) => {
)
| LayoutRepr::FunctionPointer(_) => {
// Generate a dummy function that immediately returns Unit
// Some higher-order Zig builtins *always* call an RC function on List elements.
rc_return_stmt(root, ident_ids, ctx)

View File

@ -9966,6 +9966,7 @@ where
LayoutRepr::RecursivePointer(_) => {
/* do nothing, we've already generated for this type through the Union(_) */
}
LayoutRepr::FunctionPointer(_) => todo_lambda_erasure!(),
}
}

View File

@ -684,6 +684,45 @@ pub enum LayoutRepr<'a> {
Union(UnionLayout<'a>),
LambdaSet(LambdaSet<'a>),
RecursivePointer(InLayout<'a>),
/// Only used for erased functions.
FunctionPointer(FunctionPointer<'a>),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct FunctionPointer<'a> {
args: &'a [InLayout<'a>],
ret: InLayout<'a>,
}
impl<'a> FunctionPointer<'a> {
pub fn to_doc<'b, D, A, I>(
self,
alloc: &'b D,
interner: &I,
seen_rec: &mut SeenRecPtrs<'a>,
parens: Parens,
) -> DocBuilder<'b, D, A>
where
D: DocAllocator<'b, A>,
D::Doc: Clone,
A: Clone,
I: LayoutInterner<'a>,
{
let Self { args, ret } = self;
let args = args
.iter()
.map(|arg| interner.to_doc(*arg, alloc, seen_rec, parens));
let args = alloc.intersperse(args, alloc.text(", "));
let ret = interner.to_doc(ret, alloc, seen_rec, parens);
alloc
.text("FunPtr(")
.append(args)
.append(alloc.text(" -> "))
.append(ret)
.append(")")
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
@ -2605,6 +2644,7 @@ impl<'a> LayoutRepr<'a> {
// We cannot memcpy pointers, because then we would have the same pointer in multiple places!
false
}
FunctionPointer(..) => true,
}
}
@ -2690,8 +2730,9 @@ impl<'a> LayoutRepr<'a> {
LambdaSet(lambda_set) => interner
.get_repr(lambda_set.runtime_representation())
.stack_size_without_alignment(interner),
RecursivePointer(_) => interner.target_info().ptr_width() as u32,
Ptr(_) => interner.target_info().ptr_width() as u32,
RecursivePointer(_) | Ptr(_) | FunctionPointer(_) => {
interner.target_info().ptr_width() as u32
}
}
}
@ -2743,8 +2784,9 @@ impl<'a> LayoutRepr<'a> {
.get_repr(lambda_set.runtime_representation())
.alignment_bytes(interner),
Builtin(builtin) => builtin.alignment_bytes(interner.target_info()),
RecursivePointer(_) => interner.target_info().ptr_width() as u32,
Ptr(_) => interner.target_info().ptr_width() as u32,
RecursivePointer(_) | Ptr(_) | FunctionPointer(_) => {
interner.target_info().ptr_width() as u32
}
}
}
@ -2766,6 +2808,7 @@ impl<'a> LayoutRepr<'a> {
unreachable!("should be looked up to get an actual layout")
}
Ptr(inner) => interner.get_repr(*inner).alignment_bytes(interner),
FunctionPointer(_) => ptr_width,
}
}
@ -2839,6 +2882,7 @@ impl<'a> LayoutRepr<'a> {
// author must make sure that invariants are upheld
false
}
FunctionPointer(_) => false,
}
}
@ -2900,6 +2944,9 @@ impl<'a> LayoutRepr<'a> {
RecursivePointer(_) => {
/* do nothing, we've already generated for this type through the Union(_) */
}
FunctionPointer(_) => {
// drop through
}
}
}

View File

@ -354,6 +354,7 @@ pub trait LayoutInterner<'a>: Sized {
.text("Ptr(")
.append(self.to_doc(inner, alloc, seen_rec, parens))
.append(")"),
FunctionPointer(fp) => fp.to_doc(alloc, self, seen_rec, parens),
}
}
@ -1076,7 +1077,9 @@ mod reify {
use bumpalo::{collections::Vec, Bump};
use roc_module::symbol::Symbol;
use crate::layout::{Builtin, LambdaSet, Layout, LayoutRepr, LayoutWrapper, UnionLayout};
use crate::layout::{
Builtin, FunctionPointer, LambdaSet, Layout, LayoutRepr, LayoutWrapper, UnionLayout,
};
use super::{InLayout, LayoutInterner, NeedsRecursionPointerFixup};
@ -1121,6 +1124,12 @@ mod reify {
// another recursive union's layout, do not change it.
LayoutRepr::RecursivePointer(if l == Layout::VOID { slot } else { l })
}
LayoutRepr::FunctionPointer(FunctionPointer { args, ret }) => {
LayoutRepr::FunctionPointer(FunctionPointer {
args: reify_layout_slice(arena, interner, slot, args),
ret: reify_layout(arena, interner, slot, ret),
})
}
}
}
@ -1447,6 +1456,11 @@ pub mod dbg_deep {
LayoutRepr::RecursivePointer(rp) => {
f.debug_tuple("RecursivePointer").field(&rp.0).finish()
}
LayoutRepr::FunctionPointer(fp) => f
.debug_struct("FunctionPointer")
.field("args", &fp.args)
.field("ret", &fp.ret)
.finish(),
}
}
}
@ -1620,6 +1634,11 @@ pub mod dbg_stable {
LayoutRepr::RecursivePointer(rp) => {
f.debug_tuple("RecursivePointer").field(&rp.0).finish()
}
LayoutRepr::FunctionPointer(fp) => f
.debug_struct("FunctionPointer")
.field("args", &fp.args)
.field("ret", &fp.ret)
.finish(),
}
}
}

View File

@ -2100,6 +2100,7 @@ fn tag_union_type_from_layout<'a>(
// been turned into an error earlier in the process.
unreachable!();
}
LayoutRepr::FunctionPointer(_) => todo_lambda_erasure!(),
}
}

View File

@ -537,7 +537,7 @@ fn jit_to_ast_help<'a, A: ReplApp<'a>>(
LayoutRepr::Ptr(_) => {
unreachable!("Ptr will never be visible to users")
}
LayoutRepr::LambdaSet(_) => OPAQUE_FUNCTION,
LayoutRepr::LambdaSet(_) | LayoutRepr::FunctionPointer(_) => OPAQUE_FUNCTION,
};
apply_newtypes(env, newtype_containers.into_bump_slice(), expr)
@ -575,7 +575,7 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
let raw_content = env.subs.get_content_without_compacting(raw_var);
let expr = match (raw_content, layout) {
(Content::Structure(FlatType::Func(_, _, _)), _) | (_, LayoutRepr::LambdaSet(_)) => {
(Content::Structure(FlatType::Func(_, _, _)), _) | (_, LayoutRepr::LambdaSet(_) | LayoutRepr::FunctionPointer(_)) => {
OPAQUE_FUNCTION
}
(_, LayoutRepr::Builtin(Builtin::Bool)) => {