mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-11 18:58:24 +03:00
Add FunctionPointer layout
This commit is contained in:
parent
a9e3f967a8
commit
6312d75ee0
@ -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!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4527,5 +4527,6 @@ macro_rules! pointer_layouts {
|
||||
| UnionLayout::NullableWrapped { .. }
|
||||
| UnionLayout::NullableUnwrapped { .. },
|
||||
)
|
||||
| LayoutRepr::FunctionPointer(_)
|
||||
};
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
@ -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!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -9966,6 +9966,7 @@ where
|
||||
LayoutRepr::RecursivePointer(_) => {
|
||||
/* do nothing, we've already generated for this type through the Union(_) */
|
||||
}
|
||||
LayoutRepr::FunctionPointer(_) => todo_lambda_erasure!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)) => {
|
||||
|
Loading…
Reference in New Issue
Block a user